antd-overlay 0.0.2 → 0.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/LICENSE +21 -0
- package/README.md +94 -136
- package/dist/index.cjs +19 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -8
- package/dist/index.d.ts +27 -8
- package/dist/index.js +20 -5
- package/dist/index.js.map +1 -1
- package/package.json +12 -12
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 RaineySpace
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -7,11 +7,11 @@ Ant Design Modal/Drawer 命令式调用方案。
|
|
|
7
7
|
|
|
8
8
|
## 特性
|
|
9
9
|
|
|
10
|
-
- 🚀 **命令式调用** -
|
|
11
|
-
- 🎨 **动画支持** -
|
|
12
|
-
- 🌍 **全局挂载** -
|
|
10
|
+
- 🚀 **命令式调用** - 通过函数调用打开/关闭覆盖层,无需在业务里维护 `open` 状态
|
|
11
|
+
- 🎨 **动画支持** - 正确处理打开/关闭动画(Modal 使用 `afterClose`,Drawer 使用 `afterOpenChange`),避免动画未完成就卸载
|
|
12
|
+
- 🌍 **全局挂载** - 支持跨组件调用,覆盖层挂载到 `AntdOverlayProvider` 统一容器
|
|
13
13
|
- 📦 **类型安全** - 完整的 TypeScript 类型支持
|
|
14
|
-
- 🔧 **灵活扩展** -
|
|
14
|
+
- 🔧 **灵活扩展** - `useOverlay` + `propsAdapter` 可对接自定义覆盖层组件
|
|
15
15
|
|
|
16
16
|
## 安装
|
|
17
17
|
|
|
@@ -34,24 +34,40 @@ yarn add antd-overlay
|
|
|
34
34
|
}
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
## 本地开发与示例
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pnpm install
|
|
41
|
+
pnpm dev:demo # 启动 Vite 演示(demo/:Modal / Drawer / useOverlay)
|
|
42
|
+
pnpm build # 使用 tsup 构建 dist
|
|
43
|
+
pnpm typecheck # TypeScript 检查
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
演示入口将 `ConfigProvider` 与 `AntdOverlayProvider` 组合使用,与线上应用推荐结构一致。
|
|
47
|
+
|
|
37
48
|
## 快速开始
|
|
38
49
|
|
|
39
50
|
### 1. 包裹 Provider(可选,仅全局 Hook 需要)
|
|
40
51
|
|
|
41
52
|
```tsx
|
|
42
53
|
import { AntdOverlayProvider } from 'antd-overlay';
|
|
54
|
+
import { ConfigProvider } from 'antd';
|
|
43
55
|
|
|
44
56
|
function App() {
|
|
45
57
|
return (
|
|
46
|
-
<
|
|
47
|
-
<
|
|
48
|
-
|
|
58
|
+
<ConfigProvider>
|
|
59
|
+
<AntdOverlayProvider>
|
|
60
|
+
<YourApp />
|
|
61
|
+
</AntdOverlayProvider>
|
|
62
|
+
</ConfigProvider>
|
|
49
63
|
);
|
|
50
64
|
}
|
|
51
65
|
```
|
|
52
66
|
|
|
53
67
|
### 2. 创建覆盖层组件
|
|
54
68
|
|
|
69
|
+
自定义 Modal 需实现 `CustomModalProps`(继承 antd `ModalProps` 与 `CustomOverlayProps`)。请将 antd `Modal` 的 `open` 接到 props 上,由 Hook 注入显示状态。
|
|
70
|
+
|
|
55
71
|
```tsx
|
|
56
72
|
import { Modal, Input } from 'antd';
|
|
57
73
|
import { CustomModalProps } from 'antd-overlay';
|
|
@@ -66,15 +82,17 @@ const MyModal: React.FC<MyModalProps> = ({
|
|
|
66
82
|
customClose,
|
|
67
83
|
customOk,
|
|
68
84
|
initialValue,
|
|
85
|
+
...props
|
|
69
86
|
}) => {
|
|
70
87
|
const [value, setValue] = useState(initialValue || '');
|
|
71
88
|
|
|
72
89
|
return (
|
|
73
90
|
<Modal
|
|
74
|
-
title="输入内容"
|
|
75
91
|
open={open}
|
|
92
|
+
title="输入内容"
|
|
76
93
|
onCancel={customClose}
|
|
77
94
|
onOk={() => customOk?.({ result: value })}
|
|
95
|
+
{...props}
|
|
78
96
|
>
|
|
79
97
|
<Input value={value} onChange={(e) => setValue(e.target.value)} />
|
|
80
98
|
</Modal>
|
|
@@ -91,10 +109,10 @@ import { useModal, useGlobalModal } from 'antd-overlay';
|
|
|
91
109
|
function LocalUsage() {
|
|
92
110
|
const [openModal, holder] = useModal(MyModal);
|
|
93
111
|
|
|
94
|
-
const handleOpen =
|
|
112
|
+
const handleOpen = () => {
|
|
95
113
|
const controller = openModal({ initialValue: 'hello' });
|
|
96
|
-
// controller.update({ initialValue: 'updated' });
|
|
97
|
-
// controller.close();
|
|
114
|
+
// controller.update({ initialValue: 'updated' });
|
|
115
|
+
// controller.close();
|
|
98
116
|
};
|
|
99
117
|
|
|
100
118
|
return (
|
|
@@ -117,25 +135,23 @@ function GlobalUsage() {
|
|
|
117
135
|
}
|
|
118
136
|
```
|
|
119
137
|
|
|
138
|
+
`openModal(...)` 返回 `OverlayController`:可调用 `update` 传入要更新的字段(与当前已保存的 props 及 Hook 的 `defaultProps` **浅合并**,同名键以本次 `update` 入参为准)、`close` 关闭(会尊重动画配置)。
|
|
139
|
+
|
|
120
140
|
## API
|
|
121
141
|
|
|
122
142
|
### Provider
|
|
123
143
|
|
|
124
144
|
#### `AntdOverlayProvider`
|
|
125
145
|
|
|
126
|
-
|
|
146
|
+
全局覆盖层容器;使用 `useGlobalModal`、`useGlobalDrawer`、`useGlobalOverlay` 时需要在应用内包裹。
|
|
127
147
|
|
|
128
148
|
**属性:**
|
|
129
|
-
- `children: React.ReactNode` - 子节点
|
|
130
|
-
- `defaultModalProps?: Partial<ModalProps>` - 默认 Modal 属性,会应用到所有 Modal
|
|
131
|
-
- `defaultDrawerProps?: Partial<DrawerProps>` - 默认 Drawer 属性,会应用到所有 Drawer
|
|
132
149
|
|
|
133
|
-
|
|
134
|
-
<
|
|
135
|
-
|
|
136
|
-
</AntdOverlayProvider>
|
|
150
|
+
- `children: React.ReactNode`
|
|
151
|
+
- `defaultModalProps?: Partial<ModalProps>` — 默认 Modal 属性,与每次 `open` / `update` 传入的 props 合并(传入方优先)
|
|
152
|
+
- `defaultDrawerProps?: Partial<DrawerProps>` — 同上,作用于 Drawer
|
|
137
153
|
|
|
138
|
-
|
|
154
|
+
```tsx
|
|
139
155
|
<AntdOverlayProvider
|
|
140
156
|
defaultModalProps={{ centered: true, maskClosable: false }}
|
|
141
157
|
defaultDrawerProps={{ width: 600 }}
|
|
@@ -144,93 +160,54 @@ function GlobalUsage() {
|
|
|
144
160
|
</AntdOverlayProvider>
|
|
145
161
|
```
|
|
146
162
|
|
|
163
|
+
#### `useAntdOverlayContext()`
|
|
164
|
+
|
|
165
|
+
读取 Context(含 `holders`、`addHolder`、`removeHolder` 及默认 Modal/Drawer 配置)。**必须在 `AntdOverlayProvider` 内使用**;一般供扩展或库内集成,业务侧很少直接使用。
|
|
166
|
+
|
|
147
167
|
### Modal Hooks
|
|
148
168
|
|
|
149
169
|
#### `useModal<T>(Component, options?)`
|
|
150
170
|
|
|
151
|
-
局部 Modal
|
|
171
|
+
局部 Modal Hook。
|
|
152
172
|
|
|
153
|
-
|
|
154
|
-
- `Component: React.FC<T>` - Modal 组件,需实现 `CustomModalProps` 接口
|
|
155
|
-
- `options?: UseModalOptions` - 配置选项
|
|
156
|
-
- `animation?: boolean` - 是否启用动画,默认 `true`
|
|
173
|
+
**`options`(`UseModalOptions`)** 与底层 `useOverlay` 一致(不含 `propsAdapter` / `keyPrefix`,由内部固定):
|
|
157
174
|
|
|
158
|
-
|
|
159
|
-
- `
|
|
175
|
+
- `animation?: boolean` — 是否等待关闭动画后再卸载,默认 `true`
|
|
176
|
+
- `defaultProps?: Partial<Omit<T, 'customClose'>>` — 每次打开/更新时与入参合并的默认属性
|
|
177
|
+
- 另可将 Modal 相关字段写在 `options` 顶层,与 `defaultProps` 合并时**顶层字段优先**
|
|
160
178
|
|
|
161
|
-
|
|
162
|
-
const [openModal, holder] = useModal(MyModal);
|
|
163
|
-
```
|
|
179
|
+
**返回值:** `[openModal, holder]` — `openModal` 为 `OverlayOpener<T>`,返回 `OverlayController<T>`。
|
|
164
180
|
|
|
165
181
|
#### `useGlobalModal<T>(Component, options?)`
|
|
166
182
|
|
|
167
|
-
全局 Modal
|
|
168
|
-
|
|
169
|
-
**参数:** 同 `useModal`
|
|
170
|
-
|
|
171
|
-
**返回值:**
|
|
172
|
-
- `openModal` - 打开函数
|
|
173
|
-
|
|
174
|
-
```tsx
|
|
175
|
-
const openModal = useGlobalModal(MyModal);
|
|
176
|
-
```
|
|
183
|
+
全局 Modal Hook;无需渲染 `holder`。
|
|
177
184
|
|
|
178
185
|
#### `generateUseModalHook<T>(Component)`
|
|
179
186
|
|
|
180
|
-
|
|
187
|
+
为指定 Modal 组件生成 `{ useModal, useGlobalModal }`,二者均可传入 `options?: UseModalOptions`。
|
|
181
188
|
|
|
182
189
|
```tsx
|
|
183
|
-
// modal.tsx
|
|
184
190
|
export const {
|
|
185
191
|
useModal: useMyModal,
|
|
186
192
|
useGlobalModal: useGlobalMyModal,
|
|
187
193
|
} = generateUseModalHook(MyModal);
|
|
188
|
-
|
|
189
|
-
// usage.tsx
|
|
190
|
-
const openModal = useGlobalMyModal();
|
|
191
194
|
```
|
|
192
195
|
|
|
193
196
|
### Drawer Hooks
|
|
194
197
|
|
|
195
|
-
#### `useDrawer<T>(Component, options?)`
|
|
196
|
-
|
|
197
|
-
局部 Drawer 管理 Hook。
|
|
198
|
+
#### `useDrawer<T>(Component, options?)` / `useGlobalDrawer<T>(Component, options?)`
|
|
198
199
|
|
|
199
|
-
|
|
200
|
-
const [openDrawer, holder] = useDrawer(MyDrawer);
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
#### `useGlobalDrawer<T>(Component, options?)`
|
|
204
|
-
|
|
205
|
-
全局 Drawer 管理 Hook。
|
|
206
|
-
|
|
207
|
-
```tsx
|
|
208
|
-
const openDrawer = useGlobalDrawer(MyDrawer);
|
|
209
|
-
```
|
|
200
|
+
语义与 Modal 侧相同,选项类型为 `UseDrawerOptions`(同样支持 `animation`、`defaultProps` 及顶层 Drawer 属性)。
|
|
210
201
|
|
|
211
202
|
#### `generateUseDrawerHook<T>(Component)`
|
|
212
203
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
```tsx
|
|
216
|
-
export const {
|
|
217
|
-
useDrawer: useMyDrawer,
|
|
218
|
-
useGlobalDrawer: useGlobalMyDrawer,
|
|
219
|
-
} = generateUseDrawerHook(MyDrawer);
|
|
220
|
-
```
|
|
204
|
+
生成 `{ useDrawer, useGlobalDrawer }`。
|
|
221
205
|
|
|
222
206
|
### 通用 Overlay Hooks
|
|
223
207
|
|
|
224
208
|
#### `useOverlay<T>(Component, options?)`
|
|
225
209
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
**参数:**
|
|
229
|
-
- `Component: React.FC<T>` - 覆盖层组件
|
|
230
|
-
- `options?: UseOverlayOptions<T>` - 配置选项
|
|
231
|
-
- `animation?: boolean` - 是否启用动画,默认 `true`
|
|
232
|
-
- `keyPrefix?: string` - React key 前缀
|
|
233
|
-
- `propsAdapter?: (props, state) => T` - 属性适配器函数
|
|
210
|
+
通用覆盖层 Hook;需自行提供 `propsAdapter`,把内部 `state.open` / `state.onClose` / `state.onAnimationEnd` 映射到组件 API。
|
|
234
211
|
|
|
235
212
|
```tsx
|
|
236
213
|
const [openOverlay, holder] = useOverlay(MyOverlay, {
|
|
@@ -238,7 +215,7 @@ const [openOverlay, holder] = useOverlay(MyOverlay, {
|
|
|
238
215
|
...props,
|
|
239
216
|
visible: state.open,
|
|
240
217
|
onClose: state.onClose,
|
|
241
|
-
afterVisibleChange: (visible) => {
|
|
218
|
+
afterVisibleChange: (visible: boolean) => {
|
|
242
219
|
if (!visible) state.onAnimationEnd();
|
|
243
220
|
},
|
|
244
221
|
}),
|
|
@@ -247,72 +224,57 @@ const [openOverlay, holder] = useOverlay(MyOverlay, {
|
|
|
247
224
|
|
|
248
225
|
#### `useGlobalOverlay<T>(Component, options?)`
|
|
249
226
|
|
|
250
|
-
|
|
227
|
+
全局版本,依赖 `AntdOverlayProvider`。
|
|
251
228
|
|
|
252
229
|
#### `generateUseOverlayHook<T>(Component, defaultOptions?)`
|
|
253
230
|
|
|
254
|
-
|
|
231
|
+
生成绑定组件的 `useOverlay` / `useGlobalOverlay`;调用时可再传 `options` 与 `defaultOptions` 浅合并。
|
|
255
232
|
|
|
256
233
|
### 类型定义
|
|
257
234
|
|
|
258
|
-
#### `
|
|
259
|
-
|
|
260
|
-
Modal 组件属性接口,继承自 `antd` 的 `ModalProps`。
|
|
235
|
+
#### `CustomOverlayProps<T, R>`
|
|
261
236
|
|
|
262
237
|
```typescript
|
|
263
|
-
interface
|
|
238
|
+
interface CustomOverlayProps<T = any, R = void> {
|
|
264
239
|
open?: boolean;
|
|
265
240
|
customClose: () => void;
|
|
266
241
|
customOk?: (value: T) => R;
|
|
267
242
|
}
|
|
268
243
|
```
|
|
269
244
|
|
|
270
|
-
#### `CustomDrawerProps<T, R>`
|
|
245
|
+
#### `CustomModalProps<T, R>` / `CustomDrawerProps<T, R>`
|
|
271
246
|
|
|
272
|
-
|
|
247
|
+
分别为 `ModalProps` / `DrawerProps` 与 `CustomOverlayProps` 的交叉类型。
|
|
273
248
|
|
|
274
|
-
|
|
275
|
-
interface CustomDrawerProps<T = any, R = void> extends DrawerProps {
|
|
276
|
-
open?: boolean;
|
|
277
|
-
customClose: () => void;
|
|
278
|
-
customOk?: (value: T) => R;
|
|
279
|
-
}
|
|
280
|
-
```
|
|
249
|
+
#### `InternalOverlayProps<T>`
|
|
281
250
|
|
|
282
|
-
|
|
251
|
+
`Omit<T, 'customClose'>`,表示打开/更新时可传入的属性(由 Hook 注入 `customClose`)。
|
|
283
252
|
|
|
284
|
-
|
|
253
|
+
#### `OverlayController<T>`
|
|
285
254
|
|
|
286
255
|
```typescript
|
|
287
|
-
interface
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
256
|
+
interface OverlayController<T extends CustomOverlayProps> {
|
|
257
|
+
/** 与 defaultProps、当前 props 浅合并后更新 */
|
|
258
|
+
readonly update: (props: InternalOverlayProps<T>) => void;
|
|
259
|
+
readonly close: () => void;
|
|
291
260
|
}
|
|
292
261
|
```
|
|
293
262
|
|
|
294
|
-
#### `
|
|
295
|
-
|
|
296
|
-
覆盖层控制器,由 `openModal`/`openDrawer`/`openOverlay` 返回。
|
|
263
|
+
#### `OverlayOpener<T>`
|
|
297
264
|
|
|
298
|
-
|
|
299
|
-
interface OverlayController<T> {
|
|
300
|
-
update: (props: Omit<T, 'customClose'>) => void;
|
|
301
|
-
close: () => void;
|
|
302
|
-
}
|
|
303
|
-
```
|
|
265
|
+
`(initialize?: InternalOverlayProps<T>) => OverlayController<T>`。
|
|
304
266
|
|
|
305
267
|
## 完整示例
|
|
306
268
|
|
|
307
269
|
### 确认删除 Modal
|
|
308
270
|
|
|
309
271
|
```tsx
|
|
310
|
-
import {
|
|
272
|
+
import React, { useState } from 'react';
|
|
273
|
+
import { Modal, message, List, Button } from 'antd';
|
|
311
274
|
import { CustomModalProps, useGlobalModal } from 'antd-overlay';
|
|
312
275
|
|
|
313
276
|
interface ConfirmDeleteModalProps extends CustomModalProps<void> {
|
|
314
277
|
itemName: string;
|
|
315
|
-
onConfirm: () => Promise<void>;
|
|
316
278
|
}
|
|
317
279
|
|
|
318
280
|
const ConfirmDeleteModal: React.FC<ConfirmDeleteModalProps> = ({
|
|
@@ -320,17 +282,16 @@ const ConfirmDeleteModal: React.FC<ConfirmDeleteModalProps> = ({
|
|
|
320
282
|
customClose,
|
|
321
283
|
customOk,
|
|
322
284
|
itemName,
|
|
323
|
-
|
|
285
|
+
...props
|
|
324
286
|
}) => {
|
|
325
287
|
const [loading, setLoading] = useState(false);
|
|
326
288
|
|
|
327
289
|
const handleOk = async () => {
|
|
328
290
|
setLoading(true);
|
|
329
291
|
try {
|
|
330
|
-
await onConfirm();
|
|
331
292
|
message.success('删除成功');
|
|
332
293
|
customOk?.();
|
|
333
|
-
} catch
|
|
294
|
+
} catch {
|
|
334
295
|
message.error('删除失败');
|
|
335
296
|
} finally {
|
|
336
297
|
setLoading(false);
|
|
@@ -339,37 +300,40 @@ const ConfirmDeleteModal: React.FC<ConfirmDeleteModalProps> = ({
|
|
|
339
300
|
|
|
340
301
|
return (
|
|
341
302
|
<Modal
|
|
342
|
-
title="确认删除"
|
|
343
303
|
open={open}
|
|
304
|
+
title="确认删除"
|
|
344
305
|
onCancel={customClose}
|
|
345
306
|
onOk={handleOk}
|
|
346
307
|
confirmLoading={loading}
|
|
347
308
|
okText="删除"
|
|
348
309
|
okType="danger"
|
|
310
|
+
{...props}
|
|
349
311
|
>
|
|
350
|
-
确定要删除
|
|
312
|
+
确定要删除 "{itemName}" 吗?此操作不可恢复。
|
|
351
313
|
</Modal>
|
|
352
314
|
);
|
|
353
315
|
};
|
|
354
316
|
|
|
355
|
-
//
|
|
317
|
+
// 使用(示例数据与类型请按项目替换)
|
|
356
318
|
function ItemList() {
|
|
357
319
|
const openConfirm = useGlobalModal(ConfirmDeleteModal);
|
|
358
320
|
|
|
359
|
-
const handleDelete = (item:
|
|
321
|
+
const handleDelete = (item: { id: number; name: string }) => {
|
|
360
322
|
openConfirm({
|
|
361
323
|
itemName: item.name,
|
|
362
|
-
|
|
324
|
+
customOk: () => {
|
|
325
|
+
/* deleteItem(item.id) */
|
|
326
|
+
},
|
|
363
327
|
});
|
|
364
328
|
};
|
|
365
329
|
|
|
366
330
|
return (
|
|
367
331
|
<List
|
|
368
|
-
dataSource={
|
|
332
|
+
dataSource={[]}
|
|
369
333
|
renderItem={(item) => (
|
|
370
334
|
<List.Item
|
|
371
335
|
actions={[
|
|
372
|
-
<Button danger onClick={() => handleDelete(item)}>
|
|
336
|
+
<Button key="del" danger onClick={() => handleDelete(item)}>
|
|
373
337
|
删除
|
|
374
338
|
</Button>,
|
|
375
339
|
]}
|
|
@@ -385,6 +349,7 @@ function ItemList() {
|
|
|
385
349
|
### 用户详情 Drawer
|
|
386
350
|
|
|
387
351
|
```tsx
|
|
352
|
+
import React, { useEffect, useState } from 'react';
|
|
388
353
|
import { Drawer, Descriptions, Spin } from 'antd';
|
|
389
354
|
import { CustomDrawerProps, generateUseDrawerHook } from 'antd-overlay';
|
|
390
355
|
|
|
@@ -396,26 +361,22 @@ const UserDetailDrawer: React.FC<UserDetailDrawerProps> = ({
|
|
|
396
361
|
open,
|
|
397
362
|
customClose,
|
|
398
363
|
userId,
|
|
364
|
+
...props
|
|
399
365
|
}) => {
|
|
400
|
-
const [user, setUser] = useState<
|
|
366
|
+
const [user, setUser] = useState<{ name: string; email: string; phone: string } | null>(null);
|
|
401
367
|
const [loading, setLoading] = useState(false);
|
|
402
368
|
|
|
403
369
|
useEffect(() => {
|
|
404
370
|
if (open && userId) {
|
|
405
371
|
setLoading(true);
|
|
406
|
-
fetchUser(userId)
|
|
372
|
+
Promise.resolve(/* fetchUser(userId) */)
|
|
407
373
|
.then(setUser)
|
|
408
374
|
.finally(() => setLoading(false));
|
|
409
375
|
}
|
|
410
376
|
}, [open, userId]);
|
|
411
377
|
|
|
412
378
|
return (
|
|
413
|
-
<Drawer
|
|
414
|
-
title="用户详情"
|
|
415
|
-
open={open}
|
|
416
|
-
onClose={customClose}
|
|
417
|
-
width={500}
|
|
418
|
-
>
|
|
379
|
+
<Drawer open={open} title="用户详情" onClose={customClose} width={500} {...props}>
|
|
419
380
|
{loading ? (
|
|
420
381
|
<Spin />
|
|
421
382
|
) : user ? (
|
|
@@ -429,27 +390,24 @@ const UserDetailDrawer: React.FC<UserDetailDrawerProps> = ({
|
|
|
429
390
|
);
|
|
430
391
|
};
|
|
431
392
|
|
|
432
|
-
// 导出专用 Hook
|
|
433
393
|
export const {
|
|
434
394
|
useDrawer: useUserDetailDrawer,
|
|
435
395
|
useGlobalDrawer: useGlobalUserDetailDrawer,
|
|
436
396
|
} = generateUseDrawerHook(UserDetailDrawer);
|
|
437
397
|
|
|
438
|
-
// 使用
|
|
439
398
|
function UserCard({ userId }: { userId: number }) {
|
|
440
399
|
const openDetail = useGlobalUserDetailDrawer();
|
|
441
400
|
|
|
442
|
-
return (
|
|
443
|
-
<Card onClick={() => openDetail({ userId })}>
|
|
444
|
-
查看详情
|
|
445
|
-
</Card>
|
|
446
|
-
);
|
|
401
|
+
return <div onClick={() => openDetail({ userId })}>查看详情</div>;
|
|
447
402
|
}
|
|
448
403
|
```
|
|
449
404
|
|
|
450
405
|
### 动态更新 Modal
|
|
451
406
|
|
|
452
407
|
```tsx
|
|
408
|
+
import { Button } from 'antd';
|
|
409
|
+
// UploadModal、delay 由业务自行实现
|
|
410
|
+
|
|
453
411
|
function ProgressModal() {
|
|
454
412
|
const [openModal, holder] = useModal(UploadModal);
|
|
455
413
|
|
|
@@ -479,11 +437,11 @@ function ProgressModal() {
|
|
|
479
437
|
|
|
480
438
|
```
|
|
481
439
|
┌─────────────────────────────────────────────────────────┐
|
|
482
|
-
│ useModal / useDrawer │
|
|
440
|
+
│ useModal / useDrawer │ 业务层封装
|
|
483
441
|
├─────────────────────────────────────────────────────────┤
|
|
484
|
-
│ useOverlay / useGlobalOverlay │
|
|
442
|
+
│ useOverlay / useGlobalOverlay │ 核心逻辑层
|
|
485
443
|
├─────────────────────────────────────────────────────────┤
|
|
486
|
-
│ AntdOverlayProvider │
|
|
444
|
+
│ AntdOverlayProvider │ 全局容器层
|
|
487
445
|
└─────────────────────────────────────────────────────────┘
|
|
488
446
|
```
|
|
489
447
|
|
package/dist/index.cjs
CHANGED
|
@@ -52,8 +52,16 @@ function useOverlay(OverlayComponent, options = {}) {
|
|
|
52
52
|
const {
|
|
53
53
|
animation = true,
|
|
54
54
|
keyPrefix = "use-overlay",
|
|
55
|
-
|
|
55
|
+
defaultProps: defaultPropsFromOption,
|
|
56
|
+
propsAdapter = defaultPropsAdapter,
|
|
57
|
+
...restDefaultFromTopLevel
|
|
56
58
|
} = options;
|
|
59
|
+
const mergedDefaultProps = {
|
|
60
|
+
...defaultPropsFromOption,
|
|
61
|
+
...restDefaultFromTopLevel
|
|
62
|
+
};
|
|
63
|
+
const defaultPropsRef = React2.useRef(mergedDefaultProps);
|
|
64
|
+
defaultPropsRef.current = mergedDefaultProps;
|
|
57
65
|
const id = React2.useId();
|
|
58
66
|
const key = `${keyPrefix}-${id}`;
|
|
59
67
|
const [open, setOpen] = React2.useState(false);
|
|
@@ -95,13 +103,20 @@ function useOverlay(OverlayComponent, options = {}) {
|
|
|
95
103
|
(initializeProps) => {
|
|
96
104
|
setRenderEnable(true);
|
|
97
105
|
setOpen(true);
|
|
98
|
-
setProps(
|
|
106
|
+
setProps({
|
|
107
|
+
...defaultPropsRef.current,
|
|
108
|
+
...initializeProps
|
|
109
|
+
});
|
|
99
110
|
return {
|
|
100
111
|
/**
|
|
101
112
|
* 更新覆盖层属性
|
|
102
|
-
*
|
|
113
|
+
* 与 defaultProps 合并,传入的 newProps 优先
|
|
103
114
|
*/
|
|
104
|
-
update: (newProps) => setProps(
|
|
115
|
+
update: (newProps) => setProps((prev) => ({
|
|
116
|
+
...defaultPropsRef.current,
|
|
117
|
+
...prev,
|
|
118
|
+
...newProps
|
|
119
|
+
})),
|
|
105
120
|
/**
|
|
106
121
|
* 关闭覆盖层
|
|
107
122
|
*/
|