@rachelallyson/hero-hook-form 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +54 -42
- package/README.md +161 -189
- package/dist/index.d.ts +304 -61
- package/dist/index.js +503 -16862
- package/dist/react/index.d.ts +304 -61
- package/dist/react/index.js +441 -209
- package/package.json +60 -42
- package/dist/dist-ICUU7SXF.js +0 -8
- package/dist/index.cjs +0 -17915
- package/dist/index.d.cts +0 -362
- package/dist/react/index.cjs +0 -1297
- package/dist/react/index.d.cts +0 -354
package/dist/react/index.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
1
8
|
// src/components/Form.tsx
|
|
2
|
-
import
|
|
9
|
+
import React13 from "react";
|
|
3
10
|
import { Button as Button2 } from "@heroui/react";
|
|
4
11
|
|
|
5
12
|
// src/hooks/useFormHelper.ts
|
|
@@ -68,7 +75,8 @@ function useFormHelper({
|
|
|
68
75
|
}
|
|
69
76
|
|
|
70
77
|
// src/components/FormField.tsx
|
|
71
|
-
import
|
|
78
|
+
import React12 from "react";
|
|
79
|
+
import { useWatch } from "react-hook-form";
|
|
72
80
|
|
|
73
81
|
// src/fields/CheckboxField.tsx
|
|
74
82
|
import React2 from "react";
|
|
@@ -301,8 +309,8 @@ function CoercedFileInput(props) {
|
|
|
301
309
|
type: "file",
|
|
302
310
|
value: field.value ? "" : "",
|
|
303
311
|
onBlur: field.onBlur,
|
|
304
|
-
onChange: (
|
|
305
|
-
const target =
|
|
312
|
+
onChange: (e) => {
|
|
313
|
+
const target = e.target;
|
|
306
314
|
field.onChange(target.files);
|
|
307
315
|
}
|
|
308
316
|
}
|
|
@@ -348,13 +356,60 @@ function FileField(props) {
|
|
|
348
356
|
);
|
|
349
357
|
}
|
|
350
358
|
|
|
351
|
-
// src/fields/
|
|
359
|
+
// src/fields/FontPickerField.tsx
|
|
352
360
|
import React5 from "react";
|
|
353
361
|
import { Controller as Controller4 } from "react-hook-form";
|
|
362
|
+
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
|
+
}
|
|
369
|
+
function FontPickerField(props) {
|
|
370
|
+
const {
|
|
371
|
+
className,
|
|
372
|
+
control,
|
|
373
|
+
description,
|
|
374
|
+
fontPickerProps,
|
|
375
|
+
isDisabled,
|
|
376
|
+
label,
|
|
377
|
+
name,
|
|
378
|
+
rules
|
|
379
|
+
} = 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."))));
|
|
382
|
+
}
|
|
383
|
+
return /* @__PURE__ */ React5.createElement(
|
|
384
|
+
Controller4,
|
|
385
|
+
{
|
|
386
|
+
control,
|
|
387
|
+
name,
|
|
388
|
+
render: ({ field, fieldState }) => /* @__PURE__ */ React5.createElement(
|
|
389
|
+
FontPickerComponent,
|
|
390
|
+
{
|
|
391
|
+
label,
|
|
392
|
+
description,
|
|
393
|
+
value: field.value ?? "",
|
|
394
|
+
onSelectionChange: (value) => field.onChange(value),
|
|
395
|
+
errorMessage: fieldState.error?.message,
|
|
396
|
+
isDisabled,
|
|
397
|
+
className,
|
|
398
|
+
...fontPickerProps
|
|
399
|
+
}
|
|
400
|
+
),
|
|
401
|
+
rules
|
|
402
|
+
}
|
|
403
|
+
);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// src/fields/InputField.tsx
|
|
407
|
+
import React6 from "react";
|
|
408
|
+
import { Controller as Controller5 } from "react-hook-form";
|
|
354
409
|
function CoercedInput(props) {
|
|
355
410
|
const { description, disabled, errorMessage, field, inputProps, label } = props;
|
|
356
411
|
const defaults = useHeroHookFormDefaults();
|
|
357
|
-
return /* @__PURE__ */
|
|
412
|
+
return /* @__PURE__ */ React6.createElement(
|
|
358
413
|
Input,
|
|
359
414
|
{
|
|
360
415
|
...defaults.input,
|
|
@@ -382,12 +437,12 @@ function InputField(props) {
|
|
|
382
437
|
rules,
|
|
383
438
|
transform
|
|
384
439
|
} = props;
|
|
385
|
-
return /* @__PURE__ */
|
|
386
|
-
|
|
440
|
+
return /* @__PURE__ */ React6.createElement(
|
|
441
|
+
Controller5,
|
|
387
442
|
{
|
|
388
443
|
control,
|
|
389
444
|
name,
|
|
390
|
-
render: ({ field, fieldState }) => /* @__PURE__ */
|
|
445
|
+
render: ({ field, fieldState }) => /* @__PURE__ */ React6.createElement("div", { className }, /* @__PURE__ */ React6.createElement(
|
|
391
446
|
CoercedInput,
|
|
392
447
|
{
|
|
393
448
|
description,
|
|
@@ -416,8 +471,8 @@ function InputField(props) {
|
|
|
416
471
|
}
|
|
417
472
|
|
|
418
473
|
// src/fields/RadioGroupField.tsx
|
|
419
|
-
import
|
|
420
|
-
import { Controller as
|
|
474
|
+
import React7 from "react";
|
|
475
|
+
import { Controller as Controller6 } from "react-hook-form";
|
|
421
476
|
function RadioGroupField(props) {
|
|
422
477
|
const {
|
|
423
478
|
className,
|
|
@@ -431,12 +486,12 @@ function RadioGroupField(props) {
|
|
|
431
486
|
rules
|
|
432
487
|
} = props;
|
|
433
488
|
const defaults = useHeroHookFormDefaults();
|
|
434
|
-
return /* @__PURE__ */
|
|
435
|
-
|
|
489
|
+
return /* @__PURE__ */ React7.createElement(
|
|
490
|
+
Controller6,
|
|
436
491
|
{
|
|
437
492
|
control,
|
|
438
493
|
name,
|
|
439
|
-
render: ({ field, fieldState }) => /* @__PURE__ */
|
|
494
|
+
render: ({ field, fieldState }) => /* @__PURE__ */ React7.createElement("div", { className }, /* @__PURE__ */ React7.createElement(
|
|
440
495
|
RadioGroup,
|
|
441
496
|
{
|
|
442
497
|
...defaults.radioGroup,
|
|
@@ -449,7 +504,7 @@ function RadioGroupField(props) {
|
|
|
449
504
|
onBlur: field.onBlur,
|
|
450
505
|
onValueChange: (val) => field.onChange(val)
|
|
451
506
|
},
|
|
452
|
-
options.map((opt) => /* @__PURE__ */
|
|
507
|
+
options.map((opt) => /* @__PURE__ */ React7.createElement(
|
|
453
508
|
Radio,
|
|
454
509
|
{
|
|
455
510
|
key: String(opt.value),
|
|
@@ -458,15 +513,15 @@ function RadioGroupField(props) {
|
|
|
458
513
|
},
|
|
459
514
|
opt.label
|
|
460
515
|
))
|
|
461
|
-
), fieldState.error?.message ? /* @__PURE__ */
|
|
516
|
+
), fieldState.error?.message ? /* @__PURE__ */ React7.createElement("p", { className: "text-tiny text-danger mt-1" }, fieldState.error.message) : null),
|
|
462
517
|
rules
|
|
463
518
|
}
|
|
464
519
|
);
|
|
465
520
|
}
|
|
466
521
|
|
|
467
522
|
// src/fields/SelectField.tsx
|
|
468
|
-
import
|
|
469
|
-
import { Controller as
|
|
523
|
+
import React8 from "react";
|
|
524
|
+
import { Controller as Controller7 } from "react-hook-form";
|
|
470
525
|
function SelectField(props) {
|
|
471
526
|
const {
|
|
472
527
|
className,
|
|
@@ -481,14 +536,14 @@ function SelectField(props) {
|
|
|
481
536
|
selectProps
|
|
482
537
|
} = props;
|
|
483
538
|
const defaults = useHeroHookFormDefaults();
|
|
484
|
-
return /* @__PURE__ */
|
|
485
|
-
|
|
539
|
+
return /* @__PURE__ */ React8.createElement(
|
|
540
|
+
Controller7,
|
|
486
541
|
{
|
|
487
542
|
control,
|
|
488
543
|
name,
|
|
489
544
|
render: ({ field, fieldState }) => {
|
|
490
545
|
const selectedKey = field.value;
|
|
491
|
-
return /* @__PURE__ */
|
|
546
|
+
return /* @__PURE__ */ React8.createElement("div", { className }, /* @__PURE__ */ React8.createElement(
|
|
492
547
|
Select,
|
|
493
548
|
{
|
|
494
549
|
...defaults.select,
|
|
@@ -506,7 +561,7 @@ function SelectField(props) {
|
|
|
506
561
|
field.onChange(next);
|
|
507
562
|
}
|
|
508
563
|
},
|
|
509
|
-
options.map((opt) => /* @__PURE__ */
|
|
564
|
+
options.map((opt) => /* @__PURE__ */ React8.createElement(
|
|
510
565
|
SelectItem,
|
|
511
566
|
{
|
|
512
567
|
key: String(opt.value),
|
|
@@ -523,12 +578,12 @@ function SelectField(props) {
|
|
|
523
578
|
}
|
|
524
579
|
|
|
525
580
|
// src/fields/SliderField.tsx
|
|
526
|
-
import
|
|
527
|
-
import { Controller as
|
|
581
|
+
import React9 from "react";
|
|
582
|
+
import { Controller as Controller8 } from "react-hook-form";
|
|
528
583
|
function CoercedSlider(props) {
|
|
529
584
|
const { description, disabled, errorMessage, field, label, sliderProps } = props;
|
|
530
585
|
const defaults = useHeroHookFormDefaults();
|
|
531
|
-
return /* @__PURE__ */
|
|
586
|
+
return /* @__PURE__ */ React9.createElement(
|
|
532
587
|
Slider,
|
|
533
588
|
{
|
|
534
589
|
...defaults.slider,
|
|
@@ -556,12 +611,12 @@ function SliderField(props) {
|
|
|
556
611
|
sliderProps,
|
|
557
612
|
transform
|
|
558
613
|
} = props;
|
|
559
|
-
return /* @__PURE__ */
|
|
560
|
-
|
|
614
|
+
return /* @__PURE__ */ React9.createElement(
|
|
615
|
+
Controller8,
|
|
561
616
|
{
|
|
562
617
|
control,
|
|
563
618
|
name,
|
|
564
|
-
render: ({ field, fieldState }) => /* @__PURE__ */
|
|
619
|
+
render: ({ field, fieldState }) => /* @__PURE__ */ React9.createElement("div", { className }, /* @__PURE__ */ React9.createElement(
|
|
565
620
|
CoercedSlider,
|
|
566
621
|
{
|
|
567
622
|
description,
|
|
@@ -581,8 +636,8 @@ function SliderField(props) {
|
|
|
581
636
|
}
|
|
582
637
|
|
|
583
638
|
// src/fields/SwitchField.tsx
|
|
584
|
-
import
|
|
585
|
-
import { Controller as
|
|
639
|
+
import React10 from "react";
|
|
640
|
+
import { Controller as Controller9 } from "react-hook-form";
|
|
586
641
|
function SwitchField(props) {
|
|
587
642
|
const {
|
|
588
643
|
className,
|
|
@@ -595,12 +650,12 @@ function SwitchField(props) {
|
|
|
595
650
|
switchProps
|
|
596
651
|
} = props;
|
|
597
652
|
const defaults = useHeroHookFormDefaults();
|
|
598
|
-
return /* @__PURE__ */
|
|
599
|
-
|
|
653
|
+
return /* @__PURE__ */ React10.createElement(
|
|
654
|
+
Controller9,
|
|
600
655
|
{
|
|
601
656
|
control,
|
|
602
657
|
name,
|
|
603
|
-
render: ({ field, fieldState }) => /* @__PURE__ */
|
|
658
|
+
render: ({ field, fieldState }) => /* @__PURE__ */ React10.createElement("div", { className }, /* @__PURE__ */ React10.createElement(
|
|
604
659
|
Switch,
|
|
605
660
|
{
|
|
606
661
|
...defaults.switch,
|
|
@@ -611,15 +666,15 @@ function SwitchField(props) {
|
|
|
611
666
|
onValueChange: (val) => field.onChange(val)
|
|
612
667
|
},
|
|
613
668
|
label
|
|
614
|
-
), description ? /* @__PURE__ */
|
|
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),
|
|
615
670
|
rules
|
|
616
671
|
}
|
|
617
672
|
);
|
|
618
673
|
}
|
|
619
674
|
|
|
620
675
|
// src/fields/TextareaField.tsx
|
|
621
|
-
import
|
|
622
|
-
import { Controller as
|
|
676
|
+
import React11 from "react";
|
|
677
|
+
import { Controller as Controller10 } from "react-hook-form";
|
|
623
678
|
function TextareaField(props) {
|
|
624
679
|
const {
|
|
625
680
|
className,
|
|
@@ -632,12 +687,12 @@ function TextareaField(props) {
|
|
|
632
687
|
textareaProps
|
|
633
688
|
} = props;
|
|
634
689
|
const defaults = useHeroHookFormDefaults();
|
|
635
|
-
return /* @__PURE__ */
|
|
636
|
-
|
|
690
|
+
return /* @__PURE__ */ React11.createElement(
|
|
691
|
+
Controller10,
|
|
637
692
|
{
|
|
638
693
|
control,
|
|
639
694
|
name,
|
|
640
|
-
render: ({ field, fieldState }) => /* @__PURE__ */
|
|
695
|
+
render: ({ field, fieldState }) => /* @__PURE__ */ React11.createElement("div", { className }, /* @__PURE__ */ React11.createElement(
|
|
641
696
|
Textarea,
|
|
642
697
|
{
|
|
643
698
|
...defaults.textarea,
|
|
@@ -664,7 +719,19 @@ function FormField({
|
|
|
664
719
|
submissionState
|
|
665
720
|
}) {
|
|
666
721
|
const { control } = form;
|
|
722
|
+
const watchedValues = useWatch({ control });
|
|
723
|
+
if (config.condition && !config.condition(watchedValues)) {
|
|
724
|
+
return null;
|
|
725
|
+
}
|
|
726
|
+
if (config.dependsOn) {
|
|
727
|
+
const dependentValue = watchedValues[config.dependsOn];
|
|
728
|
+
if (config.dependsOnValue !== void 0 && dependentValue !== config.dependsOnValue) {
|
|
729
|
+
return null;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
667
732
|
const baseProps = {
|
|
733
|
+
ariaDescribedBy: config.ariaDescribedBy,
|
|
734
|
+
ariaLabel: config.ariaLabel,
|
|
668
735
|
className: config.className,
|
|
669
736
|
description: config.description,
|
|
670
737
|
isDisabled: config.isDisabled ?? submissionState.isSubmitting,
|
|
@@ -674,7 +741,7 @@ function FormField({
|
|
|
674
741
|
};
|
|
675
742
|
switch (config.type) {
|
|
676
743
|
case "input":
|
|
677
|
-
return /* @__PURE__ */
|
|
744
|
+
return /* @__PURE__ */ React12.createElement(
|
|
678
745
|
InputField,
|
|
679
746
|
{
|
|
680
747
|
...baseProps,
|
|
@@ -684,7 +751,7 @@ function FormField({
|
|
|
684
751
|
}
|
|
685
752
|
);
|
|
686
753
|
case "textarea":
|
|
687
|
-
return /* @__PURE__ */
|
|
754
|
+
return /* @__PURE__ */ React12.createElement(
|
|
688
755
|
TextareaField,
|
|
689
756
|
{
|
|
690
757
|
...baseProps,
|
|
@@ -694,7 +761,7 @@ function FormField({
|
|
|
694
761
|
}
|
|
695
762
|
);
|
|
696
763
|
case "select":
|
|
697
|
-
return /* @__PURE__ */
|
|
764
|
+
return /* @__PURE__ */ React12.createElement(
|
|
698
765
|
SelectField,
|
|
699
766
|
{
|
|
700
767
|
...baseProps,
|
|
@@ -708,7 +775,7 @@ function FormField({
|
|
|
708
775
|
}
|
|
709
776
|
);
|
|
710
777
|
case "checkbox":
|
|
711
|
-
return /* @__PURE__ */
|
|
778
|
+
return /* @__PURE__ */ React12.createElement(
|
|
712
779
|
CheckboxField,
|
|
713
780
|
{
|
|
714
781
|
...baseProps,
|
|
@@ -718,7 +785,7 @@ function FormField({
|
|
|
718
785
|
}
|
|
719
786
|
);
|
|
720
787
|
case "radio":
|
|
721
|
-
return /* @__PURE__ */
|
|
788
|
+
return /* @__PURE__ */ React12.createElement(
|
|
722
789
|
RadioGroupField,
|
|
723
790
|
{
|
|
724
791
|
...baseProps,
|
|
@@ -732,7 +799,7 @@ function FormField({
|
|
|
732
799
|
}
|
|
733
800
|
);
|
|
734
801
|
case "switch":
|
|
735
|
-
return /* @__PURE__ */
|
|
802
|
+
return /* @__PURE__ */ React12.createElement(
|
|
736
803
|
SwitchField,
|
|
737
804
|
{
|
|
738
805
|
...baseProps,
|
|
@@ -742,7 +809,7 @@ function FormField({
|
|
|
742
809
|
}
|
|
743
810
|
);
|
|
744
811
|
case "slider":
|
|
745
|
-
return /* @__PURE__ */
|
|
812
|
+
return /* @__PURE__ */ React12.createElement(
|
|
746
813
|
SliderField,
|
|
747
814
|
{
|
|
748
815
|
...baseProps,
|
|
@@ -752,7 +819,7 @@ function FormField({
|
|
|
752
819
|
}
|
|
753
820
|
);
|
|
754
821
|
case "date":
|
|
755
|
-
return /* @__PURE__ */
|
|
822
|
+
return /* @__PURE__ */ React12.createElement(
|
|
756
823
|
DateField,
|
|
757
824
|
{
|
|
758
825
|
...baseProps,
|
|
@@ -762,7 +829,7 @@ function FormField({
|
|
|
762
829
|
}
|
|
763
830
|
);
|
|
764
831
|
case "file":
|
|
765
|
-
return /* @__PURE__ */
|
|
832
|
+
return /* @__PURE__ */ React12.createElement(
|
|
766
833
|
FileField,
|
|
767
834
|
{
|
|
768
835
|
...baseProps,
|
|
@@ -773,6 +840,24 @@ function FormField({
|
|
|
773
840
|
multiple: config.multiple
|
|
774
841
|
}
|
|
775
842
|
);
|
|
843
|
+
case "fontPicker":
|
|
844
|
+
return /* @__PURE__ */ React12.createElement(
|
|
845
|
+
FontPickerField,
|
|
846
|
+
{
|
|
847
|
+
...baseProps,
|
|
848
|
+
control,
|
|
849
|
+
defaultValue: config.defaultValue,
|
|
850
|
+
fontPickerProps: config.fontPickerProps
|
|
851
|
+
}
|
|
852
|
+
);
|
|
853
|
+
case "custom":
|
|
854
|
+
return config.render({
|
|
855
|
+
control,
|
|
856
|
+
errors: form.formState.errors,
|
|
857
|
+
form,
|
|
858
|
+
isSubmitting: submissionState.isSubmitting,
|
|
859
|
+
name: config.name
|
|
860
|
+
});
|
|
776
861
|
default: {
|
|
777
862
|
const fieldType = config.type;
|
|
778
863
|
console.warn(`Unknown field type: ${fieldType}`);
|
|
@@ -816,12 +901,12 @@ function ConfigurableForm({
|
|
|
816
901
|
});
|
|
817
902
|
const renderFields = () => {
|
|
818
903
|
if (layout === "grid") {
|
|
819
|
-
return /* @__PURE__ */
|
|
904
|
+
return /* @__PURE__ */ React13.createElement(
|
|
820
905
|
"div",
|
|
821
906
|
{
|
|
822
907
|
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"}`
|
|
823
908
|
},
|
|
824
|
-
fields.map((field) => /* @__PURE__ */
|
|
909
|
+
fields.map((field) => /* @__PURE__ */ React13.createElement(
|
|
825
910
|
FormField,
|
|
826
911
|
{
|
|
827
912
|
key: field.name,
|
|
@@ -833,7 +918,7 @@ function ConfigurableForm({
|
|
|
833
918
|
);
|
|
834
919
|
}
|
|
835
920
|
if (layout === "horizontal") {
|
|
836
|
-
return /* @__PURE__ */
|
|
921
|
+
return /* @__PURE__ */ React13.createElement("div", { className: `grid gap-${spacing} grid-cols-1 md:grid-cols-2` }, fields.map((field) => /* @__PURE__ */ React13.createElement(
|
|
837
922
|
FormField,
|
|
838
923
|
{
|
|
839
924
|
key: field.name,
|
|
@@ -843,7 +928,7 @@ function ConfigurableForm({
|
|
|
843
928
|
}
|
|
844
929
|
)));
|
|
845
930
|
}
|
|
846
|
-
return /* @__PURE__ */
|
|
931
|
+
return /* @__PURE__ */ React13.createElement("div", { className: `space-y-${spacing}` }, fields.map((field) => /* @__PURE__ */ React13.createElement(
|
|
847
932
|
FormField,
|
|
848
933
|
{
|
|
849
934
|
key: field.name,
|
|
@@ -853,27 +938,27 @@ function ConfigurableForm({
|
|
|
853
938
|
}
|
|
854
939
|
)));
|
|
855
940
|
};
|
|
856
|
-
const handleFormSubmit = (
|
|
857
|
-
|
|
941
|
+
const handleFormSubmit = (e) => {
|
|
942
|
+
e.preventDefault();
|
|
858
943
|
void handleSubmit();
|
|
859
944
|
};
|
|
860
|
-
return /* @__PURE__ */
|
|
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(
|
|
861
946
|
"div",
|
|
862
947
|
{
|
|
863
948
|
className: "mb-6 p-4 bg-success-50 border border-success-200 rounded-lg",
|
|
864
949
|
"data-testid": "success-message"
|
|
865
950
|
},
|
|
866
|
-
/* @__PURE__ */
|
|
867
|
-
/* @__PURE__ */
|
|
868
|
-
), error && /* @__PURE__ */
|
|
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(
|
|
869
954
|
"div",
|
|
870
955
|
{
|
|
871
956
|
className: "mb-6 p-4 bg-danger-50 border border-danger-200 rounded-lg",
|
|
872
957
|
"data-testid": "error-message"
|
|
873
958
|
},
|
|
874
|
-
/* @__PURE__ */
|
|
875
|
-
/* @__PURE__ */
|
|
876
|
-
), renderFields(), /* @__PURE__ */
|
|
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(
|
|
877
962
|
Button2,
|
|
878
963
|
{
|
|
879
964
|
color: "primary",
|
|
@@ -883,7 +968,7 @@ function ConfigurableForm({
|
|
|
883
968
|
...submitButtonProps
|
|
884
969
|
},
|
|
885
970
|
submitButtonText
|
|
886
|
-
), showResetButton && /* @__PURE__ */
|
|
971
|
+
), showResetButton && /* @__PURE__ */ React13.createElement(
|
|
887
972
|
Button2,
|
|
888
973
|
{
|
|
889
974
|
isDisabled: isSubmitting,
|
|
@@ -895,11 +980,24 @@ function ConfigurableForm({
|
|
|
895
980
|
)));
|
|
896
981
|
}
|
|
897
982
|
|
|
983
|
+
// src/hooks/useHeroForm.ts
|
|
984
|
+
import { useFormContext } from "react-hook-form";
|
|
985
|
+
function useHeroForm() {
|
|
986
|
+
const form = useFormContext();
|
|
987
|
+
const defaults = useHeroHookFormDefaults();
|
|
988
|
+
return {
|
|
989
|
+
// All React Hook Form methods and state
|
|
990
|
+
...form,
|
|
991
|
+
// Hero Hook Form styling defaults
|
|
992
|
+
defaults
|
|
993
|
+
};
|
|
994
|
+
}
|
|
995
|
+
|
|
898
996
|
// src/providers/FormProvider.tsx
|
|
899
|
-
import
|
|
997
|
+
import React14 from "react";
|
|
900
998
|
import { FormProvider as RHFProvider } from "react-hook-form";
|
|
901
999
|
function FormProvider(props) {
|
|
902
|
-
return /* @__PURE__ */
|
|
1000
|
+
return /* @__PURE__ */ React14.createElement(RHFProvider, { ...props.methods }, /* @__PURE__ */ React14.createElement(
|
|
903
1001
|
"form",
|
|
904
1002
|
{
|
|
905
1003
|
className: props.className,
|
|
@@ -912,15 +1010,14 @@ function FormProvider(props) {
|
|
|
912
1010
|
}
|
|
913
1011
|
|
|
914
1012
|
// src/submit/SubmitButton.tsx
|
|
915
|
-
import
|
|
916
|
-
import { useFormContext } from "react-hook-form";
|
|
1013
|
+
import React15 from "react";
|
|
917
1014
|
function SubmitButton(props) {
|
|
918
|
-
const ctx =
|
|
1015
|
+
const ctx = useFormContext2();
|
|
919
1016
|
const loading = props.isLoading ?? ctx.formState.isSubmitting;
|
|
920
1017
|
const isDisabledFromProps = props.buttonProps?.isDisabled ?? false;
|
|
921
1018
|
const isDisabled = Boolean(isDisabledFromProps) || Boolean(loading);
|
|
922
1019
|
const defaults = useHeroHookFormDefaults();
|
|
923
|
-
return /* @__PURE__ */
|
|
1020
|
+
return /* @__PURE__ */ React15.createElement(
|
|
924
1021
|
Button,
|
|
925
1022
|
{
|
|
926
1023
|
type: "submit",
|
|
@@ -928,7 +1025,7 @@ function SubmitButton(props) {
|
|
|
928
1025
|
...props.buttonProps,
|
|
929
1026
|
isDisabled
|
|
930
1027
|
},
|
|
931
|
-
loading ? /* @__PURE__ */
|
|
1028
|
+
loading ? /* @__PURE__ */ React15.createElement("span", { className: "inline-flex items-center gap-2" }, /* @__PURE__ */ React15.createElement(Spinner, { size: "sm" }), "Submitting\u2026") : props.children
|
|
932
1029
|
);
|
|
933
1030
|
}
|
|
934
1031
|
|
|
@@ -940,144 +1037,232 @@ function applyServerErrors(setError, serverError) {
|
|
|
940
1037
|
}
|
|
941
1038
|
}
|
|
942
1039
|
|
|
943
|
-
// src/
|
|
944
|
-
|
|
945
|
-
|
|
1040
|
+
// src/utils/testing.ts
|
|
1041
|
+
function createFormTestUtils(form) {
|
|
1042
|
+
return {
|
|
1043
|
+
/**
|
|
1044
|
+
* Get a field by name
|
|
1045
|
+
*/
|
|
1046
|
+
getField: (name) => {
|
|
1047
|
+
return {
|
|
1048
|
+
error: form.formState.errors[name],
|
|
1049
|
+
isDirty: !!form.formState.dirtyFields[name],
|
|
1050
|
+
isTouched: !!form.formState.touchedFields[name],
|
|
1051
|
+
value: form.getValues(name)
|
|
1052
|
+
};
|
|
1053
|
+
},
|
|
1054
|
+
/**
|
|
1055
|
+
* Get the current form state
|
|
1056
|
+
*/
|
|
1057
|
+
getFormState: () => ({
|
|
1058
|
+
errors: form.formState.errors,
|
|
1059
|
+
isSubmitted: form.formState.isSubmitted,
|
|
1060
|
+
isSubmitting: form.formState.isSubmitting,
|
|
1061
|
+
isSuccess: form.formState.isSubmitSuccessful,
|
|
1062
|
+
values: form.getValues()
|
|
1063
|
+
}),
|
|
1064
|
+
/**
|
|
1065
|
+
* Reset the form
|
|
1066
|
+
*/
|
|
1067
|
+
resetForm: () => {
|
|
1068
|
+
form.reset();
|
|
1069
|
+
},
|
|
1070
|
+
/**
|
|
1071
|
+
* Set a field value
|
|
1072
|
+
*/
|
|
1073
|
+
setFieldValue: (name, value) => {
|
|
1074
|
+
form.setValue(name, value, { shouldValidate: true });
|
|
1075
|
+
},
|
|
1076
|
+
/**
|
|
1077
|
+
* Submit the form
|
|
1078
|
+
*/
|
|
1079
|
+
submitForm: async () => {
|
|
1080
|
+
const isValid = await form.trigger();
|
|
1081
|
+
if (isValid) {
|
|
1082
|
+
await form.handleSubmit(() => {
|
|
1083
|
+
})();
|
|
1084
|
+
}
|
|
1085
|
+
},
|
|
1086
|
+
/**
|
|
1087
|
+
* Trigger validation for a field or all fields
|
|
1088
|
+
*/
|
|
1089
|
+
triggerValidation: async (name) => {
|
|
1090
|
+
if (name) {
|
|
1091
|
+
return await form.trigger(name);
|
|
1092
|
+
}
|
|
1093
|
+
return await form.trigger();
|
|
1094
|
+
}
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1097
|
+
function createMockFormData(overrides = {}) {
|
|
1098
|
+
return {
|
|
1099
|
+
agreeToTerms: true,
|
|
1100
|
+
confirmPassword: "password123",
|
|
1101
|
+
email: "test@example.com",
|
|
1102
|
+
firstName: "John",
|
|
1103
|
+
lastName: "Doe",
|
|
1104
|
+
password: "password123",
|
|
1105
|
+
phone: "123-456-7890",
|
|
1106
|
+
...overrides
|
|
1107
|
+
};
|
|
1108
|
+
}
|
|
1109
|
+
function createMockFormErrors(overrides = {}) {
|
|
1110
|
+
return {
|
|
1111
|
+
email: { message: "Invalid email address", type: "pattern" },
|
|
1112
|
+
password: { message: "Password is too short", type: "minLength" },
|
|
1113
|
+
...overrides
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
1116
|
+
function waitForFormState(form, condition, timeout = 5e3) {
|
|
1117
|
+
return new Promise((resolve, reject) => {
|
|
1118
|
+
const startTime = Date.now();
|
|
1119
|
+
const checkState = () => {
|
|
1120
|
+
if (condition(form.formState)) {
|
|
1121
|
+
resolve();
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
1124
|
+
if (Date.now() - startTime > timeout) {
|
|
1125
|
+
reject(new Error("Timeout waiting for form state"));
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
setTimeout(checkState, 100);
|
|
1129
|
+
};
|
|
1130
|
+
checkState();
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1133
|
+
function simulateFieldInput(form, name, value) {
|
|
1134
|
+
form.setValue(name, value);
|
|
1135
|
+
void form.trigger(name);
|
|
1136
|
+
}
|
|
1137
|
+
function simulateFormSubmission(form, onSubmit) {
|
|
1138
|
+
return form.handleSubmit(onSubmit)();
|
|
1139
|
+
}
|
|
1140
|
+
function hasFormErrors(form) {
|
|
1141
|
+
return Object.keys(form.formState.errors).length > 0;
|
|
1142
|
+
}
|
|
1143
|
+
function getFormErrors(form) {
|
|
1144
|
+
return Object.values(form.formState.errors).map(
|
|
1145
|
+
(error) => error.message
|
|
1146
|
+
);
|
|
1147
|
+
}
|
|
1148
|
+
function hasFieldError(form, name) {
|
|
1149
|
+
return !!form.formState.errors[name];
|
|
1150
|
+
}
|
|
1151
|
+
function getFieldError(form, name) {
|
|
1152
|
+
const error = form.formState.errors[name];
|
|
1153
|
+
return error?.message;
|
|
1154
|
+
}
|
|
946
1155
|
|
|
947
|
-
//
|
|
948
|
-
import {
|
|
949
|
-
var
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
1156
|
+
// src/utils/validation.ts
|
|
1157
|
+
import { z } from "zod";
|
|
1158
|
+
var createMinLengthSchema = (min, fieldName) => z.string().min(min, `${fieldName} must be at least ${min} characters`);
|
|
1159
|
+
var createMaxLengthSchema = (max, fieldName) => z.string().max(max, `${fieldName} must be no more than ${max} characters`);
|
|
1160
|
+
var createEmailSchema = () => z.email("Please enter a valid email address");
|
|
1161
|
+
var createRequiredSchema = (fieldName) => z.string().min(1, `${fieldName} is required`);
|
|
1162
|
+
var createUrlSchema = () => z.string().url("Please enter a valid URL");
|
|
1163
|
+
var createPhoneSchema = () => z.string().regex(/^[+]?[1-9][\d]{0,15}$/, "Please enter a valid phone number");
|
|
1164
|
+
var createPasswordSchema = (minLength = 8) => z.string().min(minLength, `Password must be at least ${minLength} characters`).regex(
|
|
1165
|
+
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/,
|
|
1166
|
+
"Password must contain at least one uppercase letter, one lowercase letter, and one number"
|
|
1167
|
+
);
|
|
1168
|
+
var createConfirmPasswordSchema = (passwordField) => z.string().refine(
|
|
1169
|
+
(val) => {
|
|
1170
|
+
return true;
|
|
1171
|
+
},
|
|
1172
|
+
{
|
|
1173
|
+
message: "Passwords do not match"
|
|
953
1174
|
}
|
|
954
|
-
|
|
955
|
-
var
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
1175
|
+
);
|
|
1176
|
+
var createNumberRangeSchema = (min, max, fieldName) => z.number().min(min, `${fieldName} must be at least ${min}`).max(max, `${fieldName} must be no more than ${max}`);
|
|
1177
|
+
var createDateSchema = (fieldName) => z.date({ message: `${fieldName} is required` });
|
|
1178
|
+
var createFutureDateSchema = (fieldName) => z.date({ message: `${fieldName} is required` }).refine((date) => date > /* @__PURE__ */ new Date(), {
|
|
1179
|
+
message: `${fieldName} must be in the future`
|
|
1180
|
+
});
|
|
1181
|
+
var createPastDateSchema = (fieldName) => z.date({ message: `${fieldName} is required` }).refine((date) => date < /* @__PURE__ */ new Date(), {
|
|
1182
|
+
message: `${fieldName} must be in the past`
|
|
1183
|
+
});
|
|
1184
|
+
var createFileSchema = (maxSizeInMB = 5, allowedTypes = ["image/jpeg", "image/png", "image/gif"]) => z.instanceof(File).refine(
|
|
1185
|
+
(file) => file.size <= maxSizeInMB * 1024 * 1024,
|
|
1186
|
+
`File size must be less than ${maxSizeInMB}MB`
|
|
1187
|
+
).refine(
|
|
1188
|
+
(file) => allowedTypes.includes(file.type),
|
|
1189
|
+
`File type must be one of: ${allowedTypes.join(", ")}`
|
|
1190
|
+
);
|
|
1191
|
+
var createRequiredCheckboxSchema = (fieldName) => z.boolean().refine((val) => val === true, {
|
|
1192
|
+
message: `You must agree to ${fieldName}`
|
|
1193
|
+
});
|
|
1194
|
+
var createConditionalSchema = (condition, schema, errorMessage = "This field is required") => z.any().refine(
|
|
1195
|
+
(val) => {
|
|
1196
|
+
return true;
|
|
1197
|
+
},
|
|
1198
|
+
{
|
|
1199
|
+
message: errorMessage
|
|
959
1200
|
}
|
|
1201
|
+
);
|
|
1202
|
+
var commonValidations = {
|
|
1203
|
+
conditional: (condition, schema, errorMessage) => createConditionalSchema(condition, schema, errorMessage),
|
|
1204
|
+
confirmPassword: (passwordField) => createConfirmPasswordSchema(passwordField),
|
|
1205
|
+
date: (fieldName) => createDateSchema(fieldName),
|
|
1206
|
+
email: createEmailSchema(),
|
|
1207
|
+
file: (maxSizeInMB, allowedTypes) => createFileSchema(maxSizeInMB, allowedTypes),
|
|
1208
|
+
futureDate: (fieldName) => createFutureDateSchema(fieldName),
|
|
1209
|
+
maxLength: (max, fieldName) => createMaxLengthSchema(max, fieldName),
|
|
1210
|
+
minLength: (min, fieldName) => createMinLengthSchema(min, fieldName),
|
|
1211
|
+
numberRange: (min, max, fieldName) => createNumberRangeSchema(min, max, fieldName),
|
|
1212
|
+
password: (minLength) => createPasswordSchema(minLength),
|
|
1213
|
+
pastDate: (fieldName) => createPastDateSchema(fieldName),
|
|
1214
|
+
phone: createPhoneSchema(),
|
|
1215
|
+
required: (fieldName) => createRequiredSchema(fieldName),
|
|
1216
|
+
requiredCheckbox: (fieldName) => createRequiredCheckboxSchema(fieldName),
|
|
1217
|
+
url: createUrlSchema()
|
|
960
1218
|
};
|
|
961
|
-
var s = (r2, s3) => {
|
|
962
|
-
s3.shouldUseNativeValidation && o(r2, s3);
|
|
963
|
-
const n3 = {};
|
|
964
|
-
for (const o3 in r2) {
|
|
965
|
-
const f = e(s3.fields, o3), c = Object.assign(r2[o3] || {}, { ref: f && f.ref });
|
|
966
|
-
if (i(s3.names || Object.keys(r2), o3)) {
|
|
967
|
-
const r3 = Object.assign({}, e(n3, o3));
|
|
968
|
-
t(r3, "root", c), t(n3, o3, r3);
|
|
969
|
-
} else t(n3, o3, c);
|
|
970
|
-
}
|
|
971
|
-
return n3;
|
|
972
|
-
};
|
|
973
|
-
var i = (e2, t3) => {
|
|
974
|
-
const r2 = n(t3);
|
|
975
|
-
return e2.some((e3) => n(e3).match(`^${r2}\\.\\d+`));
|
|
976
|
-
};
|
|
977
|
-
function n(e2) {
|
|
978
|
-
return e2.replace(/\]|\[/g, "");
|
|
979
|
-
}
|
|
980
1219
|
|
|
981
|
-
//
|
|
982
|
-
import {
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
for (var n3 = {}; r2.length; ) {
|
|
994
|
-
var t3 = r2[0], s3 = t3.code, i3 = t3.message, a2 = t3.path.join(".");
|
|
995
|
-
if (!n3[a2]) if ("unionErrors" in t3) {
|
|
996
|
-
var u = t3.unionErrors[0].errors[0];
|
|
997
|
-
n3[a2] = { message: u.message, type: u.code };
|
|
998
|
-
} else n3[a2] = { message: i3, type: s3 };
|
|
999
|
-
if ("unionErrors" in t3 && t3.unionErrors.forEach(function(e3) {
|
|
1000
|
-
return e3.errors.forEach(function(e4) {
|
|
1001
|
-
return r2.push(e4);
|
|
1002
|
-
});
|
|
1003
|
-
}), e2) {
|
|
1004
|
-
var c = n3[a2].types, f = c && c[t3.code];
|
|
1005
|
-
n3[a2] = o2(a2, e2, n3, s3, f ? [].concat(f, t3.message) : t3.message);
|
|
1006
|
-
}
|
|
1007
|
-
r2.shift();
|
|
1008
|
-
}
|
|
1009
|
-
return n3;
|
|
1010
|
-
}
|
|
1011
|
-
function i2(r2, e2) {
|
|
1012
|
-
for (var n3 = {}; r2.length; ) {
|
|
1013
|
-
var t3 = r2[0], s3 = t3.code, i3 = t3.message, a2 = t3.path.join(".");
|
|
1014
|
-
if (!n3[a2]) if ("invalid_union" === t3.code && t3.errors.length > 0) {
|
|
1015
|
-
var u = t3.errors[0][0];
|
|
1016
|
-
n3[a2] = { message: u.message, type: u.code };
|
|
1017
|
-
} else n3[a2] = { message: i3, type: s3 };
|
|
1018
|
-
if ("invalid_union" === t3.code && t3.errors.forEach(function(e3) {
|
|
1019
|
-
return e3.forEach(function(e4) {
|
|
1020
|
-
return r2.push(e4);
|
|
1021
|
-
});
|
|
1022
|
-
}), e2) {
|
|
1023
|
-
var c = n3[a2].types, f = c && c[t3.code];
|
|
1024
|
-
n3[a2] = o2(a2, e2, n3, s3, f ? [].concat(f, t3.message) : t3.message);
|
|
1025
|
-
}
|
|
1026
|
-
r2.shift();
|
|
1027
|
-
}
|
|
1028
|
-
return n3;
|
|
1029
|
-
}
|
|
1030
|
-
function a(o3, a2, u) {
|
|
1031
|
-
if (void 0 === u && (u = {}), (function(r2) {
|
|
1032
|
-
return "_def" in r2 && "object" == typeof r2._def && "typeName" in r2._def;
|
|
1033
|
-
})(o3)) return function(n3, i3, c) {
|
|
1034
|
-
try {
|
|
1035
|
-
return Promise.resolve(t2(function() {
|
|
1036
|
-
return Promise.resolve(o3["sync" === u.mode ? "parse" : "parseAsync"](n3, a2)).then(function(e2) {
|
|
1037
|
-
return c.shouldUseNativeValidation && o({}, c), { errors: {}, values: u.raw ? Object.assign({}, n3) : e2 };
|
|
1038
|
-
});
|
|
1039
|
-
}, function(r2) {
|
|
1040
|
-
if ((function(r3) {
|
|
1041
|
-
return Array.isArray(null == r3 ? void 0 : r3.issues);
|
|
1042
|
-
})(r2)) return { values: {}, errors: s(s2(r2.errors, !c.shouldUseNativeValidation && "all" === c.criteriaMode), c) };
|
|
1043
|
-
throw r2;
|
|
1044
|
-
}));
|
|
1045
|
-
} catch (r2) {
|
|
1046
|
-
return Promise.reject(r2);
|
|
1047
|
-
}
|
|
1048
|
-
};
|
|
1049
|
-
if ((function(r2) {
|
|
1050
|
-
return "_zod" in r2 && "object" == typeof r2._zod;
|
|
1051
|
-
})(o3)) return function(s3, c, f) {
|
|
1220
|
+
// src/index.ts
|
|
1221
|
+
import { useFormContext as useFormContext2 } from "react-hook-form";
|
|
1222
|
+
|
|
1223
|
+
// src/components/ZodForm.tsx
|
|
1224
|
+
import React16 from "react";
|
|
1225
|
+
import { Button as Button3 } from "@heroui/react";
|
|
1226
|
+
|
|
1227
|
+
// src/zod-integration.ts
|
|
1228
|
+
import { useForm as useForm2 } from "react-hook-form";
|
|
1229
|
+
import { z as z2 } from "zod";
|
|
1230
|
+
function createZodResolver(schema) {
|
|
1231
|
+
return async (values, context) => {
|
|
1052
1232
|
try {
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1233
|
+
const result = await schema.parseAsync(values);
|
|
1234
|
+
return {
|
|
1235
|
+
errors: {},
|
|
1236
|
+
values: result
|
|
1237
|
+
};
|
|
1238
|
+
} catch (error) {
|
|
1239
|
+
if (error instanceof z2.ZodError) {
|
|
1240
|
+
const errors = {};
|
|
1241
|
+
error.issues.forEach((err) => {
|
|
1242
|
+
const path = err.path.join(".");
|
|
1243
|
+
errors[path] = { message: err.message };
|
|
1056
1244
|
});
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
} catch (r2) {
|
|
1064
|
-
return Promise.reject(r2);
|
|
1245
|
+
return {
|
|
1246
|
+
errors,
|
|
1247
|
+
values: {}
|
|
1248
|
+
};
|
|
1249
|
+
}
|
|
1250
|
+
throw error;
|
|
1065
1251
|
}
|
|
1066
1252
|
};
|
|
1067
|
-
throw new Error("Invalid input: not a Zod schema");
|
|
1068
1253
|
}
|
|
1069
|
-
|
|
1070
|
-
// src/zod-integration.ts
|
|
1071
|
-
import { useForm as useForm2 } from "react-hook-form";
|
|
1072
1254
|
function useZodForm(config) {
|
|
1073
1255
|
if (!config.resolver && config.schema) {
|
|
1074
|
-
|
|
1075
|
-
config.resolver = resolver;
|
|
1256
|
+
config.resolver = createZodResolver(config.schema);
|
|
1076
1257
|
}
|
|
1077
|
-
|
|
1078
|
-
|
|
1258
|
+
return useForm2(config);
|
|
1259
|
+
}
|
|
1260
|
+
function createZodFormConfig(schema, fields, defaultValues) {
|
|
1261
|
+
return {
|
|
1262
|
+
schema,
|
|
1263
|
+
fields,
|
|
1264
|
+
...defaultValues && { defaultValues }
|
|
1079
1265
|
};
|
|
1080
|
-
return useForm2(formConfig);
|
|
1081
1266
|
}
|
|
1082
1267
|
|
|
1083
1268
|
// src/components/ZodForm.tsx
|
|
@@ -1085,10 +1270,12 @@ function ZodForm({
|
|
|
1085
1270
|
className,
|
|
1086
1271
|
columns = 1,
|
|
1087
1272
|
config,
|
|
1273
|
+
errorDisplay = "inline",
|
|
1088
1274
|
layout = "vertical",
|
|
1089
1275
|
onError,
|
|
1090
1276
|
onSubmit,
|
|
1091
1277
|
onSuccess,
|
|
1278
|
+
render,
|
|
1092
1279
|
resetButtonText = "Reset",
|
|
1093
1280
|
showResetButton = false,
|
|
1094
1281
|
spacing = "4",
|
|
@@ -1098,7 +1285,7 @@ function ZodForm({
|
|
|
1098
1285
|
title
|
|
1099
1286
|
}) {
|
|
1100
1287
|
const form = useZodForm(config);
|
|
1101
|
-
const [submissionState, setSubmissionState] =
|
|
1288
|
+
const [submissionState, setSubmissionState] = React16.useState({
|
|
1102
1289
|
error: void 0,
|
|
1103
1290
|
isSubmitted: false,
|
|
1104
1291
|
isSubmitting: false,
|
|
@@ -1155,12 +1342,12 @@ function ZodForm({
|
|
|
1155
1342
|
};
|
|
1156
1343
|
const renderFields = () => {
|
|
1157
1344
|
if (layout === "grid") {
|
|
1158
|
-
return /* @__PURE__ */
|
|
1345
|
+
return /* @__PURE__ */ React16.createElement(
|
|
1159
1346
|
"div",
|
|
1160
1347
|
{
|
|
1161
1348
|
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"}`
|
|
1162
1349
|
},
|
|
1163
|
-
config.fields.map((field) => /* @__PURE__ */
|
|
1350
|
+
config.fields.map((field) => /* @__PURE__ */ React16.createElement(
|
|
1164
1351
|
FormField,
|
|
1165
1352
|
{
|
|
1166
1353
|
key: field.name,
|
|
@@ -1172,7 +1359,7 @@ function ZodForm({
|
|
|
1172
1359
|
);
|
|
1173
1360
|
}
|
|
1174
1361
|
if (layout === "horizontal") {
|
|
1175
|
-
return /* @__PURE__ */
|
|
1362
|
+
return /* @__PURE__ */ React16.createElement("div", { className: `grid gap-${spacing} grid-cols-1 md:grid-cols-2` }, config.fields.map((field) => /* @__PURE__ */ React16.createElement(
|
|
1176
1363
|
FormField,
|
|
1177
1364
|
{
|
|
1178
1365
|
key: field.name,
|
|
@@ -1182,7 +1369,7 @@ function ZodForm({
|
|
|
1182
1369
|
}
|
|
1183
1370
|
)));
|
|
1184
1371
|
}
|
|
1185
|
-
return /* @__PURE__ */
|
|
1372
|
+
return /* @__PURE__ */ React16.createElement("div", { className: `space-y-${spacing}` }, config.fields.map((field) => /* @__PURE__ */ React16.createElement(
|
|
1186
1373
|
FormField,
|
|
1187
1374
|
{
|
|
1188
1375
|
key: field.name,
|
|
@@ -1192,27 +1379,42 @@ function ZodForm({
|
|
|
1192
1379
|
}
|
|
1193
1380
|
)));
|
|
1194
1381
|
};
|
|
1195
|
-
const handleFormSubmit = (
|
|
1196
|
-
|
|
1382
|
+
const handleFormSubmit = (e) => {
|
|
1383
|
+
e.preventDefault();
|
|
1197
1384
|
void handleSubmit();
|
|
1198
1385
|
};
|
|
1199
|
-
|
|
1386
|
+
React16.useEffect(() => {
|
|
1387
|
+
if (config.onError && Object.keys(form.formState.errors).length > 0) {
|
|
1388
|
+
config.onError(form.formState.errors);
|
|
1389
|
+
}
|
|
1390
|
+
}, [form.formState.errors, config.onError]);
|
|
1391
|
+
if (render) {
|
|
1392
|
+
return render({
|
|
1393
|
+
errors: form.formState.errors,
|
|
1394
|
+
form,
|
|
1395
|
+
isSubmitted: submissionState.isSubmitted,
|
|
1396
|
+
isSubmitting: submissionState.isSubmitting,
|
|
1397
|
+
isSuccess: submissionState.isSuccess,
|
|
1398
|
+
values: form.getValues()
|
|
1399
|
+
});
|
|
1400
|
+
}
|
|
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(
|
|
1200
1402
|
"div",
|
|
1201
1403
|
{
|
|
1202
1404
|
className: "mb-6 p-4 bg-success-50 border border-success-200 rounded-lg",
|
|
1203
1405
|
"data-testid": "success-message"
|
|
1204
1406
|
},
|
|
1205
|
-
/* @__PURE__ */
|
|
1206
|
-
/* @__PURE__ */
|
|
1207
|
-
), submissionState.error && /* @__PURE__ */
|
|
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(
|
|
1208
1410
|
"div",
|
|
1209
1411
|
{
|
|
1210
1412
|
className: "mb-6 p-4 bg-danger-50 border border-danger-200 rounded-lg",
|
|
1211
1413
|
"data-testid": "error-message"
|
|
1212
1414
|
},
|
|
1213
|
-
/* @__PURE__ */
|
|
1214
|
-
/* @__PURE__ */
|
|
1215
|
-
), renderFields(), /* @__PURE__ */
|
|
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(
|
|
1216
1418
|
Button3,
|
|
1217
1419
|
{
|
|
1218
1420
|
color: "primary",
|
|
@@ -1222,7 +1424,7 @@ function ZodForm({
|
|
|
1222
1424
|
...submitButtonProps
|
|
1223
1425
|
},
|
|
1224
1426
|
submitButtonText
|
|
1225
|
-
), showResetButton && /* @__PURE__ */
|
|
1427
|
+
), showResetButton && /* @__PURE__ */ React16.createElement(
|
|
1226
1428
|
Button3,
|
|
1227
1429
|
{
|
|
1228
1430
|
isDisabled: submissionState.isSubmitting,
|
|
@@ -1238,6 +1440,7 @@ export {
|
|
|
1238
1440
|
ConfigurableForm,
|
|
1239
1441
|
DateField,
|
|
1240
1442
|
FileField,
|
|
1443
|
+
FontPickerField,
|
|
1241
1444
|
FormField,
|
|
1242
1445
|
FormProvider,
|
|
1243
1446
|
HeroHookFormProvider,
|
|
@@ -1250,7 +1453,36 @@ export {
|
|
|
1250
1453
|
TextareaField,
|
|
1251
1454
|
ZodForm,
|
|
1252
1455
|
applyServerErrors,
|
|
1456
|
+
commonValidations,
|
|
1457
|
+
createConditionalSchema,
|
|
1458
|
+
createConfirmPasswordSchema,
|
|
1459
|
+
createDateSchema,
|
|
1460
|
+
createEmailSchema,
|
|
1461
|
+
createFileSchema,
|
|
1462
|
+
createFormTestUtils,
|
|
1463
|
+
createFutureDateSchema,
|
|
1464
|
+
createMaxLengthSchema,
|
|
1465
|
+
createMinLengthSchema,
|
|
1466
|
+
createMockFormData,
|
|
1467
|
+
createMockFormErrors,
|
|
1468
|
+
createNumberRangeSchema,
|
|
1469
|
+
createPasswordSchema,
|
|
1470
|
+
createPastDateSchema,
|
|
1471
|
+
createPhoneSchema,
|
|
1472
|
+
createRequiredCheckboxSchema,
|
|
1473
|
+
createRequiredSchema,
|
|
1474
|
+
createUrlSchema,
|
|
1475
|
+
createZodFormConfig,
|
|
1476
|
+
getFieldError,
|
|
1477
|
+
getFormErrors,
|
|
1478
|
+
hasFieldError,
|
|
1479
|
+
hasFormErrors,
|
|
1480
|
+
simulateFieldInput,
|
|
1481
|
+
simulateFormSubmission,
|
|
1482
|
+
useFormContext2 as useFormContext,
|
|
1253
1483
|
useFormHelper,
|
|
1484
|
+
useHeroForm,
|
|
1254
1485
|
useHeroHookFormDefaults,
|
|
1255
|
-
useZodForm
|
|
1486
|
+
useZodForm,
|
|
1487
|
+
waitForFormState
|
|
1256
1488
|
};
|