@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/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 React18 from "react";
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({ defaultValues });
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 React17 from "react";
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
- ...common.color !== void 0 ? { color: common.color } : {},
179
- ...common.size !== void 0 ? { size: common.size } : {},
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: { ...commonCheckbox, ...cfg.checkbox ?? {} },
242
- dateInput: { ...commonDateInput, ...cfg.dateInput ?? {} },
263
+ checkbox: cfg.checkbox ?? {},
264
+ dateInput: cfg.dateInput ?? {},
243
265
  input: { ...commonInput, ...cfg.input ?? {} },
244
- radioGroup: { ...commonRadioGroup, ...cfg.radioGroup ?? {} },
266
+ radioGroup: cfg.radioGroup ?? {},
245
267
  select: { ...commonSelect, ...cfg.select ?? {} },
246
- slider: { ...commonSlider, ...cfg.slider ?? {} },
247
- submitButton: { ...commonButton, ...cfg.submitButton ?? {} },
248
- switch: { ...commonSwitch, ...cfg.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 }) => /* @__PURE__ */ React3.createElement("div", { className }, /* @__PURE__ */ React3.createElement(
272
- Checkbox,
273
- {
274
- ...defaults.checkbox,
275
- ...checkboxProps,
276
- isDisabled,
277
- isInvalid: Boolean(fieldState.error),
278
- isSelected: Boolean(field2.value),
279
- onBlur: field2.onBlur,
280
- onValueChange: (val) => field2.onChange(val)
281
- },
282
- label
283
- ), 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),
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/ConditionalField.tsx
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__ */ React4.createElement("div", { className }, /* @__PURE__ */ React4.createElement(
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 React5 from "react";
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__ */ React5.createElement("div", { className: config.className }, config.render({
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__ */ React5.createElement("div", { className: config.className }, config.title && /* @__PURE__ */ React5.createElement("h3", { className: "text-lg font-semibold text-foreground mb-2" }, config.title), config.description && /* @__PURE__ */ React5.createElement("p", { className: "text-sm text-muted-foreground" }, config.description));
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 React6 from "react";
338
- import { Controller as Controller3 } from "react-hook-form";
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__ */ React6.createElement(
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__ */ React6.createElement(
371
- Controller3,
473
+ return /* @__PURE__ */ React7.createElement(
474
+ Controller4,
372
475
  {
373
476
  control,
374
477
  name,
375
- render: ({ field: field2, fieldState }) => /* @__PURE__ */ React6.createElement("div", { className }, /* @__PURE__ */ React6.createElement(
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 React7 from "react";
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__ */ React7.createElement("div", { className }, (title || description) && /* @__PURE__ */ React7.createElement("div", { className: "mb-6" }, title && /* @__PURE__ */ React7.createElement("h3", { className: "text-lg font-semibold text-gray-900 mb-2" }, title), description && /* @__PURE__ */ React7.createElement("p", { className: "text-sm text-gray-600" }, description)), /* @__PURE__ */ React7.createElement("div", { className: "space-y-4" }, fields.map((fieldConfig, index) => /* @__PURE__ */ React7.createElement(
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 React8 from "react";
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
- const defaultValues = fieldConfigs.reduce((acc, fieldConfig) => {
464
- const fieldName = fieldConfig.name;
465
- if (fieldConfig.type === "checkbox" || fieldConfig.type === "switch") {
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((fieldConfig) => {
499
- const fieldName = fieldConfig.name;
500
- const fullPath = `${name}.${index}.${fieldName}`;
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__ */ React8.createElement(React8.Fragment, { key: field2.id }, renderItem({
642
+ return /* @__PURE__ */ React9.createElement(React9.Fragment, { key: field2.id }, renderItem({
532
643
  canMoveDown,
533
644
  canMoveUp,
534
645
  canRemove: itemCanRemove,
535
- children: /* @__PURE__ */ React8.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, fieldElements),
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__ */ React8.createElement(
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__ */ React8.createElement("div", { className: "flex justify-between items-center" }, /* @__PURE__ */ React8.createElement("h4", { className: "text-sm font-medium text-gray-700" }, config.label, " #", index + 1), /* @__PURE__ */ React8.createElement("div", { className: "flex gap-2" }, enableReordering && /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(
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__ */ React8.createElement(
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__ */ React8.createElement(
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__ */ React8.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, fieldElements)
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__ */ React8.createElement(
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__ */ React8.createElement("div", { className }, /* @__PURE__ */ React8.createElement("div", { className: "space-y-4" }, fields.length > 0 ? renderFieldArrayItems() : /* @__PURE__ */ React8.createElement("div", { className: "text-center py-8 text-gray-500" }, /* @__PURE__ */ React8.createElement("p", null, "No ", config.label?.toLowerCase(), " added yet."), renderAddButtonElement()), fields.length > 0 && renderAddButtonElement()));
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 React9 from "react";
612
- import { Controller as Controller4 } from "react-hook-form";
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__ */ React9.createElement(
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__ */ React9.createElement(
662
- Controller4,
776
+ return /* @__PURE__ */ React10.createElement(
777
+ Controller5,
663
778
  {
664
779
  control,
665
780
  name,
666
- render: ({ field: field2, fieldState }) => /* @__PURE__ */ React9.createElement("div", { className }, /* @__PURE__ */ React9.createElement(
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 React10 from "react";
689
- import { Controller as Controller5 } from "react-hook-form";
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] = React10.useState({
820
+ const [fontPickerState, setFontPickerState] = React11.useState({
706
821
  component: FontPickerComponent,
707
822
  error: null,
708
823
  loading: false
709
824
  });
710
- React10.useEffect(() => {
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__ */ React10.createElement("div", { className }, /* @__PURE__ */ React10.createElement("div", { className: "space-y-2" }, label && /* @__PURE__ */ React10.createElement("label", { className: "block text-sm font-medium text-foreground" }, label), description && /* @__PURE__ */ React10.createElement("p", { className: "text-sm text-muted-foreground" }, description), /* @__PURE__ */ React10.createElement("div", { className: "p-4 border border-default-200 bg-default-50 rounded-medium" }, /* @__PURE__ */ React10.createElement("p", { className: "text-default-600 text-sm" }, "Loading font picker..."))));
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__ */ React10.createElement("div", { className }, /* @__PURE__ */ React10.createElement("div", { className: "space-y-2" }, label && /* @__PURE__ */ React10.createElement("label", { className: "block text-sm font-medium text-foreground" }, label), description && /* @__PURE__ */ React10.createElement("p", { className: "text-sm text-muted-foreground" }, description), /* @__PURE__ */ React10.createElement("div", { className: "p-4 border border-warning-200 bg-warning-50 rounded-medium" }, /* @__PURE__ */ React10.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."))));
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__ */ React10.createElement(
774
- Controller5,
888
+ return /* @__PURE__ */ React11.createElement(
889
+ Controller6,
775
890
  {
776
891
  control,
777
892
  name,
778
- render: ({ field: field2, fieldState }) => /* @__PURE__ */ React10.createElement(
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 React11 from "react";
798
- import { Controller as Controller6 } from "react-hook-form";
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__ */ React11.createElement(
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 = React11.memo(
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__ */ React11.createElement(
832
- Controller6,
947
+ return /* @__PURE__ */ React12.createElement(
948
+ Controller7,
833
949
  {
834
950
  control,
835
951
  name,
836
- render: ({ field: field2, fieldState }) => /* @__PURE__ */ React11.createElement("div", { className }, /* @__PURE__ */ React11.createElement(
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 React12 from "react";
867
- import { Controller as Controller7 } from "react-hook-form";
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__ */ React12.createElement(
882
- Controller7,
997
+ return /* @__PURE__ */ React13.createElement(
998
+ Controller8,
883
999
  {
884
1000
  control,
885
1001
  name,
886
- render: ({ field: field2, fieldState }) => /* @__PURE__ */ React12.createElement("div", { className }, /* @__PURE__ */ React12.createElement(
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__ */ React12.createElement(
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__ */ React12.createElement("p", { className: "text-tiny text-danger mt-1" }, fieldState.error.message) : null),
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 React13 from "react";
916
- import { Controller as Controller8 } from "react-hook-form";
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__ */ React13.createElement(
932
- Controller8,
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__ */ React13.createElement("div", { className }, /* @__PURE__ */ React13.createElement(
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__ */ React13.createElement(
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 React14 from "react";
974
- import { Controller as Controller9 } from "react-hook-form";
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__ */ React14.createElement(
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__ */ React14.createElement(
1007
- Controller9,
1125
+ return /* @__PURE__ */ React15.createElement(
1126
+ Controller10,
1008
1127
  {
1009
1128
  control,
1010
1129
  name,
1011
- render: ({ field: field2, fieldState }) => /* @__PURE__ */ React14.createElement("div", { className }, /* @__PURE__ */ React14.createElement(
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 React15 from "react";
1032
- import { Controller as Controller10 } from "react-hook-form";
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__ */ React15.createElement(
1046
- Controller10,
1278
+ return /* @__PURE__ */ React17.createElement(
1279
+ Controller12,
1047
1280
  {
1048
1281
  control,
1049
1282
  name,
1050
- render: ({ field: field2, fieldState }) => /* @__PURE__ */ React15.createElement("div", { className }, /* @__PURE__ */ React15.createElement(
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__ */ React15.createElement("p", { className: "text-small text-default-400" }, description) : null, fieldState.error?.message ? /* @__PURE__ */ React15.createElement("p", { className: "text-tiny text-danger mt-1" }, fieldState.error.message) : null),
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 React16 from "react";
1069
- import { Controller as Controller11 } from "react-hook-form";
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__ */ React16.createElement(
1083
- Controller11,
1316
+ return /* @__PURE__ */ React18.createElement(
1317
+ Controller13,
1084
1318
  {
1085
1319
  control,
1086
1320
  name,
1087
- render: ({ field: field2, fieldState }) => /* @__PURE__ */ React16.createElement("div", { className }, /* @__PURE__ */ React16.createElement(
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
- var FormField = React17.memo(
1109
- ({
1110
- config,
1111
- form,
1112
- submissionState
1113
- }) => {
1114
- if (!form || !form.control) {
1115
- return null;
1116
- }
1117
- const { control } = form;
1118
- const watchedValues = useWatch3({ control });
1119
- if (config.type === "content") {
1120
- return /* @__PURE__ */ React17.createElement(
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
- if (config.condition && !config.condition(watchedValues)) {
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
- if (config.dependsOn) {
1133
- const dependentValue = get(watchedValues, config.dependsOn);
1134
- if (config.dependsOnValue !== void 0 && dependentValue !== config.dependsOnValue) {
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
- const baseProps = {
1139
- ariaDescribedBy: config.ariaDescribedBy,
1140
- ariaLabel: config.ariaLabel,
1141
- className: config.className,
1142
- description: config.description,
1143
- isDisabled: config.isDisabled ?? submissionState.isSubmitting,
1144
- label: config.label,
1145
- name: config.name,
1146
- rules: config.rules
1147
- };
1148
- switch (config.type) {
1149
- case "input":
1150
- return /* @__PURE__ */ React17.createElement(
1151
- InputField,
1152
- {
1153
- ...baseProps,
1154
- control,
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
- errors: form.formState.errors,
1277
- form,
1278
- isSubmitting: submissionState.isSubmitting,
1279
- name: config.name
1280
- });
1281
- case "conditional":
1282
- return /* @__PURE__ */ React17.createElement(
1283
- ConditionalField,
1284
- {
1285
- config,
1286
- control,
1287
- className: config.className
1288
- }
1289
- );
1290
- case "fieldArray":
1291
- return /* @__PURE__ */ React17.createElement(
1292
- FieldArrayField,
1293
- {
1294
- config,
1295
- className: config.className
1296
- }
1297
- );
1298
- case "dynamicSection":
1299
- return /* @__PURE__ */ React17.createElement(
1300
- DynamicSectionField,
1301
- {
1302
- config,
1303
- control,
1304
- className: config.className
1305
- }
1306
- );
1307
- default: {
1308
- const fieldType = config.type;
1309
- console.warn(`Unknown field type: ${fieldType}`);
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__ */ React18.createElement(
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__ */ React18.createElement(
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__ */ React18.createElement("div", { className: `grid gap-${spacing} grid-cols-1 md:grid-cols-2` }, fields.map((field2) => /* @__PURE__ */ React18.createElement(
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__ */ React18.createElement("div", { className: `space-y-${spacing}` }, fields.map((field2) => /* @__PURE__ */ React18.createElement(
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__ */ React18.createElement("form", { className, role: "form", onSubmit: handleFormSubmit }, title && /* @__PURE__ */ React18.createElement("div", { className: "mb-6" }, /* @__PURE__ */ React18.createElement("h2", { className: "text-xl font-semibold text-foreground mb-2" }, title), subtitle && /* @__PURE__ */ React18.createElement("p", { className: "text-sm text-muted-foreground" }, subtitle)), isSubmitted && isSuccess && /* @__PURE__ */ React18.createElement(
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__ */ React18.createElement("p", { className: "text-success-800 font-medium" }, "Success!"),
1399
- /* @__PURE__ */ React18.createElement("p", { className: "text-success-700 text-sm mt-1" }, "Your request has been processed successfully.")
1400
- ), error && /* @__PURE__ */ React18.createElement(
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__ */ React18.createElement("p", { className: "text-danger-800 font-medium" }, "Error"),
1407
- /* @__PURE__ */ React18.createElement("p", { className: "text-danger-700 text-sm mt-1" }, error)
1408
- ), renderFields(), /* @__PURE__ */ React18.createElement("div", { className: "mt-6 flex gap-3 justify-end" }, /* @__PURE__ */ React18.createElement(
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__ */ React18.createElement(
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 React19 from "react";
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 = React19.useRef(null);
1457
- const [clientErrors, setClientErrors] = React19.useState({});
1458
- const lastSubmittedFormData = React19.useRef(null);
1459
- React19.useEffect(() => {
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
- React19.useEffect(() => {
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
- if (val === "on") {
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__ */ React19.createElement(
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__ */ React19.createElement(
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__ */ React19.createElement("div", { className: `grid gap-${spacing} grid-cols-1 md:grid-cols-2` }, fields.map((field2) => /* @__PURE__ */ React19.createElement(
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__ */ React19.createElement("div", { className: `space-y-${spacing}` }, fields.map((field2) => /* @__PURE__ */ React19.createElement(
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__ */ React19.createElement(
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__ */ React19.createElement("div", { className: "mb-6" }, /* @__PURE__ */ React19.createElement("h2", { className: "text-xl font-semibold text-foreground mb-2" }, title), subtitle && /* @__PURE__ */ React19.createElement("p", { className: "text-sm text-muted-foreground" }, subtitle)),
1559
- state?.success && !pending && /* @__PURE__ */ React19.createElement(
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__ */ React19.createElement("p", { className: "text-success-800 font-medium" }, "Success!"),
1566
- state.message && /* @__PURE__ */ React19.createElement("p", { className: "text-success-700 text-sm mt-1" }, state.message)
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__ */ React19.createElement(
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__ */ React19.createElement("p", { className: "text-danger-800 font-medium" }, "Error"),
1575
- /* @__PURE__ */ React19.createElement("p", { className: "text-danger-700 text-sm mt-1" }, state.message)
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__ */ React19.createElement("div", { className: "mt-6 flex gap-3 justify-end" }, /* @__PURE__ */ React19.createElement(
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__ */ React19.createElement(
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
- if (field2.type === "content") {
1607
- const contentField2 = field2;
1608
- if (contentField2.render) {
1609
- return /* @__PURE__ */ React19.createElement("div", { className: contentField2.className }, contentField2.render({
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: null,
1973
+ form: mockForm,
1612
1974
  isSubmitting: false
1613
1975
  }));
1614
1976
  }
1615
- return /* @__PURE__ */ React19.createElement("div", { className: contentField2.className }, contentField2.title && /* @__PURE__ */ React19.createElement("h3", { className: "text-lg font-semibold text-foreground mb-2" }, contentField2.title), contentField2.description && /* @__PURE__ */ React19.createElement("p", { className: "text-sm text-muted-foreground" }, contentField2.description));
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 = field2.name;
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 = field2.defaultValue;
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 = field2.defaultValue;
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] = React19.useState(getDefaultValue);
1644
- const [checked, setChecked] = React19.useState(getDefaultChecked);
1645
- React19.useEffect(() => {
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 (field2.type === "checkbox") {
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, field2.type]);
1659
- React19.useEffect(() => {
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
- if (field2.type === "checkbox") {
1665
- hiddenInput.value = checked ? "on" : "";
1666
- } else {
1667
- hiddenInput.value = value;
1668
- }
2035
+ hiddenInput.value = value || "";
1669
2036
  }
1670
- }, [value, checked, fieldName, field2.type]);
1671
- switch (field2.type) {
2037
+ }, [value, fieldName, fieldConfig.type]);
2038
+ switch (fieldConfig.type) {
1672
2039
  case "input": {
1673
- const inputType = field2.inputProps?.type || "text";
1674
- return /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("input", { type: "hidden", name: fieldName, value }), /* @__PURE__ */ React19.createElement(
2040
+ const stringConfig = fieldConfig;
2041
+ const inputType = stringConfig.inputProps?.type || "text";
2042
+ return /* @__PURE__ */ React21.createElement(
1675
2043
  Input,
1676
2044
  {
1677
- ...field2.inputProps,
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
- type: inputType,
1680
- label: field2.label,
1681
- description: field2.description,
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 "textarea": {
1691
- return /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("input", { type: "hidden", name: fieldName, value }), /* @__PURE__ */ React19.createElement(
1692
- Textarea,
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
- ...field2.textareaProps,
2221
+ ...stringConfig.autocompleteProps,
2222
+ name: fieldName,
1695
2223
  "data-field-name": fieldName,
1696
- label: field2.label,
1697
- description: field2.description,
1698
- isDisabled: field2.isDisabled,
2224
+ label: baseProps.label,
2225
+ description: baseProps.description,
2226
+ isDisabled: baseProps.isDisabled,
1699
2227
  isInvalid: Boolean(errorMessage),
1700
2228
  errorMessage,
1701
- value,
1702
- onValueChange: setValue
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 "checkbox": {
1707
- return /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("input", { type: "hidden", name: fieldName, value: checked ? "on" : "" }), /* @__PURE__ */ React19.createElement(
1708
- Checkbox,
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
- ...field2.checkboxProps,
2265
+ ...dateConfig.dateProps,
1711
2266
  "data-field-name": fieldName,
1712
- isDisabled: field2.isDisabled,
1713
- isSelected: checked,
1714
- onValueChange: setChecked,
2267
+ label: baseProps.label,
2268
+ description: baseProps.description,
2269
+ isDisabled: baseProps.isDisabled,
1715
2270
  isInvalid: Boolean(errorMessage),
1716
- errorMessage
1717
- },
1718
- field2.label
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 "select": {
1722
- const options = field2.options || [];
1723
- return /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("input", { type: "hidden", name: fieldName, value }), /* @__PURE__ */ React19.createElement(
1724
- Select,
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
- ...field2.selectProps,
2287
+ ...fileConfig.fileProps,
2288
+ name: fieldName,
1727
2289
  "data-field-name": fieldName,
1728
- label: field2.label,
1729
- description: field2.description,
1730
- isDisabled: field2.isDisabled,
2290
+ type: "file",
2291
+ label: baseProps.label,
2292
+ description: baseProps.description,
2293
+ isDisabled: baseProps.isDisabled,
1731
2294
  isInvalid: Boolean(errorMessage),
1732
2295
  errorMessage,
1733
- selectedKeys: value ? [value] : [],
1734
- onSelectionChange: (keys) => {
1735
- const selectedValue = Array.from(keys)[0];
1736
- setValue(selectedValue || "");
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__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("input", { type: "hidden", name: fieldName, value }), /* @__PURE__ */ React19.createElement(
2311
+ return /* @__PURE__ */ React21.createElement(
1746
2312
  Input,
1747
2313
  {
2314
+ name: fieldName,
1748
2315
  "data-field-name": fieldName,
1749
- label: field2.label,
1750
- description: field2.description,
1751
- isDisabled: field2.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 React20 from "react";
2342
+ import React22 from "react";
1776
2343
  import { FormProvider as RHFProvider } from "react-hook-form";
1777
2344
  function FormProvider(props) {
1778
- return /* @__PURE__ */ React20.createElement(RHFProvider, { ...props.methods }, /* @__PURE__ */ React20.createElement(
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 React21 from "react";
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__ */ React21.createElement("span", { className: "inline-flex items-center gap-2" }, "\u2705", props.successText || "Success!");
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__ */ React21.createElement("span", { className: "inline-flex items-center gap-2" }, "\u23F3", props.loadingText || "Submitting...");
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__ */ React21.createElement(
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 React23 from "react";
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
- errors,
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 useState2 } from "react";
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] = useState2("idle");
2121
- const [error, setError] = useState2(void 0);
2122
- const [submittedData, setSubmittedData] = useState2(void 0);
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 React22 from "react";
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__ */ React22.createElement(
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__ */ React22.createElement("span", { className: "text-blue-600" }, "\u23F3"),
2200
- /* @__PURE__ */ React22.createElement("div", null, /* @__PURE__ */ React22.createElement("p", { className: "text-sm font-medium text-blue-900" }, "Submitting form..."), showDetails && /* @__PURE__ */ React22.createElement("p", { className: "text-xs text-blue-700" }, "Please wait while we process your request."))
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__ */ React22.createElement(
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__ */ React22.createElement("span", { className: "text-green-600" }, "\u2705"),
2211
- /* @__PURE__ */ React22.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React22.createElement("p", { className: "text-sm font-medium text-green-900" }, "Form submitted successfully!"), showDetails && submittedData && /* @__PURE__ */ React22.createElement("p", { className: "text-xs text-green-700" }, "Your data has been saved. Thank you for your submission.")),
2212
- onDismiss && /* @__PURE__ */ React22.createElement(
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__ */ React22.createElement(
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__ */ React22.createElement("span", { className: "text-red-600" }, "\u26A0\uFE0F"),
2233
- /* @__PURE__ */ React22.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React22.createElement("p", { className: "text-sm font-medium text-red-900" }, "Error submitting form"), /* @__PURE__ */ React22.createElement("p", { className: "text-xs text-red-700" }, error)),
2234
- onDismiss && /* @__PURE__ */ React22.createElement(
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] = React22.useState(false);
2256
- React22.useEffect(() => {
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__ */ React22.createElement("div", { className: `fixed z-50 ${positionClasses[position]}` }, /* @__PURE__ */ React22.createElement(FormStatus, { state, onDismiss }));
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 form = useZodForm(config);
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__ */ React23.createElement(
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__ */ React23.createElement(
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__ */ React23.createElement("div", { className: `grid gap-${spacing} grid-cols-1 md:grid-cols-2` }, config.fields.map((field2) => /* @__PURE__ */ React23.createElement(
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__ */ React23.createElement("div", { className: `space-y-${spacing}` }, config.fields.map((field2) => /* @__PURE__ */ React23.createElement(
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
- React23.useEffect(() => {
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__ */ React23.createElement(FormProvider2, { ...form }, /* @__PURE__ */ React23.createElement("form", { className, role: "form", onSubmit: handleFormSubmit }, title && /* @__PURE__ */ React23.createElement("div", { className: "mb-6" }, /* @__PURE__ */ React23.createElement("h2", { className: "text-xl font-semibold text-foreground mb-2" }, title), subtitle && /* @__PURE__ */ React23.createElement("p", { className: "text-sm text-muted-foreground" }, subtitle)), /* @__PURE__ */ React23.createElement(
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__ */ React23.createElement("div", { className: "mt-6 flex gap-3 justify-end" }, /* @__PURE__ */ React23.createElement(
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__ */ React23.createElement(
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 React24 from "react";
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__ */ React24.createElement(
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
- return {
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
- return {
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 full customization
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: (name, label, type, inputProps) => ({
2756
- inputProps: {
2757
- type: type || "text",
2758
- ...inputProps
2759
- },
2760
- label,
2761
- name,
2762
- type: "input"
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 inputField(name, label, props) {
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 textareaField(name, label, props) {
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 selectField(name, label, options) {
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 checkboxField(name, label, props) {
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 switchField(name, label, props) {
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 radioField(name, label, options, props) {
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 sliderField(name, label, props) {
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 dateField(name, label, props) {
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
- ...props && {
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 fileField(name, label, props) {
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 fontPickerField(name, label, props) {
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 contentField(title, description, options) {
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: options?.className,
3077
- description: description || void 0,
3078
- name: options?.name,
3079
- render: options?.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 createField(type, name, label, optionsOrProps, props) {
3085
- switch (type) {
3822
+ function createFieldFromParams(params) {
3823
+ switch (params.type) {
3086
3824
  case "input":
3087
- return inputField(name, label, optionsOrProps);
3825
+ return createInputField(params.name, params.label, params.props);
3088
3826
  case "textarea":
3089
- return textareaField(name, label, optionsOrProps);
3827
+ return createTextareaField(params.name, params.label, params.props);
3090
3828
  case "select":
3091
- return selectField(name, label, optionsOrProps);
3829
+ return createSelectField(params.name, params.label, params.options);
3092
3830
  case "checkbox":
3093
- return checkboxField(name, label, optionsOrProps);
3831
+ return createCheckboxField(params.name, params.label, params.props);
3094
3832
  case "switch":
3095
- return switchField(name, label, optionsOrProps);
3833
+ return createSwitchField(params.name, params.label, params.props);
3096
3834
  case "radio":
3097
- return radioField(name, label, optionsOrProps, props);
3835
+ return createRadioField(
3836
+ params.name,
3837
+ params.label,
3838
+ params.options,
3839
+ params.props
3840
+ );
3098
3841
  case "slider":
3099
- return sliderField(name, label, optionsOrProps);
3842
+ return createSliderField(params.name, params.label, params.props);
3100
3843
  case "date":
3101
- return dateField(name, label, optionsOrProps);
3844
+ return createDateField(params.name, params.label, params.props);
3102
3845
  case "file":
3103
- return fileField(name, label, optionsOrProps);
3846
+ return createFileField(params.name, params.label, params.props);
3104
3847
  case "fontPicker":
3105
- return fontPickerField(name, label, optionsOrProps);
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
- if (typeof optionsOrProps === "string" || optionsOrProps === null) {
3108
- return contentField(optionsOrProps, props);
3109
- }
3110
- if (typeof optionsOrProps === "object" && optionsOrProps !== null) {
3111
- return contentField(
3112
- optionsOrProps.title,
3113
- optionsOrProps.description,
3114
- optionsOrProps
3115
- );
3116
- }
3117
- return contentField(
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
- field(type, name, label, optionsOrProps, props) {
3131
- this.fields.push(createField(type, name, label, optionsOrProps, props));
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
- this.fields.push({
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
- this.fields.push({
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
- this.fields.push({
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
- field(type, name, label, optionsOrProps, props) {
3188
- this.fields.push(createField(type, name, label, optionsOrProps, props));
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(type, name, label, optionsOrProps, props) {
3207
- const fullPath = `${this.arrayName}.${name}`;
3208
- const fieldConfig = createField(
3209
- type,
3210
- fullPath,
3211
- label,
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
- ...fieldOptions
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(name, label, type = "input", props) {
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(["user", "profile", "name"], "Full Name")
4290
+ * Usage: builder.fieldPath({ type: "input", name: path.join("."), label: "Full Name" })
3529
4291
  */
3530
- fieldPath(path, label, type = "input", props) {
3531
- const name = path.join(".");
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(fieldName, label, type = "input", props) {
3567
- const fullPath = `${this.path}.${fieldName}`;
3568
- this.parent.fields.push({
3569
- label,
3570
- name: fullPath,
3571
- type,
3572
- ...props
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
- `${this.path}.${subPath}`
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(fieldName, label, type = "input", props) {
3601
- const fullPath = `${this.path}.${fieldName}`;
3602
- this.parent.fields.push({
3603
- label,
3604
- name: fullPath,
3605
- type,
3606
- ...props
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.field(field2.name, field2.label, field2.type, field2.props);
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
- `${this.path}.${subPath}`
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(label, type = "input", props) {
3644
- this.parent.fields.push({
3645
- label,
3646
- name: this.path,
3647
- type,
3648
- ...props
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 useRef2 } from "react";
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 = useRef2(callback);
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 = useRef2(0);
3830
- const lastRenderTimeRef = useRef2(Date.now());
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 React25 from "react";
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 compatible with Path for CustomFieldConfig
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__ */ React25.createElement("div", { className }, /* @__PURE__ */ React25.createElement("div", { className: "space-y-4" }, fields.map((field2, index) => {
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__ */ React25.createElement(React25.Fragment, { key: field2.id }, renderItem({
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__ */ React25.createElement("div", { className: "text-center py-8 text-gray-500" }, /* @__PURE__ */ React25.createElement("p", null, "No ", label?.toLowerCase() || "items", " added yet."), renderAddButton({ canAdd, onAdd: handleAdd })) : null, fields.length > 0 && renderAddButton ? renderAddButton({ canAdd, onAdd: handleAdd }) : canAdd && /* @__PURE__ */ React25.createElement(
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,