@refinedev/react-hook-form 4.8.14 → 4.8.16

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.
Files changed (41) hide show
  1. package/dist/index.cjs +3 -0
  2. package/dist/index.cjs.map +1 -0
  3. package/dist/index.d.cts +4 -0
  4. package/dist/index.d.cts.map +1 -0
  5. package/dist/index.d.mts +4 -0
  6. package/dist/index.d.mts.map +1 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.mjs +3 -0
  9. package/dist/index.mjs.map +1 -0
  10. package/dist/useForm/index.d.cts +30 -0
  11. package/dist/useForm/index.d.cts.map +1 -0
  12. package/dist/useForm/index.d.mts +30 -0
  13. package/dist/useForm/index.d.mts.map +1 -0
  14. package/dist/useForm/index.d.ts +2 -2
  15. package/dist/useForm/index.d.ts.map +1 -1
  16. package/dist/useModalForm/index.d.cts +35 -0
  17. package/dist/useModalForm/index.d.cts.map +1 -0
  18. package/dist/useModalForm/index.d.mts +35 -0
  19. package/dist/useModalForm/index.d.mts.map +1 -0
  20. package/dist/useModalForm/index.d.ts +15 -15
  21. package/dist/useModalForm/index.d.ts.map +1 -1
  22. package/dist/useStepsForm/index.d.cts +28 -0
  23. package/dist/useStepsForm/index.d.cts.map +1 -0
  24. package/dist/useStepsForm/index.d.mts +28 -0
  25. package/dist/useStepsForm/index.d.mts.map +1 -0
  26. package/dist/useStepsForm/index.d.ts +12 -12
  27. package/dist/useStepsForm/index.d.ts.map +1 -1
  28. package/package.json +49 -35
  29. package/src/index.ts +6 -6
  30. package/src/useForm/index.spec.tsx +211 -224
  31. package/src/useForm/index.ts +229 -229
  32. package/src/useModalForm/index.spec.ts +243 -243
  33. package/src/useModalForm/index.ts +256 -265
  34. package/src/useStepsForm/index.spec.ts +103 -107
  35. package/src/useStepsForm/index.ts +127 -119
  36. package/dist/esm/index.js +0 -3
  37. package/dist/esm/index.js.map +0 -1
  38. package/dist/iife/index.js +0 -72
  39. package/dist/iife/index.js.map +0 -1
  40. package/dist/index.js +0 -3
  41. package/dist/index.js.map +0 -1
package/package.json CHANGED
@@ -1,60 +1,74 @@
1
1
  {
2
- "version": "4.8.14",
3
- "license": "MIT",
4
- "main": "dist/index.js",
5
- "typings": "dist/index.d.ts",
2
+ "name": "@refinedev/react-hook-form",
3
+ "version": "4.8.16",
6
4
  "private": false,
5
+ "description": "refine offers a React Hook Form adapter that allows you to use the React Hook Form library with refine.",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/refinedev/refine.git",
9
+ "directory": "packages/react-hook-form"
10
+ },
11
+ "license": "MIT",
12
+ "author": "refine",
7
13
  "sideEffects": false,
14
+ "exports": {
15
+ ".": {
16
+ "import": {
17
+ "types": "./dist/index.d.mts",
18
+ "default": "./dist/index.mjs"
19
+ },
20
+ "require": {
21
+ "types": "./dist/index.d.cts",
22
+ "default": "./dist/index.cjs"
23
+ }
24
+ }
25
+ },
26
+ "main": "dist/index.cjs",
27
+ "module": "dist/index.mjs",
28
+ "typings": "dist/index.d.ts",
8
29
  "files": [
9
30
  "dist",
10
31
  "src"
11
32
  ],
12
- "engines": {
13
- "node": ">=10"
14
- },
15
33
  "scripts": {
16
- "start": "tsup --watch --format esm,cjs,iife --legacy-output",
17
- "build": "tsup --format esm,cjs,iife --minify --legacy-output",
34
+ "build": "tsup",
35
+ "dev": "tsup --watch",
36
+ "prepare": "npm run build",
37
+ "publint": "publint --strict=true --level=suggestion",
18
38
  "test": "jest --passWithNoTests --runInBand",
19
- "prepare": "npm run build"
39
+ "types": "node ../shared/generate-declarations.js"
20
40
  },
21
- "name": "@refinedev/react-hook-form",
22
- "description": "refine offers a React Hook Form adapter that allows you to use the React Hook Form library with refine.",
23
- "author": "refine",
24
- "module": "dist/esm/index.js",
25
- "peerDependencies": {
26
- "@refinedev/core": "^4.46.1",
27
- "react-hook-form": "^7.30.0",
28
- "react": "^17.0.0 || ^18.0.0",
29
- "react-dom": "^17.0.0 || ^18.0.0",
30
- "@types/react": "^17.0.0 || ^18.0.0",
31
- "@types/react-dom": "^17.0.0 || ^18.0.0"
41
+ "dependencies": {
42
+ "lodash": "^4.17.21",
43
+ "lodash-es": "^4.17.21",
44
+ "react-hook-form": "^7.30.0"
32
45
  },
33
46
  "devDependencies": {
34
- "@testing-library/jest-dom": "^5.16.4",
35
- "@refinedev/core": "^4.47.1",
36
47
  "@esbuild-plugins/node-resolve": "^0.1.4",
48
+ "@refinedev/core": "^4.49.0",
49
+ "@testing-library/jest-dom": "^5.16.4",
37
50
  "@types/jest": "^29.2.4",
38
51
  "@types/lodash": "^4.14.171",
39
52
  "jest": "^29.3.1",
40
53
  "jest-environment-jsdom": "^29.3.1",
41
54
  "react-router-dom": "^6.8.1",
42
- "ts-jest": "^29.0.3",
43
- "tslib": "^2.3.1",
55
+ "ts-jest": "^29.1.2",
56
+ "tslib": "^2.6.2",
44
57
  "tsup": "^6.7.0"
45
58
  },
46
- "dependencies": {
47
- "react-hook-form": "^7.30.0",
48
- "lodash-es": "^4.17.21",
49
- "lodash": "^4.17.21"
59
+ "peerDependencies": {
60
+ "@refinedev/core": "^4.46.1",
61
+ "@types/react": "^17.0.0 || ^18.0.0",
62
+ "@types/react-dom": "^17.0.0 || ^18.0.0",
63
+ "react": "^17.0.0 || ^18.0.0",
64
+ "react-dom": "^17.0.0 || ^18.0.0",
65
+ "react-hook-form": "^7.30.0"
50
66
  },
51
- "repository": {
52
- "type": "git",
53
- "url": "https://github.com/refinedev/refine.git",
54
- "directory": "packages/react-hook-form"
67
+ "engines": {
68
+ "node": ">=10"
55
69
  },
56
- "gitHead": "829f5a516f98c06f666d6be3e6e6099c75c07719",
57
70
  "publishConfig": {
58
71
  "access": "public"
59
- }
72
+ },
73
+ "gitHead": "829f5a516f98c06f666d6be3e6e6099c75c07719"
60
74
  }
package/src/index.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  export { useForm, UseFormProps, UseFormReturnType } from "./useForm";
2
2
  export {
3
- useStepsForm,
4
- UseStepsFormProps,
5
- UseStepsFormReturnType,
3
+ useStepsForm,
4
+ UseStepsFormProps,
5
+ UseStepsFormReturnType,
6
6
  } from "./useStepsForm";
7
7
  export {
8
- useModalForm,
9
- UseModalFormProps,
10
- UseModalFormReturnType,
8
+ useModalForm,
9
+ UseModalFormProps,
10
+ UseModalFormReturnType,
11
11
  } from "./useModalForm";
@@ -1,248 +1,235 @@
1
1
  import React from "react";
2
2
 
3
3
  import { useForm } from ".";
4
- import { HttpError } from "@refinedev/core";
4
+ import { IRefineOptions, HttpError } from "@refinedev/core";
5
5
  import { MockJSONServer, TestWrapper, act, render, waitFor } from "../../test";
6
6
  import { Route, Routes } from "react-router-dom";
7
- import { IRefineOptions } from "@refinedev/core/dist/interfaces";
8
7
 
9
8
  interface IPost {
10
- title: string;
11
- content: string;
12
- slug: string;
13
- category: { id: number };
14
- tags: string[];
9
+ title: string;
10
+ content: string;
11
+ slug: string;
12
+ category: { id: number };
13
+ tags: string[];
15
14
  }
16
15
 
17
16
  const renderForm = ({
18
- refineCoreProps,
19
- refineOptions,
20
- useFormProps,
17
+ refineCoreProps,
18
+ refineOptions,
19
+ useFormProps,
21
20
  }: {
22
- useFormProps?: any;
23
- refineCoreProps?: any;
24
- refineOptions?: IRefineOptions;
21
+ useFormProps?: any;
22
+ refineCoreProps?: any;
23
+ refineOptions?: IRefineOptions;
25
24
  }) => {
26
- const EditPage = () => {
27
- const {
28
- refineCore: { formLoading },
29
- saveButtonProps,
30
- register,
31
- formState: { errors },
32
- } = useForm<IPost, HttpError, IPost>({
33
- ...useFormProps,
34
- refineCoreProps: {
35
- resource: "posts",
36
- ...refineCoreProps,
37
- },
38
- });
39
-
40
- return (
41
- <div>
42
- {formLoading && <p>loading</p>}
43
- <input {...register("title")} />
44
- {errors.title && (
45
- <span>{errors?.title?.message?.toString()}</span>
46
- )}
47
-
48
- <input {...register("content")} />
49
- {errors.content && (
50
- <span>{errors?.content?.message?.toString()}</span>
51
- )}
52
-
53
- <input {...register("slug")} />
54
- {errors.slug && (
55
- <span>{errors?.slug?.message?.toString()}</span>
56
- )}
57
-
58
- <select
59
- {...register("category.id", {
60
- required: true,
61
- })}
62
- >
63
- {["1", "2", "3"]?.map((category) => (
64
- <option key={category} value={category}>
65
- {category}
66
- </option>
67
- ))}
68
- </select>
69
- {errors.category && (
70
- <span>{`${errors.category?.id?.message}`}</span>
71
- )}
72
-
73
- <button
74
- {...saveButtonProps}
75
- onClick={(e) => {
76
- saveButtonProps?.onClick(e);
77
- }}
78
- data-testid="refine-save-button"
79
- type="submit"
80
- >
81
- save
82
- </button>
83
- </div>
84
- );
85
- };
86
-
87
- return render(
88
- <Routes>
89
- <Route path="/" element={<EditPage />} />
90
- </Routes>,
91
- {
92
- wrapper: TestWrapper({
93
- options: refineOptions,
94
- i18nProvider: {
95
- changeLocale: () => Promise.resolve(),
96
- getLocale: () => "en",
97
- translate: (key: string) => {
98
- if (key === "form.error.content") {
99
- return "Translated content error";
100
- }
101
-
102
- return key;
103
- },
25
+ const EditPage = () => {
26
+ const {
27
+ refineCore: { formLoading },
28
+ saveButtonProps,
29
+ register,
30
+ formState: { errors },
31
+ } = useForm<IPost, HttpError, IPost>({
32
+ ...useFormProps,
33
+ refineCoreProps: {
34
+ resource: "posts",
35
+ ...refineCoreProps,
36
+ },
37
+ });
38
+
39
+ return (
40
+ <div>
41
+ {formLoading && <p>loading</p>}
42
+ <input {...register("title")} />
43
+ {errors.title && <span>{errors?.title?.message?.toString()}</span>}
44
+
45
+ <input {...register("content")} />
46
+ {errors.content && <span>{errors?.content?.message?.toString()}</span>}
47
+
48
+ <input {...register("slug")} />
49
+ {errors.slug && <span>{errors?.slug?.message?.toString()}</span>}
50
+
51
+ <select
52
+ {...register("category.id", {
53
+ required: true,
54
+ })}
55
+ >
56
+ {["1", "2", "3"]?.map((category) => (
57
+ <option key={category} value={category}>
58
+ {category}
59
+ </option>
60
+ ))}
61
+ </select>
62
+ {errors.category && <span>{`${errors.category?.id?.message}`}</span>}
63
+
64
+ <button
65
+ {...saveButtonProps}
66
+ onClick={(e) => {
67
+ saveButtonProps?.onClick(e);
68
+ }}
69
+ data-testid="refine-save-button"
70
+ type="submit"
71
+ >
72
+ save
73
+ </button>
74
+ </div>
75
+ );
76
+ };
77
+
78
+ return render(
79
+ <Routes>
80
+ <Route path="/" element={<EditPage />} />
81
+ </Routes>,
82
+ {
83
+ wrapper: TestWrapper({
84
+ options: refineOptions,
85
+ i18nProvider: {
86
+ changeLocale: () => Promise.resolve(),
87
+ getLocale: () => "en",
88
+ translate: (key: string) => {
89
+ if (key === "form.error.content") {
90
+ return "Translated content error";
91
+ }
92
+
93
+ return key;
94
+ },
95
+ },
96
+ dataProvider: {
97
+ ...MockJSONServer,
98
+ update: async () => {
99
+ const error: HttpError = {
100
+ message: "An error occurred while updating the record.",
101
+ statusCode: 400,
102
+ errors: {
103
+ title: ["Title is required"],
104
+ "category.id": ["Category is required"],
105
+ slug: true,
106
+ content: {
107
+ key: "form.error.content",
108
+ message: "Content is required",
104
109
  },
105
- dataProvider: {
106
- ...MockJSONServer,
107
- update: async () => {
108
- const error: HttpError = {
109
- message:
110
- "An error occurred while updating the record.",
111
- statusCode: 400,
112
- errors: {
113
- title: ["Title is required"],
114
- "category.id": ["Category is required"],
115
- slug: true,
116
- content: {
117
- key: "form.error.content",
118
- message: "Content is required",
119
- },
120
- },
121
- };
122
-
123
- return Promise.reject(error);
124
- },
125
- create: async () => {
126
- const error: HttpError = {
127
- message:
128
- "An error occurred while creating the record.",
129
- statusCode: 400,
130
- slug: true,
131
- errors: {
132
- title: ["Title is required"],
133
- "category.id": ["Category is required"],
134
- slug: true,
135
- content: {
136
- key: "form.error.content",
137
- message: "Content is required",
138
- },
139
- },
140
- };
141
-
142
- return Promise.reject(error);
143
- },
110
+ },
111
+ };
112
+
113
+ return Promise.reject(error);
114
+ },
115
+ create: async () => {
116
+ const error: HttpError = {
117
+ message: "An error occurred while creating the record.",
118
+ statusCode: 400,
119
+ slug: true,
120
+ errors: {
121
+ title: ["Title is required"],
122
+ "category.id": ["Category is required"],
123
+ slug: true,
124
+ content: {
125
+ key: "form.error.content",
126
+ message: "Content is required",
144
127
  },
145
- }),
128
+ },
129
+ };
130
+
131
+ return Promise.reject(error);
132
+ },
146
133
  },
147
- );
134
+ }),
135
+ },
136
+ );
148
137
  };
149
138
 
150
139
  describe("useForm hook", () => {
151
- it.each(["edit", "create"] as const)(
152
- "should set %s-form errors from data provider",
153
- async (action) => {
154
- const onMutationError = jest.fn();
155
-
156
- const { getByText, getByTestId } = renderForm({
157
- refineCoreProps: {
158
- onMutationError,
159
- action: action,
160
- id: action === "edit" ? "1" : undefined,
161
- },
162
- });
163
-
164
- await waitFor(() => {
165
- expect(document.body).not.toHaveTextContent("loading");
166
- });
167
-
168
- await act(() => {
169
- getByTestId("refine-save-button").click();
170
- return Promise.resolve();
171
- });
140
+ it.each(["edit", "create"] as const)(
141
+ "should set %s-form errors from data provider",
142
+ async (action) => {
143
+ const onMutationError = jest.fn();
144
+
145
+ const { getByText, getByTestId } = renderForm({
146
+ refineCoreProps: {
147
+ onMutationError,
148
+ action: action,
149
+ id: action === "edit" ? "1" : undefined,
150
+ },
151
+ });
152
+
153
+ await waitFor(() => {
154
+ expect(document.body).not.toHaveTextContent("loading");
155
+ });
156
+
157
+ await act(() => {
158
+ getByTestId("refine-save-button").click();
159
+ return Promise.resolve();
160
+ });
161
+
162
+ await waitFor(() => {
163
+ expect(document.body).not.toHaveTextContent("loading");
164
+ });
165
+
166
+ expect(onMutationError).toBeCalledTimes(1);
167
+
168
+ expect(getByText("Title is required")).toBeInTheDocument();
169
+ expect(getByText("Category is required")).toBeInTheDocument();
170
+ expect(getByText("Translated content error")).toBeInTheDocument();
171
+ expect(getByText("Field is not valid.")).toBeInTheDocument();
172
+ },
173
+ );
174
+
175
+ it.each([
176
+ {
177
+ action: "edit",
178
+ disableFromRefineOption: false,
179
+ disableFromHook: true,
180
+ },
181
+ {
182
+ action: "edit",
183
+ disableFromRefineOption: true,
184
+ disableFromHook: false,
185
+ },
186
+ {
187
+ action: "create",
188
+ disableFromRefineOption: false,
189
+ disableFromHook: true,
190
+ },
191
+ {
192
+ action: "create",
193
+ disableFromRefineOption: true,
194
+ disableFromHook: false,
195
+ },
196
+ ] as const)("should disable server-side validation", async (testCase) => {
197
+ const onMutationErrorMock = jest.fn();
198
+
199
+ const { getByTestId, queryByText } = renderForm({
200
+ refineOptions: {
201
+ disableServerSideValidation: testCase.disableFromRefineOption,
202
+ },
203
+ useFormProps: {
204
+ disableServerSideValidation: testCase.disableFromHook,
205
+ },
206
+
207
+ refineCoreProps: {
208
+ action: testCase.action,
209
+ onMutationError: onMutationErrorMock,
210
+ id: testCase.action === "edit" ? "1" : undefined,
211
+ },
212
+ });
172
213
 
173
- await waitFor(() => {
174
- expect(document.body).not.toHaveTextContent("loading");
175
- });
214
+ await waitFor(() => {
215
+ expect(document.body).not.toHaveTextContent("loading");
216
+ });
176
217
 
177
- expect(onMutationError).toBeCalledTimes(1);
218
+ await act(() => {
219
+ getByTestId("refine-save-button").click();
220
+ return Promise.resolve();
221
+ });
178
222
 
179
- expect(getByText("Title is required")).toBeInTheDocument();
180
- expect(getByText("Category is required")).toBeInTheDocument();
181
- expect(getByText("Translated content error")).toBeInTheDocument();
182
- expect(getByText("Field is not valid.")).toBeInTheDocument();
183
- },
184
- );
223
+ await waitFor(() => {
224
+ expect(document.body).not.toHaveTextContent("loading");
225
+ expect(onMutationErrorMock).toBeCalledTimes(1);
226
+ });
185
227
 
186
- it.each([
187
- {
188
- action: "edit",
189
- disableFromRefineOption: false,
190
- disableFromHook: true,
191
- },
192
- {
193
- action: "edit",
194
- disableFromRefineOption: true,
195
- disableFromHook: false,
196
- },
197
- {
198
- action: "create",
199
- disableFromRefineOption: false,
200
- disableFromHook: true,
201
- },
202
- {
203
- action: "create",
204
- disableFromRefineOption: true,
205
- disableFromHook: false,
206
- },
207
- ] as const)("should disable server-side validation", async (testCase) => {
208
- const onMutationErrorMock = jest.fn();
209
-
210
- const { getByTestId, queryByText } = renderForm({
211
- refineOptions: {
212
- disableServerSideValidation: testCase.disableFromRefineOption,
213
- },
214
- useFormProps: {
215
- disableServerSideValidation: testCase.disableFromHook,
216
- },
217
-
218
- refineCoreProps: {
219
- action: testCase.action,
220
- onMutationError: onMutationErrorMock,
221
- id: testCase.action === "edit" ? "1" : undefined,
222
- },
223
- });
224
-
225
- await waitFor(() => {
226
- expect(document.body).not.toHaveTextContent("loading");
227
- });
228
-
229
- await act(() => {
230
- getByTestId("refine-save-button").click();
231
- return Promise.resolve();
232
- });
233
-
234
- await waitFor(() => {
235
- expect(document.body).not.toHaveTextContent("loading");
236
- expect(onMutationErrorMock).toBeCalledTimes(1);
237
- });
238
-
239
- await waitFor(() => {
240
- expect(queryByText("Title is required")).not.toBeInTheDocument();
241
- expect(queryByText("Category is required")).not.toBeInTheDocument();
242
- expect(
243
- queryByText("Translated content error"),
244
- ).not.toBeInTheDocument();
245
- expect(queryByText("Field is not valid.")).not.toBeInTheDocument();
246
- });
228
+ await waitFor(() => {
229
+ expect(queryByText("Title is required")).not.toBeInTheDocument();
230
+ expect(queryByText("Category is required")).not.toBeInTheDocument();
231
+ expect(queryByText("Translated content error")).not.toBeInTheDocument();
232
+ expect(queryByText("Field is not valid.")).not.toBeInTheDocument();
247
233
  });
234
+ });
248
235
  });