@rachelallyson/hero-hook-form 1.2.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,13 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
1
8
  // src/components/Form.tsx
2
- import React13 from "react";
3
- import { Button as Button2 } from "@heroui/react";
9
+ import React16 from "react";
10
+ import { Button as Button3 } from "@heroui/react";
4
11
 
5
12
  // src/hooks/useFormHelper.ts
6
13
  import { useState } from "react";
@@ -68,8 +75,8 @@ function useFormHelper({
68
75
  }
69
76
 
70
77
  // src/components/FormField.tsx
71
- import React12 from "react";
72
- import { useWatch } from "react-hook-form";
78
+ import React15 from "react";
79
+ import { useWatch as useWatch3 } from "react-hook-form";
73
80
 
74
81
  // src/fields/CheckboxField.tsx
75
82
  import React2 from "react";
@@ -191,16 +198,16 @@ function CheckboxField(props) {
191
198
  {
192
199
  control,
193
200
  name,
194
- render: ({ field, fieldState }) => /* @__PURE__ */ React2.createElement("div", { className }, /* @__PURE__ */ React2.createElement(
201
+ render: ({ field: field2, fieldState }) => /* @__PURE__ */ React2.createElement("div", { className }, /* @__PURE__ */ React2.createElement(
195
202
  Checkbox,
196
203
  {
197
204
  ...defaults.checkbox,
198
205
  ...checkboxProps,
199
206
  isDisabled,
200
207
  isInvalid: Boolean(fieldState.error),
201
- isSelected: Boolean(field.value),
202
- onBlur: field.onBlur,
203
- onValueChange: (val) => field.onChange(val)
208
+ isSelected: Boolean(field2.value),
209
+ onBlur: field2.onBlur,
210
+ onValueChange: (val) => field2.onChange(val)
204
211
  },
205
212
  label
206
213
  ), description ? /* @__PURE__ */ React2.createElement("p", { className: "text-small text-default-400" }, description) : null, fieldState.error?.message ? /* @__PURE__ */ React2.createElement("p", { className: "text-tiny text-danger mt-1" }, fieldState.error.message) : null),
@@ -209,13 +216,43 @@ function CheckboxField(props) {
209
216
  );
210
217
  }
211
218
 
212
- // src/fields/DateField.tsx
219
+ // src/fields/ConditionalField.tsx
213
220
  import React3 from "react";
221
+ import { useWatch, useFormContext } from "react-hook-form";
222
+ function ConditionalField({
223
+ config,
224
+ control,
225
+ className
226
+ }) {
227
+ const { condition, field: field2, name } = config;
228
+ const form = useFormContext();
229
+ const formValues = useWatch({ control });
230
+ const shouldShow = condition(formValues);
231
+ if (!shouldShow) {
232
+ return null;
233
+ }
234
+ return /* @__PURE__ */ React3.createElement("div", { className }, /* @__PURE__ */ React3.createElement(
235
+ FormField,
236
+ {
237
+ config: field2,
238
+ form,
239
+ submissionState: {
240
+ isSubmitting: false,
241
+ isSubmitted: false,
242
+ isSuccess: false,
243
+ error: void 0
244
+ }
245
+ }
246
+ ));
247
+ }
248
+
249
+ // src/fields/DateField.tsx
250
+ import React4 from "react";
214
251
  import { Controller as Controller2 } from "react-hook-form";
215
252
  function CoercedDateInput(props) {
216
- const { dateProps, description, disabled, errorMessage, field, label } = props;
253
+ const { dateProps, description, disabled, errorMessage, field: field2, label } = props;
217
254
  const defaults = useHeroHookFormDefaults();
218
- return /* @__PURE__ */ React3.createElement(
255
+ return /* @__PURE__ */ React4.createElement(
219
256
  DateInput,
220
257
  {
221
258
  ...defaults.dateInput,
@@ -225,9 +262,9 @@ function CoercedDateInput(props) {
225
262
  isDisabled: disabled,
226
263
  isInvalid: Boolean(errorMessage),
227
264
  label,
228
- value: field.value ?? null,
229
- onBlur: field.onBlur,
230
- onChange: field.onChange
265
+ value: field2.value ?? null,
266
+ onBlur: field2.onBlur,
267
+ onChange: field2.onChange
231
268
  }
232
269
  );
233
270
  }
@@ -243,12 +280,12 @@ function DateField(props) {
243
280
  rules,
244
281
  transform
245
282
  } = props;
246
- return /* @__PURE__ */ React3.createElement(
283
+ return /* @__PURE__ */ React4.createElement(
247
284
  Controller2,
248
285
  {
249
286
  control,
250
287
  name,
251
- render: ({ field, fieldState }) => /* @__PURE__ */ React3.createElement("div", { className }, /* @__PURE__ */ React3.createElement(
288
+ render: ({ field: field2, fieldState }) => /* @__PURE__ */ React4.createElement("div", { className }, /* @__PURE__ */ React4.createElement(
252
289
  CoercedDateInput,
253
290
  {
254
291
  dateProps,
@@ -256,8 +293,8 @@ function DateField(props) {
256
293
  disabled: isDisabled,
257
294
  errorMessage: fieldState.error?.message,
258
295
  field: {
259
- ...field,
260
- onChange: (value) => field.onChange(transform ? transform(value) : value)
296
+ ...field2,
297
+ onChange: (value) => field2.onChange(transform ? transform(value) : value)
261
298
  },
262
299
  label
263
300
  }
@@ -267,8 +304,136 @@ function DateField(props) {
267
304
  );
268
305
  }
269
306
 
307
+ // src/fields/DynamicSectionField.tsx
308
+ import React5 from "react";
309
+ import { useWatch as useWatch2, useFormContext as useFormContext2 } from "react-hook-form";
310
+ function DynamicSectionField({
311
+ config,
312
+ control,
313
+ className
314
+ }) {
315
+ const { condition, fields, title, description } = config;
316
+ const form = useFormContext2();
317
+ const formValues = useWatch2({ control });
318
+ const shouldShow = condition(formValues);
319
+ if (!shouldShow) {
320
+ return null;
321
+ }
322
+ return /* @__PURE__ */ React5.createElement("div", { className }, (title || description) && /* @__PURE__ */ React5.createElement("div", { className: "mb-6" }, title && /* @__PURE__ */ React5.createElement("h3", { className: "text-lg font-semibold text-gray-900 mb-2" }, title), description && /* @__PURE__ */ React5.createElement("p", { className: "text-sm text-gray-600" }, description)), /* @__PURE__ */ React5.createElement("div", { className: "space-y-4" }, fields.map((fieldConfig, index) => /* @__PURE__ */ React5.createElement(
323
+ FormField,
324
+ {
325
+ key: `${fieldConfig.name}-${index}`,
326
+ config: fieldConfig,
327
+ form,
328
+ submissionState: {
329
+ isSubmitting: false,
330
+ isSubmitted: false,
331
+ isSuccess: false,
332
+ error: void 0
333
+ }
334
+ }
335
+ ))));
336
+ }
337
+
338
+ // src/fields/FieldArrayField.tsx
339
+ import React6 from "react";
340
+ import { useFieldArray, useFormContext as useFormContext3 } from "react-hook-form";
341
+ import { Button as Button2 } from "@heroui/react";
342
+ function FieldArrayField({
343
+ config,
344
+ className
345
+ }) {
346
+ const {
347
+ name,
348
+ fields: fieldConfigs,
349
+ min = 0,
350
+ max = 10,
351
+ addButtonText = "Add Item",
352
+ removeButtonText = "Remove"
353
+ } = config;
354
+ const form = useFormContext3();
355
+ if (!form || !form.control) {
356
+ return null;
357
+ }
358
+ const { control } = form;
359
+ const { fields, append, remove } = useFieldArray({
360
+ control,
361
+ name
362
+ // FieldArray name
363
+ });
364
+ const canAdd = fields.length < max;
365
+ const canRemove = fields.length > min;
366
+ const handleAdd = () => {
367
+ if (canAdd) {
368
+ const defaultValues = fieldConfigs.reduce((acc, fieldConfig) => {
369
+ const fieldName = fieldConfig.name;
370
+ if (fieldConfig.type === "checkbox" || fieldConfig.type === "switch") {
371
+ acc[fieldName] = false;
372
+ } else if (fieldConfig.type === "slider") {
373
+ acc[fieldName] = 0;
374
+ } else {
375
+ acc[fieldName] = "";
376
+ }
377
+ return acc;
378
+ }, {});
379
+ append(defaultValues);
380
+ }
381
+ };
382
+ const handleRemove = (index) => {
383
+ if (canRemove) {
384
+ remove(index);
385
+ }
386
+ };
387
+ return /* @__PURE__ */ React6.createElement("div", { className }, /* @__PURE__ */ React6.createElement("div", { className: "space-y-4" }, fields.map((field2, index) => /* @__PURE__ */ React6.createElement("div", { key: field2.id, className: "border border-gray-200 rounded-lg p-4 space-y-4" }, /* @__PURE__ */ React6.createElement("div", { className: "flex justify-between items-center" }, /* @__PURE__ */ React6.createElement("h4", { className: "text-sm font-medium text-gray-700" }, config.label, " #", index + 1), canRemove && /* @__PURE__ */ React6.createElement(
388
+ Button2,
389
+ {
390
+ size: "sm",
391
+ variant: "light",
392
+ color: "danger",
393
+ startContent: "\u{1F5D1}\uFE0F",
394
+ onPress: () => handleRemove(index),
395
+ "aria-label": `${removeButtonText} ${config.label} ${index + 1}`
396
+ },
397
+ removeButtonText
398
+ )), /* @__PURE__ */ React6.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4" }, fieldConfigs.map((fieldConfig) => /* @__PURE__ */ React6.createElement(
399
+ FormField,
400
+ {
401
+ key: `${fieldConfig.name}-${index}`,
402
+ config: {
403
+ ...fieldConfig,
404
+ name: `${name}.${index}.${fieldConfig.name}`
405
+ },
406
+ form,
407
+ submissionState: {
408
+ isSubmitting: false,
409
+ isSubmitted: false,
410
+ isSuccess: false,
411
+ error: void 0
412
+ }
413
+ }
414
+ ))))), canAdd && /* @__PURE__ */ React6.createElement(
415
+ Button2,
416
+ {
417
+ variant: "bordered",
418
+ startContent: "\u2795",
419
+ onPress: handleAdd,
420
+ className: "w-full"
421
+ },
422
+ addButtonText
423
+ ), fields.length === 0 && /* @__PURE__ */ React6.createElement("div", { className: "text-center py-8 text-gray-500" }, /* @__PURE__ */ React6.createElement("p", null, "No ", config.label?.toLowerCase(), " added yet."), /* @__PURE__ */ React6.createElement(
424
+ Button2,
425
+ {
426
+ variant: "bordered",
427
+ startContent: "\u2795",
428
+ onPress: handleAdd,
429
+ className: "mt-2"
430
+ },
431
+ addButtonText
432
+ ))));
433
+ }
434
+
270
435
  // src/fields/FileField.tsx
271
- import React4 from "react";
436
+ import React7 from "react";
272
437
  import { Controller as Controller3 } from "react-hook-form";
273
438
  function CoercedFileInput(props) {
274
439
  const {
@@ -276,13 +441,13 @@ function CoercedFileInput(props) {
276
441
  description,
277
442
  disabled,
278
443
  errorMessage,
279
- field,
444
+ field: field2,
280
445
  fileProps,
281
446
  label,
282
447
  multiple
283
448
  } = props;
284
449
  const defaults = useHeroHookFormDefaults();
285
- return /* @__PURE__ */ React4.createElement(
450
+ return /* @__PURE__ */ React7.createElement(
286
451
  Input,
287
452
  {
288
453
  ...defaults.input,
@@ -295,11 +460,11 @@ function CoercedFileInput(props) {
295
460
  label,
296
461
  multiple,
297
462
  type: "file",
298
- value: field.value ? "" : "",
299
- onBlur: field.onBlur,
463
+ value: field2.value ? "" : "",
464
+ onBlur: field2.onBlur,
300
465
  onChange: (e) => {
301
466
  const target = e.target;
302
- field.onChange(target.files);
467
+ field2.onChange(target.files);
303
468
  }
304
469
  }
305
470
  );
@@ -318,12 +483,12 @@ function FileField(props) {
318
483
  rules,
319
484
  transform
320
485
  } = props;
321
- return /* @__PURE__ */ React4.createElement(
486
+ return /* @__PURE__ */ React7.createElement(
322
487
  Controller3,
323
488
  {
324
489
  control,
325
490
  name,
326
- render: ({ field, fieldState }) => /* @__PURE__ */ React4.createElement("div", { className }, /* @__PURE__ */ React4.createElement(
491
+ render: ({ field: field2, fieldState }) => /* @__PURE__ */ React7.createElement("div", { className }, /* @__PURE__ */ React7.createElement(
327
492
  CoercedFileInput,
328
493
  {
329
494
  accept,
@@ -331,8 +496,8 @@ function FileField(props) {
331
496
  disabled: isDisabled,
332
497
  errorMessage: fieldState.error?.message,
333
498
  field: {
334
- ...field,
335
- onChange: (value) => field.onChange(transform ? transform(value) : value)
499
+ ...field2,
500
+ onChange: (value) => field2.onChange(transform ? transform(value) : value)
336
501
  },
337
502
  fileProps,
338
503
  label,
@@ -345,7 +510,7 @@ function FileField(props) {
345
510
  }
346
511
 
347
512
  // src/fields/FontPickerField.tsx
348
- import React5 from "react";
513
+ import React8 from "react";
349
514
  import { Controller as Controller4 } from "react-hook-form";
350
515
  var FontPickerComponent = null;
351
516
  var fontPickerLoaded = false;
@@ -362,12 +527,12 @@ function FontPickerField(props) {
362
527
  name,
363
528
  rules
364
529
  } = props;
365
- const [fontPickerState, setFontPickerState] = React5.useState({
530
+ const [fontPickerState, setFontPickerState] = React8.useState({
366
531
  component: FontPickerComponent,
367
532
  loading: false,
368
533
  error: null
369
534
  });
370
- React5.useEffect(() => {
535
+ React8.useEffect(() => {
371
536
  if (fontPickerLoaded && FontPickerComponent) {
372
537
  setFontPickerState({
373
538
  component: FontPickerComponent,
@@ -425,23 +590,23 @@ function FontPickerField(props) {
425
590
  void loadFontPicker();
426
591
  }, []);
427
592
  if (fontPickerState.loading) {
428
- return /* @__PURE__ */ React5.createElement("div", { className }, /* @__PURE__ */ React5.createElement("div", { className: "space-y-2" }, label && /* @__PURE__ */ React5.createElement("label", { className: "block text-sm font-medium text-foreground" }, label), description && /* @__PURE__ */ React5.createElement("p", { className: "text-sm text-muted-foreground" }, description), /* @__PURE__ */ React5.createElement("div", { className: "p-4 border border-default-200 bg-default-50 rounded-medium" }, /* @__PURE__ */ React5.createElement("p", { className: "text-default-600 text-sm" }, "Loading font picker..."))));
593
+ return /* @__PURE__ */ React8.createElement("div", { className }, /* @__PURE__ */ React8.createElement("div", { className: "space-y-2" }, label && /* @__PURE__ */ React8.createElement("label", { className: "block text-sm font-medium text-foreground" }, label), description && /* @__PURE__ */ React8.createElement("p", { className: "text-sm text-muted-foreground" }, description), /* @__PURE__ */ React8.createElement("div", { className: "p-4 border border-default-200 bg-default-50 rounded-medium" }, /* @__PURE__ */ React8.createElement("p", { className: "text-default-600 text-sm" }, "Loading font picker..."))));
429
594
  }
430
595
  if (!fontPickerState.component) {
431
- return /* @__PURE__ */ React5.createElement("div", { className }, /* @__PURE__ */ React5.createElement("div", { className: "space-y-2" }, label && /* @__PURE__ */ React5.createElement("label", { className: "block text-sm font-medium text-foreground" }, label), description && /* @__PURE__ */ React5.createElement("p", { className: "text-sm text-muted-foreground" }, description), /* @__PURE__ */ React5.createElement("div", { className: "p-4 border border-warning-200 bg-warning-50 rounded-medium" }, /* @__PURE__ */ React5.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."))));
596
+ return /* @__PURE__ */ React8.createElement("div", { className }, /* @__PURE__ */ React8.createElement("div", { className: "space-y-2" }, label && /* @__PURE__ */ React8.createElement("label", { className: "block text-sm font-medium text-foreground" }, label), description && /* @__PURE__ */ React8.createElement("p", { className: "text-sm text-muted-foreground" }, description), /* @__PURE__ */ React8.createElement("div", { className: "p-4 border border-warning-200 bg-warning-50 rounded-medium" }, /* @__PURE__ */ React8.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."))));
432
597
  }
433
- return /* @__PURE__ */ React5.createElement(
598
+ return /* @__PURE__ */ React8.createElement(
434
599
  Controller4,
435
600
  {
436
601
  control,
437
602
  name,
438
- render: ({ field, fieldState }) => /* @__PURE__ */ React5.createElement(
603
+ render: ({ field: field2, fieldState }) => /* @__PURE__ */ React8.createElement(
439
604
  fontPickerState.component,
440
605
  {
441
606
  label,
442
607
  description,
443
- value: field.value ?? "",
444
- onSelectionChange: (value) => field.onChange(value),
608
+ value: field2.value ?? "",
609
+ onSelectionChange: (value) => field2.onChange(value),
445
610
  errorMessage: fieldState.error?.message,
446
611
  isDisabled,
447
612
  className,
@@ -454,12 +619,12 @@ function FontPickerField(props) {
454
619
  }
455
620
 
456
621
  // src/fields/InputField.tsx
457
- import React6 from "react";
622
+ import React9 from "react";
458
623
  import { Controller as Controller5 } from "react-hook-form";
459
624
  function CoercedInput(props) {
460
- const { description, disabled, errorMessage, field, inputProps, label } = props;
625
+ const { description, disabled, errorMessage, field: field2, inputProps, label } = props;
461
626
  const defaults = useHeroHookFormDefaults();
462
- return /* @__PURE__ */ React6.createElement(
627
+ return /* @__PURE__ */ React9.createElement(
463
628
  Input,
464
629
  {
465
630
  ...defaults.input,
@@ -469,13 +634,13 @@ function CoercedInput(props) {
469
634
  isDisabled: disabled,
470
635
  isInvalid: Boolean(errorMessage),
471
636
  label,
472
- value: field.value ?? "",
473
- onBlur: field.onBlur,
474
- onValueChange: field.onChange
637
+ value: field2.value ?? "",
638
+ onBlur: field2.onBlur,
639
+ onValueChange: field2.onChange
475
640
  }
476
641
  );
477
642
  }
478
- function InputField(props) {
643
+ var InputField = React9.memo((props) => {
479
644
  const {
480
645
  className,
481
646
  control,
@@ -487,27 +652,27 @@ function InputField(props) {
487
652
  rules,
488
653
  transform
489
654
  } = props;
490
- return /* @__PURE__ */ React6.createElement(
655
+ return /* @__PURE__ */ React9.createElement(
491
656
  Controller5,
492
657
  {
493
658
  control,
494
659
  name,
495
- render: ({ field, fieldState }) => /* @__PURE__ */ React6.createElement("div", { className }, /* @__PURE__ */ React6.createElement(
660
+ render: ({ field: field2, fieldState }) => /* @__PURE__ */ React9.createElement("div", { className }, /* @__PURE__ */ React9.createElement(
496
661
  CoercedInput,
497
662
  {
498
663
  description,
499
664
  disabled: isDisabled,
500
665
  errorMessage: fieldState.error?.message,
501
666
  field: {
502
- ...field,
667
+ ...field2,
503
668
  onChange: (value) => {
504
669
  if (inputProps?.type === "number") {
505
670
  const numValue = value === "" ? void 0 : Number(value);
506
- field.onChange(
671
+ field2.onChange(
507
672
  transform ? transform(String(numValue)) : numValue
508
673
  );
509
674
  } else {
510
- field.onChange(transform ? transform(value) : value);
675
+ field2.onChange(transform ? transform(value) : value);
511
676
  }
512
677
  }
513
678
  },
@@ -518,10 +683,10 @@ function InputField(props) {
518
683
  rules
519
684
  }
520
685
  );
521
- }
686
+ });
522
687
 
523
688
  // src/fields/RadioGroupField.tsx
524
- import React7 from "react";
689
+ import React10 from "react";
525
690
  import { Controller as Controller6 } from "react-hook-form";
526
691
  function RadioGroupField(props) {
527
692
  const {
@@ -536,12 +701,12 @@ function RadioGroupField(props) {
536
701
  rules
537
702
  } = props;
538
703
  const defaults = useHeroHookFormDefaults();
539
- return /* @__PURE__ */ React7.createElement(
704
+ return /* @__PURE__ */ React10.createElement(
540
705
  Controller6,
541
706
  {
542
707
  control,
543
708
  name,
544
- render: ({ field, fieldState }) => /* @__PURE__ */ React7.createElement("div", { className }, /* @__PURE__ */ React7.createElement(
709
+ render: ({ field: field2, fieldState }) => /* @__PURE__ */ React10.createElement("div", { className }, /* @__PURE__ */ React10.createElement(
545
710
  RadioGroup,
546
711
  {
547
712
  ...defaults.radioGroup,
@@ -550,11 +715,11 @@ function RadioGroupField(props) {
550
715
  isDisabled,
551
716
  isInvalid: Boolean(fieldState.error),
552
717
  label,
553
- value: String(field.value ?? ""),
554
- onBlur: field.onBlur,
555
- onValueChange: (val) => field.onChange(val)
718
+ value: String(field2.value ?? ""),
719
+ onBlur: field2.onBlur,
720
+ onValueChange: (val) => field2.onChange(val)
556
721
  },
557
- options.map((opt) => /* @__PURE__ */ React7.createElement(
722
+ options.map((opt) => /* @__PURE__ */ React10.createElement(
558
723
  Radio,
559
724
  {
560
725
  key: String(opt.value),
@@ -563,14 +728,14 @@ function RadioGroupField(props) {
563
728
  },
564
729
  opt.label
565
730
  ))
566
- ), fieldState.error?.message ? /* @__PURE__ */ React7.createElement("p", { className: "text-tiny text-danger mt-1" }, fieldState.error.message) : null),
731
+ ), fieldState.error?.message ? /* @__PURE__ */ React10.createElement("p", { className: "text-tiny text-danger mt-1" }, fieldState.error.message) : null),
567
732
  rules
568
733
  }
569
734
  );
570
735
  }
571
736
 
572
737
  // src/fields/SelectField.tsx
573
- import React8 from "react";
738
+ import React11 from "react";
574
739
  import { Controller as Controller7 } from "react-hook-form";
575
740
  function SelectField(props) {
576
741
  const {
@@ -586,14 +751,14 @@ function SelectField(props) {
586
751
  selectProps
587
752
  } = props;
588
753
  const defaults = useHeroHookFormDefaults();
589
- return /* @__PURE__ */ React8.createElement(
754
+ return /* @__PURE__ */ React11.createElement(
590
755
  Controller7,
591
756
  {
592
757
  control,
593
758
  name,
594
- render: ({ field, fieldState }) => {
595
- const selectedKey = field.value;
596
- return /* @__PURE__ */ React8.createElement("div", { className }, /* @__PURE__ */ React8.createElement(
759
+ render: ({ field: field2, fieldState }) => {
760
+ const selectedKey = field2.value;
761
+ return /* @__PURE__ */ React11.createElement("div", { className }, /* @__PURE__ */ React11.createElement(
597
762
  Select,
598
763
  {
599
764
  ...defaults.select,
@@ -608,10 +773,10 @@ function SelectField(props) {
608
773
  onSelectionChange: (keys) => {
609
774
  const keyArray = Array.from(keys);
610
775
  const next = keyArray[0] ?? "";
611
- field.onChange(next);
776
+ field2.onChange(next);
612
777
  }
613
778
  },
614
- options.map((opt) => /* @__PURE__ */ React8.createElement(
779
+ options.map((opt) => /* @__PURE__ */ React11.createElement(
615
780
  SelectItem,
616
781
  {
617
782
  key: String(opt.value),
@@ -628,12 +793,12 @@ function SelectField(props) {
628
793
  }
629
794
 
630
795
  // src/fields/SliderField.tsx
631
- import React9 from "react";
796
+ import React12 from "react";
632
797
  import { Controller as Controller8 } from "react-hook-form";
633
798
  function CoercedSlider(props) {
634
- const { description, disabled, errorMessage, field, label, sliderProps } = props;
799
+ const { description, disabled, errorMessage, field: field2, label, sliderProps } = props;
635
800
  const defaults = useHeroHookFormDefaults();
636
- return /* @__PURE__ */ React9.createElement(
801
+ return /* @__PURE__ */ React12.createElement(
637
802
  Slider,
638
803
  {
639
804
  ...defaults.slider,
@@ -643,9 +808,9 @@ function CoercedSlider(props) {
643
808
  isDisabled: disabled,
644
809
  isInvalid: Boolean(errorMessage),
645
810
  label,
646
- value: field.value ?? 0,
647
- onBlur: field.onBlur,
648
- onValueChange: field.onChange
811
+ value: field2.value ?? 0,
812
+ onBlur: field2.onBlur,
813
+ onValueChange: field2.onChange
649
814
  }
650
815
  );
651
816
  }
@@ -661,20 +826,20 @@ function SliderField(props) {
661
826
  sliderProps,
662
827
  transform
663
828
  } = props;
664
- return /* @__PURE__ */ React9.createElement(
829
+ return /* @__PURE__ */ React12.createElement(
665
830
  Controller8,
666
831
  {
667
832
  control,
668
833
  name,
669
- render: ({ field, fieldState }) => /* @__PURE__ */ React9.createElement("div", { className }, /* @__PURE__ */ React9.createElement(
834
+ render: ({ field: field2, fieldState }) => /* @__PURE__ */ React12.createElement("div", { className }, /* @__PURE__ */ React12.createElement(
670
835
  CoercedSlider,
671
836
  {
672
837
  description,
673
838
  disabled: isDisabled,
674
839
  errorMessage: fieldState.error?.message,
675
840
  field: {
676
- ...field,
677
- onChange: (value) => field.onChange(transform ? transform(value) : value)
841
+ ...field2,
842
+ onChange: (value) => field2.onChange(transform ? transform(value) : value)
678
843
  },
679
844
  label,
680
845
  sliderProps
@@ -686,7 +851,7 @@ function SliderField(props) {
686
851
  }
687
852
 
688
853
  // src/fields/SwitchField.tsx
689
- import React10 from "react";
854
+ import React13 from "react";
690
855
  import { Controller as Controller9 } from "react-hook-form";
691
856
  function SwitchField(props) {
692
857
  const {
@@ -700,30 +865,30 @@ function SwitchField(props) {
700
865
  switchProps
701
866
  } = props;
702
867
  const defaults = useHeroHookFormDefaults();
703
- return /* @__PURE__ */ React10.createElement(
868
+ return /* @__PURE__ */ React13.createElement(
704
869
  Controller9,
705
870
  {
706
871
  control,
707
872
  name,
708
- render: ({ field, fieldState }) => /* @__PURE__ */ React10.createElement("div", { className }, /* @__PURE__ */ React10.createElement(
873
+ render: ({ field: field2, fieldState }) => /* @__PURE__ */ React13.createElement("div", { className }, /* @__PURE__ */ React13.createElement(
709
874
  Switch,
710
875
  {
711
876
  ...defaults.switch,
712
877
  ...switchProps,
713
878
  isDisabled,
714
- isSelected: Boolean(field.value),
715
- onBlur: field.onBlur,
716
- onValueChange: (val) => field.onChange(val)
879
+ isSelected: Boolean(field2.value),
880
+ onBlur: field2.onBlur,
881
+ onValueChange: (val) => field2.onChange(val)
717
882
  },
718
883
  label
719
- ), description ? /* @__PURE__ */ React10.createElement("p", { className: "text-small text-default-400" }, description) : null, fieldState.error?.message ? /* @__PURE__ */ React10.createElement("p", { className: "text-tiny text-danger mt-1" }, fieldState.error.message) : null),
884
+ ), description ? /* @__PURE__ */ React13.createElement("p", { className: "text-small text-default-400" }, description) : null, fieldState.error?.message ? /* @__PURE__ */ React13.createElement("p", { className: "text-tiny text-danger mt-1" }, fieldState.error.message) : null),
720
885
  rules
721
886
  }
722
887
  );
723
888
  }
724
889
 
725
890
  // src/fields/TextareaField.tsx
726
- import React11 from "react";
891
+ import React14 from "react";
727
892
  import { Controller as Controller10 } from "react-hook-form";
728
893
  function TextareaField(props) {
729
894
  const {
@@ -737,12 +902,12 @@ function TextareaField(props) {
737
902
  textareaProps
738
903
  } = props;
739
904
  const defaults = useHeroHookFormDefaults();
740
- return /* @__PURE__ */ React11.createElement(
905
+ return /* @__PURE__ */ React14.createElement(
741
906
  Controller10,
742
907
  {
743
908
  control,
744
909
  name,
745
- render: ({ field, fieldState }) => /* @__PURE__ */ React11.createElement("div", { className }, /* @__PURE__ */ React11.createElement(
910
+ render: ({ field: field2, fieldState }) => /* @__PURE__ */ React14.createElement("div", { className }, /* @__PURE__ */ React14.createElement(
746
911
  Textarea,
747
912
  {
748
913
  ...defaults.textarea,
@@ -752,9 +917,9 @@ function TextareaField(props) {
752
917
  isDisabled,
753
918
  isInvalid: Boolean(fieldState.error),
754
919
  label,
755
- value: field.value ?? "",
756
- onBlur: field.onBlur,
757
- onValueChange: field.onChange
920
+ value: field2.value ?? "",
921
+ onBlur: field2.onBlur,
922
+ onValueChange: field2.onChange
758
923
  }
759
924
  )),
760
925
  rules
@@ -763,13 +928,16 @@ function TextareaField(props) {
763
928
  }
764
929
 
765
930
  // src/components/FormField.tsx
766
- function FormField({
931
+ var FormField = React15.memo(({
767
932
  config,
768
933
  form,
769
934
  submissionState
770
- }) {
935
+ }) => {
936
+ if (!form || !form.control) {
937
+ return null;
938
+ }
771
939
  const { control } = form;
772
- const watchedValues = useWatch({ control });
940
+ const watchedValues = useWatch3({ control });
773
941
  if (config.condition && !config.condition(watchedValues)) {
774
942
  return null;
775
943
  }
@@ -791,7 +959,7 @@ function FormField({
791
959
  };
792
960
  switch (config.type) {
793
961
  case "input":
794
- return /* @__PURE__ */ React12.createElement(
962
+ return /* @__PURE__ */ React15.createElement(
795
963
  InputField,
796
964
  {
797
965
  ...baseProps,
@@ -801,7 +969,7 @@ function FormField({
801
969
  }
802
970
  );
803
971
  case "textarea":
804
- return /* @__PURE__ */ React12.createElement(
972
+ return /* @__PURE__ */ React15.createElement(
805
973
  TextareaField,
806
974
  {
807
975
  ...baseProps,
@@ -811,7 +979,7 @@ function FormField({
811
979
  }
812
980
  );
813
981
  case "select":
814
- return /* @__PURE__ */ React12.createElement(
982
+ return /* @__PURE__ */ React15.createElement(
815
983
  SelectField,
816
984
  {
817
985
  ...baseProps,
@@ -825,7 +993,7 @@ function FormField({
825
993
  }
826
994
  );
827
995
  case "checkbox":
828
- return /* @__PURE__ */ React12.createElement(
996
+ return /* @__PURE__ */ React15.createElement(
829
997
  CheckboxField,
830
998
  {
831
999
  ...baseProps,
@@ -835,7 +1003,7 @@ function FormField({
835
1003
  }
836
1004
  );
837
1005
  case "radio":
838
- return /* @__PURE__ */ React12.createElement(
1006
+ return /* @__PURE__ */ React15.createElement(
839
1007
  RadioGroupField,
840
1008
  {
841
1009
  ...baseProps,
@@ -849,7 +1017,7 @@ function FormField({
849
1017
  }
850
1018
  );
851
1019
  case "switch":
852
- return /* @__PURE__ */ React12.createElement(
1020
+ return /* @__PURE__ */ React15.createElement(
853
1021
  SwitchField,
854
1022
  {
855
1023
  ...baseProps,
@@ -859,7 +1027,7 @@ function FormField({
859
1027
  }
860
1028
  );
861
1029
  case "slider":
862
- return /* @__PURE__ */ React12.createElement(
1030
+ return /* @__PURE__ */ React15.createElement(
863
1031
  SliderField,
864
1032
  {
865
1033
  ...baseProps,
@@ -869,7 +1037,7 @@ function FormField({
869
1037
  }
870
1038
  );
871
1039
  case "date":
872
- return /* @__PURE__ */ React12.createElement(
1040
+ return /* @__PURE__ */ React15.createElement(
873
1041
  DateField,
874
1042
  {
875
1043
  ...baseProps,
@@ -879,7 +1047,7 @@ function FormField({
879
1047
  }
880
1048
  );
881
1049
  case "file":
882
- return /* @__PURE__ */ React12.createElement(
1050
+ return /* @__PURE__ */ React15.createElement(
883
1051
  FileField,
884
1052
  {
885
1053
  ...baseProps,
@@ -891,7 +1059,7 @@ function FormField({
891
1059
  }
892
1060
  );
893
1061
  case "fontPicker":
894
- return /* @__PURE__ */ React12.createElement(
1062
+ return /* @__PURE__ */ React15.createElement(
895
1063
  FontPickerField,
896
1064
  {
897
1065
  ...baseProps,
@@ -908,13 +1076,39 @@ function FormField({
908
1076
  isSubmitting: submissionState.isSubmitting,
909
1077
  name: config.name
910
1078
  });
1079
+ case "conditional":
1080
+ return /* @__PURE__ */ React15.createElement(
1081
+ ConditionalField,
1082
+ {
1083
+ config,
1084
+ control,
1085
+ className: config.className
1086
+ }
1087
+ );
1088
+ case "fieldArray":
1089
+ return /* @__PURE__ */ React15.createElement(
1090
+ FieldArrayField,
1091
+ {
1092
+ config,
1093
+ className: config.className
1094
+ }
1095
+ );
1096
+ case "dynamicSection":
1097
+ return /* @__PURE__ */ React15.createElement(
1098
+ DynamicSectionField,
1099
+ {
1100
+ config,
1101
+ control,
1102
+ className: config.className
1103
+ }
1104
+ );
911
1105
  default: {
912
1106
  const fieldType = config.type;
913
1107
  console.warn(`Unknown field type: ${fieldType}`);
914
1108
  return null;
915
1109
  }
916
1110
  }
917
- }
1111
+ });
918
1112
 
919
1113
  // src/components/Form.tsx
920
1114
  function ConfigurableForm({
@@ -951,16 +1145,16 @@ function ConfigurableForm({
951
1145
  });
952
1146
  const renderFields = () => {
953
1147
  if (layout === "grid") {
954
- return /* @__PURE__ */ React13.createElement(
1148
+ return /* @__PURE__ */ React16.createElement(
955
1149
  "div",
956
1150
  {
957
1151
  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"}`
958
1152
  },
959
- fields.map((field) => /* @__PURE__ */ React13.createElement(
1153
+ fields.map((field2) => /* @__PURE__ */ React16.createElement(
960
1154
  FormField,
961
1155
  {
962
- key: field.name,
963
- config: field,
1156
+ key: field2.name,
1157
+ config: field2,
964
1158
  form,
965
1159
  submissionState
966
1160
  }
@@ -968,21 +1162,21 @@ function ConfigurableForm({
968
1162
  );
969
1163
  }
970
1164
  if (layout === "horizontal") {
971
- return /* @__PURE__ */ React13.createElement("div", { className: `grid gap-${spacing} grid-cols-1 md:grid-cols-2` }, fields.map((field) => /* @__PURE__ */ React13.createElement(
1165
+ return /* @__PURE__ */ React16.createElement("div", { className: `grid gap-${spacing} grid-cols-1 md:grid-cols-2` }, fields.map((field2) => /* @__PURE__ */ React16.createElement(
972
1166
  FormField,
973
1167
  {
974
- key: field.name,
975
- config: field,
1168
+ key: field2.name,
1169
+ config: field2,
976
1170
  form,
977
1171
  submissionState
978
1172
  }
979
1173
  )));
980
1174
  }
981
- return /* @__PURE__ */ React13.createElement("div", { className: `space-y-${spacing}` }, fields.map((field) => /* @__PURE__ */ React13.createElement(
1175
+ return /* @__PURE__ */ React16.createElement("div", { className: `space-y-${spacing}` }, fields.map((field2) => /* @__PURE__ */ React16.createElement(
982
1176
  FormField,
983
1177
  {
984
- key: field.name,
985
- config: field,
1178
+ key: field2.name,
1179
+ config: field2,
986
1180
  form,
987
1181
  submissionState
988
1182
  }
@@ -992,24 +1186,24 @@ function ConfigurableForm({
992
1186
  e.preventDefault();
993
1187
  void handleSubmit();
994
1188
  };
995
- return /* @__PURE__ */ React13.createElement("form", { className, role: "form", onSubmit: handleFormSubmit }, title && /* @__PURE__ */ React13.createElement("div", { className: "mb-6" }, /* @__PURE__ */ React13.createElement("h2", { className: "text-xl font-semibold text-foreground mb-2" }, title), subtitle && /* @__PURE__ */ React13.createElement("p", { className: "text-sm text-muted-foreground" }, subtitle)), isSubmitted && isSuccess && /* @__PURE__ */ React13.createElement(
1189
+ return /* @__PURE__ */ React16.createElement("form", { className, role: "form", onSubmit: handleFormSubmit }, title && /* @__PURE__ */ React16.createElement("div", { className: "mb-6" }, /* @__PURE__ */ React16.createElement("h2", { className: "text-xl font-semibold text-foreground mb-2" }, title), subtitle && /* @__PURE__ */ React16.createElement("p", { className: "text-sm text-muted-foreground" }, subtitle)), isSubmitted && isSuccess && /* @__PURE__ */ React16.createElement(
996
1190
  "div",
997
1191
  {
998
1192
  className: "mb-6 p-4 bg-success-50 border border-success-200 rounded-lg",
999
1193
  "data-testid": "success-message"
1000
1194
  },
1001
- /* @__PURE__ */ React13.createElement("p", { className: "text-success-800 font-medium" }, "Success!"),
1002
- /* @__PURE__ */ React13.createElement("p", { className: "text-success-700 text-sm mt-1" }, "Your request has been processed successfully.")
1003
- ), error && /* @__PURE__ */ React13.createElement(
1195
+ /* @__PURE__ */ React16.createElement("p", { className: "text-success-800 font-medium" }, "Success!"),
1196
+ /* @__PURE__ */ React16.createElement("p", { className: "text-success-700 text-sm mt-1" }, "Your request has been processed successfully.")
1197
+ ), error && /* @__PURE__ */ React16.createElement(
1004
1198
  "div",
1005
1199
  {
1006
1200
  className: "mb-6 p-4 bg-danger-50 border border-danger-200 rounded-lg",
1007
1201
  "data-testid": "error-message"
1008
1202
  },
1009
- /* @__PURE__ */ React13.createElement("p", { className: "text-danger-800 font-medium" }, "Error"),
1010
- /* @__PURE__ */ React13.createElement("p", { className: "text-danger-700 text-sm mt-1" }, error)
1011
- ), renderFields(), /* @__PURE__ */ React13.createElement("div", { className: "mt-6 flex gap-3 justify-end" }, /* @__PURE__ */ React13.createElement(
1012
- Button2,
1203
+ /* @__PURE__ */ React16.createElement("p", { className: "text-danger-800 font-medium" }, "Error"),
1204
+ /* @__PURE__ */ React16.createElement("p", { className: "text-danger-700 text-sm mt-1" }, error)
1205
+ ), renderFields(), /* @__PURE__ */ React16.createElement("div", { className: "mt-6 flex gap-3 justify-end" }, /* @__PURE__ */ React16.createElement(
1206
+ Button3,
1013
1207
  {
1014
1208
  color: "primary",
1015
1209
  isDisabled: isSubmitting,
@@ -1018,8 +1212,8 @@ function ConfigurableForm({
1018
1212
  ...submitButtonProps
1019
1213
  },
1020
1214
  submitButtonText
1021
- ), showResetButton && /* @__PURE__ */ React13.createElement(
1022
- Button2,
1215
+ ), showResetButton && /* @__PURE__ */ React16.createElement(
1216
+ Button3,
1023
1217
  {
1024
1218
  isDisabled: isSubmitting,
1025
1219
  type: "button",
@@ -1031,9 +1225,9 @@ function ConfigurableForm({
1031
1225
  }
1032
1226
 
1033
1227
  // src/hooks/useHeroForm.ts
1034
- import { useFormContext } from "react-hook-form";
1228
+ import { useFormContext as useFormContext4 } from "react-hook-form";
1035
1229
  function useHeroForm() {
1036
- const form = useFormContext();
1230
+ const form = useFormContext4();
1037
1231
  const defaults = useHeroHookFormDefaults();
1038
1232
  return {
1039
1233
  // All React Hook Form methods and state
@@ -1044,10 +1238,10 @@ function useHeroForm() {
1044
1238
  }
1045
1239
 
1046
1240
  // src/providers/FormProvider.tsx
1047
- import React14 from "react";
1241
+ import React17 from "react";
1048
1242
  import { FormProvider as RHFProvider } from "react-hook-form";
1049
1243
  function FormProvider(props) {
1050
- return /* @__PURE__ */ React14.createElement(RHFProvider, { ...props.methods }, /* @__PURE__ */ React14.createElement(
1244
+ return /* @__PURE__ */ React17.createElement(RHFProvider, { ...props.methods }, /* @__PURE__ */ React17.createElement(
1051
1245
  "form",
1052
1246
  {
1053
1247
  className: props.className,
@@ -1060,22 +1254,42 @@ function FormProvider(props) {
1060
1254
  }
1061
1255
 
1062
1256
  // src/submit/SubmitButton.tsx
1063
- import React15 from "react";
1257
+ import React18 from "react";
1064
1258
  function SubmitButton(props) {
1065
- const ctx = useFormContext2();
1259
+ const ctx = useFormContext5();
1066
1260
  const loading = props.isLoading ?? ctx.formState.isSubmitting;
1261
+ const enhancedState = props.enhancedState;
1067
1262
  const isDisabledFromProps = props.buttonProps?.isDisabled ?? false;
1068
1263
  const isDisabled = Boolean(isDisabledFromProps) || Boolean(loading);
1069
1264
  const defaults = useHeroHookFormDefaults();
1070
- return /* @__PURE__ */ React15.createElement(
1265
+ const getButtonContent = () => {
1266
+ if (enhancedState?.isSuccess) {
1267
+ return /* @__PURE__ */ React18.createElement("span", { className: "inline-flex items-center gap-2" }, "\u2705", props.successText || "Success!");
1268
+ }
1269
+ if (loading) {
1270
+ return /* @__PURE__ */ React18.createElement("span", { className: "inline-flex items-center gap-2" }, "\u23F3", props.loadingText || "Submitting...");
1271
+ }
1272
+ return props.children;
1273
+ };
1274
+ const getButtonColor = () => {
1275
+ if (enhancedState?.isSuccess) {
1276
+ return "success";
1277
+ }
1278
+ if (enhancedState?.isError) {
1279
+ return "danger";
1280
+ }
1281
+ return props.buttonProps?.color || defaults.submitButton.color;
1282
+ };
1283
+ return /* @__PURE__ */ React18.createElement(
1071
1284
  Button,
1072
1285
  {
1073
1286
  type: "submit",
1074
1287
  ...defaults.submitButton,
1075
1288
  ...props.buttonProps,
1076
- isDisabled
1289
+ isDisabled,
1290
+ color: getButtonColor()
1077
1291
  },
1078
- loading ? /* @__PURE__ */ React15.createElement("span", { className: "inline-flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(Spinner, { size: "sm" }), "Submitting\u2026") : props.children
1292
+ getButtonContent()
1079
1293
  );
1080
1294
  }
1081
1295
 
@@ -1266,13 +1480,69 @@ var commonValidations = {
1266
1480
  requiredCheckbox: (fieldName) => createRequiredCheckboxSchema(fieldName),
1267
1481
  url: createUrlSchema()
1268
1482
  };
1483
+ var crossFieldValidation = {
1484
+ /**
1485
+ * Password confirmation validation
1486
+ */
1487
+ passwordConfirmation: (passwordField, confirmField) => {
1488
+ return z.object({
1489
+ [passwordField]: z.string(),
1490
+ [confirmField]: z.string()
1491
+ }).refine(
1492
+ (data) => data[passwordField] === data[confirmField],
1493
+ {
1494
+ message: "Passwords do not match",
1495
+ path: [confirmField]
1496
+ }
1497
+ );
1498
+ },
1499
+ /**
1500
+ * Date range validation
1501
+ */
1502
+ dateRange: (startField, endField) => {
1503
+ return z.object({
1504
+ [startField]: z.string(),
1505
+ [endField]: z.string()
1506
+ }).refine(
1507
+ (data) => {
1508
+ const startDate = new Date(data[startField]);
1509
+ const endDate = new Date(data[endField]);
1510
+ return startDate < endDate;
1511
+ },
1512
+ {
1513
+ message: "End date must be after start date",
1514
+ path: [endField]
1515
+ }
1516
+ );
1517
+ },
1518
+ /**
1519
+ * Conditional required field validation
1520
+ */
1521
+ conditionalRequired: (field2, conditionField, conditionValue) => {
1522
+ return z.object({
1523
+ [field2]: z.string(),
1524
+ [conditionField]: z.any()
1525
+ }).refine(
1526
+ (data) => {
1527
+ if (data[conditionField] === conditionValue) {
1528
+ return data[field2] && data[field2].trim().length > 0;
1529
+ }
1530
+ return true;
1531
+ },
1532
+ {
1533
+ message: "This field is required",
1534
+ path: [field2]
1535
+ }
1536
+ );
1537
+ }
1538
+ };
1269
1539
 
1270
1540
  // src/index.ts
1271
- import { useFormContext as useFormContext2 } from "react-hook-form";
1541
+ import { useFormContext as useFormContext5 } from "react-hook-form";
1272
1542
 
1273
1543
  // src/components/ZodForm.tsx
1274
- import React16 from "react";
1275
- import { Button as Button3 } from "@heroui/react";
1544
+ import React20 from "react";
1545
+ import { Button as Button5 } from "@heroui/react";
1276
1546
 
1277
1547
  // src/zod-integration.ts
1278
1548
  import { useForm as useForm2 } from "react-hook-form";
@@ -1315,6 +1585,146 @@ function createZodFormConfig(schema, fields, defaultValues) {
1315
1585
  };
1316
1586
  }
1317
1587
 
1588
+ // src/hooks/useEnhancedFormState.ts
1589
+ import { useCallback, useEffect, useState as useState2 } from "react";
1590
+ function useEnhancedFormState(form, options = {}) {
1591
+ const {
1592
+ onSuccess,
1593
+ onError,
1594
+ successMessage = "Form submitted successfully!",
1595
+ errorMessage = "An error occurred. Please try again.",
1596
+ autoReset = true,
1597
+ resetDelay = 3e3
1598
+ } = options;
1599
+ const [status, setStatus] = useState2("idle");
1600
+ const [error, setError] = useState2(void 0);
1601
+ const [submittedData, setSubmittedData] = useState2(void 0);
1602
+ const { formState, getValues } = form;
1603
+ const { errors, touchedFields, dirtyFields, isSubmitting } = formState;
1604
+ useEffect(() => {
1605
+ if (isSubmitting) {
1606
+ setStatus("submitting");
1607
+ }
1608
+ }, [isSubmitting]);
1609
+ useEffect(() => {
1610
+ if (status === "success" && autoReset) {
1611
+ const timer = setTimeout(() => {
1612
+ setStatus("idle");
1613
+ setSubmittedData(void 0);
1614
+ setError(void 0);
1615
+ }, resetDelay);
1616
+ return () => clearTimeout(timer);
1617
+ }
1618
+ }, [status, autoReset, resetDelay]);
1619
+ const handleSuccess = useCallback((data) => {
1620
+ setStatus("success");
1621
+ setSubmittedData(data);
1622
+ setError(void 0);
1623
+ onSuccess?.(data);
1624
+ }, [onSuccess]);
1625
+ const handleError = useCallback((errorMessage2) => {
1626
+ setStatus("error");
1627
+ setError(errorMessage2);
1628
+ setSubmittedData(void 0);
1629
+ onError?.(errorMessage2);
1630
+ }, [onError]);
1631
+ const reset = useCallback(() => {
1632
+ setStatus("idle");
1633
+ setError(void 0);
1634
+ setSubmittedData(void 0);
1635
+ }, []);
1636
+ return {
1637
+ status,
1638
+ isSubmitting,
1639
+ isSuccess: status === "success",
1640
+ isError: status === "error",
1641
+ error,
1642
+ submittedData,
1643
+ touchedFields: new Set(Object.keys(touchedFields)),
1644
+ dirtyFields: new Set(Object.keys(dirtyFields)),
1645
+ hasErrors: Object.keys(errors).length > 0,
1646
+ errorCount: Object.keys(errors).length,
1647
+ handleSuccess,
1648
+ handleError,
1649
+ reset
1650
+ };
1651
+ }
1652
+
1653
+ // src/components/FormStatus.tsx
1654
+ import React19 from "react";
1655
+ import { Button as Button4 } from "@heroui/react";
1656
+ function FormStatus({
1657
+ state,
1658
+ onDismiss,
1659
+ className = "",
1660
+ showDetails = false
1661
+ }) {
1662
+ const { status, isSubmitting, isSuccess, isError, error, submittedData } = state;
1663
+ if (status === "idle") {
1664
+ return null;
1665
+ }
1666
+ if (isSubmitting) {
1667
+ return /* @__PURE__ */ React19.createElement("div", { className: `flex items-center gap-3 p-4 bg-blue-50 border border-blue-200 rounded-lg ${className}` }, /* @__PURE__ */ React19.createElement("span", { className: "text-blue-600" }, "\u23F3"), /* @__PURE__ */ React19.createElement("div", null, /* @__PURE__ */ React19.createElement("p", { className: "text-sm font-medium text-blue-900" }, "Submitting form..."), showDetails && /* @__PURE__ */ React19.createElement("p", { className: "text-xs text-blue-700" }, "Please wait while we process your request.")));
1668
+ }
1669
+ if (isSuccess) {
1670
+ return /* @__PURE__ */ React19.createElement("div", { className: `flex items-center gap-3 p-4 bg-green-50 border border-green-200 rounded-lg ${className}`, "data-testid": "success-message" }, /* @__PURE__ */ React19.createElement("span", { className: "text-green-600" }, "\u2705"), /* @__PURE__ */ React19.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React19.createElement("p", { className: "text-sm font-medium text-green-900" }, "Form submitted successfully!"), showDetails && submittedData && /* @__PURE__ */ React19.createElement("p", { className: "text-xs text-green-700" }, "Your data has been saved. Thank you for your submission.")), onDismiss && /* @__PURE__ */ React19.createElement(
1671
+ Button4,
1672
+ {
1673
+ size: "sm",
1674
+ variant: "light",
1675
+ isIconOnly: true,
1676
+ onPress: onDismiss,
1677
+ "aria-label": "Dismiss success message"
1678
+ },
1679
+ "\u2715"
1680
+ ));
1681
+ }
1682
+ if (isError && error) {
1683
+ return /* @__PURE__ */ React19.createElement("div", { className: `flex items-center gap-3 p-4 bg-red-50 border border-red-200 rounded-lg ${className}`, "data-testid": "error-message" }, /* @__PURE__ */ React19.createElement("span", { className: "text-red-600" }, "\u26A0\uFE0F"), /* @__PURE__ */ React19.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React19.createElement("p", { className: "text-sm font-medium text-red-900" }, "Error submitting form"), /* @__PURE__ */ React19.createElement("p", { className: "text-xs text-red-700" }, error)), onDismiss && /* @__PURE__ */ React19.createElement(
1684
+ Button4,
1685
+ {
1686
+ size: "sm",
1687
+ variant: "light",
1688
+ isIconOnly: true,
1689
+ onPress: onDismiss,
1690
+ "aria-label": "Dismiss error message"
1691
+ },
1692
+ "\u2715"
1693
+ ));
1694
+ }
1695
+ return null;
1696
+ }
1697
+ function FormToast({
1698
+ state,
1699
+ onDismiss,
1700
+ position = "top-right",
1701
+ duration = 5e3
1702
+ }) {
1703
+ const [isVisible, setIsVisible] = React19.useState(false);
1704
+ React19.useEffect(() => {
1705
+ if (state.isSuccess || state.isError) {
1706
+ setIsVisible(true);
1707
+ if (duration > 0) {
1708
+ const timer = setTimeout(() => {
1709
+ setIsVisible(false);
1710
+ onDismiss?.();
1711
+ }, duration);
1712
+ return () => clearTimeout(timer);
1713
+ }
1714
+ }
1715
+ }, [state.isSuccess, state.isError, duration, onDismiss]);
1716
+ if (!isVisible) {
1717
+ return null;
1718
+ }
1719
+ const positionClasses = {
1720
+ "top-right": "top-4 right-4",
1721
+ "top-left": "top-4 left-4",
1722
+ "bottom-right": "bottom-4 right-4",
1723
+ "bottom-left": "bottom-4 left-4"
1724
+ };
1725
+ return /* @__PURE__ */ React19.createElement("div", { className: `fixed z-50 ${positionClasses[position]}` }, /* @__PURE__ */ React19.createElement(FormStatus, { state, onDismiss }));
1726
+ }
1727
+
1318
1728
  // src/components/ZodForm.tsx
1319
1729
  function ZodForm({
1320
1730
  className,
@@ -1335,97 +1745,83 @@ function ZodForm({
1335
1745
  title
1336
1746
  }) {
1337
1747
  const form = useZodForm(config);
1338
- const [submissionState, setSubmissionState] = React16.useState({
1339
- error: void 0,
1340
- isSubmitted: false,
1341
- isSubmitting: false,
1342
- isSuccess: false
1748
+ const enhancedState = useEnhancedFormState(form, {
1749
+ onSuccess,
1750
+ onError: (error) => onError?.({ message: error, field: "form" }),
1751
+ autoReset: true,
1752
+ resetDelay: 3e3
1343
1753
  });
1344
1754
  const handleSubmit = async () => {
1345
- setSubmissionState((prev) => ({
1346
- ...prev,
1347
- error: void 0,
1348
- isSubmitting: true
1349
- }));
1350
- const isValid = await form.trigger();
1351
- if (!isValid) {
1352
- setSubmissionState({
1353
- error: "Please fix the validation errors above",
1354
- isSubmitted: true,
1355
- isSubmitting: false,
1356
- isSuccess: false
1357
- });
1358
- return;
1359
- }
1360
1755
  try {
1361
- await form.handleSubmit(async (formData) => {
1362
- await onSubmit(formData);
1363
- })();
1364
- setSubmissionState({
1365
- error: void 0,
1366
- isSubmitted: true,
1367
- isSubmitting: false,
1368
- isSuccess: true
1369
- });
1370
- onSuccess?.(form.getValues());
1756
+ await form.handleSubmit(
1757
+ async (formData) => {
1758
+ await onSubmit(formData);
1759
+ enhancedState.handleSuccess(formData);
1760
+ },
1761
+ (errors) => {
1762
+ enhancedState.handleError("Please fix the validation errors above");
1763
+ }
1764
+ )();
1371
1765
  } catch (error) {
1372
1766
  const errorMessage = error instanceof Error ? error.message : "An error occurred";
1373
- setSubmissionState({
1374
- error: errorMessage,
1375
- isSubmitted: true,
1376
- isSubmitting: false,
1377
- isSuccess: false
1378
- });
1379
- onError?.({
1380
- message: errorMessage
1381
- });
1767
+ enhancedState.handleError(errorMessage);
1382
1768
  }
1383
1769
  };
1384
1770
  const resetForm = () => {
1385
1771
  form.reset();
1386
- setSubmissionState({
1387
- error: void 0,
1388
- isSubmitted: false,
1389
- isSubmitting: false,
1390
- isSuccess: false
1391
- });
1772
+ enhancedState.reset();
1392
1773
  };
1393
1774
  const renderFields = () => {
1394
1775
  if (layout === "grid") {
1395
- return /* @__PURE__ */ React16.createElement(
1776
+ return /* @__PURE__ */ React20.createElement(
1396
1777
  "div",
1397
1778
  {
1398
1779
  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"}`
1399
1780
  },
1400
- config.fields.map((field) => /* @__PURE__ */ React16.createElement(
1781
+ config.fields.map((field2) => /* @__PURE__ */ React20.createElement(
1401
1782
  FormField,
1402
1783
  {
1403
- key: field.name,
1404
- config: field,
1784
+ key: field2.name,
1785
+ config: field2,
1405
1786
  form,
1406
- submissionState
1787
+ submissionState: {
1788
+ isSubmitting: enhancedState.isSubmitting,
1789
+ isSubmitted: enhancedState.status !== "idle",
1790
+ isSuccess: enhancedState.isSuccess,
1791
+ error: enhancedState.error
1792
+ }
1407
1793
  }
1408
1794
  ))
1409
1795
  );
1410
1796
  }
1411
1797
  if (layout === "horizontal") {
1412
- return /* @__PURE__ */ React16.createElement("div", { className: `grid gap-${spacing} grid-cols-1 md:grid-cols-2` }, config.fields.map((field) => /* @__PURE__ */ React16.createElement(
1798
+ return /* @__PURE__ */ React20.createElement("div", { className: `grid gap-${spacing} grid-cols-1 md:grid-cols-2` }, config.fields.map((field2) => /* @__PURE__ */ React20.createElement(
1413
1799
  FormField,
1414
1800
  {
1415
- key: field.name,
1416
- config: field,
1801
+ key: field2.name,
1802
+ config: field2,
1417
1803
  form,
1418
- submissionState
1804
+ submissionState: {
1805
+ isSubmitting: enhancedState.isSubmitting,
1806
+ isSubmitted: enhancedState.status !== "idle",
1807
+ isSuccess: enhancedState.isSuccess,
1808
+ error: enhancedState.error
1809
+ }
1419
1810
  }
1420
1811
  )));
1421
1812
  }
1422
- return /* @__PURE__ */ React16.createElement("div", { className: `space-y-${spacing}` }, config.fields.map((field) => /* @__PURE__ */ React16.createElement(
1813
+ return /* @__PURE__ */ React20.createElement("div", { className: `space-y-${spacing}` }, config.fields.map((field2) => /* @__PURE__ */ React20.createElement(
1423
1814
  FormField,
1424
1815
  {
1425
- key: field.name,
1426
- config: field,
1816
+ key: field2.name,
1817
+ config: field2,
1427
1818
  form,
1428
- submissionState
1819
+ submissionState: {
1820
+ isSubmitting: enhancedState.isSubmitting,
1821
+ isSubmitted: enhancedState.status !== "idle",
1822
+ isSuccess: enhancedState.isSuccess,
1823
+ error: enhancedState.error
1824
+ }
1429
1825
  }
1430
1826
  )));
1431
1827
  };
@@ -1433,7 +1829,7 @@ function ZodForm({
1433
1829
  e.preventDefault();
1434
1830
  void handleSubmit();
1435
1831
  };
1436
- React16.useEffect(() => {
1832
+ React20.useEffect(() => {
1437
1833
  if (config.onError && Object.keys(form.formState.errors).length > 0) {
1438
1834
  config.onError(form.formState.errors);
1439
1835
  }
@@ -1442,42 +1838,33 @@ function ZodForm({
1442
1838
  return render({
1443
1839
  errors: form.formState.errors,
1444
1840
  form,
1445
- isSubmitted: submissionState.isSubmitted,
1446
- isSubmitting: submissionState.isSubmitting,
1447
- isSuccess: submissionState.isSuccess,
1841
+ isSubmitted: enhancedState.status !== "idle",
1842
+ isSubmitting: enhancedState.isSubmitting,
1843
+ isSuccess: enhancedState.isSuccess,
1448
1844
  values: form.getValues()
1449
1845
  });
1450
1846
  }
1451
- return /* @__PURE__ */ React16.createElement("form", { className, role: "form", onSubmit: handleFormSubmit }, title && /* @__PURE__ */ React16.createElement("div", { className: "mb-6" }, /* @__PURE__ */ React16.createElement("h2", { className: "text-xl font-semibold text-foreground mb-2" }, title), subtitle && /* @__PURE__ */ React16.createElement("p", { className: "text-sm text-muted-foreground" }, subtitle)), submissionState.isSubmitted && submissionState.isSuccess && /* @__PURE__ */ React16.createElement(
1452
- "div",
1453
- {
1454
- className: "mb-6 p-4 bg-success-50 border border-success-200 rounded-lg",
1455
- "data-testid": "success-message"
1456
- },
1457
- /* @__PURE__ */ React16.createElement("p", { className: "text-success-800 font-medium" }, "Success!"),
1458
- /* @__PURE__ */ React16.createElement("p", { className: "text-success-700 text-sm mt-1" }, "Your request has been processed successfully.")
1459
- ), submissionState.error && errorDisplay !== "none" && /* @__PURE__ */ React16.createElement(
1460
- "div",
1847
+ 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)), /* @__PURE__ */ React20.createElement(
1848
+ FormStatus,
1461
1849
  {
1462
- className: "mb-6 p-4 bg-danger-50 border border-danger-200 rounded-lg",
1463
- "data-testid": "error-message"
1464
- },
1465
- /* @__PURE__ */ React16.createElement("p", { className: "text-danger-800 font-medium" }, "Error"),
1466
- /* @__PURE__ */ React16.createElement("p", { className: "text-danger-700 text-sm mt-1" }, submissionState.error)
1467
- ), renderFields(), /* @__PURE__ */ React16.createElement("div", { className: "mt-6 flex gap-3 justify-end" }, /* @__PURE__ */ React16.createElement(
1468
- Button3,
1850
+ state: enhancedState,
1851
+ onDismiss: () => enhancedState.reset(),
1852
+ showDetails: true
1853
+ }
1854
+ ), renderFields(), /* @__PURE__ */ React20.createElement("div", { className: "mt-6 flex gap-3 justify-end" }, /* @__PURE__ */ React20.createElement(
1855
+ Button5,
1469
1856
  {
1470
1857
  color: "primary",
1471
- isDisabled: submissionState.isSubmitting,
1472
- isLoading: submissionState.isSubmitting,
1858
+ isDisabled: enhancedState.isSubmitting,
1859
+ isLoading: enhancedState.isSubmitting,
1473
1860
  type: "submit",
1474
1861
  ...submitButtonProps
1475
1862
  },
1476
- submitButtonText
1477
- ), showResetButton && /* @__PURE__ */ React16.createElement(
1478
- Button3,
1863
+ enhancedState.isSuccess ? "Success!" : submitButtonText
1864
+ ), showResetButton && /* @__PURE__ */ React20.createElement(
1865
+ Button5,
1479
1866
  {
1480
- isDisabled: submissionState.isSubmitting,
1867
+ isDisabled: enhancedState.isSubmitting,
1481
1868
  type: "button",
1482
1869
  variant: "bordered",
1483
1870
  onPress: resetForm
@@ -1485,14 +1872,1209 @@ function ZodForm({
1485
1872
  resetButtonText
1486
1873
  )));
1487
1874
  }
1875
+
1876
+ // src/builders/BasicFormBuilder.ts
1877
+ var BasicFormBuilder = class {
1878
+ constructor() {
1879
+ this.fields = [];
1880
+ }
1881
+ /**
1882
+ * Add an input field
1883
+ */
1884
+ input(name, label, type = "text") {
1885
+ this.fields.push({
1886
+ name,
1887
+ label,
1888
+ type: "input",
1889
+ inputProps: { type }
1890
+ });
1891
+ return this;
1892
+ }
1893
+ /**
1894
+ * Add a textarea field
1895
+ */
1896
+ textarea(name, label, placeholder) {
1897
+ this.fields.push({
1898
+ name,
1899
+ label,
1900
+ type: "textarea",
1901
+ textareaProps: { placeholder }
1902
+ });
1903
+ return this;
1904
+ }
1905
+ /**
1906
+ * Add a select field
1907
+ */
1908
+ select(name, label, options) {
1909
+ this.fields.push({
1910
+ name,
1911
+ label,
1912
+ type: "select",
1913
+ options
1914
+ });
1915
+ return this;
1916
+ }
1917
+ /**
1918
+ * Add a checkbox field
1919
+ */
1920
+ checkbox(name, label) {
1921
+ this.fields.push({
1922
+ name,
1923
+ label,
1924
+ type: "checkbox"
1925
+ });
1926
+ return this;
1927
+ }
1928
+ /**
1929
+ * Add a switch field
1930
+ */
1931
+ switch(name, label) {
1932
+ this.fields.push({
1933
+ name,
1934
+ label,
1935
+ type: "switch"
1936
+ });
1937
+ return this;
1938
+ }
1939
+ /**
1940
+ * Build the final field configuration array
1941
+ */
1942
+ build() {
1943
+ return this.fields;
1944
+ }
1945
+ };
1946
+ function createBasicFormBuilder() {
1947
+ return new BasicFormBuilder();
1948
+ }
1949
+ var FormFieldHelpers = {
1950
+ /**
1951
+ * Create an input field
1952
+ */
1953
+ input: (name, label, type = "text") => ({
1954
+ name,
1955
+ label,
1956
+ type: "input",
1957
+ inputProps: { type }
1958
+ }),
1959
+ /**
1960
+ * Create a textarea field
1961
+ */
1962
+ textarea: (name, label, placeholder) => ({
1963
+ name,
1964
+ label,
1965
+ type: "textarea",
1966
+ textareaProps: { placeholder }
1967
+ }),
1968
+ /**
1969
+ * Create a select field
1970
+ */
1971
+ select: (name, label, options) => ({
1972
+ name,
1973
+ label,
1974
+ type: "select",
1975
+ options
1976
+ }),
1977
+ /**
1978
+ * Create a checkbox field
1979
+ */
1980
+ checkbox: (name, label) => ({
1981
+ name,
1982
+ label,
1983
+ type: "checkbox"
1984
+ }),
1985
+ /**
1986
+ * Create a switch field
1987
+ */
1988
+ switch: (name, label) => ({
1989
+ name,
1990
+ label,
1991
+ type: "switch"
1992
+ })
1993
+ };
1994
+ var CommonFields = {
1995
+ /**
1996
+ * Personal information fields
1997
+ */
1998
+ personal: () => [
1999
+ FormFieldHelpers.input("firstName", "First Name"),
2000
+ FormFieldHelpers.input("lastName", "Last Name"),
2001
+ FormFieldHelpers.input("email", "Email", "email"),
2002
+ FormFieldHelpers.input("phone", "Phone", "tel")
2003
+ ],
2004
+ /**
2005
+ * Address fields
2006
+ */
2007
+ address: () => [
2008
+ FormFieldHelpers.input("street", "Street Address"),
2009
+ FormFieldHelpers.input("city", "City"),
2010
+ FormFieldHelpers.input("state", "State/Province"),
2011
+ FormFieldHelpers.input("zipCode", "ZIP/Postal Code"),
2012
+ FormFieldHelpers.select(
2013
+ "country",
2014
+ "Country",
2015
+ [
2016
+ { label: "Select a country", value: "" },
2017
+ { label: "United States", value: "us" },
2018
+ { label: "Canada", value: "ca" },
2019
+ { label: "United Kingdom", value: "uk" },
2020
+ { label: "Australia", value: "au" },
2021
+ { label: "Germany", value: "de" },
2022
+ { label: "France", value: "fr" }
2023
+ ]
2024
+ )
2025
+ ],
2026
+ /**
2027
+ * Terms and conditions fields
2028
+ */
2029
+ terms: () => [
2030
+ FormFieldHelpers.checkbox("terms", "I agree to the terms and conditions"),
2031
+ FormFieldHelpers.checkbox("privacy", "I agree to the privacy policy"),
2032
+ FormFieldHelpers.checkbox("newsletter", "Subscribe to newsletter")
2033
+ ]
2034
+ };
2035
+
2036
+ // src/builders/AdvancedFormBuilder.ts
2037
+ function inputField(name, label, props) {
2038
+ return {
2039
+ name,
2040
+ label,
2041
+ type: "input",
2042
+ ...props && {
2043
+ inputProps: {
2044
+ type: props.type || "text",
2045
+ placeholder: props.placeholder,
2046
+ description: props.description,
2047
+ disabled: props.isDisabled,
2048
+ className: props.className
2049
+ }
2050
+ }
2051
+ };
2052
+ }
2053
+ function textareaField(name, label, props) {
2054
+ return {
2055
+ name,
2056
+ label,
2057
+ type: "textarea",
2058
+ ...props && {
2059
+ textareaProps: {
2060
+ placeholder: props.placeholder,
2061
+ description: props.description,
2062
+ disabled: props.isDisabled,
2063
+ className: props.className,
2064
+ rows: props.rows
2065
+ }
2066
+ }
2067
+ };
2068
+ }
2069
+ function selectField(name, label, options, props) {
2070
+ return {
2071
+ name,
2072
+ label,
2073
+ type: "select",
2074
+ options
2075
+ };
2076
+ }
2077
+ function checkboxField(name, label, props) {
2078
+ return {
2079
+ name,
2080
+ label,
2081
+ type: "checkbox",
2082
+ ...props && {
2083
+ checkboxProps: {
2084
+ disabled: props.isDisabled,
2085
+ className: props.className
2086
+ }
2087
+ }
2088
+ };
2089
+ }
2090
+ function switchField(name, label, props) {
2091
+ return {
2092
+ name,
2093
+ label,
2094
+ type: "switch",
2095
+ ...props && {
2096
+ switchProps: {
2097
+ disabled: props.isDisabled,
2098
+ className: props.className
2099
+ }
2100
+ }
2101
+ };
2102
+ }
2103
+ function radioField(name, label, options, props) {
2104
+ return {
2105
+ name,
2106
+ label,
2107
+ type: "radio",
2108
+ radioOptions: options,
2109
+ ...props && {
2110
+ radioProps: {
2111
+ isDisabled: props.isDisabled,
2112
+ className: props.className,
2113
+ orientation: props.orientation
2114
+ }
2115
+ }
2116
+ };
2117
+ }
2118
+ function sliderField(name, label, props) {
2119
+ return {
2120
+ name,
2121
+ label,
2122
+ type: "slider",
2123
+ ...props && {
2124
+ sliderProps: {
2125
+ min: props.min || 0,
2126
+ max: props.max || 100,
2127
+ step: props.step || 1,
2128
+ disabled: props.isDisabled || false,
2129
+ className: props.className || ""
2130
+ }
2131
+ }
2132
+ };
2133
+ }
2134
+ function dateField(name, label, props) {
2135
+ return {
2136
+ name,
2137
+ label,
2138
+ type: "date",
2139
+ ...props && {
2140
+ dateProps: {
2141
+ placeholder: props.placeholder || "",
2142
+ disabled: props.isDisabled || false,
2143
+ className: props.className || ""
2144
+ }
2145
+ }
2146
+ };
2147
+ }
2148
+ function fileField(name, label, props) {
2149
+ return {
2150
+ name,
2151
+ label,
2152
+ type: "file",
2153
+ ...props && {
2154
+ fileProps: {
2155
+ accept: props.accept || "",
2156
+ multiple: props.multiple || false,
2157
+ disabled: props.isDisabled || false,
2158
+ className: props.className || ""
2159
+ }
2160
+ }
2161
+ };
2162
+ }
2163
+ function fontPickerField(name, label, props) {
2164
+ return {
2165
+ name,
2166
+ label,
2167
+ type: "fontPicker",
2168
+ ...props && {
2169
+ fontPickerProps: {
2170
+ disabled: props.isDisabled || false,
2171
+ className: props.className || ""
2172
+ }
2173
+ }
2174
+ };
2175
+ }
2176
+ function createField(type, name, label, optionsOrProps, props) {
2177
+ switch (type) {
2178
+ case "input":
2179
+ return inputField(name, label, optionsOrProps);
2180
+ case "textarea":
2181
+ return textareaField(name, label, optionsOrProps);
2182
+ case "select":
2183
+ return selectField(name, label, optionsOrProps, props);
2184
+ case "checkbox":
2185
+ return checkboxField(name, label, optionsOrProps);
2186
+ case "switch":
2187
+ return switchField(name, label, optionsOrProps);
2188
+ case "radio":
2189
+ return radioField(name, label, optionsOrProps, props);
2190
+ case "slider":
2191
+ return sliderField(name, label, optionsOrProps);
2192
+ case "date":
2193
+ return dateField(name, label, optionsOrProps);
2194
+ case "file":
2195
+ return fileField(name, label, optionsOrProps);
2196
+ case "fontPicker":
2197
+ return fontPickerField(name, label, optionsOrProps);
2198
+ default:
2199
+ throw new Error(`Unknown field type: ${type}`);
2200
+ }
2201
+ }
2202
+ var AdvancedFieldBuilder = class {
2203
+ constructor() {
2204
+ this.fields = [];
2205
+ }
2206
+ field(type, name, label, optionsOrProps, props) {
2207
+ this.fields.push(createField(type, name, label, optionsOrProps, props));
2208
+ return this;
2209
+ }
2210
+ /**
2211
+ * Add a conditional field that shows/hides based on form data
2212
+ */
2213
+ conditionalField(name, condition, field2) {
2214
+ this.fields.push({
2215
+ name,
2216
+ type: "conditional",
2217
+ condition,
2218
+ field: field2
2219
+ });
2220
+ return this;
2221
+ }
2222
+ /**
2223
+ * Add a field array for dynamic repeating field groups
2224
+ */
2225
+ fieldArray(name, label, fields, options) {
2226
+ this.fields.push({
2227
+ name,
2228
+ label,
2229
+ type: "fieldArray",
2230
+ fields,
2231
+ min: options?.min,
2232
+ max: options?.max,
2233
+ addButtonText: options?.addButtonText,
2234
+ removeButtonText: options?.removeButtonText
2235
+ });
2236
+ return this;
2237
+ }
2238
+ /**
2239
+ * Add a dynamic section that shows/hides based on form data
2240
+ */
2241
+ dynamicSection(name, condition, fields, options) {
2242
+ this.fields.push({
2243
+ name,
2244
+ type: "dynamicSection",
2245
+ condition,
2246
+ fields,
2247
+ title: options?.title,
2248
+ description: options?.description
2249
+ });
2250
+ return this;
2251
+ }
2252
+ /**
2253
+ * Build the final field configuration array
2254
+ */
2255
+ build() {
2256
+ return this.fields;
2257
+ }
2258
+ };
2259
+ var FieldArrayItemBuilder = class {
2260
+ constructor() {
2261
+ this.fields = [];
2262
+ }
2263
+ field(type, name, label, optionsOrProps, props) {
2264
+ this.fields.push(createField(type, name, label, optionsOrProps, props));
2265
+ return this;
2266
+ }
2267
+ /**
2268
+ * Build the field array item configuration
2269
+ */
2270
+ build() {
2271
+ return this.fields;
2272
+ }
2273
+ };
2274
+ function createFieldArrayItemBuilder() {
2275
+ return new FieldArrayItemBuilder();
2276
+ }
2277
+ var FieldArrayBuilder = class {
2278
+ constructor(arrayName) {
2279
+ this.arrayName = arrayName;
2280
+ this.fields = [];
2281
+ }
2282
+ field(type, name, label, optionsOrProps, props) {
2283
+ const fullPath = `${this.arrayName}.${name}`;
2284
+ const fieldConfig = createField(type, fullPath, label, optionsOrProps, props);
2285
+ this.fields.push(fieldConfig);
2286
+ return this;
2287
+ }
2288
+ build() {
2289
+ return this.fields;
2290
+ }
2291
+ };
2292
+ function createFieldArrayBuilder(arrayName) {
2293
+ return new FieldArrayBuilder(arrayName);
2294
+ }
2295
+ function createAdvancedBuilder() {
2296
+ return new AdvancedFieldBuilder();
2297
+ }
2298
+
2299
+ // src/builders/TypeInferredBuilder.ts
2300
+ import { z as z3 } from "zod";
2301
+ var TypeInferredBuilder = class {
2302
+ constructor() {
2303
+ this.schemaFields = {};
2304
+ this.formFields = [];
2305
+ }
2306
+ /**
2307
+ * Add a text field
2308
+ */
2309
+ text(name, label, options) {
2310
+ const { minLength, maxLength, pattern, ...fieldOptions } = options || {};
2311
+ let zodType = z3.string();
2312
+ if (minLength) zodType = zodType.min(minLength, `${label} must be at least ${minLength} characters`);
2313
+ if (maxLength) zodType = zodType.max(maxLength, `${label} must be no more than ${maxLength} characters`);
2314
+ if (pattern) zodType = zodType.regex(new RegExp(pattern), `${label} format is invalid`);
2315
+ this.schemaFields[name] = zodType;
2316
+ this.formFields.push({
2317
+ name,
2318
+ label,
2319
+ type: "input",
2320
+ inputProps: { type: "text", ...fieldOptions }
2321
+ });
2322
+ return this;
2323
+ }
2324
+ /**
2325
+ * Add an email field
2326
+ */
2327
+ email(name, label, options) {
2328
+ this.schemaFields[name] = z3.string().email(`Please enter a valid email address`);
2329
+ this.formFields.push({
2330
+ name,
2331
+ label,
2332
+ type: "input",
2333
+ inputProps: { type: "email", ...options }
2334
+ });
2335
+ return this;
2336
+ }
2337
+ /**
2338
+ * Add a number field
2339
+ */
2340
+ number(name, label, options) {
2341
+ const { min, max, step, ...fieldOptions } = options || {};
2342
+ let zodType = z3.number();
2343
+ if (min !== void 0) zodType = zodType.min(min, `${label} must be at least ${min}`);
2344
+ if (max !== void 0) zodType = zodType.max(max, `${label} must be no more than ${max}`);
2345
+ this.schemaFields[name] = zodType;
2346
+ this.formFields.push({
2347
+ name,
2348
+ label,
2349
+ type: "input",
2350
+ inputProps: { type: "number", min, max, step, ...fieldOptions }
2351
+ });
2352
+ return this;
2353
+ }
2354
+ /**
2355
+ * Add a textarea field
2356
+ */
2357
+ textarea(name, label, options) {
2358
+ const { minLength, ...fieldOptions } = options || {};
2359
+ let zodType = z3.string();
2360
+ if (minLength) zodType = zodType.min(minLength, `${label} must be at least ${minLength} characters`);
2361
+ this.schemaFields[name] = zodType;
2362
+ this.formFields.push({
2363
+ name,
2364
+ label,
2365
+ type: "textarea",
2366
+ textareaProps: fieldOptions
2367
+ });
2368
+ return this;
2369
+ }
2370
+ /**
2371
+ * Add a select field
2372
+ */
2373
+ select(name, label, options, fieldOptions) {
2374
+ this.schemaFields[name] = z3.string().min(1, `Please select a ${label.toLowerCase()}`);
2375
+ this.formFields.push({
2376
+ name,
2377
+ label,
2378
+ type: "select",
2379
+ options
2380
+ });
2381
+ return this;
2382
+ }
2383
+ /**
2384
+ * Add a checkbox field
2385
+ */
2386
+ checkbox(name, label, options) {
2387
+ const { required = false, ...fieldOptions } = options || {};
2388
+ let zodType = z3.boolean();
2389
+ if (required) {
2390
+ zodType = zodType.refine((val) => val === true, `You must agree to ${label.toLowerCase()}`);
2391
+ }
2392
+ this.schemaFields[name] = zodType;
2393
+ this.formFields.push({
2394
+ name,
2395
+ label,
2396
+ type: "checkbox",
2397
+ checkboxProps: fieldOptions
2398
+ });
2399
+ return this;
2400
+ }
2401
+ /**
2402
+ * Add a switch field
2403
+ */
2404
+ switch(name, label, options) {
2405
+ this.schemaFields[name] = z3.boolean().optional();
2406
+ this.formFields.push({
2407
+ name,
2408
+ label,
2409
+ type: "switch",
2410
+ switchProps: options
2411
+ });
2412
+ return this;
2413
+ }
2414
+ /**
2415
+ * Add a radio field
2416
+ */
2417
+ radio(name, label, options, fieldOptions) {
2418
+ this.schemaFields[name] = z3.string().min(1, `Please select a ${label.toLowerCase()}`);
2419
+ this.formFields.push({
2420
+ name,
2421
+ label,
2422
+ type: "radio",
2423
+ radioOptions: options,
2424
+ radioProps: fieldOptions
2425
+ });
2426
+ return this;
2427
+ }
2428
+ /**
2429
+ * Add a slider field
2430
+ */
2431
+ slider(name, label, options) {
2432
+ const { min = 0, max = 100, step = 1, ...fieldOptions } = options || {};
2433
+ let zodType = z3.number();
2434
+ if (min !== void 0) zodType = zodType.min(min, `${label} must be at least ${min}`);
2435
+ if (max !== void 0) zodType = zodType.max(max, `${label} must be no more than ${max}`);
2436
+ this.schemaFields[name] = zodType;
2437
+ this.formFields.push({
2438
+ name,
2439
+ label,
2440
+ type: "slider",
2441
+ sliderProps: { min, max, step, ...fieldOptions }
2442
+ });
2443
+ return this;
2444
+ }
2445
+ /**
2446
+ * Add a date field
2447
+ */
2448
+ date(name, label, options) {
2449
+ this.schemaFields[name] = z3.string().min(1, `${label} is required`);
2450
+ this.formFields.push({
2451
+ name,
2452
+ label,
2453
+ type: "date",
2454
+ dateProps: options
2455
+ });
2456
+ return this;
2457
+ }
2458
+ /**
2459
+ * Add a file field
2460
+ */
2461
+ file(name, label, options) {
2462
+ this.schemaFields[name] = z3.any().optional();
2463
+ this.formFields.push({
2464
+ name,
2465
+ label,
2466
+ type: "file",
2467
+ fileProps: options
2468
+ });
2469
+ return this;
2470
+ }
2471
+ /**
2472
+ * Build the final schema and fields
2473
+ */
2474
+ build() {
2475
+ return {
2476
+ schema: z3.object(this.schemaFields),
2477
+ fields: this.formFields
2478
+ };
2479
+ }
2480
+ };
2481
+ function createTypeInferredBuilder() {
2482
+ return new TypeInferredBuilder();
2483
+ }
2484
+ function defineInferredForm(fieldDefinitions) {
2485
+ const builder = createTypeInferredBuilder();
2486
+ fieldDefinitions(builder);
2487
+ return builder.build();
2488
+ }
2489
+ var field = {
2490
+ text: (name, label, options) => {
2491
+ const builder = new TypeInferredBuilder();
2492
+ return builder.text(name, label, options);
2493
+ },
2494
+ email: (name, label, options) => {
2495
+ const builder = new TypeInferredBuilder();
2496
+ return builder.email(name, label, options);
2497
+ },
2498
+ number: (name, label, options) => {
2499
+ const builder = new TypeInferredBuilder();
2500
+ return builder.number(name, label, options);
2501
+ },
2502
+ textarea: (name, label, options) => {
2503
+ const builder = new TypeInferredBuilder();
2504
+ return builder.textarea(name, label, options);
2505
+ },
2506
+ select: (name, label, options, fieldOptions) => {
2507
+ const builder = new TypeInferredBuilder();
2508
+ return builder.select(name, label, options, fieldOptions);
2509
+ },
2510
+ checkbox: (name, label, options) => {
2511
+ const builder = new TypeInferredBuilder();
2512
+ return builder.checkbox(name, label, options);
2513
+ },
2514
+ switch: (name, label, options) => {
2515
+ const builder = new TypeInferredBuilder();
2516
+ return builder.switch(name, label, options);
2517
+ },
2518
+ radio: (name, label, options, fieldOptions) => {
2519
+ const builder = new TypeInferredBuilder();
2520
+ return builder.radio(name, label, options, fieldOptions);
2521
+ },
2522
+ slider: (name, label, options) => {
2523
+ const builder = new TypeInferredBuilder();
2524
+ return builder.slider(name, label, options);
2525
+ },
2526
+ date: (name, label, options) => {
2527
+ const builder = new TypeInferredBuilder();
2528
+ return builder.date(name, label, options);
2529
+ },
2530
+ file: (name, label, options) => {
2531
+ const builder = new TypeInferredBuilder();
2532
+ return builder.file(name, label, options);
2533
+ }
2534
+ };
2535
+
2536
+ // src/builders/NestedPathBuilder.ts
2537
+ var NestedPathBuilder = class {
2538
+ constructor() {
2539
+ this.fields = [];
2540
+ }
2541
+ /**
2542
+ * Create a nested object path builder
2543
+ * Usage: builder.nest("address").field("street", "Street Address")
2544
+ */
2545
+ nest(path) {
2546
+ return new NestedObjectBuilder(this, path);
2547
+ }
2548
+ /**
2549
+ * Create a section-based path builder
2550
+ * Usage: builder.section("shipping").field("street", "Street Address")
2551
+ */
2552
+ section(path) {
2553
+ return new SectionBuilder(this, path);
2554
+ }
2555
+ /**
2556
+ * Add a field with single path
2557
+ * Usage: builder.field("firstName", "First Name")
2558
+ */
2559
+ field(name, label, type = "input", props) {
2560
+ this.fields.push({
2561
+ name,
2562
+ label,
2563
+ type,
2564
+ ...props
2565
+ });
2566
+ return this;
2567
+ }
2568
+ /**
2569
+ * Add a field with path segments
2570
+ * Usage: builder.fieldPath(["user", "profile", "name"], "Full Name")
2571
+ */
2572
+ fieldPath(path, label, type = "input", props) {
2573
+ const name = path.join(".");
2574
+ this.fields.push({
2575
+ name,
2576
+ label,
2577
+ type,
2578
+ ...props
2579
+ });
2580
+ return this;
2581
+ }
2582
+ /**
2583
+ * Add a field with template literal path
2584
+ * Usage: builder.field`user.profile.name`("Full Name")
2585
+ */
2586
+ fieldTemplate(path, ...args) {
2587
+ const pathString = path[0];
2588
+ return new FieldTemplateBuilder(this, pathString);
2589
+ }
2590
+ /**
2591
+ * Return to the parent builder (no-op for root builder)
2592
+ */
2593
+ end() {
2594
+ return this;
2595
+ }
2596
+ build() {
2597
+ return this.fields;
2598
+ }
2599
+ };
2600
+ var NestedObjectBuilder = class _NestedObjectBuilder {
2601
+ constructor(parent, path) {
2602
+ this.parent = parent;
2603
+ this.path = path;
2604
+ }
2605
+ /**
2606
+ * Add a field to the current nested path
2607
+ */
2608
+ field(fieldName, label, type = "input", props) {
2609
+ const fullPath = `${this.path}.${fieldName}`;
2610
+ this.parent.fields.push({
2611
+ name: fullPath,
2612
+ label,
2613
+ type,
2614
+ ...props
2615
+ });
2616
+ return this;
2617
+ }
2618
+ /**
2619
+ * Nest deeper into the object
2620
+ */
2621
+ nest(subPath) {
2622
+ return new _NestedObjectBuilder(this.parent, `${this.path}.${subPath}`);
2623
+ }
2624
+ /**
2625
+ * Return to the parent builder
2626
+ */
2627
+ end() {
2628
+ return this.parent;
2629
+ }
2630
+ };
2631
+ var SectionBuilder = class {
2632
+ constructor(parent, path) {
2633
+ this.parent = parent;
2634
+ this.path = path;
2635
+ }
2636
+ /**
2637
+ * Add a field to the current section
2638
+ */
2639
+ field(fieldName, label, type = "input", props) {
2640
+ const fullPath = `${this.path}.${fieldName}`;
2641
+ this.parent.fields.push({
2642
+ name: fullPath,
2643
+ label,
2644
+ type,
2645
+ ...props
2646
+ });
2647
+ return this;
2648
+ }
2649
+ /**
2650
+ * Add multiple fields to the section
2651
+ */
2652
+ fields(fieldDefinitions) {
2653
+ fieldDefinitions.forEach((field2) => {
2654
+ this.field(field2.name, field2.label, field2.type, field2.props);
2655
+ });
2656
+ return this;
2657
+ }
2658
+ /**
2659
+ * Nest deeper into the section
2660
+ */
2661
+ nest(subPath) {
2662
+ return new NestedObjectBuilder(this.parent, `${this.path}.${subPath}`);
2663
+ }
2664
+ /**
2665
+ * Return to the parent builder
2666
+ */
2667
+ end() {
2668
+ return this.parent;
2669
+ }
2670
+ };
2671
+ var FieldTemplateBuilder = class {
2672
+ constructor(parent, path) {
2673
+ this.parent = parent;
2674
+ this.path = path;
2675
+ }
2676
+ /**
2677
+ * Complete the field definition
2678
+ */
2679
+ complete(label, type = "input", props) {
2680
+ this.parent.fields.push({
2681
+ name: this.path,
2682
+ label,
2683
+ type,
2684
+ ...props
2685
+ });
2686
+ return this.parent;
2687
+ }
2688
+ };
2689
+ function createNestedPathBuilder() {
2690
+ return new NestedPathBuilder();
2691
+ }
2692
+
2693
+ // src/hooks/useDebouncedValidation.ts
2694
+ import { useCallback as useCallback2, useEffect as useEffect2, useRef } from "react";
2695
+ function useDebouncedValidation(form, options = {}) {
2696
+ const { delay = 300, fields, enabled = true } = options;
2697
+ const timeoutRef = useRef(void 0);
2698
+ const lastValuesRef = useRef({});
2699
+ const debouncedTrigger = useCallback2(() => {
2700
+ if (!enabled) return;
2701
+ if (timeoutRef.current) {
2702
+ clearTimeout(timeoutRef.current);
2703
+ timeoutRef.current = void 0;
2704
+ }
2705
+ timeoutRef.current = setTimeout(async () => {
2706
+ const currentValues = form.getValues();
2707
+ const lastValues = lastValuesRef.current;
2708
+ const hasChanges = fields ? fields.some((field2) => currentValues[field2] !== lastValues[field2]) : Object.keys(currentValues).some((key) => currentValues[key] !== lastValues[key]);
2709
+ if (hasChanges) {
2710
+ lastValuesRef.current = { ...currentValues };
2711
+ if (fields && fields.length > 0) {
2712
+ await form.trigger(fields);
2713
+ } else {
2714
+ await form.trigger();
2715
+ }
2716
+ }
2717
+ }, delay);
2718
+ }, [form, delay, fields, enabled]);
2719
+ useEffect2(() => {
2720
+ return () => {
2721
+ if (timeoutRef.current) {
2722
+ clearTimeout(timeoutRef.current);
2723
+ timeoutRef.current = void 0;
2724
+ }
2725
+ };
2726
+ }, []);
2727
+ useEffect2(() => {
2728
+ if (form.formState.isSubmitSuccessful) {
2729
+ lastValuesRef.current = {};
2730
+ }
2731
+ }, [form.formState.isSubmitSuccessful]);
2732
+ return {
2733
+ debouncedTrigger,
2734
+ isDebouncing: !!timeoutRef.current
2735
+ };
2736
+ }
2737
+ function useDebouncedFieldValidation(form, fieldName, options = {}) {
2738
+ const { delay = 300, enabled = true } = options;
2739
+ const timeoutRef = useRef(void 0);
2740
+ const debouncedFieldTrigger = useCallback2(() => {
2741
+ if (!enabled) return;
2742
+ if (timeoutRef.current) {
2743
+ clearTimeout(timeoutRef.current);
2744
+ }
2745
+ timeoutRef.current = setTimeout(async () => {
2746
+ await form.trigger(fieldName);
2747
+ }, delay);
2748
+ }, [form, fieldName, delay, enabled]);
2749
+ useEffect2(() => {
2750
+ return () => {
2751
+ if (timeoutRef.current) {
2752
+ clearTimeout(timeoutRef.current);
2753
+ timeoutRef.current = void 0;
2754
+ }
2755
+ };
2756
+ }, []);
2757
+ return {
2758
+ debouncedFieldTrigger,
2759
+ isDebouncing: !!timeoutRef.current
2760
+ };
2761
+ }
2762
+
2763
+ // src/hooks/useInferredForm.ts
2764
+ import { useForm as useForm3 } from "react-hook-form";
2765
+ var zodResolver;
2766
+ try {
2767
+ zodResolver = __require("@hookform/resolvers/zod").zodResolver;
2768
+ } catch {
2769
+ }
2770
+ function useInferredForm(schema, fields, options = {}) {
2771
+ const {
2772
+ defaultValues,
2773
+ mode = "onChange",
2774
+ reValidateMode = "onChange",
2775
+ shouldFocusError = true,
2776
+ shouldUnregister = false,
2777
+ delayError = 0
2778
+ } = options;
2779
+ return useForm3({
2780
+ resolver: zodResolver ? zodResolver(schema) : void 0,
2781
+ defaultValues,
2782
+ mode,
2783
+ reValidateMode,
2784
+ shouldFocusError,
2785
+ shouldUnregister,
2786
+ delayError
2787
+ });
2788
+ }
2789
+ function useTypeInferredForm(formConfig, options = {}) {
2790
+ return useInferredForm(formConfig.schema, formConfig.fields, options);
2791
+ }
2792
+
2793
+ // src/utils/performance.ts
2794
+ import { useCallback as useCallback3, useMemo as useMemo2, useRef as useRef2 } from "react";
2795
+ function debounce(func, delay) {
2796
+ let timeoutId;
2797
+ return (...args) => {
2798
+ clearTimeout(timeoutId);
2799
+ timeoutId = setTimeout(() => func(...args), delay);
2800
+ };
2801
+ }
2802
+ function throttle(func, limit) {
2803
+ let inThrottle;
2804
+ return (...args) => {
2805
+ if (!inThrottle) {
2806
+ func(...args);
2807
+ inThrottle = true;
2808
+ setTimeout(() => inThrottle = false, limit);
2809
+ }
2810
+ };
2811
+ }
2812
+ function useMemoizedCallback(callback, deps) {
2813
+ const callbackRef = useRef2(callback);
2814
+ callbackRef.current = callback;
2815
+ return useCallback3(
2816
+ ((...args) => callbackRef.current(...args)),
2817
+ deps
2818
+ );
2819
+ }
2820
+ function shallowEqual(prevProps, nextProps) {
2821
+ const prevKeys = Object.keys(prevProps);
2822
+ const nextKeys = Object.keys(nextProps);
2823
+ if (prevKeys.length !== nextKeys.length) {
2824
+ return false;
2825
+ }
2826
+ for (const key of prevKeys) {
2827
+ if (prevProps[key] !== nextProps[key]) {
2828
+ return false;
2829
+ }
2830
+ }
2831
+ return true;
2832
+ }
2833
+ function deepEqual(prevProps, nextProps) {
2834
+ if (prevProps === nextProps) {
2835
+ return true;
2836
+ }
2837
+ if (typeof prevProps !== typeof nextProps) {
2838
+ return false;
2839
+ }
2840
+ if (typeof prevProps !== "object" || prevProps === null || nextProps === null) {
2841
+ return prevProps === nextProps;
2842
+ }
2843
+ const prevKeys = Object.keys(prevProps);
2844
+ const nextKeys = Object.keys(nextProps);
2845
+ if (prevKeys.length !== nextKeys.length) {
2846
+ return false;
2847
+ }
2848
+ for (const key of prevKeys) {
2849
+ if (!nextKeys.includes(key)) {
2850
+ return false;
2851
+ }
2852
+ if (!deepEqual(prevProps[key], nextProps[key])) {
2853
+ return false;
2854
+ }
2855
+ }
2856
+ return true;
2857
+ }
2858
+ function usePerformanceMonitor(componentName, enabled = process.env.NODE_ENV === "development") {
2859
+ const renderCountRef = useRef2(0);
2860
+ const lastRenderTimeRef = useRef2(Date.now());
2861
+ if (enabled) {
2862
+ renderCountRef.current += 1;
2863
+ const now = Date.now();
2864
+ const timeSinceLastRender = now - lastRenderTimeRef.current;
2865
+ console.log(`[Performance] ${componentName}:`, {
2866
+ renderCount: renderCountRef.current,
2867
+ timeSinceLastRender: `${timeSinceLastRender}ms`
2868
+ });
2869
+ lastRenderTimeRef.current = now;
2870
+ }
2871
+ return {
2872
+ renderCount: renderCountRef.current,
2873
+ resetRenderCount: () => {
2874
+ renderCountRef.current = 0;
2875
+ }
2876
+ };
2877
+ }
2878
+ function createOptimizedFieldHandler(onChange, options = {}) {
2879
+ const { debounce: debounceMs, throttle: throttleMs, validate = false } = options;
2880
+ let handler = onChange;
2881
+ if (throttleMs) {
2882
+ handler = throttle(handler, throttleMs);
2883
+ }
2884
+ if (debounceMs) {
2885
+ handler = debounce(handler, debounceMs);
2886
+ }
2887
+ return handler;
2888
+ }
2889
+ function useMemoizedFieldProps(props, deps) {
2890
+ return useMemo2(() => props, deps);
2891
+ }
2892
+ function useBatchedFieldUpdates(form, fields) {
2893
+ const batchRef = useRef2({});
2894
+ const timeoutRef = useRef2(void 0);
2895
+ const batchUpdate = useCallback3((fieldName, value) => {
2896
+ batchRef.current[fieldName] = value;
2897
+ if (timeoutRef.current) {
2898
+ clearTimeout(timeoutRef.current);
2899
+ }
2900
+ timeoutRef.current = setTimeout(() => {
2901
+ Object.entries(batchRef.current).forEach(([key, val]) => {
2902
+ form.setValue(key, val);
2903
+ });
2904
+ batchRef.current = {};
2905
+ }, 16);
2906
+ }, [form]);
2907
+ return { batchUpdate };
2908
+ }
2909
+
2910
+ // src/builders/validation-helpers.ts
2911
+ import { z as z4 } from "zod";
2912
+ var validationPatterns = {
2913
+ // Email validation
2914
+ email: z4.string().email("Please enter a valid email address"),
2915
+ // Phone number validation (US format)
2916
+ phoneUS: z4.string().regex(
2917
+ /^\(\d{3}\) \d{3}-\d{4}$/,
2918
+ "Please enter a valid phone number (XXX) XXX-XXXX"
2919
+ ),
2920
+ // Phone number validation (international)
2921
+ phoneInternational: z4.string().regex(
2922
+ /^\+?[\d\s\-\(\)]+$/,
2923
+ "Please enter a valid phone number"
2924
+ ),
2925
+ // URL validation
2926
+ url: z4.string().url("Please enter a valid URL"),
2927
+ // Password validation
2928
+ password: z4.string().min(8, "Password must be at least 8 characters").regex(/[A-Z]/, "Password must contain at least one uppercase letter").regex(/[a-z]/, "Password must contain at least one lowercase letter").regex(/[0-9]/, "Password must contain at least one number").regex(/[^A-Za-z0-9]/, "Password must contain at least one special character"),
2929
+ // Strong password validation
2930
+ strongPassword: z4.string().min(12, "Password must be at least 12 characters").regex(/[A-Z]/, "Password must contain at least one uppercase letter").regex(/[a-z]/, "Password must contain at least one lowercase letter").regex(/[0-9]/, "Password must contain at least one number").regex(/[^A-Za-z0-9]/, "Password must contain at least one special character"),
2931
+ // Credit card validation
2932
+ creditCard: z4.string().regex(
2933
+ /^[0-9]{4}[\s\-]?[0-9]{4}[\s\-]?[0-9]{4}[\s\-]?[0-9]{4}$/,
2934
+ "Please enter a valid credit card number"
2935
+ ),
2936
+ // SSN validation
2937
+ ssn: z4.string().regex(
2938
+ /^\d{3}-\d{2}-\d{4}$/,
2939
+ "Please enter a valid SSN (XXX-XX-XXXX)"
2940
+ ),
2941
+ // ZIP code validation
2942
+ zipCode: z4.string().regex(
2943
+ /^\d{5}(-\d{4})?$/,
2944
+ "Please enter a valid ZIP code"
2945
+ ),
2946
+ // Date validation (MM/DD/YYYY)
2947
+ date: z4.string().regex(
2948
+ /^(0[1-9]|1[0-2])\/(0[1-9]|[12][0-9]|3[01])\/\d{4}$/,
2949
+ "Please enter a valid date (MM/DD/YYYY)"
2950
+ ),
2951
+ // Time validation (HH:MM AM/PM)
2952
+ time: z4.string().regex(
2953
+ /^(0[1-9]|1[0-2]):[0-5][0-9] (AM|PM)$/i,
2954
+ "Please enter a valid time (HH:MM AM/PM)"
2955
+ )
2956
+ };
2957
+ var asyncValidation = {
2958
+ /**
2959
+ * Email availability check
2960
+ */
2961
+ emailAvailability: async (email) => {
2962
+ return new Promise((resolve) => {
2963
+ setTimeout(() => {
2964
+ const takenEmails = ["test@example.com", "admin@example.com"];
2965
+ resolve(!takenEmails.includes(email));
2966
+ }, 1e3);
2967
+ });
2968
+ },
2969
+ /**
2970
+ * Username availability check
2971
+ */
2972
+ usernameAvailability: async (username) => {
2973
+ return new Promise((resolve) => {
2974
+ setTimeout(() => {
2975
+ const takenUsernames = ["admin", "test", "user"];
2976
+ resolve(!takenUsernames.includes(username.toLowerCase()));
2977
+ }, 1e3);
2978
+ });
2979
+ }
2980
+ };
2981
+ var errorMessages = {
2982
+ required: (fieldName) => `${fieldName} is required`,
2983
+ minLength: (fieldName, min) => `${fieldName} must be at least ${min} characters`,
2984
+ maxLength: (fieldName, max) => `${fieldName} must be no more than ${max} characters`,
2985
+ min: (fieldName, min) => `${fieldName} must be at least ${min}`,
2986
+ max: (fieldName, max) => `${fieldName} must be no more than ${max}`,
2987
+ pattern: (fieldName) => `${fieldName} format is invalid`,
2988
+ email: () => "Please enter a valid email address",
2989
+ url: () => "Please enter a valid URL",
2990
+ phone: () => "Please enter a valid phone number",
2991
+ date: () => "Please enter a valid date",
2992
+ time: () => "Please enter a valid time"
2993
+ };
2994
+ var serverValidation = {
2995
+ /**
2996
+ * Apply server errors to form
2997
+ */
2998
+ applyServerErrors: (errors, setError) => {
2999
+ Object.entries(errors).forEach(([field2, messages]) => {
3000
+ setError(field2, {
3001
+ type: "server",
3002
+ message: messages[0]
3003
+ // Use first error message
3004
+ });
3005
+ });
3006
+ },
3007
+ /**
3008
+ * Clear server errors
3009
+ */
3010
+ clearServerErrors: (fields, clearErrors) => {
3011
+ fields.forEach((field2) => {
3012
+ clearErrors(field2, "server");
3013
+ });
3014
+ }
3015
+ };
3016
+ var validationUtils = {
3017
+ /**
3018
+ * Debounced validation
3019
+ */
3020
+ debounceValidation: (fn, delay = 300) => {
3021
+ let timeoutId;
3022
+ return (...args) => {
3023
+ clearTimeout(timeoutId);
3024
+ timeoutId = setTimeout(() => fn(...args), delay);
3025
+ };
3026
+ },
3027
+ /**
3028
+ * Validate form data against schema
3029
+ */
3030
+ validateForm: async (data, schema) => {
3031
+ try {
3032
+ await schema.parseAsync(data);
3033
+ return { success: true, errors: {} };
3034
+ } catch (error) {
3035
+ if (error instanceof z4.ZodError) {
3036
+ const errors = {};
3037
+ error.issues.forEach((err) => {
3038
+ const path = err.path.join(".");
3039
+ errors[path] = err.message;
3040
+ });
3041
+ return { success: false, errors };
3042
+ }
3043
+ throw error;
3044
+ }
3045
+ },
3046
+ /**
3047
+ * Get field error message
3048
+ */
3049
+ getFieldError: (errors, field2) => {
3050
+ return errors[field2];
3051
+ },
3052
+ /**
3053
+ * Check if field has error
3054
+ */
3055
+ hasFieldError: (errors, field2) => {
3056
+ return !!errors[field2];
3057
+ }
3058
+ };
1488
3059
  export {
3060
+ AdvancedFieldBuilder,
3061
+ BasicFormBuilder,
1489
3062
  CheckboxField,
3063
+ CommonFields,
3064
+ ConditionalField,
1490
3065
  ConfigurableForm,
1491
3066
  DateField,
3067
+ DynamicSectionField,
3068
+ FieldArrayBuilder,
3069
+ FieldArrayField,
3070
+ FieldArrayItemBuilder,
1492
3071
  FileField,
1493
3072
  FontPickerField,
1494
3073
  FormField,
3074
+ FormFieldHelpers,
1495
3075
  FormProvider,
3076
+ FormStatus,
3077
+ FormToast,
1496
3078
  HeroHookFormProvider,
1497
3079
  InputField,
1498
3080
  RadioGroupField,
@@ -1501,13 +3083,20 @@ export {
1501
3083
  SubmitButton,
1502
3084
  SwitchField,
1503
3085
  TextareaField,
3086
+ TypeInferredBuilder,
1504
3087
  ZodForm,
1505
3088
  applyServerErrors,
3089
+ asyncValidation,
1506
3090
  commonValidations,
3091
+ createAdvancedBuilder,
3092
+ createBasicFormBuilder,
1507
3093
  createConditionalSchema,
1508
3094
  createConfirmPasswordSchema,
1509
3095
  createDateSchema,
1510
3096
  createEmailSchema,
3097
+ createField,
3098
+ createFieldArrayBuilder,
3099
+ createFieldArrayItemBuilder,
1511
3100
  createFileSchema,
1512
3101
  createFormTestUtils,
1513
3102
  createFutureDateSchema,
@@ -1515,24 +3104,47 @@ export {
1515
3104
  createMinLengthSchema,
1516
3105
  createMockFormData,
1517
3106
  createMockFormErrors,
3107
+ createNestedPathBuilder,
1518
3108
  createNumberRangeSchema,
3109
+ createOptimizedFieldHandler,
1519
3110
  createPasswordSchema,
1520
3111
  createPastDateSchema,
1521
3112
  createPhoneSchema,
1522
3113
  createRequiredCheckboxSchema,
1523
3114
  createRequiredSchema,
3115
+ createTypeInferredBuilder,
1524
3116
  createUrlSchema,
1525
3117
  createZodFormConfig,
3118
+ crossFieldValidation,
3119
+ debounce,
3120
+ deepEqual,
3121
+ defineInferredForm,
3122
+ errorMessages,
3123
+ field,
1526
3124
  getFieldError,
1527
3125
  getFormErrors,
1528
3126
  hasFieldError,
1529
3127
  hasFormErrors,
3128
+ serverValidation,
3129
+ shallowEqual,
1530
3130
  simulateFieldInput,
1531
3131
  simulateFormSubmission,
1532
- useFormContext2 as useFormContext,
3132
+ throttle,
3133
+ useBatchedFieldUpdates,
3134
+ useDebouncedFieldValidation,
3135
+ useDebouncedValidation,
3136
+ useEnhancedFormState,
3137
+ useFormContext5 as useFormContext,
1533
3138
  useFormHelper,
1534
3139
  useHeroForm,
1535
3140
  useHeroHookFormDefaults,
3141
+ useInferredForm,
3142
+ useMemoizedCallback,
3143
+ useMemoizedFieldProps,
3144
+ usePerformanceMonitor,
3145
+ useTypeInferredForm,
1536
3146
  useZodForm,
3147
+ validationPatterns,
3148
+ validationUtils,
1537
3149
  waitForFormState
1538
3150
  };