@rachelallyson/hero-hook-form 1.0.0 → 1.0.1
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/README.md +30 -11
- package/dist/index.d.ts +234 -60
- package/dist/index.js +468 -16917
- package/dist/react/index.d.ts +234 -60
- package/dist/react/index.js +275 -133
- package/package.json +29 -20
- 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
|
@@ -69,6 +69,7 @@ function useFormHelper({
|
|
|
69
69
|
|
|
70
70
|
// src/components/FormField.tsx
|
|
71
71
|
import React11 from "react";
|
|
72
|
+
import { useWatch } from "react-hook-form";
|
|
72
73
|
|
|
73
74
|
// src/fields/CheckboxField.tsx
|
|
74
75
|
import React2 from "react";
|
|
@@ -301,8 +302,8 @@ function CoercedFileInput(props) {
|
|
|
301
302
|
type: "file",
|
|
302
303
|
value: field.value ? "" : "",
|
|
303
304
|
onBlur: field.onBlur,
|
|
304
|
-
onChange: (
|
|
305
|
-
const target =
|
|
305
|
+
onChange: (e) => {
|
|
306
|
+
const target = e.target;
|
|
306
307
|
field.onChange(target.files);
|
|
307
308
|
}
|
|
308
309
|
}
|
|
@@ -664,7 +665,19 @@ function FormField({
|
|
|
664
665
|
submissionState
|
|
665
666
|
}) {
|
|
666
667
|
const { control } = form;
|
|
668
|
+
const watchedValues = useWatch({ control });
|
|
669
|
+
if (config.condition && !config.condition(watchedValues)) {
|
|
670
|
+
return null;
|
|
671
|
+
}
|
|
672
|
+
if (config.dependsOn) {
|
|
673
|
+
const dependentValue = watchedValues[config.dependsOn];
|
|
674
|
+
if (config.dependsOnValue !== void 0 && dependentValue !== config.dependsOnValue) {
|
|
675
|
+
return null;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
667
678
|
const baseProps = {
|
|
679
|
+
ariaDescribedBy: config.ariaDescribedBy,
|
|
680
|
+
ariaLabel: config.ariaLabel,
|
|
668
681
|
className: config.className,
|
|
669
682
|
description: config.description,
|
|
670
683
|
isDisabled: config.isDisabled ?? submissionState.isSubmitting,
|
|
@@ -773,6 +786,14 @@ function FormField({
|
|
|
773
786
|
multiple: config.multiple
|
|
774
787
|
}
|
|
775
788
|
);
|
|
789
|
+
case "custom":
|
|
790
|
+
return config.render({
|
|
791
|
+
control,
|
|
792
|
+
errors: form.formState.errors,
|
|
793
|
+
form,
|
|
794
|
+
isSubmitting: submissionState.isSubmitting,
|
|
795
|
+
name: config.name
|
|
796
|
+
});
|
|
776
797
|
default: {
|
|
777
798
|
const fieldType = config.type;
|
|
778
799
|
console.warn(`Unknown field type: ${fieldType}`);
|
|
@@ -853,8 +874,8 @@ function ConfigurableForm({
|
|
|
853
874
|
}
|
|
854
875
|
)));
|
|
855
876
|
};
|
|
856
|
-
const handleFormSubmit = (
|
|
857
|
-
|
|
877
|
+
const handleFormSubmit = (e) => {
|
|
878
|
+
e.preventDefault();
|
|
858
879
|
void handleSubmit();
|
|
859
880
|
};
|
|
860
881
|
return /* @__PURE__ */ React12.createElement("form", { className, role: "form", onSubmit: handleFormSubmit }, title && /* @__PURE__ */ React12.createElement("div", { className: "mb-6" }, /* @__PURE__ */ React12.createElement("h2", { className: "text-xl font-semibold text-foreground mb-2" }, title), subtitle && /* @__PURE__ */ React12.createElement("p", { className: "text-sm text-muted-foreground" }, subtitle)), isSubmitted && isSuccess && /* @__PURE__ */ React12.createElement(
|
|
@@ -940,144 +961,222 @@ function applyServerErrors(setError, serverError) {
|
|
|
940
961
|
}
|
|
941
962
|
}
|
|
942
963
|
|
|
943
|
-
// src/
|
|
944
|
-
|
|
945
|
-
|
|
964
|
+
// src/utils/testing.ts
|
|
965
|
+
function createFormTestUtils(form) {
|
|
966
|
+
return {
|
|
967
|
+
/**
|
|
968
|
+
* Get a field by name
|
|
969
|
+
*/
|
|
970
|
+
getField: (name) => {
|
|
971
|
+
return {
|
|
972
|
+
error: form.formState.errors[name],
|
|
973
|
+
isDirty: !!form.formState.dirtyFields[name],
|
|
974
|
+
isTouched: !!form.formState.touchedFields[name],
|
|
975
|
+
value: form.getValues(name)
|
|
976
|
+
};
|
|
977
|
+
},
|
|
978
|
+
/**
|
|
979
|
+
* Get the current form state
|
|
980
|
+
*/
|
|
981
|
+
getFormState: () => ({
|
|
982
|
+
errors: form.formState.errors,
|
|
983
|
+
isSubmitted: form.formState.isSubmitted,
|
|
984
|
+
isSubmitting: form.formState.isSubmitting,
|
|
985
|
+
isSuccess: form.formState.isSubmitSuccessful,
|
|
986
|
+
values: form.getValues()
|
|
987
|
+
}),
|
|
988
|
+
/**
|
|
989
|
+
* Reset the form
|
|
990
|
+
*/
|
|
991
|
+
resetForm: () => {
|
|
992
|
+
form.reset();
|
|
993
|
+
},
|
|
994
|
+
/**
|
|
995
|
+
* Set a field value
|
|
996
|
+
*/
|
|
997
|
+
setFieldValue: (name, value) => {
|
|
998
|
+
form.setValue(name, value, { shouldValidate: true });
|
|
999
|
+
},
|
|
1000
|
+
/**
|
|
1001
|
+
* Submit the form
|
|
1002
|
+
*/
|
|
1003
|
+
submitForm: async () => {
|
|
1004
|
+
const isValid = await form.trigger();
|
|
1005
|
+
if (isValid) {
|
|
1006
|
+
await form.handleSubmit(() => {
|
|
1007
|
+
})();
|
|
1008
|
+
}
|
|
1009
|
+
},
|
|
1010
|
+
/**
|
|
1011
|
+
* Trigger validation for a field or all fields
|
|
1012
|
+
*/
|
|
1013
|
+
triggerValidation: async (name) => {
|
|
1014
|
+
if (name) {
|
|
1015
|
+
return await form.trigger(name);
|
|
1016
|
+
}
|
|
1017
|
+
return await form.trigger();
|
|
1018
|
+
}
|
|
1019
|
+
};
|
|
1020
|
+
}
|
|
1021
|
+
function createMockFormData(overrides = {}) {
|
|
1022
|
+
return {
|
|
1023
|
+
agreeToTerms: true,
|
|
1024
|
+
confirmPassword: "password123",
|
|
1025
|
+
email: "test@example.com",
|
|
1026
|
+
firstName: "John",
|
|
1027
|
+
lastName: "Doe",
|
|
1028
|
+
password: "password123",
|
|
1029
|
+
phone: "123-456-7890",
|
|
1030
|
+
...overrides
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
function createMockFormErrors(overrides = {}) {
|
|
1034
|
+
return {
|
|
1035
|
+
email: { message: "Invalid email address", type: "pattern" },
|
|
1036
|
+
password: { message: "Password is too short", type: "minLength" },
|
|
1037
|
+
...overrides
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
1040
|
+
function waitForFormState(form, condition, timeout = 5e3) {
|
|
1041
|
+
return new Promise((resolve, reject) => {
|
|
1042
|
+
const startTime = Date.now();
|
|
1043
|
+
const checkState = () => {
|
|
1044
|
+
if (condition(form.formState)) {
|
|
1045
|
+
resolve();
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1048
|
+
if (Date.now() - startTime > timeout) {
|
|
1049
|
+
reject(new Error("Timeout waiting for form state"));
|
|
1050
|
+
return;
|
|
1051
|
+
}
|
|
1052
|
+
setTimeout(checkState, 100);
|
|
1053
|
+
};
|
|
1054
|
+
checkState();
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
function simulateFieldInput(form, name, value) {
|
|
1058
|
+
form.setValue(name, value);
|
|
1059
|
+
void form.trigger(name);
|
|
1060
|
+
}
|
|
1061
|
+
function simulateFormSubmission(form, onSubmit) {
|
|
1062
|
+
return form.handleSubmit(onSubmit)();
|
|
1063
|
+
}
|
|
1064
|
+
function hasFormErrors(form) {
|
|
1065
|
+
return Object.keys(form.formState.errors).length > 0;
|
|
1066
|
+
}
|
|
1067
|
+
function getFormErrors(form) {
|
|
1068
|
+
return Object.values(form.formState.errors).map(
|
|
1069
|
+
(error) => error.message
|
|
1070
|
+
);
|
|
1071
|
+
}
|
|
1072
|
+
function hasFieldError(form, name) {
|
|
1073
|
+
return !!form.formState.errors[name];
|
|
1074
|
+
}
|
|
1075
|
+
function getFieldError(form, name) {
|
|
1076
|
+
const error = form.formState.errors[name];
|
|
1077
|
+
return error?.message;
|
|
1078
|
+
}
|
|
946
1079
|
|
|
947
|
-
//
|
|
948
|
-
import {
|
|
949
|
-
var
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
1080
|
+
// src/utils/validation.ts
|
|
1081
|
+
import { z } from "zod";
|
|
1082
|
+
var createMinLengthSchema = (min, fieldName) => z.string().min(min, `${fieldName} must be at least ${min} characters`);
|
|
1083
|
+
var createMaxLengthSchema = (max, fieldName) => z.string().max(max, `${fieldName} must be no more than ${max} characters`);
|
|
1084
|
+
var createEmailSchema = () => z.email("Please enter a valid email address");
|
|
1085
|
+
var createRequiredSchema = (fieldName) => z.string().min(1, `${fieldName} is required`);
|
|
1086
|
+
var createUrlSchema = () => z.string().url("Please enter a valid URL");
|
|
1087
|
+
var createPhoneSchema = () => z.string().regex(/^[+]?[1-9][\d]{0,15}$/, "Please enter a valid phone number");
|
|
1088
|
+
var createPasswordSchema = (minLength = 8) => z.string().min(minLength, `Password must be at least ${minLength} characters`).regex(
|
|
1089
|
+
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/,
|
|
1090
|
+
"Password must contain at least one uppercase letter, one lowercase letter, and one number"
|
|
1091
|
+
);
|
|
1092
|
+
var createConfirmPasswordSchema = (passwordField) => z.string().refine(
|
|
1093
|
+
(val) => {
|
|
1094
|
+
return true;
|
|
1095
|
+
},
|
|
1096
|
+
{
|
|
1097
|
+
message: "Passwords do not match"
|
|
953
1098
|
}
|
|
954
|
-
|
|
955
|
-
var
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
1099
|
+
);
|
|
1100
|
+
var createNumberRangeSchema = (min, max, fieldName) => z.number().min(min, `${fieldName} must be at least ${min}`).max(max, `${fieldName} must be no more than ${max}`);
|
|
1101
|
+
var createDateSchema = (fieldName) => z.date({ message: `${fieldName} is required` });
|
|
1102
|
+
var createFutureDateSchema = (fieldName) => z.date({ message: `${fieldName} is required` }).refine((date) => date > /* @__PURE__ */ new Date(), {
|
|
1103
|
+
message: `${fieldName} must be in the future`
|
|
1104
|
+
});
|
|
1105
|
+
var createPastDateSchema = (fieldName) => z.date({ message: `${fieldName} is required` }).refine((date) => date < /* @__PURE__ */ new Date(), {
|
|
1106
|
+
message: `${fieldName} must be in the past`
|
|
1107
|
+
});
|
|
1108
|
+
var createFileSchema = (maxSizeInMB = 5, allowedTypes = ["image/jpeg", "image/png", "image/gif"]) => z.instanceof(File).refine(
|
|
1109
|
+
(file) => file.size <= maxSizeInMB * 1024 * 1024,
|
|
1110
|
+
`File size must be less than ${maxSizeInMB}MB`
|
|
1111
|
+
).refine(
|
|
1112
|
+
(file) => allowedTypes.includes(file.type),
|
|
1113
|
+
`File type must be one of: ${allowedTypes.join(", ")}`
|
|
1114
|
+
);
|
|
1115
|
+
var createRequiredCheckboxSchema = (fieldName) => z.boolean().refine((val) => val === true, {
|
|
1116
|
+
message: `You must agree to ${fieldName}`
|
|
1117
|
+
});
|
|
1118
|
+
var createConditionalSchema = (condition, schema, errorMessage = "This field is required") => z.any().refine(
|
|
1119
|
+
(val) => {
|
|
1120
|
+
return true;
|
|
1121
|
+
},
|
|
1122
|
+
{
|
|
1123
|
+
message: errorMessage
|
|
959
1124
|
}
|
|
1125
|
+
);
|
|
1126
|
+
var commonValidations = {
|
|
1127
|
+
conditional: (condition, schema, errorMessage) => createConditionalSchema(condition, schema, errorMessage),
|
|
1128
|
+
confirmPassword: (passwordField) => createConfirmPasswordSchema(passwordField),
|
|
1129
|
+
date: (fieldName) => createDateSchema(fieldName),
|
|
1130
|
+
email: createEmailSchema(),
|
|
1131
|
+
file: (maxSizeInMB, allowedTypes) => createFileSchema(maxSizeInMB, allowedTypes),
|
|
1132
|
+
futureDate: (fieldName) => createFutureDateSchema(fieldName),
|
|
1133
|
+
maxLength: (max, fieldName) => createMaxLengthSchema(max, fieldName),
|
|
1134
|
+
minLength: (min, fieldName) => createMinLengthSchema(min, fieldName),
|
|
1135
|
+
numberRange: (min, max, fieldName) => createNumberRangeSchema(min, max, fieldName),
|
|
1136
|
+
password: (minLength) => createPasswordSchema(minLength),
|
|
1137
|
+
pastDate: (fieldName) => createPastDateSchema(fieldName),
|
|
1138
|
+
phone: createPhoneSchema(),
|
|
1139
|
+
required: (fieldName) => createRequiredSchema(fieldName),
|
|
1140
|
+
requiredCheckbox: (fieldName) => createRequiredCheckboxSchema(fieldName),
|
|
1141
|
+
url: createUrlSchema()
|
|
960
1142
|
};
|
|
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
1143
|
|
|
981
|
-
//
|
|
982
|
-
import
|
|
983
|
-
import
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
return o3 && o3.then ? o3.then(void 0, e2) : o3;
|
|
991
|
-
}
|
|
992
|
-
function s2(r2, e2) {
|
|
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) {
|
|
1144
|
+
// src/components/ZodForm.tsx
|
|
1145
|
+
import React15 from "react";
|
|
1146
|
+
import { Button as Button3 } from "@heroui/react";
|
|
1147
|
+
|
|
1148
|
+
// src/zod-integration.ts
|
|
1149
|
+
import { useForm as useForm2 } from "react-hook-form";
|
|
1150
|
+
import { z as z2 } from "zod";
|
|
1151
|
+
function createZodResolver(schema) {
|
|
1152
|
+
return async (values, context) => {
|
|
1052
1153
|
try {
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1154
|
+
const result = await schema.parseAsync(values);
|
|
1155
|
+
return {
|
|
1156
|
+
errors: {},
|
|
1157
|
+
values: result
|
|
1158
|
+
};
|
|
1159
|
+
} catch (error) {
|
|
1160
|
+
if (error instanceof z2.ZodError) {
|
|
1161
|
+
const errors = {};
|
|
1162
|
+
error.issues.forEach((err) => {
|
|
1163
|
+
const path = err.path.join(".");
|
|
1164
|
+
errors[path] = { message: err.message };
|
|
1056
1165
|
});
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
} catch (r2) {
|
|
1064
|
-
return Promise.reject(r2);
|
|
1166
|
+
return {
|
|
1167
|
+
errors,
|
|
1168
|
+
values: {}
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1171
|
+
throw error;
|
|
1065
1172
|
}
|
|
1066
1173
|
};
|
|
1067
|
-
throw new Error("Invalid input: not a Zod schema");
|
|
1068
1174
|
}
|
|
1069
|
-
|
|
1070
|
-
// src/zod-integration.ts
|
|
1071
|
-
import { useForm as useForm2 } from "react-hook-form";
|
|
1072
1175
|
function useZodForm(config) {
|
|
1073
1176
|
if (!config.resolver && config.schema) {
|
|
1074
|
-
|
|
1075
|
-
config.resolver = resolver;
|
|
1177
|
+
config.resolver = createZodResolver(config.schema);
|
|
1076
1178
|
}
|
|
1077
|
-
|
|
1078
|
-
...config
|
|
1079
|
-
};
|
|
1080
|
-
return useForm2(formConfig);
|
|
1179
|
+
return useForm2(config);
|
|
1081
1180
|
}
|
|
1082
1181
|
|
|
1083
1182
|
// src/components/ZodForm.tsx
|
|
@@ -1085,10 +1184,12 @@ function ZodForm({
|
|
|
1085
1184
|
className,
|
|
1086
1185
|
columns = 1,
|
|
1087
1186
|
config,
|
|
1187
|
+
errorDisplay = "inline",
|
|
1088
1188
|
layout = "vertical",
|
|
1089
1189
|
onError,
|
|
1090
1190
|
onSubmit,
|
|
1091
1191
|
onSuccess,
|
|
1192
|
+
render,
|
|
1092
1193
|
resetButtonText = "Reset",
|
|
1093
1194
|
showResetButton = false,
|
|
1094
1195
|
spacing = "4",
|
|
@@ -1192,10 +1293,25 @@ function ZodForm({
|
|
|
1192
1293
|
}
|
|
1193
1294
|
)));
|
|
1194
1295
|
};
|
|
1195
|
-
const handleFormSubmit = (
|
|
1196
|
-
|
|
1296
|
+
const handleFormSubmit = (e) => {
|
|
1297
|
+
e.preventDefault();
|
|
1197
1298
|
void handleSubmit();
|
|
1198
1299
|
};
|
|
1300
|
+
React15.useEffect(() => {
|
|
1301
|
+
if (config.onError && Object.keys(form.formState.errors).length > 0) {
|
|
1302
|
+
config.onError(form.formState.errors);
|
|
1303
|
+
}
|
|
1304
|
+
}, [form.formState.errors, config.onError]);
|
|
1305
|
+
if (render) {
|
|
1306
|
+
return render({
|
|
1307
|
+
errors: form.formState.errors,
|
|
1308
|
+
form,
|
|
1309
|
+
isSubmitted: submissionState.isSubmitted,
|
|
1310
|
+
isSubmitting: submissionState.isSubmitting,
|
|
1311
|
+
isSuccess: submissionState.isSuccess,
|
|
1312
|
+
values: form.getValues()
|
|
1313
|
+
});
|
|
1314
|
+
}
|
|
1199
1315
|
return /* @__PURE__ */ React15.createElement("form", { className, role: "form", onSubmit: handleFormSubmit }, title && /* @__PURE__ */ React15.createElement("div", { className: "mb-6" }, /* @__PURE__ */ React15.createElement("h2", { className: "text-xl font-semibold text-foreground mb-2" }, title), subtitle && /* @__PURE__ */ React15.createElement("p", { className: "text-sm text-muted-foreground" }, subtitle)), submissionState.isSubmitted && submissionState.isSuccess && /* @__PURE__ */ React15.createElement(
|
|
1200
1316
|
"div",
|
|
1201
1317
|
{
|
|
@@ -1204,7 +1320,7 @@ function ZodForm({
|
|
|
1204
1320
|
},
|
|
1205
1321
|
/* @__PURE__ */ React15.createElement("p", { className: "text-success-800 font-medium" }, "Success!"),
|
|
1206
1322
|
/* @__PURE__ */ React15.createElement("p", { className: "text-success-700 text-sm mt-1" }, "Your request has been processed successfully.")
|
|
1207
|
-
), submissionState.error && /* @__PURE__ */ React15.createElement(
|
|
1323
|
+
), submissionState.error && errorDisplay !== "none" && /* @__PURE__ */ React15.createElement(
|
|
1208
1324
|
"div",
|
|
1209
1325
|
{
|
|
1210
1326
|
className: "mb-6 p-4 bg-danger-50 border border-danger-200 rounded-lg",
|
|
@@ -1250,7 +1366,33 @@ export {
|
|
|
1250
1366
|
TextareaField,
|
|
1251
1367
|
ZodForm,
|
|
1252
1368
|
applyServerErrors,
|
|
1369
|
+
commonValidations,
|
|
1370
|
+
createConditionalSchema,
|
|
1371
|
+
createConfirmPasswordSchema,
|
|
1372
|
+
createDateSchema,
|
|
1373
|
+
createEmailSchema,
|
|
1374
|
+
createFileSchema,
|
|
1375
|
+
createFormTestUtils,
|
|
1376
|
+
createFutureDateSchema,
|
|
1377
|
+
createMaxLengthSchema,
|
|
1378
|
+
createMinLengthSchema,
|
|
1379
|
+
createMockFormData,
|
|
1380
|
+
createMockFormErrors,
|
|
1381
|
+
createNumberRangeSchema,
|
|
1382
|
+
createPasswordSchema,
|
|
1383
|
+
createPastDateSchema,
|
|
1384
|
+
createPhoneSchema,
|
|
1385
|
+
createRequiredCheckboxSchema,
|
|
1386
|
+
createRequiredSchema,
|
|
1387
|
+
createUrlSchema,
|
|
1388
|
+
getFieldError,
|
|
1389
|
+
getFormErrors,
|
|
1390
|
+
hasFieldError,
|
|
1391
|
+
hasFormErrors,
|
|
1392
|
+
simulateFieldInput,
|
|
1393
|
+
simulateFormSubmission,
|
|
1253
1394
|
useFormHelper,
|
|
1254
1395
|
useHeroHookFormDefaults,
|
|
1255
|
-
useZodForm
|
|
1396
|
+
useZodForm,
|
|
1397
|
+
waitForFormState
|
|
1256
1398
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rachelallyson/hero-hook-form",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Typed form helpers that combine React Hook Form and HeroUI components.",
|
|
5
5
|
"author": "Rachel Higley",
|
|
6
6
|
"homepage": "https://github.com/rachelallyson/hero-hook-form#readme",
|
|
@@ -32,19 +32,17 @@
|
|
|
32
32
|
"license": "ISC",
|
|
33
33
|
"sideEffects": false,
|
|
34
34
|
"type": "module",
|
|
35
|
-
"main": "./dist/index.
|
|
35
|
+
"main": "./dist/index.js",
|
|
36
36
|
"module": "./dist/index.js",
|
|
37
37
|
"types": "./dist/index.d.ts",
|
|
38
38
|
"exports": {
|
|
39
39
|
".": {
|
|
40
40
|
"types": "./dist/index.d.ts",
|
|
41
|
-
"import": "./dist/index.js"
|
|
42
|
-
"require": "./dist/index.cjs"
|
|
41
|
+
"import": "./dist/index.js"
|
|
43
42
|
},
|
|
44
43
|
"./react": {
|
|
45
44
|
"types": "./dist/react/index.d.ts",
|
|
46
|
-
"import": "./dist/react/index.js"
|
|
47
|
-
"require": "./dist/react/index.cjs"
|
|
45
|
+
"import": "./dist/react/index.js"
|
|
48
46
|
}
|
|
49
47
|
},
|
|
50
48
|
"files": [
|
|
@@ -57,8 +55,8 @@
|
|
|
57
55
|
"node": ">=18.0.0"
|
|
58
56
|
},
|
|
59
57
|
"scripts": {
|
|
60
|
-
"build": "tsup src/index.ts --format esm
|
|
61
|
-
"dev:build": "tsup src/index.ts --format esm
|
|
58
|
+
"build": "tsup src/index.ts --format esm --dts --clean && tsup src/index.ts --format esm --dts --env.NODE_ENV=production --tsconfig tsconfig.react.json --out-dir dist/react",
|
|
59
|
+
"dev:build": "tsup src/index.ts --format esm --dts --watch",
|
|
62
60
|
"lint": "eslint src",
|
|
63
61
|
"typecheck": "tsc --noEmit",
|
|
64
62
|
"cy:open": "cypress open --component",
|
|
@@ -72,14 +70,16 @@
|
|
|
72
70
|
"@eslint/js": "^9.34.0",
|
|
73
71
|
"@heroui/button": "^2.2.25",
|
|
74
72
|
"@heroui/checkbox": "^2.3.25",
|
|
73
|
+
"@heroui/date-input": "^2.3.25",
|
|
74
|
+
"@heroui/date-picker": "^2.3.26",
|
|
75
75
|
"@heroui/input": "^2.4.26",
|
|
76
76
|
"@heroui/radio": "^2.3.25",
|
|
77
77
|
"@heroui/react": "^2.8.3",
|
|
78
78
|
"@heroui/select": "^2.4.26",
|
|
79
|
+
"@heroui/slider": "^2.4.22",
|
|
79
80
|
"@heroui/spinner": "^2.2.22",
|
|
80
81
|
"@heroui/switch": "^2.2.23",
|
|
81
|
-
"@
|
|
82
|
-
"@kuzu-media/eslint-config-nextjs": "^0.0.20",
|
|
82
|
+
"@heroui/system": "^2.2.25",
|
|
83
83
|
"@types/node": "^24.3.0",
|
|
84
84
|
"@types/react": "^19.1.12",
|
|
85
85
|
"@types/react-dom": "^19.1.9",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"cypress": "^15.1.0",
|
|
88
88
|
"cypress-terminal-report": "^7.2.1",
|
|
89
89
|
"eslint": "^9.34.0",
|
|
90
|
-
"
|
|
90
|
+
"jsdom": "^26.1.0",
|
|
91
91
|
"react": "^19.1.1",
|
|
92
92
|
"react-dom": "^19.1.1",
|
|
93
93
|
"react-hook-form": "^7.62.0",
|
|
@@ -100,12 +100,16 @@
|
|
|
100
100
|
"peerDependencies": {
|
|
101
101
|
"@heroui/button": ">=2 <3",
|
|
102
102
|
"@heroui/checkbox": ">=2 <3",
|
|
103
|
+
"@heroui/date-input": ">=2 <3",
|
|
104
|
+
"@heroui/date-picker": ">=2 <3",
|
|
103
105
|
"@heroui/input": ">=2 <3",
|
|
104
106
|
"@heroui/radio": ">=2 <3",
|
|
105
107
|
"@heroui/react": ">=2 <3",
|
|
106
108
|
"@heroui/select": ">=2 <3",
|
|
109
|
+
"@heroui/slider": ">=2 <3",
|
|
107
110
|
"@heroui/spinner": ">=2 <3",
|
|
108
111
|
"@heroui/switch": ">=2 <3",
|
|
112
|
+
"@heroui/system": ">=2 <3",
|
|
109
113
|
"react": ">=18.2.0 <20",
|
|
110
114
|
"react-dom": ">=18.2.0 <20",
|
|
111
115
|
"react-hook-form": ">=7 <8",
|
|
@@ -118,6 +122,12 @@
|
|
|
118
122
|
"@heroui/checkbox": {
|
|
119
123
|
"optional": true
|
|
120
124
|
},
|
|
125
|
+
"@heroui/date-input": {
|
|
126
|
+
"optional": true
|
|
127
|
+
},
|
|
128
|
+
"@heroui/date-picker": {
|
|
129
|
+
"optional": true
|
|
130
|
+
},
|
|
121
131
|
"@heroui/input": {
|
|
122
132
|
"optional": true
|
|
123
133
|
},
|
|
@@ -130,19 +140,18 @@
|
|
|
130
140
|
"@heroui/select": {
|
|
131
141
|
"optional": true
|
|
132
142
|
},
|
|
143
|
+
"@heroui/slider": {
|
|
144
|
+
"optional": true
|
|
145
|
+
},
|
|
133
146
|
"@heroui/spinner": {
|
|
134
147
|
"optional": true
|
|
135
148
|
},
|
|
136
149
|
"@heroui/switch": {
|
|
137
150
|
"optional": true
|
|
151
|
+
},
|
|
152
|
+
"@heroui/system": {
|
|
153
|
+
"optional": true
|
|
138
154
|
}
|
|
139
155
|
},
|
|
140
|
-
"dependencies": {
|
|
141
|
-
|
|
142
|
-
"framer-motion": "^12.23.12",
|
|
143
|
-
"jsdom": "^26.1.0",
|
|
144
|
-
"postcss": "^8.5.6",
|
|
145
|
-
"tailwindcss": "^4.1.12",
|
|
146
|
-
"zod": ">=4"
|
|
147
|
-
}
|
|
148
|
-
}
|
|
156
|
+
"dependencies": {}
|
|
157
|
+
}
|