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