@rachelallyson/hero-hook-form 2.6.0 → 2.7.2

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