@refinedev/antd 5.2.0 → 5.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@refinedev/antd",
3
- "version": "5.2.0",
3
+ "version": "5.3.1",
4
4
  "description": "refine is a React-based framework for building internal tools, rapidly. It ships with Ant Design System, an enterprise-level UI toolkit.",
5
5
  "private": false,
6
6
  "main": "dist/index.js",
@@ -24,8 +24,8 @@
24
24
  },
25
25
  "devDependencies": {
26
26
  "@refinedev/cli": "^2.1.0",
27
- "@refinedev/ui-tests": "^1.2.0",
28
- "@refinedev/core": "^4.4.0",
27
+ "@refinedev/ui-tests": "^1.3.0",
28
+ "@refinedev/core": "^4.5.1",
29
29
  "@esbuild-plugins/node-resolve": "^0.1.4",
30
30
  "@testing-library/jest-dom": "^5.16.4",
31
31
  "@testing-library/react": "^13.1.1",
@@ -49,7 +49,7 @@
49
49
  "dependencies": {
50
50
  "@ant-design/icons": "^5.0.1",
51
51
  "@ant-design/pro-layout": "7.8.3",
52
- "@refinedev/ui-types": "^1.2.0",
52
+ "@refinedev/ui-types": "^1.3.0",
53
53
  "@tanstack/react-query": "^4.10.1",
54
54
  "antd": "^5.0.5",
55
55
  "dayjs": "^1.10.7",
@@ -8,6 +8,7 @@ import {
8
8
  useCan,
9
9
  useResource,
10
10
  pickNotDeprecated,
11
+ useWarnAboutChange,
11
12
  } from "@refinedev/core";
12
13
  import { RefineButtonTestIds } from "@refinedev/ui-types";
13
14
 
@@ -62,6 +63,8 @@ export const DeleteButton: React.FC<DeleteButtonProps> = ({
62
63
  },
63
64
  });
64
65
 
66
+ const { setWarnWhen } = useWarnAboutChange();
67
+
65
68
  if (accessControlEnabled && hideIfUnauthorized && !data?.can) {
66
69
  return null;
67
70
  }
@@ -80,6 +83,7 @@ export const DeleteButton: React.FC<DeleteButtonProps> = ({
80
83
  okButtonProps={{ disabled: isLoading }}
81
84
  onConfirm={(): void => {
82
85
  if ((recordItemId ?? id) && resource?.name) {
86
+ setWarnWhen(false);
83
87
  mutate(
84
88
  {
85
89
  id: recordItemId ?? id ?? "",
@@ -20,6 +20,7 @@ import {
20
20
  useRouterType,
21
21
  useActiveAuthProvider,
22
22
  pickNotDeprecated,
23
+ useWarnAboutChange,
23
24
  } from "@refinedev/core";
24
25
 
25
26
  import { Title as DefaultTitle } from "@components";
@@ -39,6 +40,7 @@ export const Sider: React.FC<RefineLayoutSiderProps> = ({
39
40
  const isExistAuthentication = useIsExistAuthentication();
40
41
  const routerType = useRouterType();
41
42
  const NewLink = useLink();
43
+ const { warnWhen, setWarnWhen } = useWarnAboutChange();
42
44
  const { Link: LegacyLink } = useRouterContext();
43
45
  const Link = routerType === "legacy" ? LegacyLink : NewLink;
44
46
  const TitleFromContext = useTitle();
@@ -121,10 +123,28 @@ export const Sider: React.FC<RefineLayoutSiderProps> = ({
121
123
  });
122
124
  };
123
125
 
126
+ const handleLogout = () => {
127
+ if (warnWhen) {
128
+ const confirm = window.confirm(
129
+ translate(
130
+ "warnWhenUnsavedChanges",
131
+ "Are you sure you want to leave? You have unsaved changes.",
132
+ ),
133
+ );
134
+
135
+ if (confirm) {
136
+ setWarnWhen(false);
137
+ mutateLogout();
138
+ }
139
+ } else {
140
+ mutateLogout();
141
+ }
142
+ };
143
+
124
144
  const logout = isExistAuthentication && (
125
145
  <Menu.Item
126
146
  key="logout"
127
- onClick={() => mutateLogout()}
147
+ onClick={handleLogout}
128
148
  icon={<LogoutOutlined />}
129
149
  >
130
150
  {translate("buttons.logout", "Logout")}
@@ -1,8 +1,7 @@
1
- import { useCallback, useEffect, useState } from "react";
1
+ import React, { useCallback } from "react";
2
2
  import { UseFormConfig } from "sunflower-antd";
3
3
  import { FormInstance, FormProps, DrawerProps, ButtonProps } from "antd";
4
4
  import {
5
- useMutationMode,
6
5
  useTranslate,
7
6
  useWarnAboutChange,
8
7
  UseFormProps as UseFormPropsCore,
@@ -14,11 +13,11 @@ import {
14
13
  useResource,
15
14
  useParsed,
16
15
  useGo,
16
+ useModal,
17
17
  } from "@refinedev/core";
18
18
 
19
19
  import { useForm, UseFormProps, UseFormReturnType } from "../useForm";
20
20
  import { DeleteButtonProps } from "../../../components";
21
- import React from "react";
22
21
 
23
22
  export interface UseDrawerFormConfig extends UseFormConfig {
24
23
  action: "show" | "edit" | "create" | "clone";
@@ -32,7 +31,11 @@ export type UseDrawerFormProps<
32
31
  UseFormProps<TData, TError, TVariables> &
33
32
  UseDrawerFormConfig &
34
33
  LiveModeProps &
35
- FormWithSyncWithLocationParams;
34
+ FormWithSyncWithLocationParams & {
35
+ defaultVisible?: boolean;
36
+ autoSubmitClose?: boolean;
37
+ autoResetForm?: boolean;
38
+ };
36
39
 
37
40
  export type UseDrawerFormReturnType<
38
41
  TData extends BaseRecord = BaseRecord,
@@ -67,8 +70,10 @@ export const useDrawerForm = <
67
70
  TError extends HttpError = HttpError,
68
71
  TVariables = {},
69
72
  >({
70
- mutationMode: mutationModeProp,
71
73
  syncWithLocation,
74
+ defaultVisible = false,
75
+ autoSubmitClose = true,
76
+ autoResetForm = true,
72
77
  ...rest
73
78
  }: UseDrawerFormProps<TData, TError, TVariables>): UseDrawerFormReturnType<
74
79
  TData,
@@ -77,13 +82,15 @@ export const useDrawerForm = <
77
82
  > => {
78
83
  const initiallySynced = React.useRef(false);
79
84
 
85
+ const { visible, show, close } = useModal({
86
+ defaultVisible,
87
+ });
88
+
80
89
  const useFormProps = useForm<TData, TError, TVariables>({
81
90
  ...rest,
82
- mutationMode: mutationModeProp,
83
91
  });
84
92
 
85
- const { form, formProps, formLoading, mutationResult, id, setId } =
86
- useFormProps;
93
+ const { form, formProps, formLoading, id, setId, onFinish } = useFormProps;
87
94
 
88
95
  const { resource, action: actionFromParams } = useResource(rest.resource);
89
96
 
@@ -102,15 +109,15 @@ export const useDrawerForm = <
102
109
  ? `drawer-${resource?.identifier ?? resource?.name}-${action}`
103
110
  : undefined;
104
111
 
105
- const [open, setOpen] = useState(false);
106
-
107
112
  React.useEffect(() => {
108
113
  if (initiallySynced.current === false && syncWithLocationKey) {
109
114
  const openStatus = parsed?.params?.[syncWithLocationKey]?.open;
110
115
  if (typeof openStatus === "boolean") {
111
- setOpen(openStatus);
116
+ openStatus ? show() : close();
112
117
  } else if (typeof openStatus === "string") {
113
- setOpen(openStatus === "true");
118
+ if (openStatus === "true") {
119
+ show();
120
+ }
114
121
  }
115
122
 
116
123
  if (syncingId) {
@@ -126,7 +133,7 @@ export const useDrawerForm = <
126
133
 
127
134
  React.useEffect(() => {
128
135
  if (initiallySynced.current === true) {
129
- if (open && syncWithLocationKey) {
136
+ if (visible && syncWithLocationKey) {
130
137
  go({
131
138
  query: {
132
139
  [syncWithLocationKey]: {
@@ -138,7 +145,7 @@ export const useDrawerForm = <
138
145
  options: { keepQuery: true },
139
146
  type: "replace",
140
147
  });
141
- } else if (syncWithLocationKey && !open) {
148
+ } else if (syncWithLocationKey && !visible) {
142
149
  go({
143
150
  query: {
144
151
  [syncWithLocationKey]: undefined,
@@ -148,38 +155,27 @@ export const useDrawerForm = <
148
155
  });
149
156
  }
150
157
  }
151
- }, [id, open, syncWithLocationKey, syncingId]);
158
+ }, [id, visible, show, close, syncWithLocationKey, syncingId]);
152
159
 
153
160
  const translate = useTranslate();
154
161
 
155
162
  const { warnWhen, setWarnWhen } = useWarnAboutChange();
156
163
 
157
- const { mutationMode: mutationModeContext } = useMutationMode();
158
- const mutationMode = mutationModeProp ?? mutationModeContext;
164
+ const submit = async () => {
165
+ await onFinish(form.getFieldsValue());
159
166
 
160
- const {
161
- isLoading: isLoadingMutation,
162
- isSuccess: isSuccessMutation,
163
- reset: resetMutation,
164
- } = mutationResult ?? {};
167
+ if (autoSubmitClose) {
168
+ close();
169
+ }
165
170
 
166
- useEffect(() => {
167
- if (open && mutationMode === "pessimistic") {
168
- if (isSuccessMutation && !isLoadingMutation) {
169
- setOpen(false);
170
- resetMutation?.();
171
- }
171
+ if (autoResetForm) {
172
+ form.resetFields();
172
173
  }
173
- }, [isSuccessMutation, isLoadingMutation]);
174
+ };
174
175
 
175
176
  const saveButtonProps = {
176
177
  disabled: formLoading,
177
- onClick: () => {
178
- form?.submit();
179
- if (!(mutationMode === "pessimistic")) {
180
- setOpen(false);
181
- }
182
- },
178
+ onClick: submit,
183
179
  loading: formLoading,
184
180
  };
185
181
 
@@ -187,7 +183,7 @@ export const useDrawerForm = <
187
183
  recordItemId: id,
188
184
  onSuccess: () => {
189
185
  setId?.(undefined);
190
- setOpen(false);
186
+ close();
191
187
  },
192
188
  };
193
189
 
@@ -207,14 +203,14 @@ export const useDrawerForm = <
207
203
  }
208
204
  }
209
205
 
210
- setOpen(false);
206
+ close();
211
207
  setId?.(undefined);
212
208
  }, [warnWhen]);
213
209
 
214
210
  const handleShow = useCallback((id?: BaseKey) => {
215
211
  setId?.(id);
216
212
 
217
- setOpen(true);
213
+ show();
218
214
  }, []);
219
215
 
220
216
  return {
@@ -231,7 +227,7 @@ export const useDrawerForm = <
231
227
  drawerProps: {
232
228
  width: "500px",
233
229
  onClose: handleClose,
234
- open,
230
+ open: visible,
235
231
  forceRender: true,
236
232
  },
237
233
  saveButtonProps,
@@ -1,4 +1,4 @@
1
- import { useCallback, useEffect } from "react";
1
+ import React, { useCallback } from "react";
2
2
  import { FormInstance, FormProps, ModalProps } from "antd";
3
3
  import {
4
4
  useModalForm as useModalFormSF,
@@ -6,7 +6,6 @@ import {
6
6
  } from "sunflower-antd";
7
7
 
8
8
  import {
9
- useMutationMode,
10
9
  useTranslate,
11
10
  useWarnAboutChange,
12
11
  HttpError,
@@ -21,7 +20,6 @@ import {
21
20
  useGo,
22
21
  } from "@refinedev/core";
23
22
  import { useForm, UseFormProps, UseFormReturnType } from "../useForm";
24
- import React from "react";
25
23
 
26
24
  export type useModalFormFromSFReturnType<TData, TVariables> = {
27
25
  open: boolean;
@@ -80,7 +78,6 @@ export const useModalForm = <
80
78
  TError extends HttpError = HttpError,
81
79
  TVariables = {},
82
80
  >({
83
- mutationMode: mutationModeProp,
84
81
  syncWithLocation,
85
82
  ...rest
86
83
  }: UseModalFormProps<TData, TError, TVariables>): UseModalFormReturnType<
@@ -92,11 +89,9 @@ export const useModalForm = <
92
89
 
93
90
  const useFormProps = useForm<TData, TError, TVariables>({
94
91
  ...rest,
95
- mutationMode: mutationModeProp,
96
92
  });
97
93
 
98
- const { form, formProps, id, setId, formLoading, mutationResult } =
99
- useFormProps;
94
+ const { form, formProps, id, setId, formLoading, onFinish } = useFormProps;
100
95
 
101
96
  const { resource, action: actionFromParams } = useResource(rest.resource);
102
97
 
@@ -122,13 +117,12 @@ export const useModalForm = <
122
117
  const sunflowerUseModal = useModalFormSF<TData, TVariables>({
123
118
  ...rest,
124
119
  form: form,
120
+ submit: onFinish as any,
125
121
  });
126
122
 
127
123
  const {
128
124
  visible,
129
- close,
130
125
  show,
131
- form: modalForm,
132
126
  formProps: modalFormProps,
133
127
  modalProps,
134
128
  } = sunflowerUseModal;
@@ -183,41 +177,8 @@ export const useModalForm = <
183
177
  }
184
178
  }, [id, visible, show, syncWithLocationKey, syncingId]);
185
179
 
186
- const { mutationMode: mutationModeContext } = useMutationMode();
187
- const mutationMode = mutationModeProp ?? mutationModeContext;
188
-
189
- const {
190
- isLoading: isLoadingMutation,
191
- isSuccess: isSuccessMutation,
192
- reset: resetMutation,
193
- } = mutationResult ?? {};
194
-
195
- useEffect(() => {
196
- if (visible && mutationMode === "pessimistic") {
197
- if (isSuccessMutation && !isLoadingMutation) {
198
- close();
199
- resetMutation?.();
200
- // Prevents resetting form values before closing modal in UI
201
- setTimeout(() => {
202
- form.resetFields();
203
- });
204
- }
205
- }
206
- }, [isSuccessMutation, isLoadingMutation]);
207
-
208
180
  const saveButtonPropsSF = {
209
181
  disabled: formLoading,
210
- onClick: () => {
211
- modalForm.submit();
212
-
213
- if (!(mutationMode === "pessimistic")) {
214
- close();
215
- // Prevents resetting form values before closing modal in UI
216
- setTimeout(() => {
217
- form.resetFields();
218
- });
219
- }
220
- },
221
182
  loading: formLoading,
222
183
  };
223
184
 
@@ -247,6 +208,9 @@ export const useModalForm = <
247
208
  sunflowerUseModal.show();
248
209
  }, []);
249
210
 
211
+ const { visible: _visible, ...otherModalProps } = modalProps;
212
+ const newModalProps = { open: _visible, ...otherModalProps };
213
+
250
214
  return {
251
215
  ...useFormProps,
252
216
  ...sunflowerUseModal,
@@ -261,7 +225,7 @@ export const useModalForm = <
261
225
  onFinish: formProps.onFinish,
262
226
  },
263
227
  modalProps: {
264
- ...modalProps,
228
+ ...newModalProps,
265
229
  width: "1000px",
266
230
  okButtonProps: saveButtonPropsSF,
267
231
  title: translate(
@@ -54,7 +54,6 @@ declare module "sunflower-antd" {
54
54
  config: Omit<UseModalFormConfig, "defaultFormValues">,
55
55
  ) => {
56
56
  form: FormInstance<TVariables>;
57
- open: boolean;
58
57
  show: () => void;
59
58
  close: () => void;
60
59
  modalProps: {
@@ -62,18 +61,11 @@ declare module "sunflower-antd" {
62
61
  visible: boolean;
63
62
  onCancel: () => void;
64
63
  };
65
- formProps:
66
- | {
67
- form: FormInstance<TVariables>;
68
- onFinish: (formValue: TVariables) => Promise<TData>;
69
- initialValues: {};
70
- }
71
- | {
72
- onSubmit(e: any): void;
73
- form?: undefined;
74
- onFinish?: undefined;
75
- initialValues?: undefined;
76
- };
64
+ formProps: {
65
+ form: FormInstance<TVariables>;
66
+ onFinish: (formValue: TVariables) => Promise<TData>;
67
+ initialValues: {};
68
+ };
77
69
  formLoading: boolean;
78
70
  defaultFormValuesLoading: boolean;
79
71
  formValues: {};