@rachelallyson/hero-hook-form 1.1.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.
@@ -6,8 +6,8 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
6
6
  });
7
7
 
8
8
  // src/components/Form.tsx
9
- import React13 from "react";
10
- import { Button as Button2 } from "@heroui/react";
9
+ import React16 from "react";
10
+ import { Button as Button3 } from "@heroui/react";
11
11
 
12
12
  // src/hooks/useFormHelper.ts
13
13
  import { useState } from "react";
@@ -75,8 +75,8 @@ function useFormHelper({
75
75
  }
76
76
 
77
77
  // src/components/FormField.tsx
78
- import React12 from "react";
79
- import { useWatch } from "react-hook-form";
78
+ import React15 from "react";
79
+ import { useWatch as useWatch3 } from "react-hook-form";
80
80
 
81
81
  // src/fields/CheckboxField.tsx
82
82
  import React2 from "react";
@@ -203,16 +203,16 @@ function CheckboxField(props) {
203
203
  {
204
204
  control,
205
205
  name,
206
- render: ({ field, fieldState }) => /* @__PURE__ */ React2.createElement("div", { className }, /* @__PURE__ */ React2.createElement(
206
+ render: ({ field: field2, fieldState }) => /* @__PURE__ */ React2.createElement("div", { className }, /* @__PURE__ */ React2.createElement(
207
207
  Checkbox,
208
208
  {
209
209
  ...defaults.checkbox,
210
210
  ...checkboxProps,
211
211
  isDisabled,
212
212
  isInvalid: Boolean(fieldState.error),
213
- isSelected: Boolean(field.value),
214
- onBlur: field.onBlur,
215
- onValueChange: (val) => field.onChange(val)
213
+ isSelected: Boolean(field2.value),
214
+ onBlur: field2.onBlur,
215
+ onValueChange: (val) => field2.onChange(val)
216
216
  },
217
217
  label
218
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),
@@ -221,13 +221,43 @@ function CheckboxField(props) {
221
221
  );
222
222
  }
223
223
 
224
- // src/fields/DateField.tsx
224
+ // src/fields/ConditionalField.tsx
225
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";
226
256
  import { Controller as Controller2 } from "react-hook-form";
227
257
  function CoercedDateInput(props) {
228
- const { dateProps, description, disabled, errorMessage, field, label } = props;
258
+ const { dateProps, description, disabled, errorMessage, field: field2, label } = props;
229
259
  const defaults = useHeroHookFormDefaults();
230
- return /* @__PURE__ */ React3.createElement(
260
+ return /* @__PURE__ */ React4.createElement(
231
261
  DateInput,
232
262
  {
233
263
  ...defaults.dateInput,
@@ -237,9 +267,9 @@ function CoercedDateInput(props) {
237
267
  isDisabled: disabled,
238
268
  isInvalid: Boolean(errorMessage),
239
269
  label,
240
- value: field.value ?? null,
241
- onBlur: field.onBlur,
242
- onChange: field.onChange
270
+ value: field2.value ?? null,
271
+ onBlur: field2.onBlur,
272
+ onChange: field2.onChange
243
273
  }
244
274
  );
245
275
  }
@@ -255,12 +285,12 @@ function DateField(props) {
255
285
  rules,
256
286
  transform
257
287
  } = props;
258
- return /* @__PURE__ */ React3.createElement(
288
+ return /* @__PURE__ */ React4.createElement(
259
289
  Controller2,
260
290
  {
261
291
  control,
262
292
  name,
263
- render: ({ field, fieldState }) => /* @__PURE__ */ React3.createElement("div", { className }, /* @__PURE__ */ React3.createElement(
293
+ render: ({ field: field2, fieldState }) => /* @__PURE__ */ React4.createElement("div", { className }, /* @__PURE__ */ React4.createElement(
264
294
  CoercedDateInput,
265
295
  {
266
296
  dateProps,
@@ -268,8 +298,8 @@ function DateField(props) {
268
298
  disabled: isDisabled,
269
299
  errorMessage: fieldState.error?.message,
270
300
  field: {
271
- ...field,
272
- onChange: (value) => field.onChange(transform ? transform(value) : value)
301
+ ...field2,
302
+ onChange: (value) => field2.onChange(transform ? transform(value) : value)
273
303
  },
274
304
  label
275
305
  }
@@ -279,8 +309,136 @@ function DateField(props) {
279
309
  );
280
310
  }
281
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
+
282
440
  // src/fields/FileField.tsx
283
- import React4 from "react";
441
+ import React7 from "react";
284
442
  import { Controller as Controller3 } from "react-hook-form";
285
443
  function CoercedFileInput(props) {
286
444
  const {
@@ -288,13 +446,13 @@ function CoercedFileInput(props) {
288
446
  description,
289
447
  disabled,
290
448
  errorMessage,
291
- field,
449
+ field: field2,
292
450
  fileProps,
293
451
  label,
294
452
  multiple
295
453
  } = props;
296
454
  const defaults = useHeroHookFormDefaults();
297
- return /* @__PURE__ */ React4.createElement(
455
+ return /* @__PURE__ */ React7.createElement(
298
456
  Input,
299
457
  {
300
458
  ...defaults.input,
@@ -307,11 +465,11 @@ function CoercedFileInput(props) {
307
465
  label,
308
466
  multiple,
309
467
  type: "file",
310
- value: field.value ? "" : "",
311
- onBlur: field.onBlur,
468
+ value: field2.value ? "" : "",
469
+ onBlur: field2.onBlur,
312
470
  onChange: (e) => {
313
471
  const target = e.target;
314
- field.onChange(target.files);
472
+ field2.onChange(target.files);
315
473
  }
316
474
  }
317
475
  );
@@ -330,12 +488,12 @@ function FileField(props) {
330
488
  rules,
331
489
  transform
332
490
  } = props;
333
- return /* @__PURE__ */ React4.createElement(
491
+ return /* @__PURE__ */ React7.createElement(
334
492
  Controller3,
335
493
  {
336
494
  control,
337
495
  name,
338
- render: ({ field, fieldState }) => /* @__PURE__ */ React4.createElement("div", { className }, /* @__PURE__ */ React4.createElement(
496
+ render: ({ field: field2, fieldState }) => /* @__PURE__ */ React7.createElement("div", { className }, /* @__PURE__ */ React7.createElement(
339
497
  CoercedFileInput,
340
498
  {
341
499
  accept,
@@ -343,8 +501,8 @@ function FileField(props) {
343
501
  disabled: isDisabled,
344
502
  errorMessage: fieldState.error?.message,
345
503
  field: {
346
- ...field,
347
- onChange: (value) => field.onChange(transform ? transform(value) : value)
504
+ ...field2,
505
+ onChange: (value) => field2.onChange(transform ? transform(value) : value)
348
506
  },
349
507
  fileProps,
350
508
  label,
@@ -357,15 +515,12 @@ function FileField(props) {
357
515
  }
358
516
 
359
517
  // src/fields/FontPickerField.tsx
360
- import React5 from "react";
518
+ import React8 from "react";
361
519
  import { Controller as Controller4 } from "react-hook-form";
362
520
  var FontPickerComponent = null;
363
- try {
364
- const fontPickerModule = __require("@rachelallyson/heroui-font-picker");
365
- FontPickerComponent = fontPickerModule.FontPicker;
366
- } catch (e) {
367
- console.debug("Font picker package not available - FontPickerField will show fallback UI");
368
- }
521
+ var fontPickerLoaded = false;
522
+ var fontPickerLoading = false;
523
+ var loadingCallbacks = [];
369
524
  function FontPickerField(props) {
370
525
  const {
371
526
  className,
@@ -377,21 +532,86 @@ function FontPickerField(props) {
377
532
  name,
378
533
  rules
379
534
  } = props;
380
- if (!FontPickerComponent) {
381
- 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."))));
535
+ const [fontPickerState, setFontPickerState] = React8.useState({
536
+ component: FontPickerComponent,
537
+ loading: false,
538
+ error: null
539
+ });
540
+ React8.useEffect(() => {
541
+ if (fontPickerLoaded && FontPickerComponent) {
542
+ setFontPickerState({
543
+ component: FontPickerComponent,
544
+ loading: false,
545
+ error: null
546
+ });
547
+ return;
548
+ }
549
+ if (fontPickerLoading) {
550
+ setFontPickerState((prev) => ({ ...prev, loading: true }));
551
+ const callback = () => {
552
+ if (fontPickerLoaded && FontPickerComponent) {
553
+ setFontPickerState({
554
+ component: FontPickerComponent,
555
+ loading: false,
556
+ error: null
557
+ });
558
+ } else {
559
+ setFontPickerState({
560
+ component: null,
561
+ loading: false,
562
+ error: "Font picker package not found"
563
+ });
564
+ }
565
+ };
566
+ loadingCallbacks.push(callback);
567
+ return;
568
+ }
569
+ const loadFontPicker = async () => {
570
+ fontPickerLoading = true;
571
+ setFontPickerState((prev) => ({ ...prev, loading: true }));
572
+ try {
573
+ const fontPickerModule = await import("@rachelallyson/heroui-font-picker");
574
+ FontPickerComponent = fontPickerModule.FontPicker || fontPickerModule.default;
575
+ fontPickerLoaded = true;
576
+ fontPickerLoading = false;
577
+ setFontPickerState({
578
+ component: FontPickerComponent,
579
+ loading: false,
580
+ error: null
581
+ });
582
+ loadingCallbacks.forEach((callback) => callback());
583
+ loadingCallbacks.length = 0;
584
+ } catch (error) {
585
+ fontPickerLoading = false;
586
+ setFontPickerState({
587
+ component: null,
588
+ loading: false,
589
+ error: "Font picker package not found"
590
+ });
591
+ loadingCallbacks.forEach((callback) => callback());
592
+ loadingCallbacks.length = 0;
593
+ }
594
+ };
595
+ void loadFontPicker();
596
+ }, []);
597
+ if (fontPickerState.loading) {
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..."))));
599
+ }
600
+ if (!fontPickerState.component) {
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."))));
382
602
  }
383
- return /* @__PURE__ */ React5.createElement(
603
+ return /* @__PURE__ */ React8.createElement(
384
604
  Controller4,
385
605
  {
386
606
  control,
387
607
  name,
388
- render: ({ field, fieldState }) => /* @__PURE__ */ React5.createElement(
389
- FontPickerComponent,
608
+ render: ({ field: field2, fieldState }) => /* @__PURE__ */ React8.createElement(
609
+ fontPickerState.component,
390
610
  {
391
611
  label,
392
612
  description,
393
- value: field.value ?? "",
394
- onSelectionChange: (value) => field.onChange(value),
613
+ value: field2.value ?? "",
614
+ onSelectionChange: (value) => field2.onChange(value),
395
615
  errorMessage: fieldState.error?.message,
396
616
  isDisabled,
397
617
  className,
@@ -404,12 +624,12 @@ function FontPickerField(props) {
404
624
  }
405
625
 
406
626
  // src/fields/InputField.tsx
407
- import React6 from "react";
627
+ import React9 from "react";
408
628
  import { Controller as Controller5 } from "react-hook-form";
409
629
  function CoercedInput(props) {
410
- const { description, disabled, errorMessage, field, inputProps, label } = props;
630
+ const { description, disabled, errorMessage, field: field2, inputProps, label } = props;
411
631
  const defaults = useHeroHookFormDefaults();
412
- return /* @__PURE__ */ React6.createElement(
632
+ return /* @__PURE__ */ React9.createElement(
413
633
  Input,
414
634
  {
415
635
  ...defaults.input,
@@ -419,13 +639,13 @@ function CoercedInput(props) {
419
639
  isDisabled: disabled,
420
640
  isInvalid: Boolean(errorMessage),
421
641
  label,
422
- value: field.value ?? "",
423
- onBlur: field.onBlur,
424
- onValueChange: field.onChange
642
+ value: field2.value ?? "",
643
+ onBlur: field2.onBlur,
644
+ onValueChange: field2.onChange
425
645
  }
426
646
  );
427
647
  }
428
- function InputField(props) {
648
+ var InputField = React9.memo((props) => {
429
649
  const {
430
650
  className,
431
651
  control,
@@ -437,27 +657,27 @@ function InputField(props) {
437
657
  rules,
438
658
  transform
439
659
  } = props;
440
- return /* @__PURE__ */ React6.createElement(
660
+ return /* @__PURE__ */ React9.createElement(
441
661
  Controller5,
442
662
  {
443
663
  control,
444
664
  name,
445
- render: ({ field, fieldState }) => /* @__PURE__ */ React6.createElement("div", { className }, /* @__PURE__ */ React6.createElement(
665
+ render: ({ field: field2, fieldState }) => /* @__PURE__ */ React9.createElement("div", { className }, /* @__PURE__ */ React9.createElement(
446
666
  CoercedInput,
447
667
  {
448
668
  description,
449
669
  disabled: isDisabled,
450
670
  errorMessage: fieldState.error?.message,
451
671
  field: {
452
- ...field,
672
+ ...field2,
453
673
  onChange: (value) => {
454
674
  if (inputProps?.type === "number") {
455
675
  const numValue = value === "" ? void 0 : Number(value);
456
- field.onChange(
676
+ field2.onChange(
457
677
  transform ? transform(String(numValue)) : numValue
458
678
  );
459
679
  } else {
460
- field.onChange(transform ? transform(value) : value);
680
+ field2.onChange(transform ? transform(value) : value);
461
681
  }
462
682
  }
463
683
  },
@@ -468,10 +688,10 @@ function InputField(props) {
468
688
  rules
469
689
  }
470
690
  );
471
- }
691
+ });
472
692
 
473
693
  // src/fields/RadioGroupField.tsx
474
- import React7 from "react";
694
+ import React10 from "react";
475
695
  import { Controller as Controller6 } from "react-hook-form";
476
696
  function RadioGroupField(props) {
477
697
  const {
@@ -486,12 +706,12 @@ function RadioGroupField(props) {
486
706
  rules
487
707
  } = props;
488
708
  const defaults = useHeroHookFormDefaults();
489
- return /* @__PURE__ */ React7.createElement(
709
+ return /* @__PURE__ */ React10.createElement(
490
710
  Controller6,
491
711
  {
492
712
  control,
493
713
  name,
494
- render: ({ field, fieldState }) => /* @__PURE__ */ React7.createElement("div", { className }, /* @__PURE__ */ React7.createElement(
714
+ render: ({ field: field2, fieldState }) => /* @__PURE__ */ React10.createElement("div", { className }, /* @__PURE__ */ React10.createElement(
495
715
  RadioGroup,
496
716
  {
497
717
  ...defaults.radioGroup,
@@ -500,11 +720,11 @@ function RadioGroupField(props) {
500
720
  isDisabled,
501
721
  isInvalid: Boolean(fieldState.error),
502
722
  label,
503
- value: String(field.value ?? ""),
504
- onBlur: field.onBlur,
505
- onValueChange: (val) => field.onChange(val)
723
+ value: String(field2.value ?? ""),
724
+ onBlur: field2.onBlur,
725
+ onValueChange: (val) => field2.onChange(val)
506
726
  },
507
- options.map((opt) => /* @__PURE__ */ React7.createElement(
727
+ options.map((opt) => /* @__PURE__ */ React10.createElement(
508
728
  Radio,
509
729
  {
510
730
  key: String(opt.value),
@@ -513,14 +733,14 @@ function RadioGroupField(props) {
513
733
  },
514
734
  opt.label
515
735
  ))
516
- ), 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),
517
737
  rules
518
738
  }
519
739
  );
520
740
  }
521
741
 
522
742
  // src/fields/SelectField.tsx
523
- import React8 from "react";
743
+ import React11 from "react";
524
744
  import { Controller as Controller7 } from "react-hook-form";
525
745
  function SelectField(props) {
526
746
  const {
@@ -536,14 +756,14 @@ function SelectField(props) {
536
756
  selectProps
537
757
  } = props;
538
758
  const defaults = useHeroHookFormDefaults();
539
- return /* @__PURE__ */ React8.createElement(
759
+ return /* @__PURE__ */ React11.createElement(
540
760
  Controller7,
541
761
  {
542
762
  control,
543
763
  name,
544
- render: ({ field, fieldState }) => {
545
- const selectedKey = field.value;
546
- 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(
547
767
  Select,
548
768
  {
549
769
  ...defaults.select,
@@ -558,10 +778,10 @@ function SelectField(props) {
558
778
  onSelectionChange: (keys) => {
559
779
  const keyArray = Array.from(keys);
560
780
  const next = keyArray[0] ?? "";
561
- field.onChange(next);
781
+ field2.onChange(next);
562
782
  }
563
783
  },
564
- options.map((opt) => /* @__PURE__ */ React8.createElement(
784
+ options.map((opt) => /* @__PURE__ */ React11.createElement(
565
785
  SelectItem,
566
786
  {
567
787
  key: String(opt.value),
@@ -578,12 +798,12 @@ function SelectField(props) {
578
798
  }
579
799
 
580
800
  // src/fields/SliderField.tsx
581
- import React9 from "react";
801
+ import React12 from "react";
582
802
  import { Controller as Controller8 } from "react-hook-form";
583
803
  function CoercedSlider(props) {
584
- const { description, disabled, errorMessage, field, label, sliderProps } = props;
804
+ const { description, disabled, errorMessage, field: field2, label, sliderProps } = props;
585
805
  const defaults = useHeroHookFormDefaults();
586
- return /* @__PURE__ */ React9.createElement(
806
+ return /* @__PURE__ */ React12.createElement(
587
807
  Slider,
588
808
  {
589
809
  ...defaults.slider,
@@ -593,9 +813,9 @@ function CoercedSlider(props) {
593
813
  isDisabled: disabled,
594
814
  isInvalid: Boolean(errorMessage),
595
815
  label,
596
- value: field.value ?? 0,
597
- onBlur: field.onBlur,
598
- onValueChange: field.onChange
816
+ value: field2.value ?? 0,
817
+ onBlur: field2.onBlur,
818
+ onValueChange: field2.onChange
599
819
  }
600
820
  );
601
821
  }
@@ -611,20 +831,20 @@ function SliderField(props) {
611
831
  sliderProps,
612
832
  transform
613
833
  } = props;
614
- return /* @__PURE__ */ React9.createElement(
834
+ return /* @__PURE__ */ React12.createElement(
615
835
  Controller8,
616
836
  {
617
837
  control,
618
838
  name,
619
- render: ({ field, fieldState }) => /* @__PURE__ */ React9.createElement("div", { className }, /* @__PURE__ */ React9.createElement(
839
+ render: ({ field: field2, fieldState }) => /* @__PURE__ */ React12.createElement("div", { className }, /* @__PURE__ */ React12.createElement(
620
840
  CoercedSlider,
621
841
  {
622
842
  description,
623
843
  disabled: isDisabled,
624
844
  errorMessage: fieldState.error?.message,
625
845
  field: {
626
- ...field,
627
- onChange: (value) => field.onChange(transform ? transform(value) : value)
846
+ ...field2,
847
+ onChange: (value) => field2.onChange(transform ? transform(value) : value)
628
848
  },
629
849
  label,
630
850
  sliderProps
@@ -636,7 +856,7 @@ function SliderField(props) {
636
856
  }
637
857
 
638
858
  // src/fields/SwitchField.tsx
639
- import React10 from "react";
859
+ import React13 from "react";
640
860
  import { Controller as Controller9 } from "react-hook-form";
641
861
  function SwitchField(props) {
642
862
  const {
@@ -650,30 +870,30 @@ function SwitchField(props) {
650
870
  switchProps
651
871
  } = props;
652
872
  const defaults = useHeroHookFormDefaults();
653
- return /* @__PURE__ */ React10.createElement(
873
+ return /* @__PURE__ */ React13.createElement(
654
874
  Controller9,
655
875
  {
656
876
  control,
657
877
  name,
658
- render: ({ field, fieldState }) => /* @__PURE__ */ React10.createElement("div", { className }, /* @__PURE__ */ React10.createElement(
878
+ render: ({ field: field2, fieldState }) => /* @__PURE__ */ React13.createElement("div", { className }, /* @__PURE__ */ React13.createElement(
659
879
  Switch,
660
880
  {
661
881
  ...defaults.switch,
662
882
  ...switchProps,
663
883
  isDisabled,
664
- isSelected: Boolean(field.value),
665
- onBlur: field.onBlur,
666
- onValueChange: (val) => field.onChange(val)
884
+ isSelected: Boolean(field2.value),
885
+ onBlur: field2.onBlur,
886
+ onValueChange: (val) => field2.onChange(val)
667
887
  },
668
888
  label
669
- ), 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),
670
890
  rules
671
891
  }
672
892
  );
673
893
  }
674
894
 
675
895
  // src/fields/TextareaField.tsx
676
- import React11 from "react";
896
+ import React14 from "react";
677
897
  import { Controller as Controller10 } from "react-hook-form";
678
898
  function TextareaField(props) {
679
899
  const {
@@ -687,12 +907,12 @@ function TextareaField(props) {
687
907
  textareaProps
688
908
  } = props;
689
909
  const defaults = useHeroHookFormDefaults();
690
- return /* @__PURE__ */ React11.createElement(
910
+ return /* @__PURE__ */ React14.createElement(
691
911
  Controller10,
692
912
  {
693
913
  control,
694
914
  name,
695
- render: ({ field, fieldState }) => /* @__PURE__ */ React11.createElement("div", { className }, /* @__PURE__ */ React11.createElement(
915
+ render: ({ field: field2, fieldState }) => /* @__PURE__ */ React14.createElement("div", { className }, /* @__PURE__ */ React14.createElement(
696
916
  Textarea,
697
917
  {
698
918
  ...defaults.textarea,
@@ -702,9 +922,9 @@ function TextareaField(props) {
702
922
  isDisabled,
703
923
  isInvalid: Boolean(fieldState.error),
704
924
  label,
705
- value: field.value ?? "",
706
- onBlur: field.onBlur,
707
- onValueChange: field.onChange
925
+ value: field2.value ?? "",
926
+ onBlur: field2.onBlur,
927
+ onValueChange: field2.onChange
708
928
  }
709
929
  )),
710
930
  rules
@@ -713,13 +933,16 @@ function TextareaField(props) {
713
933
  }
714
934
 
715
935
  // src/components/FormField.tsx
716
- function FormField({
936
+ var FormField = React15.memo(({
717
937
  config,
718
938
  form,
719
939
  submissionState
720
- }) {
940
+ }) => {
941
+ if (!form || !form.control) {
942
+ return null;
943
+ }
721
944
  const { control } = form;
722
- const watchedValues = useWatch({ control });
945
+ const watchedValues = useWatch3({ control });
723
946
  if (config.condition && !config.condition(watchedValues)) {
724
947
  return null;
725
948
  }
@@ -741,7 +964,7 @@ function FormField({
741
964
  };
742
965
  switch (config.type) {
743
966
  case "input":
744
- return /* @__PURE__ */ React12.createElement(
967
+ return /* @__PURE__ */ React15.createElement(
745
968
  InputField,
746
969
  {
747
970
  ...baseProps,
@@ -751,7 +974,7 @@ function FormField({
751
974
  }
752
975
  );
753
976
  case "textarea":
754
- return /* @__PURE__ */ React12.createElement(
977
+ return /* @__PURE__ */ React15.createElement(
755
978
  TextareaField,
756
979
  {
757
980
  ...baseProps,
@@ -761,7 +984,7 @@ function FormField({
761
984
  }
762
985
  );
763
986
  case "select":
764
- return /* @__PURE__ */ React12.createElement(
987
+ return /* @__PURE__ */ React15.createElement(
765
988
  SelectField,
766
989
  {
767
990
  ...baseProps,
@@ -775,7 +998,7 @@ function FormField({
775
998
  }
776
999
  );
777
1000
  case "checkbox":
778
- return /* @__PURE__ */ React12.createElement(
1001
+ return /* @__PURE__ */ React15.createElement(
779
1002
  CheckboxField,
780
1003
  {
781
1004
  ...baseProps,
@@ -785,7 +1008,7 @@ function FormField({
785
1008
  }
786
1009
  );
787
1010
  case "radio":
788
- return /* @__PURE__ */ React12.createElement(
1011
+ return /* @__PURE__ */ React15.createElement(
789
1012
  RadioGroupField,
790
1013
  {
791
1014
  ...baseProps,
@@ -799,7 +1022,7 @@ function FormField({
799
1022
  }
800
1023
  );
801
1024
  case "switch":
802
- return /* @__PURE__ */ React12.createElement(
1025
+ return /* @__PURE__ */ React15.createElement(
803
1026
  SwitchField,
804
1027
  {
805
1028
  ...baseProps,
@@ -809,7 +1032,7 @@ function FormField({
809
1032
  }
810
1033
  );
811
1034
  case "slider":
812
- return /* @__PURE__ */ React12.createElement(
1035
+ return /* @__PURE__ */ React15.createElement(
813
1036
  SliderField,
814
1037
  {
815
1038
  ...baseProps,
@@ -819,7 +1042,7 @@ function FormField({
819
1042
  }
820
1043
  );
821
1044
  case "date":
822
- return /* @__PURE__ */ React12.createElement(
1045
+ return /* @__PURE__ */ React15.createElement(
823
1046
  DateField,
824
1047
  {
825
1048
  ...baseProps,
@@ -829,7 +1052,7 @@ function FormField({
829
1052
  }
830
1053
  );
831
1054
  case "file":
832
- return /* @__PURE__ */ React12.createElement(
1055
+ return /* @__PURE__ */ React15.createElement(
833
1056
  FileField,
834
1057
  {
835
1058
  ...baseProps,
@@ -841,7 +1064,7 @@ function FormField({
841
1064
  }
842
1065
  );
843
1066
  case "fontPicker":
844
- return /* @__PURE__ */ React12.createElement(
1067
+ return /* @__PURE__ */ React15.createElement(
845
1068
  FontPickerField,
846
1069
  {
847
1070
  ...baseProps,
@@ -858,13 +1081,39 @@ function FormField({
858
1081
  isSubmitting: submissionState.isSubmitting,
859
1082
  name: config.name
860
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
+ );
861
1110
  default: {
862
1111
  const fieldType = config.type;
863
1112
  console.warn(`Unknown field type: ${fieldType}`);
864
1113
  return null;
865
1114
  }
866
1115
  }
867
- }
1116
+ });
868
1117
 
869
1118
  // src/components/Form.tsx
870
1119
  function ConfigurableForm({
@@ -901,16 +1150,16 @@ function ConfigurableForm({
901
1150
  });
902
1151
  const renderFields = () => {
903
1152
  if (layout === "grid") {
904
- return /* @__PURE__ */ React13.createElement(
1153
+ return /* @__PURE__ */ React16.createElement(
905
1154
  "div",
906
1155
  {
907
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"}`
908
1157
  },
909
- fields.map((field) => /* @__PURE__ */ React13.createElement(
1158
+ fields.map((field2) => /* @__PURE__ */ React16.createElement(
910
1159
  FormField,
911
1160
  {
912
- key: field.name,
913
- config: field,
1161
+ key: field2.name,
1162
+ config: field2,
914
1163
  form,
915
1164
  submissionState
916
1165
  }
@@ -918,21 +1167,21 @@ function ConfigurableForm({
918
1167
  );
919
1168
  }
920
1169
  if (layout === "horizontal") {
921
- 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(
922
1171
  FormField,
923
1172
  {
924
- key: field.name,
925
- config: field,
1173
+ key: field2.name,
1174
+ config: field2,
926
1175
  form,
927
1176
  submissionState
928
1177
  }
929
1178
  )));
930
1179
  }
931
- 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(
932
1181
  FormField,
933
1182
  {
934
- key: field.name,
935
- config: field,
1183
+ key: field2.name,
1184
+ config: field2,
936
1185
  form,
937
1186
  submissionState
938
1187
  }
@@ -942,24 +1191,24 @@ function ConfigurableForm({
942
1191
  e.preventDefault();
943
1192
  void handleSubmit();
944
1193
  };
945
- 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(
946
1195
  "div",
947
1196
  {
948
1197
  className: "mb-6 p-4 bg-success-50 border border-success-200 rounded-lg",
949
1198
  "data-testid": "success-message"
950
1199
  },
951
- /* @__PURE__ */ React13.createElement("p", { className: "text-success-800 font-medium" }, "Success!"),
952
- /* @__PURE__ */ React13.createElement("p", { className: "text-success-700 text-sm mt-1" }, "Your request has been processed successfully.")
953
- ), 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(
954
1203
  "div",
955
1204
  {
956
1205
  className: "mb-6 p-4 bg-danger-50 border border-danger-200 rounded-lg",
957
1206
  "data-testid": "error-message"
958
1207
  },
959
- /* @__PURE__ */ React13.createElement("p", { className: "text-danger-800 font-medium" }, "Error"),
960
- /* @__PURE__ */ React13.createElement("p", { className: "text-danger-700 text-sm mt-1" }, error)
961
- ), renderFields(), /* @__PURE__ */ React13.createElement("div", { className: "mt-6 flex gap-3 justify-end" }, /* @__PURE__ */ React13.createElement(
962
- 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,
963
1212
  {
964
1213
  color: "primary",
965
1214
  isDisabled: isSubmitting,
@@ -968,8 +1217,8 @@ function ConfigurableForm({
968
1217
  ...submitButtonProps
969
1218
  },
970
1219
  submitButtonText
971
- ), showResetButton && /* @__PURE__ */ React13.createElement(
972
- Button2,
1220
+ ), showResetButton && /* @__PURE__ */ React16.createElement(
1221
+ Button3,
973
1222
  {
974
1223
  isDisabled: isSubmitting,
975
1224
  type: "button",
@@ -981,9 +1230,9 @@ function ConfigurableForm({
981
1230
  }
982
1231
 
983
1232
  // src/hooks/useHeroForm.ts
984
- import { useFormContext } from "react-hook-form";
1233
+ import { useFormContext as useFormContext4 } from "react-hook-form";
985
1234
  function useHeroForm() {
986
- const form = useFormContext();
1235
+ const form = useFormContext4();
987
1236
  const defaults = useHeroHookFormDefaults();
988
1237
  return {
989
1238
  // All React Hook Form methods and state
@@ -994,10 +1243,10 @@ function useHeroForm() {
994
1243
  }
995
1244
 
996
1245
  // src/providers/FormProvider.tsx
997
- import React14 from "react";
1246
+ import React17 from "react";
998
1247
  import { FormProvider as RHFProvider } from "react-hook-form";
999
1248
  function FormProvider(props) {
1000
- return /* @__PURE__ */ React14.createElement(RHFProvider, { ...props.methods }, /* @__PURE__ */ React14.createElement(
1249
+ return /* @__PURE__ */ React17.createElement(RHFProvider, { ...props.methods }, /* @__PURE__ */ React17.createElement(
1001
1250
  "form",
1002
1251
  {
1003
1252
  className: props.className,
@@ -1010,22 +1259,42 @@ function FormProvider(props) {
1010
1259
  }
1011
1260
 
1012
1261
  // src/submit/SubmitButton.tsx
1013
- import React15 from "react";
1262
+ import React18 from "react";
1014
1263
  function SubmitButton(props) {
1015
- const ctx = useFormContext2();
1264
+ const ctx = useFormContext5();
1016
1265
  const loading = props.isLoading ?? ctx.formState.isSubmitting;
1266
+ const enhancedState = props.enhancedState;
1017
1267
  const isDisabledFromProps = props.buttonProps?.isDisabled ?? false;
1018
1268
  const isDisabled = Boolean(isDisabledFromProps) || Boolean(loading);
1019
1269
  const defaults = useHeroHookFormDefaults();
1020
- 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(
1021
1289
  Button,
1022
1290
  {
1023
1291
  type: "submit",
1024
1292
  ...defaults.submitButton,
1025
1293
  ...props.buttonProps,
1026
- isDisabled
1294
+ isDisabled,
1295
+ color: getButtonColor()
1027
1296
  },
1028
- loading ? /* @__PURE__ */ React15.createElement("span", { className: "inline-flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(Spinner, { size: "sm" }), "Submitting\u2026") : props.children
1297
+ getButtonContent()
1029
1298
  );
1030
1299
  }
1031
1300
 
@@ -1216,13 +1485,69 @@ var commonValidations = {
1216
1485
  requiredCheckbox: (fieldName) => createRequiredCheckboxSchema(fieldName),
1217
1486
  url: createUrlSchema()
1218
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
+ };
1219
1544
 
1220
1545
  // src/index.ts
1221
- import { useFormContext as useFormContext2 } from "react-hook-form";
1546
+ import { useFormContext as useFormContext5 } from "react-hook-form";
1222
1547
 
1223
1548
  // src/components/ZodForm.tsx
1224
- import React16 from "react";
1225
- import { Button as Button3 } from "@heroui/react";
1549
+ import React20 from "react";
1550
+ import { Button as Button5 } from "@heroui/react";
1226
1551
 
1227
1552
  // src/zod-integration.ts
1228
1553
  import { useForm as useForm2 } from "react-hook-form";
@@ -1265,6 +1590,146 @@ function createZodFormConfig(schema, fields, defaultValues) {
1265
1590
  };
1266
1591
  }
1267
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
+
1268
1733
  // src/components/ZodForm.tsx
1269
1734
  function ZodForm({
1270
1735
  className,
@@ -1285,97 +1750,83 @@ function ZodForm({
1285
1750
  title
1286
1751
  }) {
1287
1752
  const form = useZodForm(config);
1288
- const [submissionState, setSubmissionState] = React16.useState({
1289
- error: void 0,
1290
- isSubmitted: false,
1291
- isSubmitting: false,
1292
- isSuccess: false
1753
+ const enhancedState = useEnhancedFormState(form, {
1754
+ onSuccess,
1755
+ onError: (error) => onError?.({ message: error, field: "form" }),
1756
+ autoReset: true,
1757
+ resetDelay: 3e3
1293
1758
  });
1294
1759
  const handleSubmit = async () => {
1295
- setSubmissionState((prev) => ({
1296
- ...prev,
1297
- error: void 0,
1298
- isSubmitting: true
1299
- }));
1300
- const isValid = await form.trigger();
1301
- if (!isValid) {
1302
- setSubmissionState({
1303
- error: "Please fix the validation errors above",
1304
- isSubmitted: true,
1305
- isSubmitting: false,
1306
- isSuccess: false
1307
- });
1308
- return;
1309
- }
1310
1760
  try {
1311
- await form.handleSubmit(async (formData) => {
1312
- await onSubmit(formData);
1313
- })();
1314
- setSubmissionState({
1315
- error: void 0,
1316
- isSubmitted: true,
1317
- isSubmitting: false,
1318
- isSuccess: true
1319
- });
1320
- 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
+ )();
1321
1770
  } catch (error) {
1322
1771
  const errorMessage = error instanceof Error ? error.message : "An error occurred";
1323
- setSubmissionState({
1324
- error: errorMessage,
1325
- isSubmitted: true,
1326
- isSubmitting: false,
1327
- isSuccess: false
1328
- });
1329
- onError?.({
1330
- message: errorMessage
1331
- });
1772
+ enhancedState.handleError(errorMessage);
1332
1773
  }
1333
1774
  };
1334
1775
  const resetForm = () => {
1335
1776
  form.reset();
1336
- setSubmissionState({
1337
- error: void 0,
1338
- isSubmitted: false,
1339
- isSubmitting: false,
1340
- isSuccess: false
1341
- });
1777
+ enhancedState.reset();
1342
1778
  };
1343
1779
  const renderFields = () => {
1344
1780
  if (layout === "grid") {
1345
- return /* @__PURE__ */ React16.createElement(
1781
+ return /* @__PURE__ */ React20.createElement(
1346
1782
  "div",
1347
1783
  {
1348
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"}`
1349
1785
  },
1350
- config.fields.map((field) => /* @__PURE__ */ React16.createElement(
1786
+ config.fields.map((field2) => /* @__PURE__ */ React20.createElement(
1351
1787
  FormField,
1352
1788
  {
1353
- key: field.name,
1354
- config: field,
1789
+ key: field2.name,
1790
+ config: field2,
1355
1791
  form,
1356
- submissionState
1792
+ submissionState: {
1793
+ isSubmitting: enhancedState.isSubmitting,
1794
+ isSubmitted: enhancedState.status !== "idle",
1795
+ isSuccess: enhancedState.isSuccess,
1796
+ error: enhancedState.error
1797
+ }
1357
1798
  }
1358
1799
  ))
1359
1800
  );
1360
1801
  }
1361
1802
  if (layout === "horizontal") {
1362
- 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(
1363
1804
  FormField,
1364
1805
  {
1365
- key: field.name,
1366
- config: field,
1806
+ key: field2.name,
1807
+ config: field2,
1367
1808
  form,
1368
- submissionState
1809
+ submissionState: {
1810
+ isSubmitting: enhancedState.isSubmitting,
1811
+ isSubmitted: enhancedState.status !== "idle",
1812
+ isSuccess: enhancedState.isSuccess,
1813
+ error: enhancedState.error
1814
+ }
1369
1815
  }
1370
1816
  )));
1371
1817
  }
1372
- 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(
1373
1819
  FormField,
1374
1820
  {
1375
- key: field.name,
1376
- config: field,
1821
+ key: field2.name,
1822
+ config: field2,
1377
1823
  form,
1378
- submissionState
1824
+ submissionState: {
1825
+ isSubmitting: enhancedState.isSubmitting,
1826
+ isSubmitted: enhancedState.status !== "idle",
1827
+ isSuccess: enhancedState.isSuccess,
1828
+ error: enhancedState.error
1829
+ }
1379
1830
  }
1380
1831
  )));
1381
1832
  };
@@ -1383,7 +1834,7 @@ function ZodForm({
1383
1834
  e.preventDefault();
1384
1835
  void handleSubmit();
1385
1836
  };
1386
- React16.useEffect(() => {
1837
+ React20.useEffect(() => {
1387
1838
  if (config.onError && Object.keys(form.formState.errors).length > 0) {
1388
1839
  config.onError(form.formState.errors);
1389
1840
  }
@@ -1392,42 +1843,33 @@ function ZodForm({
1392
1843
  return render({
1393
1844
  errors: form.formState.errors,
1394
1845
  form,
1395
- isSubmitted: submissionState.isSubmitted,
1396
- isSubmitting: submissionState.isSubmitting,
1397
- isSuccess: submissionState.isSuccess,
1846
+ isSubmitted: enhancedState.status !== "idle",
1847
+ isSubmitting: enhancedState.isSubmitting,
1848
+ isSuccess: enhancedState.isSuccess,
1398
1849
  values: form.getValues()
1399
1850
  });
1400
1851
  }
1401
- 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(
1402
- "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,
1403
1854
  {
1404
- className: "mb-6 p-4 bg-success-50 border border-success-200 rounded-lg",
1405
- "data-testid": "success-message"
1406
- },
1407
- /* @__PURE__ */ React16.createElement("p", { className: "text-success-800 font-medium" }, "Success!"),
1408
- /* @__PURE__ */ React16.createElement("p", { className: "text-success-700 text-sm mt-1" }, "Your request has been processed successfully.")
1409
- ), submissionState.error && errorDisplay !== "none" && /* @__PURE__ */ React16.createElement(
1410
- "div",
1411
- {
1412
- className: "mb-6 p-4 bg-danger-50 border border-danger-200 rounded-lg",
1413
- "data-testid": "error-message"
1414
- },
1415
- /* @__PURE__ */ React16.createElement("p", { className: "text-danger-800 font-medium" }, "Error"),
1416
- /* @__PURE__ */ React16.createElement("p", { className: "text-danger-700 text-sm mt-1" }, submissionState.error)
1417
- ), renderFields(), /* @__PURE__ */ React16.createElement("div", { className: "mt-6 flex gap-3 justify-end" }, /* @__PURE__ */ React16.createElement(
1418
- 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,
1419
1861
  {
1420
1862
  color: "primary",
1421
- isDisabled: submissionState.isSubmitting,
1422
- isLoading: submissionState.isSubmitting,
1863
+ isDisabled: enhancedState.isSubmitting,
1864
+ isLoading: enhancedState.isSubmitting,
1423
1865
  type: "submit",
1424
1866
  ...submitButtonProps
1425
1867
  },
1426
- submitButtonText
1427
- ), showResetButton && /* @__PURE__ */ React16.createElement(
1428
- Button3,
1868
+ enhancedState.isSuccess ? "Success!" : submitButtonText
1869
+ ), showResetButton && /* @__PURE__ */ React20.createElement(
1870
+ Button5,
1429
1871
  {
1430
- isDisabled: submissionState.isSubmitting,
1872
+ isDisabled: enhancedState.isSubmitting,
1431
1873
  type: "button",
1432
1874
  variant: "bordered",
1433
1875
  onPress: resetForm
@@ -1435,14 +1877,1209 @@ function ZodForm({
1435
1877
  resetButtonText
1436
1878
  )));
1437
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
+ };
1438
3064
  export {
3065
+ AdvancedFieldBuilder,
3066
+ BasicFormBuilder,
1439
3067
  CheckboxField,
3068
+ CommonFields,
3069
+ ConditionalField,
1440
3070
  ConfigurableForm,
1441
3071
  DateField,
3072
+ DynamicSectionField,
3073
+ FieldArrayBuilder,
3074
+ FieldArrayField,
3075
+ FieldArrayItemBuilder,
1442
3076
  FileField,
1443
3077
  FontPickerField,
1444
3078
  FormField,
3079
+ FormFieldHelpers,
1445
3080
  FormProvider,
3081
+ FormStatus,
3082
+ FormToast,
1446
3083
  HeroHookFormProvider,
1447
3084
  InputField,
1448
3085
  RadioGroupField,
@@ -1451,13 +3088,20 @@ export {
1451
3088
  SubmitButton,
1452
3089
  SwitchField,
1453
3090
  TextareaField,
3091
+ TypeInferredBuilder,
1454
3092
  ZodForm,
1455
3093
  applyServerErrors,
3094
+ asyncValidation,
1456
3095
  commonValidations,
3096
+ createAdvancedBuilder,
3097
+ createBasicFormBuilder,
1457
3098
  createConditionalSchema,
1458
3099
  createConfirmPasswordSchema,
1459
3100
  createDateSchema,
1460
3101
  createEmailSchema,
3102
+ createField,
3103
+ createFieldArrayBuilder,
3104
+ createFieldArrayItemBuilder,
1461
3105
  createFileSchema,
1462
3106
  createFormTestUtils,
1463
3107
  createFutureDateSchema,
@@ -1465,24 +3109,47 @@ export {
1465
3109
  createMinLengthSchema,
1466
3110
  createMockFormData,
1467
3111
  createMockFormErrors,
3112
+ createNestedPathBuilder,
1468
3113
  createNumberRangeSchema,
3114
+ createOptimizedFieldHandler,
1469
3115
  createPasswordSchema,
1470
3116
  createPastDateSchema,
1471
3117
  createPhoneSchema,
1472
3118
  createRequiredCheckboxSchema,
1473
3119
  createRequiredSchema,
3120
+ createTypeInferredBuilder,
1474
3121
  createUrlSchema,
1475
3122
  createZodFormConfig,
3123
+ crossFieldValidation,
3124
+ debounce,
3125
+ deepEqual,
3126
+ defineInferredForm,
3127
+ errorMessages,
3128
+ field,
1476
3129
  getFieldError,
1477
3130
  getFormErrors,
1478
3131
  hasFieldError,
1479
3132
  hasFormErrors,
3133
+ serverValidation,
3134
+ shallowEqual,
1480
3135
  simulateFieldInput,
1481
3136
  simulateFormSubmission,
1482
- useFormContext2 as useFormContext,
3137
+ throttle,
3138
+ useBatchedFieldUpdates,
3139
+ useDebouncedFieldValidation,
3140
+ useDebouncedValidation,
3141
+ useEnhancedFormState,
3142
+ useFormContext5 as useFormContext,
1483
3143
  useFormHelper,
1484
3144
  useHeroForm,
1485
3145
  useHeroHookFormDefaults,
3146
+ useInferredForm,
3147
+ useMemoizedCallback,
3148
+ useMemoizedFieldProps,
3149
+ usePerformanceMonitor,
3150
+ useTypeInferredForm,
1486
3151
  useZodForm,
3152
+ validationPatterns,
3153
+ validationUtils,
1487
3154
  waitForFormState
1488
3155
  };