@refinedev/react-hook-form 4.8.14 → 4.8.15
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/dist/esm/index.js.map +1 -1
- package/dist/iife/index.js +18 -18
- package/dist/iife/index.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/useForm/index.d.ts.map +1 -1
- package/dist/useModalForm/index.d.ts +13 -13
- package/dist/useModalForm/index.d.ts.map +1 -1
- package/dist/useStepsForm/index.d.ts +10 -10
- package/dist/useStepsForm/index.d.ts.map +1 -1
- package/package.json +32 -32
- package/src/index.ts +6 -6
- package/src/useForm/index.spec.tsx +210 -222
- package/src/useForm/index.ts +227 -229
- package/src/useModalForm/index.spec.ts +243 -243
- package/src/useModalForm/index.ts +256 -265
- package/src/useStepsForm/index.spec.ts +103 -107
- package/src/useStepsForm/index.ts +120 -120
|
@@ -6,127 +6,123 @@ import { useStepsForm } from "./";
|
|
|
6
6
|
import * as UseForm from "../useForm";
|
|
7
7
|
|
|
8
8
|
describe("useStepsForm Hook", () => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
9
|
+
it("'defaultStep' props should set the initial value of 'currentStep'", async () => {
|
|
10
|
+
const { result } = renderHook(
|
|
11
|
+
() =>
|
|
12
|
+
useStepsForm({
|
|
13
|
+
stepsProps: {
|
|
14
|
+
defaultStep: 4,
|
|
15
|
+
},
|
|
16
|
+
}),
|
|
17
|
+
{
|
|
18
|
+
wrapper: TestWrapper({}),
|
|
19
|
+
},
|
|
20
|
+
);
|
|
21
|
+
expect(result.current.steps.currentStep).toBe(4);
|
|
22
|
+
});
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
});
|
|
28
|
-
await act(async () => {
|
|
29
|
-
result.current.steps.gotoStep(1);
|
|
30
|
-
});
|
|
31
|
-
expect(result.current.steps.currentStep).toBe(1);
|
|
24
|
+
it("'goToStep' should update the current step state", async () => {
|
|
25
|
+
const { result } = renderHook(() => useStepsForm({}), {
|
|
26
|
+
wrapper: TestWrapper({}),
|
|
32
27
|
});
|
|
28
|
+
await act(async () => {
|
|
29
|
+
result.current.steps.gotoStep(1);
|
|
30
|
+
});
|
|
31
|
+
expect(result.current.steps.currentStep).toBe(1);
|
|
32
|
+
});
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
});
|
|
41
|
-
expect(result.current.steps.currentStep).toBe(0);
|
|
34
|
+
it("'currentStep' should be 0 when the 'goToSteps' params less than zero", async () => {
|
|
35
|
+
const { result } = renderHook(() => useStepsForm({}), {
|
|
36
|
+
wrapper: TestWrapper({}),
|
|
37
|
+
});
|
|
38
|
+
await act(async () => {
|
|
39
|
+
result.current.steps.gotoStep(-7);
|
|
42
40
|
});
|
|
41
|
+
expect(result.current.steps.currentStep).toBe(0);
|
|
42
|
+
});
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
});
|
|
48
|
-
await act(async () => {
|
|
49
|
-
result.current.steps.gotoStep(-7);
|
|
50
|
-
});
|
|
51
|
-
expect(result.current.steps.currentStep).toBe(0);
|
|
44
|
+
it("'currentStep' should be 0 when the 'goToSteps' params less than zero", async () => {
|
|
45
|
+
const { result } = renderHook(() => useStepsForm({}), {
|
|
46
|
+
wrapper: TestWrapper({}),
|
|
52
47
|
});
|
|
48
|
+
await act(async () => {
|
|
49
|
+
result.current.steps.gotoStep(-7);
|
|
50
|
+
});
|
|
51
|
+
expect(result.current.steps.currentStep).toBe(0);
|
|
52
|
+
});
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
});
|
|
69
|
-
expect(result.current.steps.currentStep).toBe(2);
|
|
54
|
+
it("'currentStep' should not update when the 'goToSteps' params equal to the 'currentStep'", async () => {
|
|
55
|
+
const { result } = renderHook(
|
|
56
|
+
() =>
|
|
57
|
+
useStepsForm({
|
|
58
|
+
stepsProps: {
|
|
59
|
+
defaultStep: 2,
|
|
60
|
+
},
|
|
61
|
+
}),
|
|
62
|
+
{
|
|
63
|
+
wrapper: TestWrapper({}),
|
|
64
|
+
},
|
|
65
|
+
);
|
|
66
|
+
await act(async () => {
|
|
67
|
+
result.current.steps.gotoStep(2);
|
|
70
68
|
});
|
|
69
|
+
expect(result.current.steps.currentStep).toBe(2);
|
|
70
|
+
});
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
72
|
+
it.each([
|
|
73
|
+
{
|
|
74
|
+
mockDirtyFields: {},
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
mockDirtyFields: { field2: true },
|
|
78
|
+
},
|
|
79
|
+
])(
|
|
80
|
+
"should call setValue with correct data according to dirty fields",
|
|
81
|
+
async (scenario) => {
|
|
82
|
+
const mockData = { field1: "field1", field2: "field2" };
|
|
83
|
+
const mockDirtyFields = scenario.mockDirtyFields;
|
|
84
|
+
const setValue = jest.fn();
|
|
85
|
+
const getValues = () => mockData;
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
87
|
+
(jest.spyOn(UseForm, "useForm") as jest.Mock).mockReturnValueOnce({
|
|
88
|
+
setValue,
|
|
89
|
+
getValues,
|
|
90
|
+
formState: { dirtyFields: mockDirtyFields },
|
|
91
|
+
refineCore: { queryResult: { data: { data: mockData } } },
|
|
92
|
+
});
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
94
|
+
const { result } = renderHook(
|
|
95
|
+
() =>
|
|
96
|
+
useStepsForm({
|
|
97
|
+
stepsProps: {
|
|
98
|
+
defaultStep: 1,
|
|
99
|
+
},
|
|
100
|
+
}),
|
|
101
|
+
{
|
|
102
|
+
wrapper: TestWrapper({}),
|
|
103
|
+
},
|
|
104
|
+
);
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
await waitFor(() => {
|
|
107
|
+
expect(!result.current.refineCore.formLoading).toBeTruthy();
|
|
108
|
+
});
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
expect(result.current.refineCore.queryResult?.data?.data).toEqual(
|
|
111
|
+
mockData,
|
|
112
|
+
);
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
expect(setValue).toHaveBeenCalledTimes(setValueCallTimes);
|
|
114
|
+
const setValueCallTimes =
|
|
115
|
+
Object.keys(mockData).length - Object.keys(mockDirtyFields).length;
|
|
116
|
+
expect(setValue).toHaveBeenCalledTimes(setValueCallTimes);
|
|
118
117
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
118
|
+
Object.keys(mockData).forEach((key) => {
|
|
119
|
+
const keyName = key as keyof typeof mockData &
|
|
120
|
+
keyof typeof mockDirtyFields;
|
|
122
121
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
});
|
|
130
|
-
},
|
|
131
|
-
);
|
|
122
|
+
if (!mockDirtyFields[keyName]) {
|
|
123
|
+
expect(setValue).toHaveBeenCalledWith(key, mockData[keyName]);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
},
|
|
127
|
+
);
|
|
132
128
|
});
|
|
@@ -5,46 +5,46 @@ import { BaseRecord, HttpError } from "@refinedev/core";
|
|
|
5
5
|
import { useForm, UseFormProps, UseFormReturnType } from "../useForm";
|
|
6
6
|
|
|
7
7
|
export type UseStepsFormReturnType<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
TQueryFnData extends BaseRecord = BaseRecord,
|
|
9
|
+
TError extends HttpError = HttpError,
|
|
10
|
+
TVariables extends FieldValues = FieldValues,
|
|
11
|
+
TContext extends object = {},
|
|
12
|
+
TData extends BaseRecord = TQueryFnData,
|
|
13
|
+
TResponse extends BaseRecord = TData,
|
|
14
|
+
TResponseError extends HttpError = TError,
|
|
15
15
|
> = UseFormReturnType<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
TQueryFnData,
|
|
17
|
+
TError,
|
|
18
|
+
TVariables,
|
|
19
|
+
TContext,
|
|
20
|
+
TData,
|
|
21
|
+
TResponse,
|
|
22
|
+
TResponseError
|
|
23
23
|
> & {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
steps: {
|
|
25
|
+
currentStep: number;
|
|
26
|
+
gotoStep: (step: number) => void;
|
|
27
|
+
};
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
export type UseStepsFormProps<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
TQueryFnData extends BaseRecord = BaseRecord,
|
|
32
|
+
TError extends HttpError = HttpError,
|
|
33
|
+
TVariables extends FieldValues = FieldValues,
|
|
34
|
+
TContext extends object = {},
|
|
35
|
+
TData extends BaseRecord = TQueryFnData,
|
|
36
|
+
TResponse extends BaseRecord = TData,
|
|
37
|
+
TResponseError extends HttpError = TError,
|
|
38
38
|
> = UseFormProps<
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
TQueryFnData,
|
|
40
|
+
TError,
|
|
41
|
+
TVariables,
|
|
42
|
+
TContext,
|
|
43
|
+
TData,
|
|
44
|
+
TResponse,
|
|
45
|
+
TResponseError
|
|
46
46
|
> & {
|
|
47
|
-
|
|
47
|
+
/**
|
|
48
48
|
* @description Configuration object for the steps.
|
|
49
49
|
* `defaultStep`: Allows you to set the initial step.
|
|
50
50
|
*
|
|
@@ -55,32 +55,44 @@ export type UseStepsFormProps<
|
|
|
55
55
|
}`
|
|
56
56
|
* @default `defaultStep = 0` `isBackValidate = false`
|
|
57
57
|
*/
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
stepsProps?: {
|
|
59
|
+
defaultStep?: number;
|
|
60
|
+
isBackValidate?: boolean;
|
|
61
|
+
};
|
|
62
62
|
};
|
|
63
63
|
|
|
64
64
|
export const useStepsForm = <
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
65
|
+
TQueryFnData extends BaseRecord = BaseRecord,
|
|
66
|
+
TError extends HttpError = HttpError,
|
|
67
|
+
TVariables extends FieldValues = FieldValues,
|
|
68
|
+
TContext extends object = {},
|
|
69
|
+
TData extends BaseRecord = TQueryFnData,
|
|
70
|
+
TResponse extends BaseRecord = TData,
|
|
71
|
+
TResponseError extends HttpError = TError,
|
|
72
72
|
>({
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
stepsProps,
|
|
74
|
+
...rest
|
|
75
75
|
}: UseStepsFormProps<
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
76
|
+
TQueryFnData,
|
|
77
|
+
TError,
|
|
78
|
+
TVariables,
|
|
79
|
+
TContext,
|
|
80
|
+
TData,
|
|
81
|
+
TResponse,
|
|
82
|
+
TResponseError
|
|
83
83
|
> = {}): UseStepsFormReturnType<
|
|
84
|
+
TQueryFnData,
|
|
85
|
+
TError,
|
|
86
|
+
TVariables,
|
|
87
|
+
TContext,
|
|
88
|
+
TData,
|
|
89
|
+
TResponse,
|
|
90
|
+
TResponseError
|
|
91
|
+
> => {
|
|
92
|
+
const { defaultStep = 0, isBackValidate = false } = stepsProps ?? {};
|
|
93
|
+
const [current, setCurrent] = useState(defaultStep);
|
|
94
|
+
|
|
95
|
+
const useHookFormResult = useForm<
|
|
84
96
|
TQueryFnData,
|
|
85
97
|
TError,
|
|
86
98
|
TVariables,
|
|
@@ -88,77 +100,65 @@ export const useStepsForm = <
|
|
|
88
100
|
TData,
|
|
89
101
|
TResponse,
|
|
90
102
|
TResponseError
|
|
91
|
-
>
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
>({
|
|
104
|
+
...rest,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const {
|
|
108
|
+
trigger,
|
|
109
|
+
getValues,
|
|
110
|
+
setValue,
|
|
111
|
+
formState: { dirtyFields },
|
|
112
|
+
refineCore: { queryResult },
|
|
113
|
+
} = useHookFormResult;
|
|
114
|
+
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
const data = queryResult?.data?.data;
|
|
117
|
+
if (!data) return;
|
|
118
|
+
|
|
119
|
+
const registeredFields = Object.keys(getValues());
|
|
120
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
121
|
+
const name = key as Path<TVariables>;
|
|
122
|
+
|
|
123
|
+
if (registeredFields.includes(name)) {
|
|
124
|
+
if (!dirtyFields[name]) {
|
|
125
|
+
setValue(name, value);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
105
128
|
});
|
|
129
|
+
}, [queryResult?.data, current, setValue, getValues]);
|
|
106
130
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
getValues,
|
|
110
|
-
setValue,
|
|
111
|
-
formState: { dirtyFields },
|
|
112
|
-
refineCore: { queryResult },
|
|
113
|
-
} = useHookFormResult;
|
|
114
|
-
|
|
115
|
-
useEffect(() => {
|
|
116
|
-
const data = queryResult?.data?.data;
|
|
117
|
-
if (!data) return;
|
|
118
|
-
|
|
119
|
-
const registeredFields = Object.keys(getValues());
|
|
120
|
-
Object.entries(data).forEach(([key, value]) => {
|
|
121
|
-
const name = key as Path<TVariables>;
|
|
122
|
-
|
|
123
|
-
if (registeredFields.includes(name)) {
|
|
124
|
-
if (!dirtyFields[name]) {
|
|
125
|
-
setValue(name, value);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
}, [queryResult?.data, current, setValue, getValues]);
|
|
130
|
-
|
|
131
|
-
const go = (step: number) => {
|
|
132
|
-
let targetStep = step;
|
|
133
|
-
|
|
134
|
-
if (step < 0) {
|
|
135
|
-
targetStep = 0;
|
|
136
|
-
}
|
|
131
|
+
const go = (step: number) => {
|
|
132
|
+
let targetStep = step;
|
|
137
133
|
|
|
138
|
-
|
|
139
|
-
|
|
134
|
+
if (step < 0) {
|
|
135
|
+
targetStep = 0;
|
|
136
|
+
}
|
|
140
137
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
138
|
+
setCurrent(targetStep);
|
|
139
|
+
};
|
|
145
140
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
141
|
+
const gotoStep = async (step: number) => {
|
|
142
|
+
if (step === current) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
150
145
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
146
|
+
if (step < current && !isBackValidate) {
|
|
147
|
+
go(step);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const isValid = await trigger();
|
|
152
|
+
if (isValid) {
|
|
153
|
+
go(step);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
...useHookFormResult,
|
|
159
|
+
steps: {
|
|
160
|
+
currentStep: current,
|
|
161
|
+
gotoStep,
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
164
|
};
|