@rachelallyson/hero-hook-form 2.7.0 → 2.8.0
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 +50 -0
- package/dist/cypress/index.d.ts +62 -71
- package/dist/cypress/index.js +583 -70
- package/dist/index.d.ts +605 -79
- package/dist/index.js +1611 -695
- package/package.json +15 -12
- package/dist/react/index.d.ts +0 -3777
- package/dist/react/index.js +0 -4235
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,8 +77,14 @@ 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
|
|
87
|
+
import React19 from "react";
|
|
79
88
|
import { get, useWatch as useWatch3 } from "react-hook-form";
|
|
80
89
|
|
|
81
90
|
// src/fields/AutocompleteField.tsx
|
|
@@ -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,10 +526,11 @@ 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({
|
|
533
|
+
alwaysRegistered = false,
|
|
430
534
|
className,
|
|
431
535
|
config
|
|
432
536
|
}) {
|
|
@@ -451,27 +555,63 @@ function FieldArrayField({
|
|
|
451
555
|
const { append, fields, move, remove } = useFieldArray({
|
|
452
556
|
control,
|
|
453
557
|
name
|
|
454
|
-
// FieldArray name
|
|
455
558
|
});
|
|
456
559
|
const canAdd = fields.length < max;
|
|
457
560
|
const canRemove = fields.length > min;
|
|
561
|
+
if (alwaysRegistered && fields.length === 0) {
|
|
562
|
+
return null;
|
|
563
|
+
}
|
|
564
|
+
const getFieldPath = (fieldName, itemIndex) => {
|
|
565
|
+
return `${String(name)}.${itemIndex}.${fieldName}`;
|
|
566
|
+
};
|
|
567
|
+
const processFieldConfig = (fieldConfig, itemIndex) => {
|
|
568
|
+
const fieldName = String(fieldConfig.name);
|
|
569
|
+
const fullPath = getFieldPath(fieldName, itemIndex);
|
|
570
|
+
if ("dependsOn" in fieldConfig && fieldConfig.dependsOn && typeof fieldConfig.dependsOn === "string") {
|
|
571
|
+
const dependsOnPath = fieldConfig.dependsOn;
|
|
572
|
+
const arrayNamePrefix = `${String(name)}.`;
|
|
573
|
+
if (!dependsOnPath.startsWith(arrayNamePrefix)) {
|
|
574
|
+
const nestedDependsOn = getFieldPath(dependsOnPath, itemIndex);
|
|
575
|
+
return {
|
|
576
|
+
...fieldConfig,
|
|
577
|
+
dependsOn: nestedDependsOn,
|
|
578
|
+
name: fullPath,
|
|
579
|
+
..."dependsOnValue" in fieldConfig && {
|
|
580
|
+
dependsOnValue: fieldConfig.dependsOnValue
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
return {
|
|
586
|
+
...fieldConfig,
|
|
587
|
+
name: fullPath
|
|
588
|
+
};
|
|
589
|
+
};
|
|
590
|
+
const renderField = (fieldConfig, itemIndex) => {
|
|
591
|
+
const processedConfig = processFieldConfig(fieldConfig, itemIndex);
|
|
592
|
+
return /* @__PURE__ */ React9.createElement(
|
|
593
|
+
FormField,
|
|
594
|
+
{
|
|
595
|
+
key: `${fieldConfig.name}-${itemIndex}`,
|
|
596
|
+
config: processedConfig,
|
|
597
|
+
form,
|
|
598
|
+
submissionState: {
|
|
599
|
+
error: void 0,
|
|
600
|
+
isSubmitted: false,
|
|
601
|
+
isSubmitting: false,
|
|
602
|
+
isSuccess: false
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
);
|
|
606
|
+
};
|
|
458
607
|
const handleAdd = () => {
|
|
459
608
|
if (canAdd) {
|
|
460
609
|
if (defaultItem) {
|
|
461
610
|
append(defaultItem());
|
|
462
611
|
} else {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
acc[fieldName] = false;
|
|
467
|
-
} else if (fieldConfig.type === "slider") {
|
|
468
|
-
acc[fieldName] = 0;
|
|
469
|
-
} else {
|
|
470
|
-
acc[fieldName] = "";
|
|
471
|
-
}
|
|
472
|
-
return acc;
|
|
473
|
-
}, {});
|
|
474
|
-
append(defaultValues);
|
|
612
|
+
console.warn(
|
|
613
|
+
`FieldArrayField: defaultItem is required for field array "${String(name)}". Please provide a defaultItem function that returns the default item structure.`
|
|
614
|
+
);
|
|
475
615
|
}
|
|
476
616
|
}
|
|
477
617
|
};
|
|
@@ -495,44 +635,15 @@ function FieldArrayField({
|
|
|
495
635
|
const canMoveUp = enableReordering && index > 0;
|
|
496
636
|
const canMoveDown = enableReordering && index < fields.length - 1;
|
|
497
637
|
const itemCanRemove = canRemove;
|
|
498
|
-
const fieldElements = fieldConfigs.map(
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
let processedConfig = { ...fieldConfig, name: fullPath };
|
|
502
|
-
if ("dependsOn" in fieldConfig && fieldConfig.dependsOn && typeof fieldConfig.dependsOn === "string") {
|
|
503
|
-
const dependsOnPath = fieldConfig.dependsOn;
|
|
504
|
-
if (!dependsOnPath.startsWith(`${name}.`)) {
|
|
505
|
-
processedConfig = {
|
|
506
|
-
...processedConfig,
|
|
507
|
-
dependsOn: `${name}.${index}.${dependsOnPath}`,
|
|
508
|
-
// Preserve dependsOnValue if it exists
|
|
509
|
-
..."dependsOnValue" in fieldConfig && {
|
|
510
|
-
dependsOnValue: fieldConfig.dependsOnValue
|
|
511
|
-
}
|
|
512
|
-
};
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
return /* @__PURE__ */ React8.createElement(
|
|
516
|
-
FormField,
|
|
517
|
-
{
|
|
518
|
-
key: `${fieldConfig.name}-${index}`,
|
|
519
|
-
config: processedConfig,
|
|
520
|
-
form,
|
|
521
|
-
submissionState: {
|
|
522
|
-
error: void 0,
|
|
523
|
-
isSubmitted: false,
|
|
524
|
-
isSubmitting: false,
|
|
525
|
-
isSuccess: false
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
);
|
|
529
|
-
});
|
|
638
|
+
const fieldElements = fieldConfigs.map(
|
|
639
|
+
(fieldConfig) => renderField(fieldConfig, index)
|
|
640
|
+
);
|
|
530
641
|
if (renderItem) {
|
|
531
|
-
return /* @__PURE__ */
|
|
642
|
+
return /* @__PURE__ */ React9.createElement(React9.Fragment, { key: field2.id }, renderItem({
|
|
532
643
|
canMoveDown,
|
|
533
644
|
canMoveUp,
|
|
534
645
|
canRemove: itemCanRemove,
|
|
535
|
-
children: /* @__PURE__ */
|
|
646
|
+
children: /* @__PURE__ */ React9.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, fieldElements),
|
|
536
647
|
field: field2,
|
|
537
648
|
fields,
|
|
538
649
|
index,
|
|
@@ -541,13 +652,13 @@ function FieldArrayField({
|
|
|
541
652
|
onRemove: () => handleRemove(index)
|
|
542
653
|
}));
|
|
543
654
|
}
|
|
544
|
-
return /* @__PURE__ */
|
|
655
|
+
return /* @__PURE__ */ React9.createElement(
|
|
545
656
|
"div",
|
|
546
657
|
{
|
|
547
658
|
key: field2.id,
|
|
548
659
|
className: "border border-gray-200 rounded-lg p-4 space-y-4"
|
|
549
660
|
},
|
|
550
|
-
/* @__PURE__ */
|
|
661
|
+
/* @__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(
|
|
551
662
|
Button2,
|
|
552
663
|
{
|
|
553
664
|
size: "sm",
|
|
@@ -557,7 +668,7 @@ function FieldArrayField({
|
|
|
557
668
|
"aria-label": `Move ${config.label} ${index + 1} up`
|
|
558
669
|
},
|
|
559
670
|
reorderButtonText.up
|
|
560
|
-
), /* @__PURE__ */
|
|
671
|
+
), /* @__PURE__ */ React9.createElement(
|
|
561
672
|
Button2,
|
|
562
673
|
{
|
|
563
674
|
size: "sm",
|
|
@@ -567,7 +678,7 @@ function FieldArrayField({
|
|
|
567
678
|
"aria-label": `Move ${config.label} ${index + 1} down`
|
|
568
679
|
},
|
|
569
680
|
reorderButtonText.down
|
|
570
|
-
)), itemCanRemove && /* @__PURE__ */
|
|
681
|
+
)), itemCanRemove && /* @__PURE__ */ React9.createElement(
|
|
571
682
|
Button2,
|
|
572
683
|
{
|
|
573
684
|
size: "sm",
|
|
@@ -579,7 +690,7 @@ function FieldArrayField({
|
|
|
579
690
|
},
|
|
580
691
|
removeButtonText
|
|
581
692
|
))),
|
|
582
|
-
/* @__PURE__ */
|
|
693
|
+
/* @__PURE__ */ React9.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, fieldElements)
|
|
583
694
|
);
|
|
584
695
|
});
|
|
585
696
|
};
|
|
@@ -593,7 +704,7 @@ function FieldArrayField({
|
|
|
593
704
|
if (!canAdd) {
|
|
594
705
|
return null;
|
|
595
706
|
}
|
|
596
|
-
return /* @__PURE__ */
|
|
707
|
+
return /* @__PURE__ */ React9.createElement(
|
|
597
708
|
Button2,
|
|
598
709
|
{
|
|
599
710
|
variant: "bordered",
|
|
@@ -604,12 +715,12 @@ function FieldArrayField({
|
|
|
604
715
|
addButtonText
|
|
605
716
|
);
|
|
606
717
|
};
|
|
607
|
-
return /* @__PURE__ */
|
|
718
|
+
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()));
|
|
608
719
|
}
|
|
609
720
|
|
|
610
721
|
// src/fields/FileField.tsx
|
|
611
|
-
import
|
|
612
|
-
import { Controller as
|
|
722
|
+
import React10 from "react";
|
|
723
|
+
import { Controller as Controller5 } from "react-hook-form";
|
|
613
724
|
function CoercedFileInput(props) {
|
|
614
725
|
const {
|
|
615
726
|
accept,
|
|
@@ -622,7 +733,7 @@ function CoercedFileInput(props) {
|
|
|
622
733
|
multiple
|
|
623
734
|
} = props;
|
|
624
735
|
const defaults = useHeroHookFormDefaults();
|
|
625
|
-
return /* @__PURE__ */
|
|
736
|
+
return /* @__PURE__ */ React10.createElement(
|
|
626
737
|
Input,
|
|
627
738
|
{
|
|
628
739
|
...defaults.input,
|
|
@@ -634,10 +745,14 @@ function CoercedFileInput(props) {
|
|
|
634
745
|
isInvalid: Boolean(errorMessage),
|
|
635
746
|
label,
|
|
636
747
|
multiple,
|
|
748
|
+
name: field2.name,
|
|
637
749
|
type: "file",
|
|
638
750
|
value: field2.value ? "" : "",
|
|
639
751
|
onBlur: field2.onBlur,
|
|
640
752
|
onChange: (e) => {
|
|
753
|
+
if (!(e.target instanceof HTMLInputElement)) {
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
641
756
|
const target = e.target;
|
|
642
757
|
field2.onChange(target.files);
|
|
643
758
|
}
|
|
@@ -658,12 +773,12 @@ function FileField(props) {
|
|
|
658
773
|
rules,
|
|
659
774
|
transform
|
|
660
775
|
} = props;
|
|
661
|
-
return /* @__PURE__ */
|
|
662
|
-
|
|
776
|
+
return /* @__PURE__ */ React10.createElement(
|
|
777
|
+
Controller5,
|
|
663
778
|
{
|
|
664
779
|
control,
|
|
665
780
|
name,
|
|
666
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
781
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React10.createElement("div", { className }, /* @__PURE__ */ React10.createElement(
|
|
667
782
|
CoercedFileInput,
|
|
668
783
|
{
|
|
669
784
|
accept,
|
|
@@ -685,8 +800,8 @@ function FileField(props) {
|
|
|
685
800
|
}
|
|
686
801
|
|
|
687
802
|
// src/fields/FontPickerField.tsx
|
|
688
|
-
import
|
|
689
|
-
import { Controller as
|
|
803
|
+
import React11 from "react";
|
|
804
|
+
import { Controller as Controller6 } from "react-hook-form";
|
|
690
805
|
var FontPickerComponent = null;
|
|
691
806
|
var fontPickerLoaded = false;
|
|
692
807
|
var fontPickerLoading = false;
|
|
@@ -702,12 +817,12 @@ function FontPickerField(props) {
|
|
|
702
817
|
name,
|
|
703
818
|
rules
|
|
704
819
|
} = props;
|
|
705
|
-
const [fontPickerState, setFontPickerState] =
|
|
820
|
+
const [fontPickerState, setFontPickerState] = React11.useState({
|
|
706
821
|
component: FontPickerComponent,
|
|
707
822
|
error: null,
|
|
708
823
|
loading: false
|
|
709
824
|
});
|
|
710
|
-
|
|
825
|
+
React11.useEffect(() => {
|
|
711
826
|
if (fontPickerLoaded && FontPickerComponent) {
|
|
712
827
|
setFontPickerState({
|
|
713
828
|
component: FontPickerComponent,
|
|
@@ -765,17 +880,17 @@ function FontPickerField(props) {
|
|
|
765
880
|
void loadFontPicker();
|
|
766
881
|
}, []);
|
|
767
882
|
if (fontPickerState.loading) {
|
|
768
|
-
return /* @__PURE__ */
|
|
883
|
+
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..."))));
|
|
769
884
|
}
|
|
770
885
|
if (!fontPickerState.component) {
|
|
771
|
-
return /* @__PURE__ */
|
|
886
|
+
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."))));
|
|
772
887
|
}
|
|
773
|
-
return /* @__PURE__ */
|
|
774
|
-
|
|
888
|
+
return /* @__PURE__ */ React11.createElement(
|
|
889
|
+
Controller6,
|
|
775
890
|
{
|
|
776
891
|
control,
|
|
777
892
|
name,
|
|
778
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
893
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React11.createElement(
|
|
779
894
|
fontPickerState.component,
|
|
780
895
|
{
|
|
781
896
|
label,
|
|
@@ -794,12 +909,12 @@ function FontPickerField(props) {
|
|
|
794
909
|
}
|
|
795
910
|
|
|
796
911
|
// src/fields/InputField.tsx
|
|
797
|
-
import
|
|
798
|
-
import { Controller as
|
|
912
|
+
import React12 from "react";
|
|
913
|
+
import { Controller as Controller7 } from "react-hook-form";
|
|
799
914
|
function CoercedInput(props) {
|
|
800
915
|
const { description, disabled, errorMessage, field: field2, inputProps, label } = props;
|
|
801
916
|
const defaults = useHeroHookFormDefaults();
|
|
802
|
-
return /* @__PURE__ */
|
|
917
|
+
return /* @__PURE__ */ React12.createElement(
|
|
803
918
|
Input,
|
|
804
919
|
{
|
|
805
920
|
...defaults.input,
|
|
@@ -809,13 +924,14 @@ function CoercedInput(props) {
|
|
|
809
924
|
isDisabled: disabled,
|
|
810
925
|
isInvalid: Boolean(errorMessage),
|
|
811
926
|
label,
|
|
927
|
+
name: field2.name,
|
|
812
928
|
value: field2.value ?? "",
|
|
813
929
|
onBlur: field2.onBlur,
|
|
814
930
|
onValueChange: field2.onChange
|
|
815
931
|
}
|
|
816
932
|
);
|
|
817
933
|
}
|
|
818
|
-
var InputField =
|
|
934
|
+
var InputField = React12.memo(
|
|
819
935
|
(props) => {
|
|
820
936
|
const {
|
|
821
937
|
className,
|
|
@@ -828,12 +944,12 @@ var InputField = React11.memo(
|
|
|
828
944
|
rules,
|
|
829
945
|
transform
|
|
830
946
|
} = props;
|
|
831
|
-
return /* @__PURE__ */
|
|
832
|
-
|
|
947
|
+
return /* @__PURE__ */ React12.createElement(
|
|
948
|
+
Controller7,
|
|
833
949
|
{
|
|
834
950
|
control,
|
|
835
951
|
name,
|
|
836
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
952
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React12.createElement("div", { className }, /* @__PURE__ */ React12.createElement(
|
|
837
953
|
CoercedInput,
|
|
838
954
|
{
|
|
839
955
|
description,
|
|
@@ -863,8 +979,8 @@ var InputField = React11.memo(
|
|
|
863
979
|
);
|
|
864
980
|
|
|
865
981
|
// src/fields/RadioGroupField.tsx
|
|
866
|
-
import
|
|
867
|
-
import { Controller as
|
|
982
|
+
import React13 from "react";
|
|
983
|
+
import { Controller as Controller8 } from "react-hook-form";
|
|
868
984
|
function RadioGroupField(props) {
|
|
869
985
|
const {
|
|
870
986
|
className,
|
|
@@ -878,12 +994,12 @@ function RadioGroupField(props) {
|
|
|
878
994
|
rules
|
|
879
995
|
} = props;
|
|
880
996
|
const defaults = useHeroHookFormDefaults();
|
|
881
|
-
return /* @__PURE__ */
|
|
882
|
-
|
|
997
|
+
return /* @__PURE__ */ React13.createElement(
|
|
998
|
+
Controller8,
|
|
883
999
|
{
|
|
884
1000
|
control,
|
|
885
1001
|
name,
|
|
886
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
1002
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React13.createElement("div", { className }, /* @__PURE__ */ React13.createElement(
|
|
887
1003
|
RadioGroup,
|
|
888
1004
|
{
|
|
889
1005
|
...defaults.radioGroup,
|
|
@@ -892,11 +1008,12 @@ function RadioGroupField(props) {
|
|
|
892
1008
|
isDisabled,
|
|
893
1009
|
isInvalid: Boolean(fieldState.error),
|
|
894
1010
|
label,
|
|
1011
|
+
name,
|
|
895
1012
|
value: String(field2.value ?? ""),
|
|
896
1013
|
onBlur: field2.onBlur,
|
|
897
1014
|
onValueChange: (val) => field2.onChange(val)
|
|
898
1015
|
},
|
|
899
|
-
options.map((opt) => /* @__PURE__ */
|
|
1016
|
+
options.map((opt) => /* @__PURE__ */ React13.createElement(
|
|
900
1017
|
Radio,
|
|
901
1018
|
{
|
|
902
1019
|
key: String(opt.value),
|
|
@@ -905,15 +1022,15 @@ function RadioGroupField(props) {
|
|
|
905
1022
|
},
|
|
906
1023
|
opt.label
|
|
907
1024
|
))
|
|
908
|
-
), fieldState.error?.message ? /* @__PURE__ */
|
|
1025
|
+
), fieldState.error?.message ? /* @__PURE__ */ React13.createElement("p", { className: "text-tiny text-danger mt-1" }, fieldState.error.message) : null),
|
|
909
1026
|
rules
|
|
910
1027
|
}
|
|
911
1028
|
);
|
|
912
1029
|
}
|
|
913
1030
|
|
|
914
1031
|
// src/fields/SelectField.tsx
|
|
915
|
-
import
|
|
916
|
-
import { Controller as
|
|
1032
|
+
import React14 from "react";
|
|
1033
|
+
import { Controller as Controller9 } from "react-hook-form";
|
|
917
1034
|
function SelectField(props) {
|
|
918
1035
|
const {
|
|
919
1036
|
className,
|
|
@@ -928,14 +1045,14 @@ function SelectField(props) {
|
|
|
928
1045
|
selectProps
|
|
929
1046
|
} = props;
|
|
930
1047
|
const defaults = useHeroHookFormDefaults();
|
|
931
|
-
return /* @__PURE__ */
|
|
932
|
-
|
|
1048
|
+
return /* @__PURE__ */ React14.createElement(
|
|
1049
|
+
Controller9,
|
|
933
1050
|
{
|
|
934
1051
|
control,
|
|
935
1052
|
name,
|
|
936
1053
|
render: ({ field: field2, fieldState }) => {
|
|
937
1054
|
const selectedKey = field2.value;
|
|
938
|
-
return /* @__PURE__ */
|
|
1055
|
+
return /* @__PURE__ */ React14.createElement("div", { className }, /* @__PURE__ */ React14.createElement(
|
|
939
1056
|
Select,
|
|
940
1057
|
{
|
|
941
1058
|
...defaults.select,
|
|
@@ -945,6 +1062,7 @@ function SelectField(props) {
|
|
|
945
1062
|
isDisabled,
|
|
946
1063
|
isInvalid: Boolean(fieldState.error),
|
|
947
1064
|
label,
|
|
1065
|
+
name,
|
|
948
1066
|
placeholder,
|
|
949
1067
|
selectedKeys: selectedKey != null ? /* @__PURE__ */ new Set([String(selectedKey)]) : /* @__PURE__ */ new Set(),
|
|
950
1068
|
onSelectionChange: (keys) => {
|
|
@@ -953,7 +1071,7 @@ function SelectField(props) {
|
|
|
953
1071
|
field2.onChange(next);
|
|
954
1072
|
}
|
|
955
1073
|
},
|
|
956
|
-
options.map((opt) => /* @__PURE__ */
|
|
1074
|
+
options.map((opt) => /* @__PURE__ */ React14.createElement(
|
|
957
1075
|
SelectItem,
|
|
958
1076
|
{
|
|
959
1077
|
key: String(opt.value),
|
|
@@ -970,12 +1088,12 @@ function SelectField(props) {
|
|
|
970
1088
|
}
|
|
971
1089
|
|
|
972
1090
|
// src/fields/SliderField.tsx
|
|
973
|
-
import
|
|
974
|
-
import { Controller as
|
|
1091
|
+
import React15 from "react";
|
|
1092
|
+
import { Controller as Controller10 } from "react-hook-form";
|
|
975
1093
|
function CoercedSlider(props) {
|
|
976
1094
|
const { description, disabled, errorMessage, field: field2, label, sliderProps } = props;
|
|
977
1095
|
const defaults = useHeroHookFormDefaults();
|
|
978
|
-
return /* @__PURE__ */
|
|
1096
|
+
return /* @__PURE__ */ React15.createElement(
|
|
979
1097
|
Slider,
|
|
980
1098
|
{
|
|
981
1099
|
...defaults.slider,
|
|
@@ -985,6 +1103,7 @@ function CoercedSlider(props) {
|
|
|
985
1103
|
isDisabled: disabled,
|
|
986
1104
|
isInvalid: Boolean(errorMessage),
|
|
987
1105
|
label,
|
|
1106
|
+
name: field2.name,
|
|
988
1107
|
value: field2.value ?? 0,
|
|
989
1108
|
onBlur: field2.onBlur,
|
|
990
1109
|
onValueChange: field2.onChange
|
|
@@ -1003,12 +1122,12 @@ function SliderField(props) {
|
|
|
1003
1122
|
sliderProps,
|
|
1004
1123
|
transform
|
|
1005
1124
|
} = props;
|
|
1006
|
-
return /* @__PURE__ */
|
|
1007
|
-
|
|
1125
|
+
return /* @__PURE__ */ React15.createElement(
|
|
1126
|
+
Controller10,
|
|
1008
1127
|
{
|
|
1009
1128
|
control,
|
|
1010
1129
|
name,
|
|
1011
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
1130
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React15.createElement("div", { className }, /* @__PURE__ */ React15.createElement(
|
|
1012
1131
|
CoercedSlider,
|
|
1013
1132
|
{
|
|
1014
1133
|
description,
|
|
@@ -1027,9 +1146,123 @@ function SliderField(props) {
|
|
|
1027
1146
|
);
|
|
1028
1147
|
}
|
|
1029
1148
|
|
|
1149
|
+
// src/fields/StringArrayField.tsx
|
|
1150
|
+
import React16, { useState as useState2 } from "react";
|
|
1151
|
+
import { Controller as Controller11 } from "react-hook-form";
|
|
1152
|
+
function StringArrayInput(props) {
|
|
1153
|
+
const {
|
|
1154
|
+
description,
|
|
1155
|
+
disabled,
|
|
1156
|
+
errorMessage,
|
|
1157
|
+
field: field2,
|
|
1158
|
+
label,
|
|
1159
|
+
stringArrayProps
|
|
1160
|
+
} = props;
|
|
1161
|
+
const [inputValue, setInputValue] = useState2("");
|
|
1162
|
+
const items = field2.value || [];
|
|
1163
|
+
const {
|
|
1164
|
+
addButtonText = "Add",
|
|
1165
|
+
allowDuplicates = false,
|
|
1166
|
+
maxItems,
|
|
1167
|
+
minItems,
|
|
1168
|
+
placeholder = "Add item...",
|
|
1169
|
+
showAddButton = true,
|
|
1170
|
+
transformItem = (item) => item.trim(),
|
|
1171
|
+
validateItem = () => true
|
|
1172
|
+
} = stringArrayProps || {};
|
|
1173
|
+
const canAddMore = !maxItems || items.length < maxItems;
|
|
1174
|
+
const handleAddItem = () => {
|
|
1175
|
+
const trimmedValue = inputValue.trim();
|
|
1176
|
+
if (!trimmedValue) return;
|
|
1177
|
+
const transformedValue = transformItem(trimmedValue);
|
|
1178
|
+
const validation = validateItem(transformedValue);
|
|
1179
|
+
if (validation !== true) return;
|
|
1180
|
+
if (!allowDuplicates && items.includes(transformedValue)) return;
|
|
1181
|
+
const newItems = [...items, transformedValue];
|
|
1182
|
+
field2.onChange(newItems);
|
|
1183
|
+
setInputValue("");
|
|
1184
|
+
};
|
|
1185
|
+
const handleRemoveItem = (indexToRemove) => {
|
|
1186
|
+
const newItems = items.filter((_, index) => index !== indexToRemove);
|
|
1187
|
+
field2.onChange(newItems);
|
|
1188
|
+
};
|
|
1189
|
+
const handleKeyPress = (e) => {
|
|
1190
|
+
if (e.key === "Enter") {
|
|
1191
|
+
e.preventDefault();
|
|
1192
|
+
if (!showAddButton) {
|
|
1193
|
+
handleAddItem();
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
};
|
|
1197
|
+
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(
|
|
1198
|
+
Input,
|
|
1199
|
+
{
|
|
1200
|
+
className: "flex-1",
|
|
1201
|
+
disabled,
|
|
1202
|
+
placeholder,
|
|
1203
|
+
value: inputValue,
|
|
1204
|
+
onChange: (e) => setInputValue(e.target.value),
|
|
1205
|
+
onKeyPress: handleKeyPress,
|
|
1206
|
+
isInvalid: !!errorMessage,
|
|
1207
|
+
errorMessage
|
|
1208
|
+
}
|
|
1209
|
+
), showAddButton && /* @__PURE__ */ React16.createElement(
|
|
1210
|
+
Button,
|
|
1211
|
+
{
|
|
1212
|
+
type: "button",
|
|
1213
|
+
variant: "flat",
|
|
1214
|
+
onClick: handleAddItem,
|
|
1215
|
+
disabled: disabled || !inputValue.trim(),
|
|
1216
|
+
size: "sm"
|
|
1217
|
+
},
|
|
1218
|
+
addButtonText
|
|
1219
|
+
)), items.length > 0 && /* @__PURE__ */ React16.createElement("div", { className: "space-y-1" }, items.map((item, index) => /* @__PURE__ */ React16.createElement(
|
|
1220
|
+
"div",
|
|
1221
|
+
{
|
|
1222
|
+
key: index,
|
|
1223
|
+
className: "flex items-center gap-2 p-2 bg-content2 rounded-md"
|
|
1224
|
+
},
|
|
1225
|
+
/* @__PURE__ */ React16.createElement("span", { className: "flex-1 text-sm" }, item),
|
|
1226
|
+
/* @__PURE__ */ React16.createElement(
|
|
1227
|
+
Button,
|
|
1228
|
+
{
|
|
1229
|
+
type: "button",
|
|
1230
|
+
variant: "light",
|
|
1231
|
+
size: "sm",
|
|
1232
|
+
onClick: () => handleRemoveItem(index),
|
|
1233
|
+
disabled,
|
|
1234
|
+
className: "min-w-[60px]"
|
|
1235
|
+
},
|
|
1236
|
+
"Remove"
|
|
1237
|
+
)
|
|
1238
|
+
))), 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"));
|
|
1239
|
+
}
|
|
1240
|
+
function StringArrayField(props) {
|
|
1241
|
+
const { control, label, name, rules, ...fieldProps } = props;
|
|
1242
|
+
return /* @__PURE__ */ React16.createElement(
|
|
1243
|
+
Controller11,
|
|
1244
|
+
{
|
|
1245
|
+
control,
|
|
1246
|
+
name,
|
|
1247
|
+
rules,
|
|
1248
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React16.createElement(
|
|
1249
|
+
StringArrayInput,
|
|
1250
|
+
{
|
|
1251
|
+
field: field2,
|
|
1252
|
+
label,
|
|
1253
|
+
description: fieldProps.description,
|
|
1254
|
+
disabled: fieldProps.isDisabled,
|
|
1255
|
+
errorMessage: fieldState.error?.message,
|
|
1256
|
+
stringArrayProps: fieldProps.stringArrayProps
|
|
1257
|
+
}
|
|
1258
|
+
)
|
|
1259
|
+
}
|
|
1260
|
+
);
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1030
1263
|
// src/fields/SwitchField.tsx
|
|
1031
|
-
import
|
|
1032
|
-
import { Controller as
|
|
1264
|
+
import React17 from "react";
|
|
1265
|
+
import { Controller as Controller12 } from "react-hook-form";
|
|
1033
1266
|
function SwitchField(props) {
|
|
1034
1267
|
const {
|
|
1035
1268
|
className,
|
|
@@ -1042,31 +1275,32 @@ function SwitchField(props) {
|
|
|
1042
1275
|
switchProps
|
|
1043
1276
|
} = props;
|
|
1044
1277
|
const defaults = useHeroHookFormDefaults();
|
|
1045
|
-
return /* @__PURE__ */
|
|
1046
|
-
|
|
1278
|
+
return /* @__PURE__ */ React17.createElement(
|
|
1279
|
+
Controller12,
|
|
1047
1280
|
{
|
|
1048
1281
|
control,
|
|
1049
1282
|
name,
|
|
1050
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
1283
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React17.createElement("div", { className }, /* @__PURE__ */ React17.createElement(
|
|
1051
1284
|
Switch,
|
|
1052
1285
|
{
|
|
1053
1286
|
...defaults.switch,
|
|
1054
1287
|
...switchProps,
|
|
1055
1288
|
isDisabled,
|
|
1056
1289
|
isSelected: Boolean(field2.value),
|
|
1290
|
+
name,
|
|
1057
1291
|
onBlur: field2.onBlur,
|
|
1058
1292
|
onValueChange: (val) => field2.onChange(val)
|
|
1059
1293
|
},
|
|
1060
1294
|
label
|
|
1061
|
-
), description ? /* @__PURE__ */
|
|
1295
|
+
), 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),
|
|
1062
1296
|
rules
|
|
1063
1297
|
}
|
|
1064
1298
|
);
|
|
1065
1299
|
}
|
|
1066
1300
|
|
|
1067
1301
|
// src/fields/TextareaField.tsx
|
|
1068
|
-
import
|
|
1069
|
-
import { Controller as
|
|
1302
|
+
import React18 from "react";
|
|
1303
|
+
import { Controller as Controller13 } from "react-hook-form";
|
|
1070
1304
|
function TextareaField(props) {
|
|
1071
1305
|
const {
|
|
1072
1306
|
className,
|
|
@@ -1079,12 +1313,12 @@ function TextareaField(props) {
|
|
|
1079
1313
|
textareaProps
|
|
1080
1314
|
} = props;
|
|
1081
1315
|
const defaults = useHeroHookFormDefaults();
|
|
1082
|
-
return /* @__PURE__ */
|
|
1083
|
-
|
|
1316
|
+
return /* @__PURE__ */ React18.createElement(
|
|
1317
|
+
Controller13,
|
|
1084
1318
|
{
|
|
1085
1319
|
control,
|
|
1086
1320
|
name,
|
|
1087
|
-
render: ({ field: field2, fieldState }) => /* @__PURE__ */
|
|
1321
|
+
render: ({ field: field2, fieldState }) => /* @__PURE__ */ React18.createElement("div", { className }, /* @__PURE__ */ React18.createElement(
|
|
1088
1322
|
Textarea,
|
|
1089
1323
|
{
|
|
1090
1324
|
...defaults.textarea,
|
|
@@ -1094,6 +1328,7 @@ function TextareaField(props) {
|
|
|
1094
1328
|
isDisabled,
|
|
1095
1329
|
isInvalid: Boolean(fieldState.error),
|
|
1096
1330
|
label,
|
|
1331
|
+
name: field2.name,
|
|
1097
1332
|
value: field2.value ?? "",
|
|
1098
1333
|
onBlur: field2.onBlur,
|
|
1099
1334
|
onValueChange: field2.onChange
|
|
@@ -1105,213 +1340,320 @@ function TextareaField(props) {
|
|
|
1105
1340
|
}
|
|
1106
1341
|
|
|
1107
1342
|
// src/components/FormField.tsx
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1343
|
+
function FormFieldComponent({
|
|
1344
|
+
config,
|
|
1345
|
+
form,
|
|
1346
|
+
submissionState
|
|
1347
|
+
}) {
|
|
1348
|
+
if (!form || !form.control) {
|
|
1349
|
+
return null;
|
|
1350
|
+
}
|
|
1351
|
+
const { control } = form;
|
|
1352
|
+
const watchedValues = useWatch3({ control });
|
|
1353
|
+
const fieldConfig = config;
|
|
1354
|
+
if ("type" in fieldConfig && fieldConfig.type === "content") {
|
|
1355
|
+
if ("render" in fieldConfig || "content" in fieldConfig) {
|
|
1356
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1121
1357
|
ContentField,
|
|
1122
1358
|
{
|
|
1123
|
-
config,
|
|
1359
|
+
config: fieldConfig,
|
|
1124
1360
|
form,
|
|
1125
1361
|
submissionState
|
|
1126
1362
|
}
|
|
1127
1363
|
);
|
|
1128
1364
|
}
|
|
1129
|
-
|
|
1365
|
+
}
|
|
1366
|
+
if ("condition" in fieldConfig && fieldConfig.condition && !fieldConfig.condition(watchedValues)) {
|
|
1367
|
+
return null;
|
|
1368
|
+
}
|
|
1369
|
+
if ("dependsOn" in fieldConfig && fieldConfig.dependsOn) {
|
|
1370
|
+
const dependentValue = get(watchedValues, fieldConfig.dependsOn);
|
|
1371
|
+
if ("dependsOnValue" in fieldConfig && fieldConfig.dependsOnValue !== void 0 && dependentValue !== fieldConfig.dependsOnValue) {
|
|
1130
1372
|
return null;
|
|
1131
1373
|
}
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1374
|
+
}
|
|
1375
|
+
const baseProps = {
|
|
1376
|
+
ariaDescribedBy: "ariaDescribedBy" in fieldConfig ? fieldConfig.ariaDescribedBy : void 0,
|
|
1377
|
+
ariaLabel: "ariaLabel" in fieldConfig ? fieldConfig.ariaLabel : void 0,
|
|
1378
|
+
className: "className" in fieldConfig ? fieldConfig.className : void 0,
|
|
1379
|
+
description: "description" in fieldConfig ? fieldConfig.description : void 0,
|
|
1380
|
+
isDisabled: ("isDisabled" in fieldConfig ? fieldConfig.isDisabled : void 0) ?? submissionState.isSubmitting,
|
|
1381
|
+
label: "label" in fieldConfig ? fieldConfig.label : void 0,
|
|
1382
|
+
// name is Path<TFieldValues> | string, but FieldBaseProps expects Path<TFieldValues>
|
|
1383
|
+
// We pass it directly to each component instead of through baseProps
|
|
1384
|
+
rules: "rules" in fieldConfig ? fieldConfig.rules : void 0
|
|
1385
|
+
};
|
|
1386
|
+
switch (fieldConfig.type) {
|
|
1387
|
+
case "input": {
|
|
1388
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1389
|
+
InputField,
|
|
1390
|
+
{
|
|
1391
|
+
...baseProps,
|
|
1392
|
+
name: fieldConfig.name,
|
|
1393
|
+
control,
|
|
1394
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1395
|
+
inputProps: "inputProps" in fieldConfig ? fieldConfig.inputProps : void 0
|
|
1396
|
+
}
|
|
1397
|
+
);
|
|
1398
|
+
}
|
|
1399
|
+
case "textarea": {
|
|
1400
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1401
|
+
TextareaField,
|
|
1402
|
+
{
|
|
1403
|
+
...baseProps,
|
|
1404
|
+
name: fieldConfig.name,
|
|
1405
|
+
control,
|
|
1406
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1407
|
+
textareaProps: "textareaProps" in fieldConfig ? fieldConfig.textareaProps : void 0
|
|
1408
|
+
}
|
|
1409
|
+
);
|
|
1410
|
+
}
|
|
1411
|
+
case "select": {
|
|
1412
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1413
|
+
SelectField,
|
|
1414
|
+
{
|
|
1415
|
+
...baseProps,
|
|
1416
|
+
name: fieldConfig.name,
|
|
1417
|
+
control,
|
|
1418
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1419
|
+
options: "options" in fieldConfig && fieldConfig.options ? fieldConfig.options.map((opt) => ({
|
|
1420
|
+
label: opt.label,
|
|
1421
|
+
value: String(opt.value)
|
|
1422
|
+
})) : [],
|
|
1423
|
+
selectProps: "selectProps" in fieldConfig ? fieldConfig.selectProps : void 0
|
|
1424
|
+
}
|
|
1425
|
+
);
|
|
1426
|
+
}
|
|
1427
|
+
case "autocomplete": {
|
|
1428
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1429
|
+
AutocompleteField,
|
|
1430
|
+
{
|
|
1431
|
+
...baseProps,
|
|
1432
|
+
name: fieldConfig.name,
|
|
1433
|
+
control,
|
|
1434
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1435
|
+
items: ("options" in fieldConfig && fieldConfig.options ? fieldConfig.options : []).map((opt) => ({
|
|
1436
|
+
label: opt.label,
|
|
1437
|
+
value: String(opt.value)
|
|
1438
|
+
})),
|
|
1439
|
+
autocompleteProps: "autocompleteProps" in fieldConfig ? fieldConfig.autocompleteProps : void 0
|
|
1440
|
+
}
|
|
1441
|
+
);
|
|
1442
|
+
}
|
|
1443
|
+
case "checkbox": {
|
|
1444
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1445
|
+
CheckboxField,
|
|
1446
|
+
{
|
|
1447
|
+
...baseProps,
|
|
1448
|
+
name: fieldConfig.name,
|
|
1449
|
+
checkboxProps: "checkboxProps" in fieldConfig ? fieldConfig.checkboxProps : void 0,
|
|
1450
|
+
control,
|
|
1451
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0
|
|
1452
|
+
}
|
|
1453
|
+
);
|
|
1454
|
+
}
|
|
1455
|
+
case "checkboxGroup": {
|
|
1456
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1457
|
+
CheckboxGroupField,
|
|
1458
|
+
{
|
|
1459
|
+
...baseProps,
|
|
1460
|
+
name: fieldConfig.name,
|
|
1461
|
+
checkboxProps: "checkboxProps" in fieldConfig ? fieldConfig.checkboxProps : void 0,
|
|
1462
|
+
control,
|
|
1463
|
+
defaultValue: "defaultValue" in fieldConfig && fieldConfig.defaultValue && Array.isArray(fieldConfig.defaultValue) ? fieldConfig.defaultValue.map((v) => String(v)) : void 0,
|
|
1464
|
+
options: ("checkboxGroupOptions" in fieldConfig && fieldConfig.checkboxGroupOptions ? fieldConfig.checkboxGroupOptions : []).map((opt) => ({
|
|
1465
|
+
label: opt.label,
|
|
1466
|
+
value: String(opt.value)
|
|
1467
|
+
})),
|
|
1468
|
+
orientation: "orientation" in fieldConfig ? fieldConfig.orientation : void 0
|
|
1469
|
+
}
|
|
1470
|
+
);
|
|
1471
|
+
}
|
|
1472
|
+
case "radio": {
|
|
1473
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1474
|
+
RadioGroupField,
|
|
1475
|
+
{
|
|
1476
|
+
...baseProps,
|
|
1477
|
+
name: fieldConfig.name,
|
|
1478
|
+
control,
|
|
1479
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1480
|
+
options: ("radioOptions" in fieldConfig && fieldConfig.radioOptions ? fieldConfig.radioOptions : []).map((opt) => ({
|
|
1481
|
+
label: opt.label,
|
|
1482
|
+
value: String(opt.value)
|
|
1483
|
+
})),
|
|
1484
|
+
radioGroupProps: "radioProps" in fieldConfig ? fieldConfig.radioProps : void 0
|
|
1485
|
+
}
|
|
1486
|
+
);
|
|
1487
|
+
}
|
|
1488
|
+
case "switch": {
|
|
1489
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1490
|
+
SwitchField,
|
|
1491
|
+
{
|
|
1492
|
+
...baseProps,
|
|
1493
|
+
name: fieldConfig.name,
|
|
1494
|
+
control,
|
|
1495
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1496
|
+
switchProps: "switchProps" in fieldConfig ? fieldConfig.switchProps : void 0
|
|
1497
|
+
}
|
|
1498
|
+
);
|
|
1499
|
+
}
|
|
1500
|
+
case "slider": {
|
|
1501
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1502
|
+
SliderField,
|
|
1503
|
+
{
|
|
1504
|
+
...baseProps,
|
|
1505
|
+
name: fieldConfig.name,
|
|
1506
|
+
control,
|
|
1507
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1508
|
+
sliderProps: "sliderProps" in fieldConfig ? fieldConfig.sliderProps : void 0
|
|
1509
|
+
}
|
|
1510
|
+
);
|
|
1511
|
+
}
|
|
1512
|
+
case "stringArray": {
|
|
1513
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1514
|
+
StringArrayField,
|
|
1515
|
+
{
|
|
1516
|
+
...baseProps,
|
|
1517
|
+
name: fieldConfig.name,
|
|
1518
|
+
control,
|
|
1519
|
+
stringArrayProps: "stringArrayProps" in fieldConfig ? fieldConfig.stringArrayProps : void 0,
|
|
1520
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0
|
|
1521
|
+
}
|
|
1522
|
+
);
|
|
1523
|
+
}
|
|
1524
|
+
case "date": {
|
|
1525
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1526
|
+
DateField,
|
|
1527
|
+
{
|
|
1528
|
+
...baseProps,
|
|
1529
|
+
name: fieldConfig.name,
|
|
1530
|
+
control,
|
|
1531
|
+
dateProps: "dateProps" in fieldConfig ? fieldConfig.dateProps : void 0,
|
|
1532
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0
|
|
1533
|
+
}
|
|
1534
|
+
);
|
|
1535
|
+
}
|
|
1536
|
+
case "file": {
|
|
1537
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1538
|
+
FileField,
|
|
1539
|
+
{
|
|
1540
|
+
...baseProps,
|
|
1541
|
+
name: fieldConfig.name,
|
|
1542
|
+
accept: "accept" in fieldConfig ? fieldConfig.accept : void 0,
|
|
1543
|
+
control,
|
|
1544
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1545
|
+
fileProps: "fileProps" in fieldConfig ? fieldConfig.fileProps : void 0,
|
|
1546
|
+
multiple: "multiple" in fieldConfig ? fieldConfig.multiple : void 0
|
|
1547
|
+
}
|
|
1548
|
+
);
|
|
1549
|
+
}
|
|
1550
|
+
case "fontPicker": {
|
|
1551
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1552
|
+
FontPickerField,
|
|
1553
|
+
{
|
|
1554
|
+
...baseProps,
|
|
1555
|
+
name: fieldConfig.name,
|
|
1556
|
+
control,
|
|
1557
|
+
defaultValue: "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0,
|
|
1558
|
+
fontPickerProps: "fontPickerProps" in fieldConfig ? fieldConfig.fontPickerProps : void 0
|
|
1559
|
+
}
|
|
1560
|
+
);
|
|
1561
|
+
}
|
|
1562
|
+
case "custom": {
|
|
1563
|
+
if (!("render" in fieldConfig)) {
|
|
1135
1564
|
return null;
|
|
1136
1565
|
}
|
|
1566
|
+
return fieldConfig.render({
|
|
1567
|
+
control,
|
|
1568
|
+
errors: form.formState.errors,
|
|
1569
|
+
form,
|
|
1570
|
+
isSubmitting: submissionState.isSubmitting,
|
|
1571
|
+
name: fieldConfig.name
|
|
1572
|
+
});
|
|
1137
1573
|
}
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
defaultValue: config.defaultValue,
|
|
1156
|
-
inputProps: config.inputProps
|
|
1157
|
-
}
|
|
1158
|
-
);
|
|
1159
|
-
case "textarea":
|
|
1160
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1161
|
-
TextareaField,
|
|
1162
|
-
{
|
|
1163
|
-
...baseProps,
|
|
1164
|
-
control,
|
|
1165
|
-
defaultValue: config.defaultValue,
|
|
1166
|
-
textareaProps: config.textareaProps
|
|
1167
|
-
}
|
|
1168
|
-
);
|
|
1169
|
-
case "select":
|
|
1170
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1171
|
-
SelectField,
|
|
1172
|
-
{
|
|
1173
|
-
...baseProps,
|
|
1174
|
-
control,
|
|
1175
|
-
defaultValue: config.defaultValue,
|
|
1176
|
-
options: (config.options ?? []).map((opt) => ({
|
|
1177
|
-
label: opt.label,
|
|
1178
|
-
value: String(opt.value)
|
|
1179
|
-
})),
|
|
1180
|
-
selectProps: config.selectProps
|
|
1181
|
-
}
|
|
1182
|
-
);
|
|
1183
|
-
case "autocomplete":
|
|
1184
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1185
|
-
AutocompleteField,
|
|
1186
|
-
{
|
|
1187
|
-
...baseProps,
|
|
1188
|
-
control,
|
|
1189
|
-
defaultValue: config.defaultValue,
|
|
1190
|
-
items: (config.options ?? []).map((opt) => ({
|
|
1191
|
-
label: opt.label,
|
|
1192
|
-
value: String(opt.value)
|
|
1193
|
-
})),
|
|
1194
|
-
autocompleteProps: config.autocompleteProps
|
|
1195
|
-
}
|
|
1196
|
-
);
|
|
1197
|
-
case "checkbox":
|
|
1198
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1199
|
-
CheckboxField,
|
|
1200
|
-
{
|
|
1201
|
-
...baseProps,
|
|
1202
|
-
checkboxProps: config.checkboxProps,
|
|
1203
|
-
control,
|
|
1204
|
-
defaultValue: config.defaultValue
|
|
1205
|
-
}
|
|
1206
|
-
);
|
|
1207
|
-
case "radio":
|
|
1208
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1209
|
-
RadioGroupField,
|
|
1210
|
-
{
|
|
1211
|
-
...baseProps,
|
|
1212
|
-
control,
|
|
1213
|
-
defaultValue: config.defaultValue,
|
|
1214
|
-
options: (config.radioOptions ?? []).map((opt) => ({
|
|
1215
|
-
label: opt.label,
|
|
1216
|
-
value: String(opt.value)
|
|
1217
|
-
})),
|
|
1218
|
-
radioGroupProps: config.radioProps
|
|
1219
|
-
}
|
|
1220
|
-
);
|
|
1221
|
-
case "switch":
|
|
1222
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1223
|
-
SwitchField,
|
|
1224
|
-
{
|
|
1225
|
-
...baseProps,
|
|
1226
|
-
control,
|
|
1227
|
-
defaultValue: config.defaultValue,
|
|
1228
|
-
switchProps: config.switchProps
|
|
1229
|
-
}
|
|
1230
|
-
);
|
|
1231
|
-
case "slider":
|
|
1232
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1233
|
-
SliderField,
|
|
1234
|
-
{
|
|
1235
|
-
...baseProps,
|
|
1236
|
-
control,
|
|
1237
|
-
defaultValue: config.defaultValue,
|
|
1238
|
-
sliderProps: config.sliderProps
|
|
1239
|
-
}
|
|
1240
|
-
);
|
|
1241
|
-
case "date":
|
|
1242
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1243
|
-
DateField,
|
|
1244
|
-
{
|
|
1245
|
-
...baseProps,
|
|
1246
|
-
control,
|
|
1247
|
-
dateProps: config.dateProps,
|
|
1248
|
-
defaultValue: config.defaultValue
|
|
1249
|
-
}
|
|
1250
|
-
);
|
|
1251
|
-
case "file":
|
|
1252
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1253
|
-
FileField,
|
|
1254
|
-
{
|
|
1255
|
-
...baseProps,
|
|
1256
|
-
accept: config.accept,
|
|
1257
|
-
control,
|
|
1258
|
-
defaultValue: config.defaultValue,
|
|
1259
|
-
fileProps: config.fileProps,
|
|
1260
|
-
multiple: config.multiple
|
|
1261
|
-
}
|
|
1262
|
-
);
|
|
1263
|
-
case "fontPicker":
|
|
1264
|
-
return /* @__PURE__ */ React17.createElement(
|
|
1265
|
-
FontPickerField,
|
|
1266
|
-
{
|
|
1267
|
-
...baseProps,
|
|
1268
|
-
control,
|
|
1269
|
-
defaultValue: config.defaultValue,
|
|
1270
|
-
fontPickerProps: config.fontPickerProps
|
|
1271
|
-
}
|
|
1272
|
-
);
|
|
1273
|
-
case "custom":
|
|
1274
|
-
return config.render({
|
|
1574
|
+
case "conditional": {
|
|
1575
|
+
if (!("condition" in fieldConfig) || !("field" in fieldConfig)) {
|
|
1576
|
+
return null;
|
|
1577
|
+
}
|
|
1578
|
+
const conditionalConfig = {
|
|
1579
|
+
className: "className" in fieldConfig ? fieldConfig.className : void 0,
|
|
1580
|
+
condition: fieldConfig.condition,
|
|
1581
|
+
description: "description" in fieldConfig ? fieldConfig.description : void 0,
|
|
1582
|
+
field: fieldConfig.field,
|
|
1583
|
+
label: "label" in fieldConfig ? fieldConfig.label : void 0,
|
|
1584
|
+
name: fieldConfig.name,
|
|
1585
|
+
type: "conditional"
|
|
1586
|
+
};
|
|
1587
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1588
|
+
ConditionalField,
|
|
1589
|
+
{
|
|
1590
|
+
config: conditionalConfig,
|
|
1275
1591
|
control,
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
return
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1592
|
+
className: conditionalConfig.className
|
|
1593
|
+
}
|
|
1594
|
+
);
|
|
1595
|
+
}
|
|
1596
|
+
case "fieldArray": {
|
|
1597
|
+
if (!("fields" in fieldConfig) || !fieldConfig.fields) {
|
|
1598
|
+
return null;
|
|
1599
|
+
}
|
|
1600
|
+
const fieldArrayConfig = {
|
|
1601
|
+
addButtonText: "addButtonText" in fieldConfig ? fieldConfig.addButtonText : void 0,
|
|
1602
|
+
className: "className" in fieldConfig ? fieldConfig.className : void 0,
|
|
1603
|
+
defaultItem: "defaultItem" in fieldConfig ? fieldConfig.defaultItem : void 0,
|
|
1604
|
+
description: "description" in fieldConfig ? fieldConfig.description : void 0,
|
|
1605
|
+
enableReordering: "enableReordering" in fieldConfig ? fieldConfig.enableReordering : void 0,
|
|
1606
|
+
fields: fieldConfig.fields,
|
|
1607
|
+
label: "label" in fieldConfig ? fieldConfig.label : void 0,
|
|
1608
|
+
max: "max" in fieldConfig ? fieldConfig.max : void 0,
|
|
1609
|
+
min: "min" in fieldConfig ? fieldConfig.min : void 0,
|
|
1610
|
+
name: fieldConfig.name,
|
|
1611
|
+
removeButtonText: "removeButtonText" in fieldConfig ? fieldConfig.removeButtonText : void 0,
|
|
1612
|
+
renderAddButton: "renderAddButton" in fieldConfig ? fieldConfig.renderAddButton : void 0,
|
|
1613
|
+
renderItem: "renderItem" in fieldConfig ? fieldConfig.renderItem : void 0,
|
|
1614
|
+
reorderButtonText: "reorderButtonText" in fieldConfig ? fieldConfig.reorderButtonText : void 0,
|
|
1615
|
+
type: "fieldArray"
|
|
1616
|
+
};
|
|
1617
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1618
|
+
FieldArrayField,
|
|
1619
|
+
{
|
|
1620
|
+
config: fieldArrayConfig,
|
|
1621
|
+
className: fieldArrayConfig.className,
|
|
1622
|
+
alwaysRegistered: "alwaysRegistered" in fieldConfig ? fieldConfig.alwaysRegistered : false
|
|
1623
|
+
}
|
|
1624
|
+
);
|
|
1625
|
+
}
|
|
1626
|
+
case "dynamicSection": {
|
|
1627
|
+
if (!("sections" in fieldConfig) || !("condition" in fieldConfig) || !("fields" in fieldConfig)) {
|
|
1310
1628
|
return null;
|
|
1311
1629
|
}
|
|
1630
|
+
const dynamicSectionConfig = {
|
|
1631
|
+
className: "className" in fieldConfig ? fieldConfig.className : void 0,
|
|
1632
|
+
condition: fieldConfig.condition,
|
|
1633
|
+
description: "description" in fieldConfig ? fieldConfig.description : void 0,
|
|
1634
|
+
fields: fieldConfig.fields,
|
|
1635
|
+
label: "label" in fieldConfig ? fieldConfig.label : void 0,
|
|
1636
|
+
name: fieldConfig.name,
|
|
1637
|
+
title: "title" in fieldConfig ? fieldConfig.title : void 0,
|
|
1638
|
+
type: "dynamicSection"
|
|
1639
|
+
};
|
|
1640
|
+
return /* @__PURE__ */ React19.createElement(
|
|
1641
|
+
DynamicSectionField,
|
|
1642
|
+
{
|
|
1643
|
+
config: dynamicSectionConfig,
|
|
1644
|
+
control,
|
|
1645
|
+
className: dynamicSectionConfig.className
|
|
1646
|
+
}
|
|
1647
|
+
);
|
|
1648
|
+
}
|
|
1649
|
+
default: {
|
|
1650
|
+
const fieldType = "type" in config ? config.type : "unknown";
|
|
1651
|
+
console.warn(`Unknown field type: ${fieldType}`);
|
|
1652
|
+
return null;
|
|
1312
1653
|
}
|
|
1313
1654
|
}
|
|
1314
|
-
|
|
1655
|
+
}
|
|
1656
|
+
var FormField = FormFieldComponent;
|
|
1315
1657
|
|
|
1316
1658
|
// src/components/Form.tsx
|
|
1317
1659
|
function ConfigurableForm({
|
|
@@ -1348,12 +1690,12 @@ function ConfigurableForm({
|
|
|
1348
1690
|
});
|
|
1349
1691
|
const renderFields = () => {
|
|
1350
1692
|
if (layout === "grid") {
|
|
1351
|
-
return /* @__PURE__ */
|
|
1693
|
+
return /* @__PURE__ */ React20.createElement(
|
|
1352
1694
|
"div",
|
|
1353
1695
|
{
|
|
1354
1696
|
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"}`
|
|
1355
1697
|
},
|
|
1356
|
-
fields.map((field2) => /* @__PURE__ */
|
|
1698
|
+
fields.map((field2) => /* @__PURE__ */ React20.createElement(
|
|
1357
1699
|
FormField,
|
|
1358
1700
|
{
|
|
1359
1701
|
key: field2.name,
|
|
@@ -1365,7 +1707,7 @@ function ConfigurableForm({
|
|
|
1365
1707
|
);
|
|
1366
1708
|
}
|
|
1367
1709
|
if (layout === "horizontal") {
|
|
1368
|
-
return /* @__PURE__ */
|
|
1710
|
+
return /* @__PURE__ */ React20.createElement("div", { className: `grid gap-${spacing} grid-cols-1 md:grid-cols-2` }, fields.map((field2) => /* @__PURE__ */ React20.createElement(
|
|
1369
1711
|
FormField,
|
|
1370
1712
|
{
|
|
1371
1713
|
key: field2.name,
|
|
@@ -1375,10 +1717,10 @@ function ConfigurableForm({
|
|
|
1375
1717
|
}
|
|
1376
1718
|
)));
|
|
1377
1719
|
}
|
|
1378
|
-
return /* @__PURE__ */
|
|
1720
|
+
return /* @__PURE__ */ React20.createElement("div", { className: `space-y-${spacing}` }, fields.map((field2) => /* @__PURE__ */ React20.createElement(
|
|
1379
1721
|
FormField,
|
|
1380
1722
|
{
|
|
1381
|
-
key: field2.name
|
|
1723
|
+
key: field2.name ? pathToString(field2.name) : `field-${Math.random()}`,
|
|
1382
1724
|
config: field2,
|
|
1383
1725
|
form,
|
|
1384
1726
|
submissionState
|
|
@@ -1389,23 +1731,23 @@ function ConfigurableForm({
|
|
|
1389
1731
|
e.preventDefault();
|
|
1390
1732
|
void handleSubmit();
|
|
1391
1733
|
};
|
|
1392
|
-
return /* @__PURE__ */
|
|
1734
|
+
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(
|
|
1393
1735
|
"div",
|
|
1394
1736
|
{
|
|
1395
1737
|
className: "mb-6 p-4 bg-success-50 border border-success-200 rounded-lg",
|
|
1396
1738
|
"data-testid": "success-message"
|
|
1397
1739
|
},
|
|
1398
|
-
/* @__PURE__ */
|
|
1399
|
-
/* @__PURE__ */
|
|
1400
|
-
), error && /* @__PURE__ */
|
|
1740
|
+
/* @__PURE__ */ React20.createElement("p", { className: "text-success-800 font-medium" }, "Success!"),
|
|
1741
|
+
/* @__PURE__ */ React20.createElement("p", { className: "text-success-700 text-sm mt-1" }, "Your request has been processed successfully.")
|
|
1742
|
+
), error && /* @__PURE__ */ React20.createElement(
|
|
1401
1743
|
"div",
|
|
1402
1744
|
{
|
|
1403
1745
|
className: "mb-6 p-4 bg-danger-50 border border-danger-200 rounded-lg",
|
|
1404
1746
|
"data-testid": "error-message"
|
|
1405
1747
|
},
|
|
1406
|
-
/* @__PURE__ */
|
|
1407
|
-
/* @__PURE__ */
|
|
1408
|
-
), renderFields(), /* @__PURE__ */
|
|
1748
|
+
/* @__PURE__ */ React20.createElement("p", { className: "text-danger-800 font-medium" }, "Error"),
|
|
1749
|
+
/* @__PURE__ */ React20.createElement("p", { className: "text-danger-700 text-sm mt-1" }, error)
|
|
1750
|
+
), renderFields(), /* @__PURE__ */ React20.createElement("div", { className: "mt-6 flex gap-3 justify-end" }, /* @__PURE__ */ React20.createElement(
|
|
1409
1751
|
Button3,
|
|
1410
1752
|
{
|
|
1411
1753
|
color: "primary",
|
|
@@ -1415,7 +1757,7 @@ function ConfigurableForm({
|
|
|
1415
1757
|
...submitButtonProps
|
|
1416
1758
|
},
|
|
1417
1759
|
submitButtonText
|
|
1418
|
-
), showResetButton && /* @__PURE__ */
|
|
1760
|
+
), showResetButton && /* @__PURE__ */ React20.createElement(
|
|
1419
1761
|
Button3,
|
|
1420
1762
|
{
|
|
1421
1763
|
isDisabled: isSubmitting,
|
|
@@ -1428,7 +1770,7 @@ function ConfigurableForm({
|
|
|
1428
1770
|
}
|
|
1429
1771
|
|
|
1430
1772
|
// src/components/ServerActionForm.tsx
|
|
1431
|
-
import
|
|
1773
|
+
import React21 from "react";
|
|
1432
1774
|
import { useActionState } from "react";
|
|
1433
1775
|
function ServerActionForm({
|
|
1434
1776
|
action,
|
|
@@ -1453,10 +1795,10 @@ function ServerActionForm({
|
|
|
1453
1795
|
action,
|
|
1454
1796
|
initialState ?? { errors: void 0, message: void 0, success: false }
|
|
1455
1797
|
);
|
|
1456
|
-
const formRef =
|
|
1457
|
-
const [clientErrors, setClientErrors] =
|
|
1458
|
-
const lastSubmittedFormData =
|
|
1459
|
-
|
|
1798
|
+
const formRef = React21.useRef(null);
|
|
1799
|
+
const [clientErrors, setClientErrors] = React21.useState({});
|
|
1800
|
+
const lastSubmittedFormData = React21.useRef(null);
|
|
1801
|
+
React21.useEffect(() => {
|
|
1460
1802
|
if (state && (state.errors || state.message && !state.success)) {
|
|
1461
1803
|
onError?.({
|
|
1462
1804
|
errors: state.errors,
|
|
@@ -1464,7 +1806,7 @@ function ServerActionForm({
|
|
|
1464
1806
|
});
|
|
1465
1807
|
}
|
|
1466
1808
|
}, [state, onError]);
|
|
1467
|
-
|
|
1809
|
+
React21.useEffect(() => {
|
|
1468
1810
|
if (state?.success && lastSubmittedFormData.current) {
|
|
1469
1811
|
onSuccess?.(lastSubmittedFormData.current);
|
|
1470
1812
|
}
|
|
@@ -1477,14 +1819,14 @@ function ServerActionForm({
|
|
|
1477
1819
|
e.preventDefault();
|
|
1478
1820
|
if (clientValidationSchema) {
|
|
1479
1821
|
const formData2 = new FormData(e.currentTarget);
|
|
1822
|
+
const form = e.currentTarget;
|
|
1480
1823
|
const values = {};
|
|
1481
1824
|
formData2.forEach((val, key) => {
|
|
1482
|
-
|
|
1825
|
+
const formElement = form.querySelector(
|
|
1826
|
+
`input[type="checkbox"][name="${key}"], input[role="switch"][name="${key}"]`
|
|
1827
|
+
);
|
|
1828
|
+
if (formElement instanceof HTMLInputElement && (formElement.type === "checkbox" || formElement.getAttribute("role") === "switch")) {
|
|
1483
1829
|
values[key] = true;
|
|
1484
|
-
} else if (val === "") {
|
|
1485
|
-
if (!values[key]) {
|
|
1486
|
-
values[key] = false;
|
|
1487
|
-
}
|
|
1488
1830
|
} else {
|
|
1489
1831
|
values[key] = val;
|
|
1490
1832
|
}
|
|
@@ -1507,12 +1849,12 @@ function ServerActionForm({
|
|
|
1507
1849
|
};
|
|
1508
1850
|
const renderFields = () => {
|
|
1509
1851
|
if (layout === "grid") {
|
|
1510
|
-
return /* @__PURE__ */
|
|
1852
|
+
return /* @__PURE__ */ React21.createElement(
|
|
1511
1853
|
"div",
|
|
1512
1854
|
{
|
|
1513
1855
|
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"}`
|
|
1514
1856
|
},
|
|
1515
|
-
fields.map((field2) => /* @__PURE__ */
|
|
1857
|
+
fields.map((field2) => /* @__PURE__ */ React21.createElement(
|
|
1516
1858
|
ServerActionField,
|
|
1517
1859
|
{
|
|
1518
1860
|
key: field2.name,
|
|
@@ -1525,7 +1867,7 @@ function ServerActionForm({
|
|
|
1525
1867
|
);
|
|
1526
1868
|
}
|
|
1527
1869
|
if (layout === "horizontal") {
|
|
1528
|
-
return /* @__PURE__ */
|
|
1870
|
+
return /* @__PURE__ */ React21.createElement("div", { className: `grid gap-${spacing} grid-cols-1 md:grid-cols-2` }, fields.map((field2) => /* @__PURE__ */ React21.createElement(
|
|
1529
1871
|
ServerActionField,
|
|
1530
1872
|
{
|
|
1531
1873
|
key: field2.name,
|
|
@@ -1536,10 +1878,10 @@ function ServerActionForm({
|
|
|
1536
1878
|
}
|
|
1537
1879
|
)));
|
|
1538
1880
|
}
|
|
1539
|
-
return /* @__PURE__ */
|
|
1881
|
+
return /* @__PURE__ */ React21.createElement("div", { className: `space-y-${spacing}` }, fields.map((field2) => /* @__PURE__ */ React21.createElement(
|
|
1540
1882
|
ServerActionField,
|
|
1541
1883
|
{
|
|
1542
|
-
key: field2.name,
|
|
1884
|
+
key: pathToString(field2.name),
|
|
1543
1885
|
clientErrors,
|
|
1544
1886
|
defaultValues,
|
|
1545
1887
|
errors: state?.errors,
|
|
@@ -1547,7 +1889,7 @@ function ServerActionForm({
|
|
|
1547
1889
|
}
|
|
1548
1890
|
)));
|
|
1549
1891
|
};
|
|
1550
|
-
return /* @__PURE__ */
|
|
1892
|
+
return /* @__PURE__ */ React21.createElement(
|
|
1551
1893
|
"form",
|
|
1552
1894
|
{
|
|
1553
1895
|
ref: formRef,
|
|
@@ -1555,27 +1897,27 @@ function ServerActionForm({
|
|
|
1555
1897
|
role: "form",
|
|
1556
1898
|
onSubmit: handleSubmit
|
|
1557
1899
|
},
|
|
1558
|
-
title && /* @__PURE__ */
|
|
1559
|
-
state?.success && !pending && /* @__PURE__ */
|
|
1900
|
+
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)),
|
|
1901
|
+
state?.success && !pending && /* @__PURE__ */ React21.createElement(
|
|
1560
1902
|
"div",
|
|
1561
1903
|
{
|
|
1562
1904
|
className: "mb-6 p-4 bg-success-50 border border-success-200 rounded-lg",
|
|
1563
1905
|
"data-testid": "success-message"
|
|
1564
1906
|
},
|
|
1565
|
-
/* @__PURE__ */
|
|
1566
|
-
state.message && /* @__PURE__ */
|
|
1907
|
+
/* @__PURE__ */ React21.createElement("p", { className: "text-success-800 font-medium" }, "Success!"),
|
|
1908
|
+
state.message && /* @__PURE__ */ React21.createElement("p", { className: "text-success-700 text-sm mt-1" }, state.message)
|
|
1567
1909
|
),
|
|
1568
|
-
state?.message && !state.success && /* @__PURE__ */
|
|
1910
|
+
state?.message && !state.success && /* @__PURE__ */ React21.createElement(
|
|
1569
1911
|
"div",
|
|
1570
1912
|
{
|
|
1571
1913
|
className: "mb-6 p-4 bg-danger-50 border border-danger-200 rounded-lg",
|
|
1572
1914
|
"data-testid": "error-message"
|
|
1573
1915
|
},
|
|
1574
|
-
/* @__PURE__ */
|
|
1575
|
-
/* @__PURE__ */
|
|
1916
|
+
/* @__PURE__ */ React21.createElement("p", { className: "text-danger-800 font-medium" }, "Error"),
|
|
1917
|
+
/* @__PURE__ */ React21.createElement("p", { className: "text-danger-700 text-sm mt-1" }, state.message)
|
|
1576
1918
|
),
|
|
1577
1919
|
renderFields(),
|
|
1578
|
-
/* @__PURE__ */
|
|
1920
|
+
/* @__PURE__ */ React21.createElement("div", { className: "mt-6 flex gap-3 justify-end" }, /* @__PURE__ */ React21.createElement(
|
|
1579
1921
|
Button,
|
|
1580
1922
|
{
|
|
1581
1923
|
color: "primary",
|
|
@@ -1585,7 +1927,7 @@ function ServerActionForm({
|
|
|
1585
1927
|
...submitButtonProps
|
|
1586
1928
|
},
|
|
1587
1929
|
submitButtonText
|
|
1588
|
-
), showResetButton && /* @__PURE__ */
|
|
1930
|
+
), showResetButton && /* @__PURE__ */ React21.createElement(
|
|
1589
1931
|
Button,
|
|
1590
1932
|
{
|
|
1591
1933
|
isDisabled: pending,
|
|
@@ -1603,24 +1945,44 @@ function ServerActionField({
|
|
|
1603
1945
|
errors,
|
|
1604
1946
|
field: field2
|
|
1605
1947
|
}) {
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1948
|
+
const fieldConfig = field2;
|
|
1949
|
+
const getBaseProps = () => {
|
|
1950
|
+
const baseProps2 = {};
|
|
1951
|
+
if ("label" in fieldConfig) {
|
|
1952
|
+
baseProps2.label = fieldConfig.label;
|
|
1953
|
+
}
|
|
1954
|
+
if ("description" in fieldConfig) {
|
|
1955
|
+
baseProps2.description = fieldConfig.description;
|
|
1956
|
+
}
|
|
1957
|
+
if ("isDisabled" in fieldConfig) {
|
|
1958
|
+
baseProps2.isDisabled = fieldConfig.isDisabled;
|
|
1959
|
+
}
|
|
1960
|
+
return baseProps2;
|
|
1961
|
+
};
|
|
1962
|
+
const baseProps = getBaseProps();
|
|
1963
|
+
if (fieldConfig.type === "content") {
|
|
1964
|
+
const contentField = fieldConfig;
|
|
1965
|
+
if (contentField.render) {
|
|
1966
|
+
const mockForm = {
|
|
1967
|
+
formState: { errors: {} },
|
|
1968
|
+
watch: () => ({})
|
|
1969
|
+
};
|
|
1970
|
+
const renderFn = contentField.render;
|
|
1971
|
+
return /* @__PURE__ */ React21.createElement("div", { className: contentField.className }, renderFn({
|
|
1610
1972
|
errors: {},
|
|
1611
|
-
form:
|
|
1973
|
+
form: mockForm,
|
|
1612
1974
|
isSubmitting: false
|
|
1613
1975
|
}));
|
|
1614
1976
|
}
|
|
1615
|
-
return /* @__PURE__ */
|
|
1977
|
+
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));
|
|
1616
1978
|
}
|
|
1617
|
-
const fieldName =
|
|
1979
|
+
const fieldName = pathToString(fieldConfig.name);
|
|
1618
1980
|
const fieldErrors = errors?.[fieldName];
|
|
1619
1981
|
const clientError = clientErrors?.[fieldName];
|
|
1620
1982
|
const errorMessage = clientError || (fieldErrors && fieldErrors.length > 0 ? fieldErrors[0] : void 0);
|
|
1621
1983
|
const getDefaultValue = () => {
|
|
1622
1984
|
const fromProps = defaultValues?.[fieldName];
|
|
1623
|
-
const fromField =
|
|
1985
|
+
const fromField = "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0;
|
|
1624
1986
|
if (fromProps !== void 0 && fromProps !== null) {
|
|
1625
1987
|
return typeof fromProps === "string" ? fromProps : String(fromProps);
|
|
1626
1988
|
}
|
|
@@ -1631,7 +1993,7 @@ function ServerActionField({
|
|
|
1631
1993
|
};
|
|
1632
1994
|
const getDefaultChecked = () => {
|
|
1633
1995
|
const fromProps = defaultValues?.[fieldName];
|
|
1634
|
-
const fromField =
|
|
1996
|
+
const fromField = "defaultValue" in fieldConfig ? fieldConfig.defaultValue : void 0;
|
|
1635
1997
|
if (fromProps !== void 0 && fromProps !== null) {
|
|
1636
1998
|
return typeof fromProps === "boolean" ? fromProps : false;
|
|
1637
1999
|
}
|
|
@@ -1640,121 +2002,326 @@ function ServerActionField({
|
|
|
1640
2002
|
}
|
|
1641
2003
|
return false;
|
|
1642
2004
|
};
|
|
1643
|
-
const [value, setValue] =
|
|
1644
|
-
const [checked, setChecked] =
|
|
1645
|
-
|
|
2005
|
+
const [value, setValue] = React21.useState(getDefaultValue);
|
|
2006
|
+
const [checked, setChecked] = React21.useState(getDefaultChecked);
|
|
2007
|
+
React21.useEffect(() => {
|
|
1646
2008
|
const newDefaultValue = defaultValues?.[fieldName];
|
|
1647
2009
|
if (newDefaultValue !== void 0 && newDefaultValue !== null) {
|
|
1648
|
-
if (
|
|
2010
|
+
if (fieldConfig.type === "checkbox") {
|
|
1649
2011
|
setChecked(
|
|
1650
2012
|
typeof newDefaultValue === "boolean" ? newDefaultValue : false
|
|
1651
2013
|
);
|
|
2014
|
+
} else if (fieldConfig.type === "checkboxGroup") {
|
|
2015
|
+
const arrayValue = Array.isArray(newDefaultValue) ? newDefaultValue.map(String).join(",") : "";
|
|
2016
|
+
setValue(arrayValue);
|
|
1652
2017
|
} else {
|
|
1653
2018
|
setValue(
|
|
1654
2019
|
typeof newDefaultValue === "string" ? newDefaultValue : String(newDefaultValue)
|
|
1655
2020
|
);
|
|
1656
2021
|
}
|
|
1657
2022
|
}
|
|
1658
|
-
}, [defaultValues, fieldName,
|
|
1659
|
-
|
|
2023
|
+
}, [defaultValues, fieldName, fieldConfig.type]);
|
|
2024
|
+
React21.useEffect(() => {
|
|
2025
|
+
if (fieldConfig.type !== "date") {
|
|
2026
|
+
return;
|
|
2027
|
+
}
|
|
1660
2028
|
const hiddenInput = document.querySelector(
|
|
1661
2029
|
`input[type="hidden"][name="${fieldName}"]`
|
|
1662
2030
|
);
|
|
2031
|
+
if (!(hiddenInput instanceof HTMLInputElement)) {
|
|
2032
|
+
throw new Error(`Expected HTMLInputElement for field ${fieldName}`);
|
|
2033
|
+
}
|
|
1663
2034
|
if (hiddenInput) {
|
|
1664
|
-
|
|
1665
|
-
hiddenInput.value = checked ? "on" : "";
|
|
1666
|
-
} else {
|
|
1667
|
-
hiddenInput.value = value;
|
|
1668
|
-
}
|
|
2035
|
+
hiddenInput.value = value || "";
|
|
1669
2036
|
}
|
|
1670
|
-
}, [value,
|
|
1671
|
-
switch (
|
|
2037
|
+
}, [value, fieldName, fieldConfig.type]);
|
|
2038
|
+
switch (fieldConfig.type) {
|
|
1672
2039
|
case "input": {
|
|
1673
|
-
const
|
|
1674
|
-
|
|
2040
|
+
const stringConfig = fieldConfig;
|
|
2041
|
+
const inputType = stringConfig.inputProps?.type || "text";
|
|
2042
|
+
return /* @__PURE__ */ React21.createElement(
|
|
1675
2043
|
Input,
|
|
1676
2044
|
{
|
|
1677
|
-
...
|
|
2045
|
+
...stringConfig.inputProps,
|
|
2046
|
+
name: fieldName,
|
|
2047
|
+
"data-field-name": fieldName,
|
|
2048
|
+
type: inputType,
|
|
2049
|
+
label: baseProps.label,
|
|
2050
|
+
description: baseProps.description,
|
|
2051
|
+
isDisabled: baseProps.isDisabled,
|
|
2052
|
+
isInvalid: Boolean(errorMessage),
|
|
2053
|
+
errorMessage,
|
|
2054
|
+
value,
|
|
2055
|
+
onValueChange: setValue
|
|
2056
|
+
}
|
|
2057
|
+
);
|
|
2058
|
+
}
|
|
2059
|
+
case "textarea": {
|
|
2060
|
+
const stringConfig = fieldConfig;
|
|
2061
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2062
|
+
Textarea,
|
|
2063
|
+
{
|
|
2064
|
+
...stringConfig.textareaProps,
|
|
2065
|
+
name: fieldName,
|
|
2066
|
+
"data-field-name": fieldName,
|
|
2067
|
+
label: baseProps.label,
|
|
2068
|
+
description: baseProps.description,
|
|
2069
|
+
isDisabled: baseProps.isDisabled,
|
|
2070
|
+
isInvalid: Boolean(errorMessage),
|
|
2071
|
+
errorMessage,
|
|
2072
|
+
value,
|
|
2073
|
+
onValueChange: setValue
|
|
2074
|
+
}
|
|
2075
|
+
);
|
|
2076
|
+
}
|
|
2077
|
+
case "checkbox": {
|
|
2078
|
+
const booleanConfig = fieldConfig;
|
|
2079
|
+
const checkboxValue = booleanConfig.checkboxProps?.value ?? "on";
|
|
2080
|
+
const containerRef = React21.useRef(null);
|
|
2081
|
+
React21.useLayoutEffect(() => {
|
|
2082
|
+
const setValue2 = () => {
|
|
2083
|
+
if (containerRef.current) {
|
|
2084
|
+
const input = containerRef.current.querySelector(
|
|
2085
|
+
`input[type="checkbox"][name="${fieldName}"]`
|
|
2086
|
+
);
|
|
2087
|
+
if (input instanceof HTMLInputElement) {
|
|
2088
|
+
input.setAttribute("value", checkboxValue);
|
|
2089
|
+
input.value = checkboxValue;
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2092
|
+
};
|
|
2093
|
+
setValue2();
|
|
2094
|
+
const timeoutId = setTimeout(setValue2, 0);
|
|
2095
|
+
return () => clearTimeout(timeoutId);
|
|
2096
|
+
}, [fieldName, checkboxValue, checked]);
|
|
2097
|
+
return /* @__PURE__ */ React21.createElement("div", { ref: containerRef }, /* @__PURE__ */ React21.createElement(
|
|
2098
|
+
Checkbox,
|
|
2099
|
+
{
|
|
2100
|
+
...booleanConfig.checkboxProps,
|
|
2101
|
+
name: fieldName,
|
|
2102
|
+
"data-field-name": fieldName,
|
|
2103
|
+
value: checkboxValue,
|
|
2104
|
+
isDisabled: baseProps.isDisabled,
|
|
2105
|
+
isSelected: checked,
|
|
2106
|
+
onValueChange: setChecked,
|
|
2107
|
+
isInvalid: Boolean(errorMessage),
|
|
2108
|
+
errorMessage
|
|
2109
|
+
},
|
|
2110
|
+
baseProps.label
|
|
2111
|
+
));
|
|
2112
|
+
}
|
|
2113
|
+
case "checkboxGroup": {
|
|
2114
|
+
const checkboxGroupConfig = fieldConfig;
|
|
2115
|
+
const options = checkboxGroupConfig.checkboxGroupOptions || [];
|
|
2116
|
+
const currentValues = value ? String(value).split(",").filter(Boolean) : [];
|
|
2117
|
+
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(
|
|
2118
|
+
"div",
|
|
2119
|
+
{
|
|
2120
|
+
className: checkboxGroupConfig.orientation === "horizontal" ? "flex flex-row gap-4 flex-wrap" : "flex flex-col gap-2"
|
|
2121
|
+
},
|
|
2122
|
+
options.map(
|
|
2123
|
+
(option) => {
|
|
2124
|
+
const optionValue = String(option.value);
|
|
2125
|
+
const isSelected = currentValues.includes(optionValue);
|
|
2126
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2127
|
+
Checkbox,
|
|
2128
|
+
{
|
|
2129
|
+
key: optionValue,
|
|
2130
|
+
...checkboxGroupConfig.checkboxProps,
|
|
2131
|
+
name: fieldName,
|
|
2132
|
+
"data-field-name": fieldName,
|
|
2133
|
+
"data-checkbox-value": optionValue,
|
|
2134
|
+
isDisabled: baseProps.isDisabled,
|
|
2135
|
+
isSelected,
|
|
2136
|
+
onValueChange: (checked2) => {
|
|
2137
|
+
const newValues = checked2 ? [
|
|
2138
|
+
...currentValues.filter((v) => v !== optionValue),
|
|
2139
|
+
optionValue
|
|
2140
|
+
] : currentValues.filter((v) => v !== optionValue);
|
|
2141
|
+
setValue(newValues.join(","));
|
|
2142
|
+
},
|
|
2143
|
+
isInvalid: Boolean(errorMessage),
|
|
2144
|
+
errorMessage
|
|
2145
|
+
},
|
|
2146
|
+
option.label
|
|
2147
|
+
);
|
|
2148
|
+
}
|
|
2149
|
+
)
|
|
2150
|
+
), errorMessage && /* @__PURE__ */ React21.createElement("p", { className: "text-tiny text-danger mt-1" }, errorMessage));
|
|
2151
|
+
}
|
|
2152
|
+
case "switch": {
|
|
2153
|
+
const booleanConfig = fieldConfig;
|
|
2154
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2155
|
+
Switch,
|
|
2156
|
+
{
|
|
2157
|
+
...booleanConfig.switchProps,
|
|
2158
|
+
name: fieldName,
|
|
2159
|
+
"data-field-name": fieldName,
|
|
2160
|
+
isDisabled: baseProps.isDisabled,
|
|
2161
|
+
isSelected: checked,
|
|
2162
|
+
onValueChange: setChecked,
|
|
2163
|
+
isInvalid: Boolean(errorMessage),
|
|
2164
|
+
errorMessage
|
|
2165
|
+
},
|
|
2166
|
+
baseProps.label
|
|
2167
|
+
);
|
|
2168
|
+
}
|
|
2169
|
+
case "select": {
|
|
2170
|
+
const stringConfig = fieldConfig;
|
|
2171
|
+
const options = stringConfig.options || [];
|
|
2172
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2173
|
+
Select,
|
|
2174
|
+
{
|
|
2175
|
+
...stringConfig.selectProps,
|
|
2176
|
+
name: fieldName,
|
|
2177
|
+
"data-field-name": fieldName,
|
|
2178
|
+
label: baseProps.label,
|
|
2179
|
+
description: baseProps.description,
|
|
2180
|
+
isDisabled: baseProps.isDisabled,
|
|
2181
|
+
isInvalid: Boolean(errorMessage),
|
|
2182
|
+
errorMessage,
|
|
2183
|
+
selectedKeys: value ? [value] : [],
|
|
2184
|
+
onSelectionChange: (keys) => {
|
|
2185
|
+
const selectedValue = Array.from(keys)[0];
|
|
2186
|
+
setValue(selectedValue || "");
|
|
2187
|
+
}
|
|
2188
|
+
},
|
|
2189
|
+
options.map((option) => /* @__PURE__ */ React21.createElement(SelectItem, { key: String(option.value) }, option.label))
|
|
2190
|
+
);
|
|
2191
|
+
}
|
|
2192
|
+
case "radio": {
|
|
2193
|
+
const radioConfig = fieldConfig;
|
|
2194
|
+
const options = radioConfig.radioOptions || [];
|
|
2195
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2196
|
+
RadioGroup,
|
|
2197
|
+
{
|
|
2198
|
+
...radioConfig.radioProps,
|
|
2199
|
+
name: fieldName,
|
|
1678
2200
|
"data-field-name": fieldName,
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
isDisabled: field2.isDisabled,
|
|
2201
|
+
label: baseProps.label,
|
|
2202
|
+
description: baseProps.description,
|
|
2203
|
+
isDisabled: baseProps.isDisabled,
|
|
1683
2204
|
isInvalid: Boolean(errorMessage),
|
|
1684
2205
|
errorMessage,
|
|
1685
|
-
value,
|
|
2206
|
+
value: value || "",
|
|
1686
2207
|
onValueChange: setValue
|
|
1687
|
-
}
|
|
1688
|
-
|
|
2208
|
+
},
|
|
2209
|
+
options.map((option) => /* @__PURE__ */ React21.createElement(Radio, { key: String(option.value), value: String(option.value) }, option.label))
|
|
2210
|
+
);
|
|
1689
2211
|
}
|
|
1690
|
-
case "
|
|
1691
|
-
|
|
1692
|
-
|
|
2212
|
+
case "autocomplete": {
|
|
2213
|
+
const stringConfig = fieldConfig;
|
|
2214
|
+
const items = stringConfig.options?.map((opt) => ({
|
|
2215
|
+
label: opt.label,
|
|
2216
|
+
value: String(opt.value)
|
|
2217
|
+
})) || [];
|
|
2218
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2219
|
+
Autocomplete,
|
|
1693
2220
|
{
|
|
1694
|
-
...
|
|
2221
|
+
...stringConfig.autocompleteProps,
|
|
2222
|
+
name: fieldName,
|
|
1695
2223
|
"data-field-name": fieldName,
|
|
1696
|
-
label:
|
|
1697
|
-
description:
|
|
1698
|
-
isDisabled:
|
|
2224
|
+
label: baseProps.label,
|
|
2225
|
+
description: baseProps.description,
|
|
2226
|
+
isDisabled: baseProps.isDisabled,
|
|
1699
2227
|
isInvalid: Boolean(errorMessage),
|
|
1700
2228
|
errorMessage,
|
|
1701
|
-
value,
|
|
1702
|
-
|
|
2229
|
+
selectedKey: value || null,
|
|
2230
|
+
inputValue: value || "",
|
|
2231
|
+
onSelectionChange: (key) => {
|
|
2232
|
+
setValue(key ? String(key) : "");
|
|
2233
|
+
},
|
|
2234
|
+
onInputChange: setValue,
|
|
2235
|
+
items
|
|
2236
|
+
},
|
|
2237
|
+
items.map((item) => /* @__PURE__ */ React21.createElement(AutocompleteItem, { key: String(item.value) }, item.label))
|
|
2238
|
+
);
|
|
2239
|
+
}
|
|
2240
|
+
case "slider": {
|
|
2241
|
+
const sliderConfig = fieldConfig;
|
|
2242
|
+
const numValue = value ? Number(value) : 0;
|
|
2243
|
+
return /* @__PURE__ */ React21.createElement(
|
|
2244
|
+
Slider,
|
|
2245
|
+
{
|
|
2246
|
+
...sliderConfig.sliderProps,
|
|
2247
|
+
name: fieldName,
|
|
2248
|
+
"data-field-name": fieldName,
|
|
2249
|
+
label: baseProps.label,
|
|
2250
|
+
description: baseProps.description,
|
|
2251
|
+
isDisabled: baseProps.isDisabled,
|
|
2252
|
+
value: numValue,
|
|
2253
|
+
onChange: (val) => {
|
|
2254
|
+
const newValue = Array.isArray(val) ? val[0] : val;
|
|
2255
|
+
setValue(String(newValue));
|
|
2256
|
+
}
|
|
1703
2257
|
}
|
|
1704
|
-
)
|
|
2258
|
+
);
|
|
1705
2259
|
}
|
|
1706
|
-
case "
|
|
1707
|
-
|
|
1708
|
-
|
|
2260
|
+
case "date": {
|
|
2261
|
+
const dateConfig = fieldConfig;
|
|
2262
|
+
return /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement("input", { type: "hidden", name: fieldName, value: value || "" }), /* @__PURE__ */ React21.createElement(
|
|
2263
|
+
DateInput,
|
|
1709
2264
|
{
|
|
1710
|
-
...
|
|
2265
|
+
...dateConfig.dateProps,
|
|
1711
2266
|
"data-field-name": fieldName,
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
2267
|
+
label: baseProps.label,
|
|
2268
|
+
description: baseProps.description,
|
|
2269
|
+
isDisabled: baseProps.isDisabled,
|
|
1715
2270
|
isInvalid: Boolean(errorMessage),
|
|
1716
|
-
errorMessage
|
|
1717
|
-
|
|
1718
|
-
|
|
2271
|
+
errorMessage,
|
|
2272
|
+
value: value ? value : null,
|
|
2273
|
+
onChange: (date) => {
|
|
2274
|
+
const dateString = date ? `${date.year}-${String(date.month).padStart(2, "0")}-${String(date.day).padStart(2, "0")}` : "";
|
|
2275
|
+
setValue(dateString);
|
|
2276
|
+
}
|
|
2277
|
+
}
|
|
1719
2278
|
));
|
|
1720
2279
|
}
|
|
1721
|
-
case "
|
|
1722
|
-
const
|
|
1723
|
-
|
|
1724
|
-
|
|
2280
|
+
case "file": {
|
|
2281
|
+
const fileConfig = fieldConfig;
|
|
2282
|
+
const multiple = fileConfig.multiple || false;
|
|
2283
|
+
const accept = fileConfig.accept;
|
|
2284
|
+
return /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement(
|
|
2285
|
+
Input,
|
|
1725
2286
|
{
|
|
1726
|
-
...
|
|
2287
|
+
...fileConfig.fileProps,
|
|
2288
|
+
name: fieldName,
|
|
1727
2289
|
"data-field-name": fieldName,
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
2290
|
+
type: "file",
|
|
2291
|
+
label: baseProps.label,
|
|
2292
|
+
description: baseProps.description,
|
|
2293
|
+
isDisabled: baseProps.isDisabled,
|
|
1731
2294
|
isInvalid: Boolean(errorMessage),
|
|
1732
2295
|
errorMessage,
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
2296
|
+
multiple,
|
|
2297
|
+
accept,
|
|
2298
|
+
onChange: (e) => {
|
|
2299
|
+
if (!(e.target instanceof HTMLInputElement)) {
|
|
2300
|
+
return;
|
|
2301
|
+
}
|
|
2302
|
+
const target = e.target;
|
|
2303
|
+
if (target.files) {
|
|
2304
|
+
setValue(String(target.files.length));
|
|
2305
|
+
}
|
|
1737
2306
|
}
|
|
1738
|
-
}
|
|
1739
|
-
options.map(
|
|
1740
|
-
(option) => /* @__PURE__ */ React19.createElement(SelectItem, { key: String(option.value) }, option.label)
|
|
1741
|
-
)
|
|
2307
|
+
}
|
|
1742
2308
|
));
|
|
1743
2309
|
}
|
|
1744
2310
|
default:
|
|
1745
|
-
return /* @__PURE__ */
|
|
2311
|
+
return /* @__PURE__ */ React21.createElement(
|
|
1746
2312
|
Input,
|
|
1747
2313
|
{
|
|
2314
|
+
name: fieldName,
|
|
1748
2315
|
"data-field-name": fieldName,
|
|
1749
|
-
label:
|
|
1750
|
-
description:
|
|
1751
|
-
isDisabled:
|
|
2316
|
+
label: baseProps.label,
|
|
2317
|
+
description: baseProps.description,
|
|
2318
|
+
isDisabled: baseProps.isDisabled,
|
|
1752
2319
|
isInvalid: Boolean(errorMessage),
|
|
1753
2320
|
errorMessage,
|
|
1754
2321
|
value,
|
|
1755
2322
|
onValueChange: setValue
|
|
1756
2323
|
}
|
|
1757
|
-
)
|
|
2324
|
+
);
|
|
1758
2325
|
}
|
|
1759
2326
|
}
|
|
1760
2327
|
|
|
@@ -1772,10 +2339,10 @@ function useHeroForm() {
|
|
|
1772
2339
|
}
|
|
1773
2340
|
|
|
1774
2341
|
// src/providers/FormProvider.tsx
|
|
1775
|
-
import
|
|
2342
|
+
import React22 from "react";
|
|
1776
2343
|
import { FormProvider as RHFProvider } from "react-hook-form";
|
|
1777
2344
|
function FormProvider(props) {
|
|
1778
|
-
return /* @__PURE__ */
|
|
2345
|
+
return /* @__PURE__ */ React22.createElement(RHFProvider, { ...props.methods }, /* @__PURE__ */ React22.createElement(
|
|
1779
2346
|
"form",
|
|
1780
2347
|
{
|
|
1781
2348
|
className: props.className,
|
|
@@ -1788,7 +2355,7 @@ function FormProvider(props) {
|
|
|
1788
2355
|
}
|
|
1789
2356
|
|
|
1790
2357
|
// src/submit/SubmitButton.tsx
|
|
1791
|
-
import
|
|
2358
|
+
import React23 from "react";
|
|
1792
2359
|
function SubmitButton(props) {
|
|
1793
2360
|
const ctx = useFormContext5();
|
|
1794
2361
|
const loading = props.isLoading ?? ctx.formState.isSubmitting;
|
|
@@ -1798,10 +2365,10 @@ function SubmitButton(props) {
|
|
|
1798
2365
|
const defaults = useHeroHookFormDefaults();
|
|
1799
2366
|
const getButtonContent = () => {
|
|
1800
2367
|
if (enhancedState?.isSuccess) {
|
|
1801
|
-
return /* @__PURE__ */
|
|
2368
|
+
return /* @__PURE__ */ React23.createElement("span", { className: "inline-flex items-center gap-2" }, "\u2705", props.successText || "Success!");
|
|
1802
2369
|
}
|
|
1803
2370
|
if (loading) {
|
|
1804
|
-
return /* @__PURE__ */
|
|
2371
|
+
return /* @__PURE__ */ React23.createElement("span", { className: "inline-flex items-center gap-2" }, "\u23F3", props.loadingText || "Submitting...");
|
|
1805
2372
|
}
|
|
1806
2373
|
return props.children;
|
|
1807
2374
|
};
|
|
@@ -1814,7 +2381,7 @@ function SubmitButton(props) {
|
|
|
1814
2381
|
}
|
|
1815
2382
|
return props.buttonProps?.color || defaults.submitButton.color;
|
|
1816
2383
|
};
|
|
1817
|
-
return /* @__PURE__ */
|
|
2384
|
+
return /* @__PURE__ */ React23.createElement(
|
|
1818
2385
|
Button,
|
|
1819
2386
|
{
|
|
1820
2387
|
type: "submit",
|
|
@@ -2055,7 +2622,7 @@ var commonValidations = {
|
|
|
2055
2622
|
import { useFormContext as useFormContext5 } from "react-hook-form";
|
|
2056
2623
|
|
|
2057
2624
|
// src/components/ZodForm.tsx
|
|
2058
|
-
import
|
|
2625
|
+
import React25 from "react";
|
|
2059
2626
|
import { Button as Button5 } from "@heroui/react";
|
|
2060
2627
|
import {
|
|
2061
2628
|
FormProvider as FormProvider2
|
|
@@ -2079,8 +2646,15 @@ function createZodResolver(schema) {
|
|
|
2079
2646
|
const path = err.path.join(".");
|
|
2080
2647
|
errors[path] = { message: err.message };
|
|
2081
2648
|
});
|
|
2649
|
+
const fieldErrors = {};
|
|
2650
|
+
Object.entries(errors).forEach(([path, error2]) => {
|
|
2651
|
+
fieldErrors[path] = error2;
|
|
2652
|
+
});
|
|
2082
2653
|
return {
|
|
2083
|
-
|
|
2654
|
+
// TypeScript can't prove all paths are valid field paths, but at runtime they will be
|
|
2655
|
+
// because Zod validates against the schema which matches T
|
|
2656
|
+
// This is a necessary type assertion due to TypeScript's limitations with dynamic paths
|
|
2657
|
+
errors: fieldErrors,
|
|
2084
2658
|
values: {}
|
|
2085
2659
|
};
|
|
2086
2660
|
}
|
|
@@ -2098,14 +2672,12 @@ function createZodFormConfig(schema, fields, defaultValues) {
|
|
|
2098
2672
|
return {
|
|
2099
2673
|
fields,
|
|
2100
2674
|
schema,
|
|
2101
|
-
...defaultValues && {
|
|
2102
|
-
defaultValues
|
|
2103
|
-
}
|
|
2675
|
+
...defaultValues && { defaultValues }
|
|
2104
2676
|
};
|
|
2105
2677
|
}
|
|
2106
2678
|
|
|
2107
2679
|
// src/hooks/useEnhancedFormState.ts
|
|
2108
|
-
import { useCallback, useEffect, useState as
|
|
2680
|
+
import { useCallback, useEffect, useState as useState3 } from "react";
|
|
2109
2681
|
function useEnhancedFormState(form, options = {}) {
|
|
2110
2682
|
const {
|
|
2111
2683
|
autoReset = true,
|
|
@@ -2117,9 +2689,9 @@ function useEnhancedFormState(form, options = {}) {
|
|
|
2117
2689
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2118
2690
|
successMessage: _successMessage = "Form submitted successfully!"
|
|
2119
2691
|
} = options;
|
|
2120
|
-
const [status, setStatus] =
|
|
2121
|
-
const [error, setError] =
|
|
2122
|
-
const [submittedData, setSubmittedData] =
|
|
2692
|
+
const [status, setStatus] = useState3("idle");
|
|
2693
|
+
const [error, setError] = useState3(void 0);
|
|
2694
|
+
const [submittedData, setSubmittedData] = useState3(void 0);
|
|
2123
2695
|
const { formState, getValues: _getValues } = form;
|
|
2124
2696
|
const { dirtyFields, errors, isSubmitting, touchedFields } = formState;
|
|
2125
2697
|
useEffect(() => {
|
|
@@ -2178,7 +2750,7 @@ function useEnhancedFormState(form, options = {}) {
|
|
|
2178
2750
|
}
|
|
2179
2751
|
|
|
2180
2752
|
// src/components/FormStatus.tsx
|
|
2181
|
-
import
|
|
2753
|
+
import React24 from "react";
|
|
2182
2754
|
import { Button as Button4 } from "@heroui/react";
|
|
2183
2755
|
function FormStatus({
|
|
2184
2756
|
className = "",
|
|
@@ -2191,25 +2763,25 @@ function FormStatus({
|
|
|
2191
2763
|
return null;
|
|
2192
2764
|
}
|
|
2193
2765
|
if (isSubmitting) {
|
|
2194
|
-
return /* @__PURE__ */
|
|
2766
|
+
return /* @__PURE__ */ React24.createElement(
|
|
2195
2767
|
"div",
|
|
2196
2768
|
{
|
|
2197
2769
|
className: `flex items-center gap-3 p-4 bg-blue-50 border border-blue-200 rounded-lg ${className}`
|
|
2198
2770
|
},
|
|
2199
|
-
/* @__PURE__ */
|
|
2200
|
-
/* @__PURE__ */
|
|
2771
|
+
/* @__PURE__ */ React24.createElement("span", { className: "text-blue-600" }, "\u23F3"),
|
|
2772
|
+
/* @__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."))
|
|
2201
2773
|
);
|
|
2202
2774
|
}
|
|
2203
2775
|
if (isSuccess) {
|
|
2204
|
-
return /* @__PURE__ */
|
|
2776
|
+
return /* @__PURE__ */ React24.createElement(
|
|
2205
2777
|
"div",
|
|
2206
2778
|
{
|
|
2207
2779
|
className: `flex items-center gap-3 p-4 bg-green-50 border border-green-200 rounded-lg ${className}`,
|
|
2208
2780
|
"data-testid": "success-message"
|
|
2209
2781
|
},
|
|
2210
|
-
/* @__PURE__ */
|
|
2211
|
-
/* @__PURE__ */
|
|
2212
|
-
onDismiss && /* @__PURE__ */
|
|
2782
|
+
/* @__PURE__ */ React24.createElement("span", { className: "text-green-600" }, "\u2705"),
|
|
2783
|
+
/* @__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.")),
|
|
2784
|
+
onDismiss && /* @__PURE__ */ React24.createElement(
|
|
2213
2785
|
Button4,
|
|
2214
2786
|
{
|
|
2215
2787
|
size: "sm",
|
|
@@ -2223,15 +2795,15 @@ function FormStatus({
|
|
|
2223
2795
|
);
|
|
2224
2796
|
}
|
|
2225
2797
|
if (isError && error) {
|
|
2226
|
-
return /* @__PURE__ */
|
|
2798
|
+
return /* @__PURE__ */ React24.createElement(
|
|
2227
2799
|
"div",
|
|
2228
2800
|
{
|
|
2229
2801
|
className: `flex items-center gap-3 p-4 bg-red-50 border border-red-200 rounded-lg ${className}`,
|
|
2230
2802
|
"data-testid": "error-message"
|
|
2231
2803
|
},
|
|
2232
|
-
/* @__PURE__ */
|
|
2233
|
-
/* @__PURE__ */
|
|
2234
|
-
onDismiss && /* @__PURE__ */
|
|
2804
|
+
/* @__PURE__ */ React24.createElement("span", { className: "text-red-600" }, "\u26A0\uFE0F"),
|
|
2805
|
+
/* @__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)),
|
|
2806
|
+
onDismiss && /* @__PURE__ */ React24.createElement(
|
|
2235
2807
|
Button4,
|
|
2236
2808
|
{
|
|
2237
2809
|
size: "sm",
|
|
@@ -2252,8 +2824,8 @@ function FormToast({
|
|
|
2252
2824
|
position = "top-right",
|
|
2253
2825
|
state
|
|
2254
2826
|
}) {
|
|
2255
|
-
const [isVisible, setIsVisible] =
|
|
2256
|
-
|
|
2827
|
+
const [isVisible, setIsVisible] = React24.useState(false);
|
|
2828
|
+
React24.useEffect(() => {
|
|
2257
2829
|
if (state.isSuccess || state.isError) {
|
|
2258
2830
|
setIsVisible(true);
|
|
2259
2831
|
if (duration > 0) {
|
|
@@ -2274,7 +2846,7 @@ function FormToast({
|
|
|
2274
2846
|
"top-left": "top-4 left-4",
|
|
2275
2847
|
"top-right": "top-4 right-4"
|
|
2276
2848
|
};
|
|
2277
|
-
return /* @__PURE__ */
|
|
2849
|
+
return /* @__PURE__ */ React24.createElement("div", { className: `fixed z-50 ${positionClasses[position]}` }, /* @__PURE__ */ React24.createElement(FormStatus, { state, onDismiss }));
|
|
2278
2850
|
}
|
|
2279
2851
|
|
|
2280
2852
|
// src/components/ZodForm.tsx
|
|
@@ -2294,7 +2866,10 @@ function ZodForm({
|
|
|
2294
2866
|
subtitle,
|
|
2295
2867
|
title
|
|
2296
2868
|
}) {
|
|
2297
|
-
const
|
|
2869
|
+
const formConfig = {
|
|
2870
|
+
...config
|
|
2871
|
+
};
|
|
2872
|
+
const form = useZodForm(formConfig);
|
|
2298
2873
|
const enhancedState = useEnhancedFormState(form, {
|
|
2299
2874
|
autoReset: true,
|
|
2300
2875
|
onError: (error) => onError?.({ field: "form", message: error }),
|
|
@@ -2324,12 +2899,12 @@ function ZodForm({
|
|
|
2324
2899
|
};
|
|
2325
2900
|
const renderFields = () => {
|
|
2326
2901
|
if (layout === "grid") {
|
|
2327
|
-
return /* @__PURE__ */
|
|
2902
|
+
return /* @__PURE__ */ React25.createElement(
|
|
2328
2903
|
"div",
|
|
2329
2904
|
{
|
|
2330
2905
|
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"}`
|
|
2331
2906
|
},
|
|
2332
|
-
config.fields.map((field2) => /* @__PURE__ */
|
|
2907
|
+
config.fields.map((field2) => /* @__PURE__ */ React25.createElement(
|
|
2333
2908
|
FormField,
|
|
2334
2909
|
{
|
|
2335
2910
|
key: field2.name,
|
|
@@ -2346,7 +2921,7 @@ function ZodForm({
|
|
|
2346
2921
|
);
|
|
2347
2922
|
}
|
|
2348
2923
|
if (layout === "horizontal") {
|
|
2349
|
-
return /* @__PURE__ */
|
|
2924
|
+
return /* @__PURE__ */ React25.createElement("div", { className: `grid gap-${spacing} grid-cols-1 md:grid-cols-2` }, config.fields.map((field2) => /* @__PURE__ */ React25.createElement(
|
|
2350
2925
|
FormField,
|
|
2351
2926
|
{
|
|
2352
2927
|
key: field2.name,
|
|
@@ -2361,10 +2936,10 @@ function ZodForm({
|
|
|
2361
2936
|
}
|
|
2362
2937
|
)));
|
|
2363
2938
|
}
|
|
2364
|
-
return /* @__PURE__ */
|
|
2939
|
+
return /* @__PURE__ */ React25.createElement("div", { className: `space-y-${spacing}` }, config.fields.map((field2) => /* @__PURE__ */ React25.createElement(
|
|
2365
2940
|
FormField,
|
|
2366
2941
|
{
|
|
2367
|
-
key: field2.name,
|
|
2942
|
+
key: pathToString(field2.name),
|
|
2368
2943
|
config: field2,
|
|
2369
2944
|
form,
|
|
2370
2945
|
submissionState: {
|
|
@@ -2380,19 +2955,19 @@ function ZodForm({
|
|
|
2380
2955
|
e.preventDefault();
|
|
2381
2956
|
void handleSubmit();
|
|
2382
2957
|
};
|
|
2383
|
-
|
|
2958
|
+
React25.useEffect(() => {
|
|
2384
2959
|
if (config.onError && Object.keys(form.formState.errors).length > 0) {
|
|
2385
2960
|
config.onError(form.formState.errors);
|
|
2386
2961
|
}
|
|
2387
2962
|
}, [form.formState.errors, config.onError]);
|
|
2388
|
-
return /* @__PURE__ */
|
|
2963
|
+
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(
|
|
2389
2964
|
FormStatus,
|
|
2390
2965
|
{
|
|
2391
2966
|
state: enhancedState,
|
|
2392
2967
|
onDismiss: () => enhancedState.reset(),
|
|
2393
2968
|
showDetails: true
|
|
2394
2969
|
}
|
|
2395
|
-
), renderFields(), /* @__PURE__ */
|
|
2970
|
+
), renderFields(), /* @__PURE__ */ React25.createElement("div", { className: "mt-6 flex gap-3 justify-end" }, /* @__PURE__ */ React25.createElement(
|
|
2396
2971
|
Button5,
|
|
2397
2972
|
{
|
|
2398
2973
|
color: "primary",
|
|
@@ -2402,7 +2977,7 @@ function ZodForm({
|
|
|
2402
2977
|
...submitButtonProps
|
|
2403
2978
|
},
|
|
2404
2979
|
enhancedState.isSuccess ? "Success!" : submitButtonText
|
|
2405
|
-
), showResetButton && /* @__PURE__ */
|
|
2980
|
+
), showResetButton && /* @__PURE__ */ React25.createElement(
|
|
2406
2981
|
Button5,
|
|
2407
2982
|
{
|
|
2408
2983
|
isDisabled: enhancedState.isSubmitting,
|
|
@@ -2415,7 +2990,7 @@ function ZodForm({
|
|
|
2415
2990
|
}
|
|
2416
2991
|
|
|
2417
2992
|
// src/components/SimpleForm.tsx
|
|
2418
|
-
import
|
|
2993
|
+
import React26 from "react";
|
|
2419
2994
|
function SimpleForm({
|
|
2420
2995
|
className,
|
|
2421
2996
|
defaultValues,
|
|
@@ -2429,7 +3004,7 @@ function SimpleForm({
|
|
|
2429
3004
|
subtitle,
|
|
2430
3005
|
title
|
|
2431
3006
|
}) {
|
|
2432
|
-
return /* @__PURE__ */
|
|
3007
|
+
return /* @__PURE__ */ React26.createElement(
|
|
2433
3008
|
ZodForm,
|
|
2434
3009
|
{
|
|
2435
3010
|
className,
|
|
@@ -2553,6 +3128,29 @@ var BasicFormBuilder = class {
|
|
|
2553
3128
|
function createBasicFormBuilder() {
|
|
2554
3129
|
return new BasicFormBuilder();
|
|
2555
3130
|
}
|
|
3131
|
+
function inputHelper(name, label, typeOrProps, inputProps) {
|
|
3132
|
+
if (typeOrProps && typeof typeOrProps === "object" && !("type" in typeOrProps && typeof typeOrProps.type === "string" && ["text", "email", "tel", "password"].includes(typeOrProps.type))) {
|
|
3133
|
+
return {
|
|
3134
|
+
inputProps: {
|
|
3135
|
+
type: "text",
|
|
3136
|
+
...typeOrProps
|
|
3137
|
+
},
|
|
3138
|
+
label,
|
|
3139
|
+
name,
|
|
3140
|
+
type: "input"
|
|
3141
|
+
};
|
|
3142
|
+
}
|
|
3143
|
+
const type = typeof typeOrProps === "string" ? typeOrProps : void 0;
|
|
3144
|
+
return {
|
|
3145
|
+
inputProps: {
|
|
3146
|
+
type: type || "text",
|
|
3147
|
+
...inputProps
|
|
3148
|
+
},
|
|
3149
|
+
label,
|
|
3150
|
+
name,
|
|
3151
|
+
type: "input"
|
|
3152
|
+
};
|
|
3153
|
+
}
|
|
2556
3154
|
var FormFieldHelpers = {
|
|
2557
3155
|
/**
|
|
2558
3156
|
* Create an autocomplete field
|
|
@@ -2603,6 +3201,34 @@ var FormFieldHelpers = {
|
|
|
2603
3201
|
name,
|
|
2604
3202
|
type: "checkbox"
|
|
2605
3203
|
}),
|
|
3204
|
+
/**
|
|
3205
|
+
* Create a checkbox group field (multiple checkboxes saving to an array)
|
|
3206
|
+
*
|
|
3207
|
+
* @example
|
|
3208
|
+
* ```tsx
|
|
3209
|
+
* // Simple checkbox group
|
|
3210
|
+
* FormFieldHelpers.checkboxGroup("interests", "Interests", [
|
|
3211
|
+
* { label: "Reading", value: "reading" },
|
|
3212
|
+
* { label: "Sports", value: "sports" },
|
|
3213
|
+
* { label: "Music", value: "music" },
|
|
3214
|
+
* ])
|
|
3215
|
+
*
|
|
3216
|
+
* // With horizontal layout and custom styling
|
|
3217
|
+
* FormFieldHelpers.checkboxGroup("interests", "Interests", options, {
|
|
3218
|
+
* orientation: "horizontal",
|
|
3219
|
+
* checkboxProps: { color: "primary", size: "lg" }
|
|
3220
|
+
* })
|
|
3221
|
+
* ```
|
|
3222
|
+
*/
|
|
3223
|
+
checkboxGroup: (name, label, options, config) => ({
|
|
3224
|
+
checkboxGroupOptions: options,
|
|
3225
|
+
checkboxProps: config?.checkboxProps,
|
|
3226
|
+
description: config?.description,
|
|
3227
|
+
label,
|
|
3228
|
+
name,
|
|
3229
|
+
orientation: config?.orientation || "vertical",
|
|
3230
|
+
type: "checkboxGroup"
|
|
3231
|
+
}),
|
|
2606
3232
|
/**
|
|
2607
3233
|
* Create a conditional field that shows/hides based on form data
|
|
2608
3234
|
*
|
|
@@ -2627,12 +3253,64 @@ var FormFieldHelpers = {
|
|
|
2627
3253
|
* ```
|
|
2628
3254
|
*/
|
|
2629
3255
|
conditional: (name, condition, field2) => {
|
|
2630
|
-
|
|
3256
|
+
const config = {
|
|
2631
3257
|
condition,
|
|
2632
3258
|
field: field2,
|
|
2633
3259
|
name,
|
|
2634
3260
|
type: "conditional"
|
|
2635
3261
|
};
|
|
3262
|
+
return config;
|
|
3263
|
+
},
|
|
3264
|
+
/**
|
|
3265
|
+
* Create a conditional field array that avoids memory leaks in Cypress tests.
|
|
3266
|
+
*
|
|
3267
|
+
* This helper creates a field array that is always registered but conditionally
|
|
3268
|
+
* rendered, preventing the register/unregister cycles that cause memory
|
|
3269
|
+
* accumulation in Cypress Electron renderer.
|
|
3270
|
+
*
|
|
3271
|
+
* @param name - The field array name
|
|
3272
|
+
* @param condition - Function that determines if the field array should be visible
|
|
3273
|
+
* @param label - Display label for the field array
|
|
3274
|
+
* @param fields - Field configurations for array items
|
|
3275
|
+
* @param options - Additional field array options
|
|
3276
|
+
*
|
|
3277
|
+
* @example
|
|
3278
|
+
* ```tsx
|
|
3279
|
+
* // Memory-safe conditional field array for multiple choice options
|
|
3280
|
+
* FormFieldHelpers.conditionalFieldArray(
|
|
3281
|
+
* "choices",
|
|
3282
|
+
* (data) => data.questionType === 'MULTIPLE_CHOICE',
|
|
3283
|
+
* "Answer Choices",
|
|
3284
|
+
* [
|
|
3285
|
+
* FormFieldHelpers.input("text", "Choice Text"),
|
|
3286
|
+
* FormFieldHelpers.checkbox("isCorrect", "Correct Answer"),
|
|
3287
|
+
* ]
|
|
3288
|
+
* )
|
|
3289
|
+
* ```
|
|
3290
|
+
*/
|
|
3291
|
+
conditionalFieldArray: (name, condition, label, fields, options) => {
|
|
3292
|
+
const fieldArrayConfig = {
|
|
3293
|
+
addButtonText: options?.addButtonText ?? "Add Item",
|
|
3294
|
+
alwaysRegistered: true,
|
|
3295
|
+
defaultItem: options?.defaultItem,
|
|
3296
|
+
enableReordering: options?.enableReordering ?? false,
|
|
3297
|
+
fields,
|
|
3298
|
+
label,
|
|
3299
|
+
max: options?.max ?? 10,
|
|
3300
|
+
// This prevents register/unregister cycles
|
|
3301
|
+
min: options?.min ?? 0,
|
|
3302
|
+
name,
|
|
3303
|
+
removeButtonText: options?.removeButtonText ?? "Remove",
|
|
3304
|
+
type: "fieldArray"
|
|
3305
|
+
};
|
|
3306
|
+
const config = {
|
|
3307
|
+
condition,
|
|
3308
|
+
field: fieldArrayConfig,
|
|
3309
|
+
name,
|
|
3310
|
+
// ArrayPath extends Path, so this is safe
|
|
3311
|
+
type: "conditional"
|
|
3312
|
+
};
|
|
3313
|
+
return config;
|
|
2636
3314
|
},
|
|
2637
3315
|
/**
|
|
2638
3316
|
* Create a content field for headers, questions, or custom content between fields
|
|
@@ -2649,7 +3327,7 @@ var FormFieldHelpers = {
|
|
|
2649
3327
|
* ```
|
|
2650
3328
|
*/
|
|
2651
3329
|
content: (title, description, options) => {
|
|
2652
|
-
|
|
3330
|
+
const config = {
|
|
2653
3331
|
className: options?.className,
|
|
2654
3332
|
description: description || void 0,
|
|
2655
3333
|
name: options?.name,
|
|
@@ -2657,7 +3335,31 @@ var FormFieldHelpers = {
|
|
|
2657
3335
|
title: title || void 0,
|
|
2658
3336
|
type: "content"
|
|
2659
3337
|
};
|
|
3338
|
+
return config;
|
|
2660
3339
|
},
|
|
3340
|
+
/**
|
|
3341
|
+
* Create a custom field with full control over rendering
|
|
3342
|
+
*
|
|
3343
|
+
* @example
|
|
3344
|
+
* ```tsx
|
|
3345
|
+
* // Custom field with render function
|
|
3346
|
+
* FormFieldHelpers.custom<FormData>(
|
|
3347
|
+
* "skills",
|
|
3348
|
+
* "Skills",
|
|
3349
|
+
* ({ form, control }) => {
|
|
3350
|
+
* // Custom rendering logic
|
|
3351
|
+
* return <div>...</div>;
|
|
3352
|
+
* }
|
|
3353
|
+
* )
|
|
3354
|
+
* ```
|
|
3355
|
+
*/
|
|
3356
|
+
custom: (name, label, render, options) => ({
|
|
3357
|
+
label,
|
|
3358
|
+
name,
|
|
3359
|
+
render,
|
|
3360
|
+
type: "custom",
|
|
3361
|
+
...options
|
|
3362
|
+
}),
|
|
2661
3363
|
/**
|
|
2662
3364
|
* Create a date field
|
|
2663
3365
|
*
|
|
@@ -2743,7 +3445,10 @@ var FormFieldHelpers = {
|
|
|
2743
3445
|
* // With type
|
|
2744
3446
|
* FormFieldHelpers.input("email", "Email", "email")
|
|
2745
3447
|
*
|
|
2746
|
-
* // With
|
|
3448
|
+
* // With props only (no type)
|
|
3449
|
+
* FormFieldHelpers.input("name", "Name", { placeholder: "Enter name" })
|
|
3450
|
+
*
|
|
3451
|
+
* // With type and props
|
|
2747
3452
|
* FormFieldHelpers.input("email", "Email", "email", {
|
|
2748
3453
|
* placeholder: "Enter your email",
|
|
2749
3454
|
* classNames: { input: "custom-input" },
|
|
@@ -2752,15 +3457,25 @@ var FormFieldHelpers = {
|
|
|
2752
3457
|
* })
|
|
2753
3458
|
* ```
|
|
2754
3459
|
*/
|
|
2755
|
-
input:
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
3460
|
+
input: inputHelper,
|
|
3461
|
+
/**
|
|
3462
|
+
* Create a radio group field
|
|
3463
|
+
*
|
|
3464
|
+
* @example
|
|
3465
|
+
* ```tsx
|
|
3466
|
+
* // Simple radio group
|
|
3467
|
+
* FormFieldHelpers.radio("gender", "Gender", [
|
|
3468
|
+
* { label: "Male", value: "male" },
|
|
3469
|
+
* { label: "Female", value: "female" }
|
|
3470
|
+
* ])
|
|
3471
|
+
*
|
|
3472
|
+
* // With full customization
|
|
3473
|
+
* FormFieldHelpers.radio("gender", "Gender", options, {
|
|
3474
|
+
* orientation: "horizontal",
|
|
3475
|
+
* classNames: { base: "custom-radio" }
|
|
3476
|
+
* })
|
|
3477
|
+
* ```
|
|
3478
|
+
*/
|
|
2764
3479
|
/**
|
|
2765
3480
|
* Create a radio group field
|
|
2766
3481
|
*
|
|
@@ -2893,6 +3608,8 @@ var CommonFields = {
|
|
|
2893
3608
|
* Address fields
|
|
2894
3609
|
*/
|
|
2895
3610
|
address: () => [
|
|
3611
|
+
// Type assertions are necessary: TypeScript can't prove these strings are valid Path<T>
|
|
3612
|
+
// for an arbitrary T, but they will be valid when used with a matching schema
|
|
2896
3613
|
FormFieldHelpers.input("street", "Street Address"),
|
|
2897
3614
|
FormFieldHelpers.input("city", "City"),
|
|
2898
3615
|
FormFieldHelpers.input("state", "State/Province"),
|
|
@@ -2911,6 +3628,7 @@ var CommonFields = {
|
|
|
2911
3628
|
* Personal information fields
|
|
2912
3629
|
*/
|
|
2913
3630
|
personal: () => [
|
|
3631
|
+
// Type assertions are necessary - see CommonFields documentation above
|
|
2914
3632
|
FormFieldHelpers.input("firstName", "First Name"),
|
|
2915
3633
|
FormFieldHelpers.input("lastName", "Last Name"),
|
|
2916
3634
|
FormFieldHelpers.input("email", "Email", "email"),
|
|
@@ -2920,6 +3638,7 @@ var CommonFields = {
|
|
|
2920
3638
|
* Terms and conditions fields
|
|
2921
3639
|
*/
|
|
2922
3640
|
terms: () => [
|
|
3641
|
+
// Type assertions are necessary - see CommonFields documentation above
|
|
2923
3642
|
FormFieldHelpers.checkbox(
|
|
2924
3643
|
"terms",
|
|
2925
3644
|
"I agree to the terms and conditions"
|
|
@@ -2936,7 +3655,7 @@ var CommonFields = {
|
|
|
2936
3655
|
};
|
|
2937
3656
|
|
|
2938
3657
|
// src/builders/AdvancedFormBuilder.ts
|
|
2939
|
-
function
|
|
3658
|
+
function createInputField(name, label, props) {
|
|
2940
3659
|
return {
|
|
2941
3660
|
label,
|
|
2942
3661
|
name,
|
|
@@ -2952,7 +3671,7 @@ function inputField(name, label, props) {
|
|
|
2952
3671
|
}
|
|
2953
3672
|
};
|
|
2954
3673
|
}
|
|
2955
|
-
function
|
|
3674
|
+
function createTextareaField(name, label, props) {
|
|
2956
3675
|
return {
|
|
2957
3676
|
label,
|
|
2958
3677
|
name,
|
|
@@ -2968,7 +3687,7 @@ function textareaField(name, label, props) {
|
|
|
2968
3687
|
}
|
|
2969
3688
|
};
|
|
2970
3689
|
}
|
|
2971
|
-
function
|
|
3690
|
+
function createSelectField(name, label, options) {
|
|
2972
3691
|
return {
|
|
2973
3692
|
label,
|
|
2974
3693
|
name,
|
|
@@ -2976,7 +3695,7 @@ function selectField(name, label, options) {
|
|
|
2976
3695
|
type: "select"
|
|
2977
3696
|
};
|
|
2978
3697
|
}
|
|
2979
|
-
function
|
|
3698
|
+
function createCheckboxField(name, label, props) {
|
|
2980
3699
|
return {
|
|
2981
3700
|
label,
|
|
2982
3701
|
name,
|
|
@@ -2989,7 +3708,7 @@ function checkboxField(name, label, props) {
|
|
|
2989
3708
|
}
|
|
2990
3709
|
};
|
|
2991
3710
|
}
|
|
2992
|
-
function
|
|
3711
|
+
function createSwitchField(name, label, props) {
|
|
2993
3712
|
return {
|
|
2994
3713
|
description: props?.description,
|
|
2995
3714
|
isDisabled: props?.isDisabled,
|
|
@@ -3003,7 +3722,7 @@ function switchField(name, label, props) {
|
|
|
3003
3722
|
}
|
|
3004
3723
|
};
|
|
3005
3724
|
}
|
|
3006
|
-
function
|
|
3725
|
+
function createRadioField(name, label, options, props) {
|
|
3007
3726
|
return {
|
|
3008
3727
|
label,
|
|
3009
3728
|
name,
|
|
@@ -3018,7 +3737,7 @@ function radioField(name, label, options, props) {
|
|
|
3018
3737
|
}
|
|
3019
3738
|
};
|
|
3020
3739
|
}
|
|
3021
|
-
function
|
|
3740
|
+
function createSliderField(name, label, props) {
|
|
3022
3741
|
return {
|
|
3023
3742
|
label,
|
|
3024
3743
|
name,
|
|
@@ -3033,20 +3752,19 @@ function sliderField(name, label, props) {
|
|
|
3033
3752
|
}
|
|
3034
3753
|
};
|
|
3035
3754
|
}
|
|
3036
|
-
function
|
|
3755
|
+
function createDateField(name, label, props) {
|
|
3756
|
+
const dateProps = {};
|
|
3757
|
+
if (props?.className !== void 0) {
|
|
3758
|
+
dateProps.className = props.className;
|
|
3759
|
+
}
|
|
3037
3760
|
return {
|
|
3038
3761
|
label,
|
|
3039
3762
|
name,
|
|
3040
3763
|
type: "date",
|
|
3041
|
-
...
|
|
3042
|
-
dateProps: {
|
|
3043
|
-
className: props.className,
|
|
3044
|
-
placeholder: props.placeholder
|
|
3045
|
-
}
|
|
3046
|
-
}
|
|
3764
|
+
...Object.keys(dateProps).length > 0 && { dateProps }
|
|
3047
3765
|
};
|
|
3048
3766
|
}
|
|
3049
|
-
function
|
|
3767
|
+
function createFileField(name, label, props) {
|
|
3050
3768
|
return {
|
|
3051
3769
|
label,
|
|
3052
3770
|
name,
|
|
@@ -3061,7 +3779,7 @@ function fileField(name, label, props) {
|
|
|
3061
3779
|
}
|
|
3062
3780
|
};
|
|
3063
3781
|
}
|
|
3064
|
-
function
|
|
3782
|
+
function createFontPickerField(name, label, props) {
|
|
3065
3783
|
return {
|
|
3066
3784
|
className: props?.className,
|
|
3067
3785
|
description: props?.description,
|
|
@@ -3071,83 +3789,119 @@ function fontPickerField(name, label, props) {
|
|
|
3071
3789
|
type: "fontPicker"
|
|
3072
3790
|
};
|
|
3073
3791
|
}
|
|
3074
|
-
function
|
|
3792
|
+
function createStringArrayField(name, label, props) {
|
|
3793
|
+
return {
|
|
3794
|
+
className: props?.className,
|
|
3795
|
+
description: props?.description,
|
|
3796
|
+
isDisabled: props?.isDisabled,
|
|
3797
|
+
label,
|
|
3798
|
+
name,
|
|
3799
|
+
stringArrayProps: {
|
|
3800
|
+
addButtonText: props?.addButtonText,
|
|
3801
|
+
allowDuplicates: props?.allowDuplicates,
|
|
3802
|
+
maxItems: props?.maxItems,
|
|
3803
|
+
minItems: props?.minItems,
|
|
3804
|
+
placeholder: props?.placeholder,
|
|
3805
|
+
showAddButton: props?.showAddButton,
|
|
3806
|
+
transformItem: props?.transformItem,
|
|
3807
|
+
validateItem: props?.validateItem
|
|
3808
|
+
},
|
|
3809
|
+
type: "stringArray"
|
|
3810
|
+
};
|
|
3811
|
+
}
|
|
3812
|
+
function createContentField(config) {
|
|
3075
3813
|
return {
|
|
3076
|
-
className:
|
|
3077
|
-
description: description || void 0,
|
|
3078
|
-
name:
|
|
3079
|
-
render:
|
|
3080
|
-
title: title || void 0,
|
|
3814
|
+
className: config.className,
|
|
3815
|
+
description: config.description || void 0,
|
|
3816
|
+
name: config.name,
|
|
3817
|
+
render: config.render,
|
|
3818
|
+
title: config.title || void 0,
|
|
3081
3819
|
type: "content"
|
|
3082
3820
|
};
|
|
3083
3821
|
}
|
|
3084
|
-
function
|
|
3085
|
-
switch (type) {
|
|
3822
|
+
function createFieldFromParams(params) {
|
|
3823
|
+
switch (params.type) {
|
|
3086
3824
|
case "input":
|
|
3087
|
-
return
|
|
3825
|
+
return createInputField(params.name, params.label, params.props);
|
|
3088
3826
|
case "textarea":
|
|
3089
|
-
return
|
|
3827
|
+
return createTextareaField(params.name, params.label, params.props);
|
|
3090
3828
|
case "select":
|
|
3091
|
-
return
|
|
3829
|
+
return createSelectField(params.name, params.label, params.options);
|
|
3092
3830
|
case "checkbox":
|
|
3093
|
-
return
|
|
3831
|
+
return createCheckboxField(params.name, params.label, params.props);
|
|
3094
3832
|
case "switch":
|
|
3095
|
-
return
|
|
3833
|
+
return createSwitchField(params.name, params.label, params.props);
|
|
3096
3834
|
case "radio":
|
|
3097
|
-
return
|
|
3835
|
+
return createRadioField(
|
|
3836
|
+
params.name,
|
|
3837
|
+
params.label,
|
|
3838
|
+
params.options,
|
|
3839
|
+
params.props
|
|
3840
|
+
);
|
|
3098
3841
|
case "slider":
|
|
3099
|
-
return
|
|
3842
|
+
return createSliderField(params.name, params.label, params.props);
|
|
3100
3843
|
case "date":
|
|
3101
|
-
return
|
|
3844
|
+
return createDateField(params.name, params.label, params.props);
|
|
3102
3845
|
case "file":
|
|
3103
|
-
return
|
|
3846
|
+
return createFileField(params.name, params.label, params.props);
|
|
3104
3847
|
case "fontPicker":
|
|
3105
|
-
return
|
|
3848
|
+
return createFontPickerField(params.name, params.label, params.props);
|
|
3849
|
+
case "stringArray":
|
|
3850
|
+
return createStringArrayField(params.name, params.label, params.props);
|
|
3851
|
+
case "autocomplete":
|
|
3852
|
+
return {
|
|
3853
|
+
autocompleteProps: params.props,
|
|
3854
|
+
label: params.label,
|
|
3855
|
+
name: params.name,
|
|
3856
|
+
options: params.options,
|
|
3857
|
+
type: "autocomplete"
|
|
3858
|
+
};
|
|
3106
3859
|
case "content":
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
}
|
|
3117
|
-
|
|
3118
|
-
name,
|
|
3119
|
-
label,
|
|
3120
|
-
optionsOrProps
|
|
3121
|
-
);
|
|
3122
|
-
default:
|
|
3123
|
-
throw new Error(`Unknown field type: ${type}`);
|
|
3860
|
+
return createContentField({
|
|
3861
|
+
className: params.className,
|
|
3862
|
+
description: params.description,
|
|
3863
|
+
name: params.name,
|
|
3864
|
+
render: params.render,
|
|
3865
|
+
title: params.title
|
|
3866
|
+
});
|
|
3867
|
+
default: {
|
|
3868
|
+
const _exhaustive = params;
|
|
3869
|
+
throw new Error(`Unknown field type: ${_exhaustive.type}`);
|
|
3870
|
+
}
|
|
3124
3871
|
}
|
|
3125
3872
|
}
|
|
3873
|
+
function createField(params) {
|
|
3874
|
+
return createFieldFromParams(params);
|
|
3875
|
+
}
|
|
3126
3876
|
var AdvancedFieldBuilder = class {
|
|
3127
3877
|
constructor() {
|
|
3128
3878
|
this.fields = [];
|
|
3129
3879
|
}
|
|
3130
|
-
|
|
3131
|
-
|
|
3880
|
+
/**
|
|
3881
|
+
* Add any field type using the unified API
|
|
3882
|
+
*/
|
|
3883
|
+
field(params) {
|
|
3884
|
+
this.fields.push(createField(params));
|
|
3132
3885
|
return this;
|
|
3133
3886
|
}
|
|
3134
3887
|
/**
|
|
3135
3888
|
* Add a conditional field that shows/hides based on form data
|
|
3136
3889
|
*/
|
|
3137
3890
|
conditionalField(name, condition, field2) {
|
|
3138
|
-
|
|
3891
|
+
const config = {
|
|
3139
3892
|
condition,
|
|
3140
3893
|
field: field2,
|
|
3141
3894
|
name,
|
|
3142
3895
|
type: "conditional"
|
|
3143
|
-
}
|
|
3896
|
+
};
|
|
3897
|
+
this.fields.push(config);
|
|
3144
3898
|
return this;
|
|
3145
3899
|
}
|
|
3146
3900
|
/**
|
|
3147
3901
|
* Add a field array for dynamic repeating field groups
|
|
3148
3902
|
*/
|
|
3149
3903
|
fieldArray(name, label, fields, options) {
|
|
3150
|
-
|
|
3904
|
+
const config = {
|
|
3151
3905
|
addButtonText: options?.addButtonText,
|
|
3152
3906
|
fields,
|
|
3153
3907
|
label,
|
|
@@ -3156,21 +3910,23 @@ var AdvancedFieldBuilder = class {
|
|
|
3156
3910
|
name,
|
|
3157
3911
|
removeButtonText: options?.removeButtonText,
|
|
3158
3912
|
type: "fieldArray"
|
|
3159
|
-
}
|
|
3913
|
+
};
|
|
3914
|
+
this.fields.push(config);
|
|
3160
3915
|
return this;
|
|
3161
3916
|
}
|
|
3162
3917
|
/**
|
|
3163
3918
|
* Add a dynamic section that shows/hides based on form data
|
|
3164
3919
|
*/
|
|
3165
3920
|
dynamicSection(name, condition, fields, options) {
|
|
3166
|
-
|
|
3921
|
+
const config = {
|
|
3167
3922
|
condition,
|
|
3168
3923
|
description: options?.description,
|
|
3169
3924
|
fields,
|
|
3170
3925
|
name,
|
|
3171
3926
|
title: options?.title,
|
|
3172
3927
|
type: "dynamicSection"
|
|
3173
|
-
}
|
|
3928
|
+
};
|
|
3929
|
+
this.fields.push(config);
|
|
3174
3930
|
return this;
|
|
3175
3931
|
}
|
|
3176
3932
|
/**
|
|
@@ -3184,8 +3940,11 @@ var FieldArrayItemBuilder = class {
|
|
|
3184
3940
|
constructor() {
|
|
3185
3941
|
this.fields = [];
|
|
3186
3942
|
}
|
|
3187
|
-
|
|
3188
|
-
|
|
3943
|
+
/**
|
|
3944
|
+
* Add any field type using the unified API for array items
|
|
3945
|
+
*/
|
|
3946
|
+
field(params) {
|
|
3947
|
+
this.fields.push(createField(params));
|
|
3189
3948
|
return this;
|
|
3190
3949
|
}
|
|
3191
3950
|
/**
|
|
@@ -3203,15 +3962,12 @@ var FieldArrayBuilder = class {
|
|
|
3203
3962
|
this.arrayName = arrayName;
|
|
3204
3963
|
this.fields = [];
|
|
3205
3964
|
}
|
|
3206
|
-
field(
|
|
3207
|
-
const fullPath = `${this.arrayName}.${name}`;
|
|
3208
|
-
const fieldConfig = createField(
|
|
3209
|
-
|
|
3210
|
-
fullPath
|
|
3211
|
-
|
|
3212
|
-
optionsOrProps,
|
|
3213
|
-
props
|
|
3214
|
-
);
|
|
3965
|
+
field(params) {
|
|
3966
|
+
const fullPath = `${this.arrayName}.${params.name}`;
|
|
3967
|
+
const fieldConfig = createField({
|
|
3968
|
+
...params,
|
|
3969
|
+
name: fullPath
|
|
3970
|
+
});
|
|
3215
3971
|
this.fields.push(fieldConfig);
|
|
3216
3972
|
return this;
|
|
3217
3973
|
}
|
|
@@ -3254,7 +4010,7 @@ var TypeInferredBuilder = class {
|
|
|
3254
4010
|
new RegExp(pattern),
|
|
3255
4011
|
`${label} format is invalid`
|
|
3256
4012
|
);
|
|
3257
|
-
this.schemaFields[name] = zodType;
|
|
4013
|
+
this.schemaFields[pathToString(name)] = zodType;
|
|
3258
4014
|
this.formFields.push({
|
|
3259
4015
|
inputProps: { type: "text", ...fieldOptions },
|
|
3260
4016
|
label,
|
|
@@ -3267,7 +4023,7 @@ var TypeInferredBuilder = class {
|
|
|
3267
4023
|
* Add an email field
|
|
3268
4024
|
*/
|
|
3269
4025
|
email(name, label, options) {
|
|
3270
|
-
this.schemaFields[name] = z3.string().email(`Please enter a valid email address`);
|
|
4026
|
+
this.schemaFields[pathToString(name)] = z3.string().email(`Please enter a valid email address`);
|
|
3271
4027
|
this.formFields.push({
|
|
3272
4028
|
inputProps: { type: "email", ...options },
|
|
3273
4029
|
label,
|
|
@@ -3286,7 +4042,7 @@ var TypeInferredBuilder = class {
|
|
|
3286
4042
|
zodType = zodType.min(min, `${label} must be at least ${min}`);
|
|
3287
4043
|
if (max !== void 0)
|
|
3288
4044
|
zodType = zodType.max(max, `${label} must be no more than ${max}`);
|
|
3289
|
-
this.schemaFields[name] = zodType;
|
|
4045
|
+
this.schemaFields[pathToString(name)] = zodType;
|
|
3290
4046
|
this.formFields.push({
|
|
3291
4047
|
inputProps: { max, min, step, type: "number", ...fieldOptions },
|
|
3292
4048
|
label,
|
|
@@ -3306,7 +4062,7 @@ var TypeInferredBuilder = class {
|
|
|
3306
4062
|
minLength,
|
|
3307
4063
|
`${label} must be at least ${minLength} characters`
|
|
3308
4064
|
);
|
|
3309
|
-
this.schemaFields[name] = zodType;
|
|
4065
|
+
this.schemaFields[pathToString(name)] = zodType;
|
|
3310
4066
|
this.formFields.push({
|
|
3311
4067
|
label,
|
|
3312
4068
|
name,
|
|
@@ -3319,7 +4075,7 @@ var TypeInferredBuilder = class {
|
|
|
3319
4075
|
* Add a select field
|
|
3320
4076
|
*/
|
|
3321
4077
|
select(name, label, options) {
|
|
3322
|
-
this.schemaFields[name] = z3.string().min(1, `Please select a ${label.toLowerCase()}`);
|
|
4078
|
+
this.schemaFields[pathToString(name)] = z3.string().min(1, `Please select a ${label.toLowerCase()}`);
|
|
3323
4079
|
this.formFields.push({
|
|
3324
4080
|
label,
|
|
3325
4081
|
name,
|
|
@@ -3340,7 +4096,7 @@ var TypeInferredBuilder = class {
|
|
|
3340
4096
|
`You must agree to ${label.toLowerCase()}`
|
|
3341
4097
|
);
|
|
3342
4098
|
}
|
|
3343
|
-
this.schemaFields[name] = zodType;
|
|
4099
|
+
this.schemaFields[pathToString(name)] = zodType;
|
|
3344
4100
|
this.formFields.push({
|
|
3345
4101
|
checkboxProps: fieldOptions,
|
|
3346
4102
|
label,
|
|
@@ -3353,7 +4109,7 @@ var TypeInferredBuilder = class {
|
|
|
3353
4109
|
* Add a switch field
|
|
3354
4110
|
*/
|
|
3355
4111
|
switch(name, label, options) {
|
|
3356
|
-
this.schemaFields[name] = z3.boolean().optional();
|
|
4112
|
+
this.schemaFields[pathToString(name)] = z3.boolean().optional();
|
|
3357
4113
|
this.formFields.push({
|
|
3358
4114
|
label,
|
|
3359
4115
|
name,
|
|
@@ -3366,7 +4122,7 @@ var TypeInferredBuilder = class {
|
|
|
3366
4122
|
* Add a radio field
|
|
3367
4123
|
*/
|
|
3368
4124
|
radio(name, label, options, fieldOptions) {
|
|
3369
|
-
this.schemaFields[name] = z3.string().min(1, `Please select a ${label.toLowerCase()}`);
|
|
4125
|
+
this.schemaFields[pathToString(name)] = z3.string().min(1, `Please select a ${label.toLowerCase()}`);
|
|
3370
4126
|
this.formFields.push({
|
|
3371
4127
|
label,
|
|
3372
4128
|
name,
|
|
@@ -3386,15 +4142,19 @@ var TypeInferredBuilder = class {
|
|
|
3386
4142
|
zodType = zodType.min(min, `${label} must be at least ${min}`);
|
|
3387
4143
|
if (max !== void 0)
|
|
3388
4144
|
zodType = zodType.max(max, `${label} must be no more than ${max}`);
|
|
3389
|
-
this.schemaFields[name] = zodType;
|
|
4145
|
+
this.schemaFields[pathToString(name)] = zodType;
|
|
4146
|
+
const { className, description, isDisabled, ...validSliderProps } = fieldOptions || {};
|
|
3390
4147
|
this.formFields.push({
|
|
4148
|
+
className,
|
|
4149
|
+
description,
|
|
4150
|
+
isDisabled,
|
|
3391
4151
|
label,
|
|
3392
4152
|
name,
|
|
3393
4153
|
sliderProps: {
|
|
3394
4154
|
maxValue: max,
|
|
3395
4155
|
minValue: min,
|
|
3396
4156
|
step,
|
|
3397
|
-
...
|
|
4157
|
+
...validSliderProps
|
|
3398
4158
|
},
|
|
3399
4159
|
type: "slider"
|
|
3400
4160
|
});
|
|
@@ -3404,7 +4164,7 @@ var TypeInferredBuilder = class {
|
|
|
3404
4164
|
* Add a date field
|
|
3405
4165
|
*/
|
|
3406
4166
|
date(name, label, options) {
|
|
3407
|
-
this.schemaFields[name] = z3.string().min(1, `${label} is required`);
|
|
4167
|
+
this.schemaFields[pathToString(name)] = z3.string().min(1, `${label} is required`);
|
|
3408
4168
|
this.formFields.push({
|
|
3409
4169
|
dateProps: options,
|
|
3410
4170
|
label,
|
|
@@ -3417,7 +4177,7 @@ var TypeInferredBuilder = class {
|
|
|
3417
4177
|
* Add a file field
|
|
3418
4178
|
*/
|
|
3419
4179
|
file(name, label, options) {
|
|
3420
|
-
this.schemaFields[name] = z3.any().optional();
|
|
4180
|
+
this.schemaFields[pathToString(name)] = z3.any().optional();
|
|
3421
4181
|
this.formFields.push({
|
|
3422
4182
|
fileProps: options,
|
|
3423
4183
|
label,
|
|
@@ -3494,11 +4254,18 @@ var field = {
|
|
|
3494
4254
|
// src/builders/NestedPathBuilder.ts
|
|
3495
4255
|
var NestedPathBuilder = class {
|
|
3496
4256
|
constructor() {
|
|
4257
|
+
// fields is accessed by nested builder classes, so it needs to be accessible
|
|
4258
|
+
// Making it public allows nested builders to add fields while maintaining encapsulation
|
|
3497
4259
|
this.fields = [];
|
|
3498
4260
|
}
|
|
3499
4261
|
/**
|
|
3500
4262
|
* Create a nested object path builder
|
|
3501
4263
|
* Usage: builder.nest("address").field("street", "Street Address")
|
|
4264
|
+
*
|
|
4265
|
+
* @param path - A path in the form data structure. When called from root level,
|
|
4266
|
+
* accepts Path<T>. When called after .end() from a nested context,
|
|
4267
|
+
* accepts any string for nested paths under sections.
|
|
4268
|
+
* @returns A builder for nested paths under the specified path
|
|
3502
4269
|
*/
|
|
3503
4270
|
nest(path) {
|
|
3504
4271
|
return new NestedObjectBuilder(this, path);
|
|
@@ -3512,29 +4279,18 @@ var NestedPathBuilder = class {
|
|
|
3512
4279
|
}
|
|
3513
4280
|
/**
|
|
3514
4281
|
* Add a field with single path
|
|
3515
|
-
* Usage: builder.field("firstName", "First Name")
|
|
4282
|
+
* Usage: builder.field({ type: "input", name: "firstName", label: "First Name" })
|
|
3516
4283
|
*/
|
|
3517
|
-
field(
|
|
3518
|
-
this.fields.push(
|
|
3519
|
-
label,
|
|
3520
|
-
name,
|
|
3521
|
-
type,
|
|
3522
|
-
...props
|
|
3523
|
-
});
|
|
4284
|
+
field(params) {
|
|
4285
|
+
this.fields.push(createField(params));
|
|
3524
4286
|
return this;
|
|
3525
4287
|
}
|
|
3526
4288
|
/**
|
|
3527
4289
|
* Add a field with path segments
|
|
3528
|
-
* Usage: builder.fieldPath(
|
|
4290
|
+
* Usage: builder.fieldPath({ type: "input", name: path.join("."), label: "Full Name" })
|
|
3529
4291
|
*/
|
|
3530
|
-
fieldPath(
|
|
3531
|
-
|
|
3532
|
-
this.fields.push({
|
|
3533
|
-
label,
|
|
3534
|
-
name,
|
|
3535
|
-
type,
|
|
3536
|
-
...props
|
|
3537
|
-
});
|
|
4292
|
+
fieldPath(params) {
|
|
4293
|
+
this.fields.push(createField(params));
|
|
3538
4294
|
return this;
|
|
3539
4295
|
}
|
|
3540
4296
|
/**
|
|
@@ -3563,23 +4319,28 @@ var NestedObjectBuilder = class _NestedObjectBuilder {
|
|
|
3563
4319
|
/**
|
|
3564
4320
|
* Add a field to the current nested path
|
|
3565
4321
|
*/
|
|
3566
|
-
field(
|
|
3567
|
-
const fullPath = `${this.path}.${
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
name: fullPath
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
});
|
|
4322
|
+
field(params) {
|
|
4323
|
+
const fullPath = typeof params.name === "string" ? `${this.path}.${params.name}` : params.name;
|
|
4324
|
+
const fieldParams = {
|
|
4325
|
+
...params,
|
|
4326
|
+
name: fullPath
|
|
4327
|
+
};
|
|
4328
|
+
this.parent.fields.push(createField(fieldParams));
|
|
3574
4329
|
return this;
|
|
3575
4330
|
}
|
|
3576
4331
|
/**
|
|
3577
4332
|
* Nest deeper into the object
|
|
4333
|
+
*
|
|
4334
|
+
* @param subPath - A string representing a nested path under the current path.
|
|
4335
|
+
* The parameter accepts any string; TypeScript validates the constructed
|
|
4336
|
+
* path (basePath.subPath) in the return type.
|
|
4337
|
+
* @returns A builder for the nested path
|
|
3578
4338
|
*/
|
|
3579
4339
|
nest(subPath) {
|
|
4340
|
+
const fullPath = `${this.path}.${subPath}`;
|
|
3580
4341
|
return new _NestedObjectBuilder(
|
|
3581
4342
|
this.parent,
|
|
3582
|
-
|
|
4343
|
+
fullPath
|
|
3583
4344
|
);
|
|
3584
4345
|
}
|
|
3585
4346
|
/**
|
|
@@ -3597,14 +4358,13 @@ var SectionBuilder = class {
|
|
|
3597
4358
|
/**
|
|
3598
4359
|
* Add a field to the current section
|
|
3599
4360
|
*/
|
|
3600
|
-
field(
|
|
3601
|
-
const fullPath = `${this.path}.${
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
name: fullPath
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
});
|
|
4361
|
+
field(params) {
|
|
4362
|
+
const fullPath = typeof params.name === "string" ? `${this.path}.${params.name}` : params.name;
|
|
4363
|
+
const fieldParams = {
|
|
4364
|
+
...params,
|
|
4365
|
+
name: fullPath
|
|
4366
|
+
};
|
|
4367
|
+
this.parent.fields.push(createField(fieldParams));
|
|
3608
4368
|
return this;
|
|
3609
4369
|
}
|
|
3610
4370
|
/**
|
|
@@ -3612,17 +4372,29 @@ var SectionBuilder = class {
|
|
|
3612
4372
|
*/
|
|
3613
4373
|
fields(fieldDefinitions) {
|
|
3614
4374
|
fieldDefinitions.forEach((field2) => {
|
|
3615
|
-
this.
|
|
4375
|
+
const fullPath = `${this.path}.${field2.name}`;
|
|
4376
|
+
this.parent.fields.push({
|
|
4377
|
+
label: field2.label,
|
|
4378
|
+
name: fullPath,
|
|
4379
|
+
type: field2.type || "input",
|
|
4380
|
+
...field2.props
|
|
4381
|
+
});
|
|
3616
4382
|
});
|
|
3617
4383
|
return this;
|
|
3618
4384
|
}
|
|
3619
4385
|
/**
|
|
3620
4386
|
* Nest deeper into the section
|
|
4387
|
+
*
|
|
4388
|
+
* @param subPath - A string representing a nested path under the current section path.
|
|
4389
|
+
* The parameter accepts any string; TypeScript validates the constructed
|
|
4390
|
+
* path (basePath.subPath) in the return type.
|
|
4391
|
+
* @returns A builder for the nested path
|
|
3621
4392
|
*/
|
|
3622
4393
|
nest(subPath) {
|
|
4394
|
+
const fullPath = `${this.path}.${subPath}`;
|
|
3623
4395
|
return new NestedObjectBuilder(
|
|
3624
4396
|
this.parent,
|
|
3625
|
-
|
|
4397
|
+
fullPath
|
|
3626
4398
|
);
|
|
3627
4399
|
}
|
|
3628
4400
|
/**
|
|
@@ -3640,13 +4412,12 @@ var FieldTemplateBuilder = class {
|
|
|
3640
4412
|
/**
|
|
3641
4413
|
* Complete the field definition
|
|
3642
4414
|
*/
|
|
3643
|
-
complete(
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
name: this.path
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
});
|
|
4415
|
+
complete(params) {
|
|
4416
|
+
const fieldParams = {
|
|
4417
|
+
...params,
|
|
4418
|
+
name: params.name ? `${this.path}.${params.name}` : this.path
|
|
4419
|
+
};
|
|
4420
|
+
this.parent.fields.push(createField(fieldParams));
|
|
3650
4421
|
return this.parent;
|
|
3651
4422
|
}
|
|
3652
4423
|
};
|
|
@@ -3760,8 +4531,74 @@ function useTypeInferredForm(formConfig, options = {}) {
|
|
|
3760
4531
|
return useInferredForm(formConfig.schema, formConfig.fields, options);
|
|
3761
4532
|
}
|
|
3762
4533
|
|
|
4534
|
+
// src/hooks/useLazyFieldRegistration.ts
|
|
4535
|
+
import { useEffect as useEffect3, useRef as useRef2, useState as useState4 } from "react";
|
|
4536
|
+
import { useFormContext as useFormContext6 } from "react-hook-form";
|
|
4537
|
+
function useLazyFieldRegistration(fieldName, shouldRegister, defaultValue, rules) {
|
|
4538
|
+
const { register, setValue, unregister, watch } = useFormContext6();
|
|
4539
|
+
const [isRegistered, setIsRegistered] = useState4(false);
|
|
4540
|
+
const hasCheckedRegistration = useRef2(false);
|
|
4541
|
+
const conditionMet = shouldRegister();
|
|
4542
|
+
useEffect3(() => {
|
|
4543
|
+
if (conditionMet && !isRegistered) {
|
|
4544
|
+
register(fieldName, rules);
|
|
4545
|
+
if (defaultValue !== void 0) {
|
|
4546
|
+
setValue(fieldName, defaultValue);
|
|
4547
|
+
}
|
|
4548
|
+
setIsRegistered(true);
|
|
4549
|
+
hasCheckedRegistration.current = true;
|
|
4550
|
+
} else if (!conditionMet && isRegistered && hasCheckedRegistration.current) {
|
|
4551
|
+
unregister(fieldName);
|
|
4552
|
+
setIsRegistered(false);
|
|
4553
|
+
}
|
|
4554
|
+
}, [
|
|
4555
|
+
conditionMet,
|
|
4556
|
+
fieldName,
|
|
4557
|
+
register,
|
|
4558
|
+
unregister,
|
|
4559
|
+
setValue,
|
|
4560
|
+
rules,
|
|
4561
|
+
defaultValue,
|
|
4562
|
+
isRegistered
|
|
4563
|
+
]);
|
|
4564
|
+
return {
|
|
4565
|
+
currentValue: isRegistered ? watch(fieldName) : void 0,
|
|
4566
|
+
isRegistered
|
|
4567
|
+
};
|
|
4568
|
+
}
|
|
4569
|
+
function useLazyFieldArrayRegistration(arrayName, shouldRegister, defaultValue = []) {
|
|
4570
|
+
const { setValue, watch } = useFormContext6();
|
|
4571
|
+
const [isRegistered, setIsRegistered] = useState4(false);
|
|
4572
|
+
const hasCheckedRegistration = useRef2(false);
|
|
4573
|
+
const conditionMet = shouldRegister();
|
|
4574
|
+
const currentValue = watch(arrayName);
|
|
4575
|
+
useEffect3(() => {
|
|
4576
|
+
if (conditionMet && !isRegistered) {
|
|
4577
|
+
if (!currentValue || !Array.isArray(currentValue)) {
|
|
4578
|
+
setValue(arrayName, defaultValue);
|
|
4579
|
+
}
|
|
4580
|
+
setIsRegistered(true);
|
|
4581
|
+
hasCheckedRegistration.current = true;
|
|
4582
|
+
} else if (!conditionMet && isRegistered && hasCheckedRegistration.current) {
|
|
4583
|
+
setValue(arrayName, []);
|
|
4584
|
+
setIsRegistered(false);
|
|
4585
|
+
}
|
|
4586
|
+
}, [
|
|
4587
|
+
conditionMet,
|
|
4588
|
+
arrayName,
|
|
4589
|
+
setValue,
|
|
4590
|
+
defaultValue,
|
|
4591
|
+
isRegistered,
|
|
4592
|
+
currentValue
|
|
4593
|
+
]);
|
|
4594
|
+
return {
|
|
4595
|
+
currentValue: isRegistered ? currentValue : [],
|
|
4596
|
+
isRegistered
|
|
4597
|
+
};
|
|
4598
|
+
}
|
|
4599
|
+
|
|
3763
4600
|
// src/utils/performance.ts
|
|
3764
|
-
import { useCallback as useCallback3, useMemo as useMemo2, useRef as
|
|
4601
|
+
import { useCallback as useCallback3, useMemo as useMemo2, useRef as useRef3 } from "react";
|
|
3765
4602
|
function debounce(func, delay) {
|
|
3766
4603
|
let timeoutId;
|
|
3767
4604
|
return (...args) => {
|
|
@@ -3780,7 +4617,7 @@ function throttle(func, limit) {
|
|
|
3780
4617
|
};
|
|
3781
4618
|
}
|
|
3782
4619
|
function useMemoizedCallback(callback, deps) {
|
|
3783
|
-
const callbackRef =
|
|
4620
|
+
const callbackRef = useRef3(callback);
|
|
3784
4621
|
callbackRef.current = callback;
|
|
3785
4622
|
return useCallback3(
|
|
3786
4623
|
((...args) => callbackRef.current(...args)),
|
|
@@ -3826,8 +4663,8 @@ function deepEqual(prevProps, nextProps) {
|
|
|
3826
4663
|
return true;
|
|
3827
4664
|
}
|
|
3828
4665
|
function usePerformanceMonitor(componentName, enabled = process.env.NODE_ENV === "development") {
|
|
3829
|
-
const renderCountRef =
|
|
3830
|
-
const lastRenderTimeRef =
|
|
4666
|
+
const renderCountRef = useRef3(0);
|
|
4667
|
+
const lastRenderTimeRef = useRef3(Date.now());
|
|
3831
4668
|
if (enabled) {
|
|
3832
4669
|
renderCountRef.current += 1;
|
|
3833
4670
|
const now = Date.now();
|
|
@@ -3904,7 +4741,7 @@ function syncArrays(options) {
|
|
|
3904
4741
|
}
|
|
3905
4742
|
|
|
3906
4743
|
// src/utils/createFieldArrayCustomConfig.tsx
|
|
3907
|
-
import
|
|
4744
|
+
import React27 from "react";
|
|
3908
4745
|
import { useFieldArray as useFieldArray2 } from "react-hook-form";
|
|
3909
4746
|
import { Button as Button6 } from "@heroui/react";
|
|
3910
4747
|
function createFieldArrayCustomConfig(options) {
|
|
@@ -3923,11 +4760,12 @@ function createFieldArrayCustomConfig(options) {
|
|
|
3923
4760
|
className,
|
|
3924
4761
|
label,
|
|
3925
4762
|
name,
|
|
3926
|
-
// ArrayPath is
|
|
4763
|
+
// ArrayPath is now accepted by CustomFieldConfig
|
|
3927
4764
|
render: ({ control, errors, form }) => {
|
|
3928
4765
|
const { append, fields, move, remove } = useFieldArray2({
|
|
3929
4766
|
control,
|
|
3930
4767
|
name
|
|
4768
|
+
// ArrayPath is the correct type for useFieldArray
|
|
3931
4769
|
});
|
|
3932
4770
|
const canAdd = fields.length < max;
|
|
3933
4771
|
const canRemove = fields.length > min;
|
|
@@ -3955,14 +4793,15 @@ function createFieldArrayCustomConfig(options) {
|
|
|
3955
4793
|
move(index, index + 1);
|
|
3956
4794
|
}
|
|
3957
4795
|
};
|
|
3958
|
-
return /* @__PURE__ */
|
|
4796
|
+
return /* @__PURE__ */ React27.createElement("div", { className }, /* @__PURE__ */ React27.createElement("div", { className: "space-y-4" }, fields.map((field2, index) => {
|
|
3959
4797
|
const canMoveUp = enableReordering && index > 0;
|
|
3960
4798
|
const canMoveDown = enableReordering && index < fields.length - 1;
|
|
3961
|
-
return /* @__PURE__ */
|
|
4799
|
+
return /* @__PURE__ */ React27.createElement(React27.Fragment, { key: field2.id }, renderItem({
|
|
3962
4800
|
canMoveDown,
|
|
3963
4801
|
canMoveUp,
|
|
3964
4802
|
control,
|
|
3965
4803
|
errors,
|
|
4804
|
+
// fields from useFieldArray are already typed correctly
|
|
3966
4805
|
field: field2,
|
|
3967
4806
|
fields,
|
|
3968
4807
|
form,
|
|
@@ -3971,7 +4810,7 @@ function createFieldArrayCustomConfig(options) {
|
|
|
3971
4810
|
onMoveUp: () => handleMoveUp(index),
|
|
3972
4811
|
onRemove: () => handleRemove(index)
|
|
3973
4812
|
}));
|
|
3974
|
-
}), fields.length === 0 && renderAddButton ? /* @__PURE__ */
|
|
4813
|
+
}), 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(
|
|
3975
4814
|
Button6,
|
|
3976
4815
|
{
|
|
3977
4816
|
variant: "bordered",
|
|
@@ -3985,6 +4824,76 @@ function createFieldArrayCustomConfig(options) {
|
|
|
3985
4824
|
};
|
|
3986
4825
|
}
|
|
3987
4826
|
|
|
4827
|
+
// src/utils/fieldArrayMemory.ts
|
|
4828
|
+
import { useFormContext as useFormContext7 } from "react-hook-form";
|
|
4829
|
+
function useFieldArrayMemoryCleanup(arrayName) {
|
|
4830
|
+
const { reset, unregister } = useFormContext7();
|
|
4831
|
+
const cleanup = () => {
|
|
4832
|
+
try {
|
|
4833
|
+
reset((formValues) => ({
|
|
4834
|
+
...formValues,
|
|
4835
|
+
[arrayName]: []
|
|
4836
|
+
}));
|
|
4837
|
+
setTimeout(() => {
|
|
4838
|
+
try {
|
|
4839
|
+
unregister(arrayName);
|
|
4840
|
+
} catch (error) {
|
|
4841
|
+
console.debug("Field array cleanup unregister failed:", error);
|
|
4842
|
+
}
|
|
4843
|
+
}, 0);
|
|
4844
|
+
} catch (error) {
|
|
4845
|
+
console.debug("Field array cleanup failed:", error);
|
|
4846
|
+
}
|
|
4847
|
+
};
|
|
4848
|
+
return { cleanup };
|
|
4849
|
+
}
|
|
4850
|
+
function suggestGarbageCollection() {
|
|
4851
|
+
if (typeof window !== "undefined" && "gc" in window) {
|
|
4852
|
+
try {
|
|
4853
|
+
window.gc();
|
|
4854
|
+
} catch (error) {
|
|
4855
|
+
}
|
|
4856
|
+
}
|
|
4857
|
+
}
|
|
4858
|
+
var memorySafeFieldArray = {
|
|
4859
|
+
/**
|
|
4860
|
+
* Add items to a field array with memory management.
|
|
4861
|
+
*/
|
|
4862
|
+
addItems: (append, items, onProgress) => {
|
|
4863
|
+
let addedCount = 0;
|
|
4864
|
+
const batchSize = 10;
|
|
4865
|
+
for (let i = 0; i < items.length; i += batchSize) {
|
|
4866
|
+
const batch = items.slice(i, i + batchSize);
|
|
4867
|
+
batch.forEach((item) => {
|
|
4868
|
+
append(item);
|
|
4869
|
+
addedCount++;
|
|
4870
|
+
});
|
|
4871
|
+
if (addedCount % batchSize === 0) {
|
|
4872
|
+
suggestGarbageCollection();
|
|
4873
|
+
onProgress?.(addedCount);
|
|
4874
|
+
}
|
|
4875
|
+
}
|
|
4876
|
+
suggestGarbageCollection();
|
|
4877
|
+
},
|
|
4878
|
+
/**
|
|
4879
|
+
* Clear entire field array with memory cleanup.
|
|
4880
|
+
*/
|
|
4881
|
+
clearArray: (setValue, arrayName) => {
|
|
4882
|
+
setValue(arrayName, []);
|
|
4883
|
+
suggestGarbageCollection();
|
|
4884
|
+
},
|
|
4885
|
+
/**
|
|
4886
|
+
* Remove items from a field array with memory cleanup.
|
|
4887
|
+
*/
|
|
4888
|
+
removeItems: (remove, indices) => {
|
|
4889
|
+
const sortedIndices = [...indices].sort((a, b) => b - a);
|
|
4890
|
+
sortedIndices.forEach((index) => {
|
|
4891
|
+
remove(index);
|
|
4892
|
+
});
|
|
4893
|
+
suggestGarbageCollection();
|
|
4894
|
+
}
|
|
4895
|
+
};
|
|
4896
|
+
|
|
3988
4897
|
// src/builders/validation-helpers.ts
|
|
3989
4898
|
import { z as z4 } from "zod";
|
|
3990
4899
|
var validationPatterns = {
|
|
@@ -4137,6 +5046,7 @@ export {
|
|
|
4137
5046
|
AutocompleteField,
|
|
4138
5047
|
BasicFormBuilder,
|
|
4139
5048
|
CheckboxField,
|
|
5049
|
+
CheckboxGroupField,
|
|
4140
5050
|
CommonFields,
|
|
4141
5051
|
ConditionalField,
|
|
4142
5052
|
ConfigurableForm,
|
|
@@ -4204,20 +5114,26 @@ export {
|
|
|
4204
5114
|
getFormErrors,
|
|
4205
5115
|
hasFieldError,
|
|
4206
5116
|
hasFormErrors,
|
|
5117
|
+
memorySafeFieldArray,
|
|
5118
|
+
pathToString,
|
|
4207
5119
|
serverValidation,
|
|
4208
5120
|
shallowEqual,
|
|
4209
5121
|
simulateFieldInput,
|
|
4210
5122
|
simulateFormSubmission,
|
|
5123
|
+
suggestGarbageCollection,
|
|
4211
5124
|
syncArrays,
|
|
4212
5125
|
throttle,
|
|
4213
5126
|
useDebouncedFieldValidation,
|
|
4214
5127
|
useDebouncedValidation,
|
|
4215
5128
|
useEnhancedFormState,
|
|
5129
|
+
useFieldArrayMemoryCleanup,
|
|
4216
5130
|
useFormContext5 as useFormContext,
|
|
4217
5131
|
useFormHelper,
|
|
4218
5132
|
useHeroForm,
|
|
4219
5133
|
useHeroHookFormDefaults,
|
|
4220
5134
|
useInferredForm,
|
|
5135
|
+
useLazyFieldArrayRegistration,
|
|
5136
|
+
useLazyFieldRegistration,
|
|
4221
5137
|
useMemoizedCallback,
|
|
4222
5138
|
useMemoizedFieldProps,
|
|
4223
5139
|
usePerformanceMonitor,
|