antd-overlay 0.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 +479 -0
- package/dist/index.cjs +247 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +635 -0
- package/dist/index.d.ts +635 -0
- package/dist/index.js +231 -0
- package/dist/index.js.map +1 -0
- package/package.json +69 -0
package/README.md
ADDED
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
# antd-overlay
|
|
2
|
+
|
|
3
|
+
Ant Design Modal/Drawer 命令式调用方案。
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/antd-overlay)
|
|
6
|
+
[](https://github.com/RaineySpace/antd-overlay/blob/main/LICENSE)
|
|
7
|
+
|
|
8
|
+
## 特性
|
|
9
|
+
|
|
10
|
+
- 🚀 **命令式调用** - 通过函数调用打开/关闭覆盖层,无需管理 `open` 状态
|
|
11
|
+
- 🎨 **动画支持** - 正确处理打开/关闭动画,避免动画未完成就卸载组件
|
|
12
|
+
- 🌍 **全局挂载** - 支持跨组件调用,覆盖层可挂载到全局容器
|
|
13
|
+
- 📦 **类型安全** - 完整的 TypeScript 类型支持
|
|
14
|
+
- 🔧 **灵活扩展** - 支持自定义覆盖层组件
|
|
15
|
+
|
|
16
|
+
## 安装
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install antd-overlay
|
|
20
|
+
# 或
|
|
21
|
+
pnpm add antd-overlay
|
|
22
|
+
# 或
|
|
23
|
+
yarn add antd-overlay
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 前置依赖
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"antd": ">=5.0.0",
|
|
32
|
+
"react": ">=18.0.0"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 快速开始
|
|
38
|
+
|
|
39
|
+
### 1. 包裹 Provider(可选,仅全局 Hook 需要)
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import { AntdOverlayProvider } from 'antd-overlay';
|
|
43
|
+
|
|
44
|
+
function App() {
|
|
45
|
+
return (
|
|
46
|
+
<AntdOverlayProvider>
|
|
47
|
+
<YourApp />
|
|
48
|
+
</AntdOverlayProvider>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 2. 创建覆盖层组件
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
import { Modal, Input } from 'antd';
|
|
57
|
+
import { CustomModalProps } from 'antd-overlay';
|
|
58
|
+
import { useState } from 'react';
|
|
59
|
+
|
|
60
|
+
interface MyModalProps extends CustomModalProps<{ result: string }> {
|
|
61
|
+
initialValue?: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const MyModal: React.FC<MyModalProps> = ({
|
|
65
|
+
open,
|
|
66
|
+
customClose,
|
|
67
|
+
customOk,
|
|
68
|
+
initialValue,
|
|
69
|
+
}) => {
|
|
70
|
+
const [value, setValue] = useState(initialValue || '');
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<Modal
|
|
74
|
+
title="输入内容"
|
|
75
|
+
open={open}
|
|
76
|
+
onCancel={customClose}
|
|
77
|
+
onOk={() => customOk?.({ result: value })}
|
|
78
|
+
>
|
|
79
|
+
<Input value={value} onChange={(e) => setValue(e.target.value)} />
|
|
80
|
+
</Modal>
|
|
81
|
+
);
|
|
82
|
+
};
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 3. 使用 Hook 调用
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
import { useModal, useGlobalModal } from 'antd-overlay';
|
|
89
|
+
|
|
90
|
+
// 局部使用(需要渲染 holder)
|
|
91
|
+
function LocalUsage() {
|
|
92
|
+
const [openModal, holder] = useModal(MyModal);
|
|
93
|
+
|
|
94
|
+
const handleOpen = async () => {
|
|
95
|
+
const controller = openModal({ initialValue: 'hello' });
|
|
96
|
+
// controller.update({ initialValue: 'updated' }); // 可动态更新
|
|
97
|
+
// controller.close(); // 可编程式关闭
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<>
|
|
102
|
+
<button onClick={handleOpen}>打开 Modal</button>
|
|
103
|
+
{holder}
|
|
104
|
+
</>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// 全局使用(无需渲染 holder,但需要 AntdOverlayProvider)
|
|
109
|
+
function GlobalUsage() {
|
|
110
|
+
const openModal = useGlobalModal(MyModal);
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<button onClick={() => openModal({ initialValue: 'world' })}>
|
|
114
|
+
打开全局 Modal
|
|
115
|
+
</button>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## API
|
|
121
|
+
|
|
122
|
+
### Provider
|
|
123
|
+
|
|
124
|
+
#### `AntdOverlayProvider`
|
|
125
|
+
|
|
126
|
+
全局覆盖层容器,使用 `useGlobalModal`、`useGlobalDrawer`、`useGlobalOverlay` 时需要在应用外层包裹。
|
|
127
|
+
|
|
128
|
+
```tsx
|
|
129
|
+
<AntdOverlayProvider>
|
|
130
|
+
<App />
|
|
131
|
+
</AntdOverlayProvider>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Modal Hooks
|
|
135
|
+
|
|
136
|
+
#### `useModal<T>(Component, options?)`
|
|
137
|
+
|
|
138
|
+
局部 Modal 管理 Hook。
|
|
139
|
+
|
|
140
|
+
**参数:**
|
|
141
|
+
- `Component: React.FC<T>` - Modal 组件,需实现 `CustomModalProps` 接口
|
|
142
|
+
- `options?: UseModalOptions` - 配置选项
|
|
143
|
+
- `animation?: boolean` - 是否启用动画,默认 `true`
|
|
144
|
+
|
|
145
|
+
**返回值:**
|
|
146
|
+
- `[openModal, holder]` - 打开函数和需要渲染的 holder 节点
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
const [openModal, holder] = useModal(MyModal);
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
#### `useGlobalModal<T>(Component, options?)`
|
|
153
|
+
|
|
154
|
+
全局 Modal 管理 Hook,无需手动渲染 holder。
|
|
155
|
+
|
|
156
|
+
**参数:** 同 `useModal`
|
|
157
|
+
|
|
158
|
+
**返回值:**
|
|
159
|
+
- `openModal` - 打开函数
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
const openModal = useGlobalModal(MyModal);
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
#### `generateUseModalHook<T>(Component)`
|
|
166
|
+
|
|
167
|
+
为特定 Modal 组件生成专用 Hook 工厂函数。
|
|
168
|
+
|
|
169
|
+
```tsx
|
|
170
|
+
// modal.tsx
|
|
171
|
+
export const {
|
|
172
|
+
useModal: useMyModal,
|
|
173
|
+
useGlobalModal: useGlobalMyModal,
|
|
174
|
+
} = generateUseModalHook(MyModal);
|
|
175
|
+
|
|
176
|
+
// usage.tsx
|
|
177
|
+
const openModal = useGlobalMyModal();
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Drawer Hooks
|
|
181
|
+
|
|
182
|
+
#### `useDrawer<T>(Component, options?)`
|
|
183
|
+
|
|
184
|
+
局部 Drawer 管理 Hook。
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
const [openDrawer, holder] = useDrawer(MyDrawer);
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
#### `useGlobalDrawer<T>(Component, options?)`
|
|
191
|
+
|
|
192
|
+
全局 Drawer 管理 Hook。
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
const openDrawer = useGlobalDrawer(MyDrawer);
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
#### `generateUseDrawerHook<T>(Component)`
|
|
199
|
+
|
|
200
|
+
为特定 Drawer 组件生成专用 Hook 工厂函数。
|
|
201
|
+
|
|
202
|
+
```tsx
|
|
203
|
+
export const {
|
|
204
|
+
useDrawer: useMyDrawer,
|
|
205
|
+
useGlobalDrawer: useGlobalMyDrawer,
|
|
206
|
+
} = generateUseDrawerHook(MyDrawer);
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### 通用 Overlay Hooks
|
|
210
|
+
|
|
211
|
+
#### `useOverlay<T>(Component, options?)`
|
|
212
|
+
|
|
213
|
+
通用覆盖层管理 Hook,适用于自定义覆盖层组件。
|
|
214
|
+
|
|
215
|
+
**参数:**
|
|
216
|
+
- `Component: React.FC<T>` - 覆盖层组件
|
|
217
|
+
- `options?: UseOverlayOptions<T>` - 配置选项
|
|
218
|
+
- `animation?: boolean` - 是否启用动画,默认 `true`
|
|
219
|
+
- `keyPrefix?: string` - React key 前缀
|
|
220
|
+
- `propsAdapter?: (props, state) => T` - 属性适配器函数
|
|
221
|
+
|
|
222
|
+
```tsx
|
|
223
|
+
const [openOverlay, holder] = useOverlay(MyOverlay, {
|
|
224
|
+
propsAdapter: (props, state) => ({
|
|
225
|
+
...props,
|
|
226
|
+
visible: state.open,
|
|
227
|
+
onClose: state.onClose,
|
|
228
|
+
afterVisibleChange: (visible) => {
|
|
229
|
+
if (!visible) state.onAnimationEnd();
|
|
230
|
+
},
|
|
231
|
+
}),
|
|
232
|
+
});
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
#### `useGlobalOverlay<T>(Component, options?)`
|
|
236
|
+
|
|
237
|
+
全局通用覆盖层管理 Hook。
|
|
238
|
+
|
|
239
|
+
#### `generateUseOverlayHook<T>(Component, defaultOptions?)`
|
|
240
|
+
|
|
241
|
+
为特定覆盖层组件生成专用 Hook 工厂函数。
|
|
242
|
+
|
|
243
|
+
### 类型定义
|
|
244
|
+
|
|
245
|
+
#### `CustomModalProps<T, R>`
|
|
246
|
+
|
|
247
|
+
Modal 组件属性接口,继承自 `antd` 的 `ModalProps`。
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
interface CustomModalProps<T = any, R = void> extends ModalProps {
|
|
251
|
+
open?: boolean;
|
|
252
|
+
customClose: () => void;
|
|
253
|
+
customOk?: (value: T) => R;
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
#### `CustomDrawerProps<T, R>`
|
|
258
|
+
|
|
259
|
+
Drawer 组件属性接口,继承自 `antd` 的 `DrawerProps`。
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
interface CustomDrawerProps<T = any, R = void> extends DrawerProps {
|
|
263
|
+
open?: boolean;
|
|
264
|
+
customClose: () => void;
|
|
265
|
+
customOk?: (value: T) => R;
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
#### `CustomOverlayProps<T, R>`
|
|
270
|
+
|
|
271
|
+
通用覆盖层组件属性接口。
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
interface CustomOverlayProps<T = any, R = void> {
|
|
275
|
+
open?: boolean;
|
|
276
|
+
customClose: () => void;
|
|
277
|
+
customOk?: (value: T) => R;
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
#### `OverlayController<T>`
|
|
282
|
+
|
|
283
|
+
覆盖层控制器,由 `openModal`/`openDrawer`/`openOverlay` 返回。
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
interface OverlayController<T> {
|
|
287
|
+
update: (props: Omit<T, 'customClose'>) => void;
|
|
288
|
+
close: () => void;
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## 完整示例
|
|
293
|
+
|
|
294
|
+
### 确认删除 Modal
|
|
295
|
+
|
|
296
|
+
```tsx
|
|
297
|
+
import { Modal, message } from 'antd';
|
|
298
|
+
import { CustomModalProps, useGlobalModal } from 'antd-overlay';
|
|
299
|
+
|
|
300
|
+
interface ConfirmDeleteModalProps extends CustomModalProps<void> {
|
|
301
|
+
itemName: string;
|
|
302
|
+
onConfirm: () => Promise<void>;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const ConfirmDeleteModal: React.FC<ConfirmDeleteModalProps> = ({
|
|
306
|
+
open,
|
|
307
|
+
customClose,
|
|
308
|
+
customOk,
|
|
309
|
+
itemName,
|
|
310
|
+
onConfirm,
|
|
311
|
+
}) => {
|
|
312
|
+
const [loading, setLoading] = useState(false);
|
|
313
|
+
|
|
314
|
+
const handleOk = async () => {
|
|
315
|
+
setLoading(true);
|
|
316
|
+
try {
|
|
317
|
+
await onConfirm();
|
|
318
|
+
message.success('删除成功');
|
|
319
|
+
customOk?.();
|
|
320
|
+
} catch (error) {
|
|
321
|
+
message.error('删除失败');
|
|
322
|
+
} finally {
|
|
323
|
+
setLoading(false);
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
return (
|
|
328
|
+
<Modal
|
|
329
|
+
title="确认删除"
|
|
330
|
+
open={open}
|
|
331
|
+
onCancel={customClose}
|
|
332
|
+
onOk={handleOk}
|
|
333
|
+
confirmLoading={loading}
|
|
334
|
+
okText="删除"
|
|
335
|
+
okType="danger"
|
|
336
|
+
>
|
|
337
|
+
确定要删除 "{itemName}" 吗?此操作不可恢复。
|
|
338
|
+
</Modal>
|
|
339
|
+
);
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
// 使用
|
|
343
|
+
function ItemList() {
|
|
344
|
+
const openConfirm = useGlobalModal(ConfirmDeleteModal);
|
|
345
|
+
|
|
346
|
+
const handleDelete = (item: Item) => {
|
|
347
|
+
openConfirm({
|
|
348
|
+
itemName: item.name,
|
|
349
|
+
onConfirm: () => deleteItem(item.id),
|
|
350
|
+
});
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
return (
|
|
354
|
+
<List
|
|
355
|
+
dataSource={items}
|
|
356
|
+
renderItem={(item) => (
|
|
357
|
+
<List.Item
|
|
358
|
+
actions={[
|
|
359
|
+
<Button danger onClick={() => handleDelete(item)}>
|
|
360
|
+
删除
|
|
361
|
+
</Button>,
|
|
362
|
+
]}
|
|
363
|
+
>
|
|
364
|
+
{item.name}
|
|
365
|
+
</List.Item>
|
|
366
|
+
)}
|
|
367
|
+
/>
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### 用户详情 Drawer
|
|
373
|
+
|
|
374
|
+
```tsx
|
|
375
|
+
import { Drawer, Descriptions, Spin } from 'antd';
|
|
376
|
+
import { CustomDrawerProps, generateUseDrawerHook } from 'antd-overlay';
|
|
377
|
+
|
|
378
|
+
interface UserDetailDrawerProps extends CustomDrawerProps {
|
|
379
|
+
userId: number;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
const UserDetailDrawer: React.FC<UserDetailDrawerProps> = ({
|
|
383
|
+
open,
|
|
384
|
+
customClose,
|
|
385
|
+
userId,
|
|
386
|
+
}) => {
|
|
387
|
+
const [user, setUser] = useState<User | null>(null);
|
|
388
|
+
const [loading, setLoading] = useState(false);
|
|
389
|
+
|
|
390
|
+
useEffect(() => {
|
|
391
|
+
if (open && userId) {
|
|
392
|
+
setLoading(true);
|
|
393
|
+
fetchUser(userId)
|
|
394
|
+
.then(setUser)
|
|
395
|
+
.finally(() => setLoading(false));
|
|
396
|
+
}
|
|
397
|
+
}, [open, userId]);
|
|
398
|
+
|
|
399
|
+
return (
|
|
400
|
+
<Drawer
|
|
401
|
+
title="用户详情"
|
|
402
|
+
open={open}
|
|
403
|
+
onClose={customClose}
|
|
404
|
+
width={500}
|
|
405
|
+
>
|
|
406
|
+
{loading ? (
|
|
407
|
+
<Spin />
|
|
408
|
+
) : user ? (
|
|
409
|
+
<Descriptions column={1}>
|
|
410
|
+
<Descriptions.Item label="姓名">{user.name}</Descriptions.Item>
|
|
411
|
+
<Descriptions.Item label="邮箱">{user.email}</Descriptions.Item>
|
|
412
|
+
<Descriptions.Item label="手机">{user.phone}</Descriptions.Item>
|
|
413
|
+
</Descriptions>
|
|
414
|
+
) : null}
|
|
415
|
+
</Drawer>
|
|
416
|
+
);
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
// 导出专用 Hook
|
|
420
|
+
export const {
|
|
421
|
+
useDrawer: useUserDetailDrawer,
|
|
422
|
+
useGlobalDrawer: useGlobalUserDetailDrawer,
|
|
423
|
+
} = generateUseDrawerHook(UserDetailDrawer);
|
|
424
|
+
|
|
425
|
+
// 使用
|
|
426
|
+
function UserCard({ userId }: { userId: number }) {
|
|
427
|
+
const openDetail = useGlobalUserDetailDrawer();
|
|
428
|
+
|
|
429
|
+
return (
|
|
430
|
+
<Card onClick={() => openDetail({ userId })}>
|
|
431
|
+
查看详情
|
|
432
|
+
</Card>
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### 动态更新 Modal
|
|
438
|
+
|
|
439
|
+
```tsx
|
|
440
|
+
function ProgressModal() {
|
|
441
|
+
const [openModal, holder] = useModal(UploadModal);
|
|
442
|
+
|
|
443
|
+
const handleUpload = async () => {
|
|
444
|
+
const controller = openModal({ progress: 0, status: 'uploading' });
|
|
445
|
+
|
|
446
|
+
for (let i = 0; i <= 100; i += 10) {
|
|
447
|
+
await delay(500);
|
|
448
|
+
controller.update({ progress: i, status: 'uploading' });
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
controller.update({ progress: 100, status: 'done' });
|
|
452
|
+
await delay(1000);
|
|
453
|
+
controller.close();
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
return (
|
|
457
|
+
<>
|
|
458
|
+
<Button onClick={handleUpload}>开始上传</Button>
|
|
459
|
+
{holder}
|
|
460
|
+
</>
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
## 架构说明
|
|
466
|
+
|
|
467
|
+
```
|
|
468
|
+
┌─────────────────────────────────────────────────────────┐
|
|
469
|
+
│ useModal / useDrawer │ <- 业务层封装
|
|
470
|
+
├─────────────────────────────────────────────────────────┤
|
|
471
|
+
│ useOverlay / useGlobalOverlay │ <- 核心逻辑层
|
|
472
|
+
├─────────────────────────────────────────────────────────┤
|
|
473
|
+
│ AntdOverlayProvider │ <- 全局容器层
|
|
474
|
+
└─────────────────────────────────────────────────────────┘
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
## License
|
|
478
|
+
|
|
479
|
+
MIT © [RaineySpace](https://github.com/RaineySpace)
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React2 = require('react');
|
|
4
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
+
|
|
6
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
|
+
|
|
8
|
+
var React2__default = /*#__PURE__*/_interopDefault(React2);
|
|
9
|
+
|
|
10
|
+
// src/AntdOverlayContext.tsx
|
|
11
|
+
var AntdOverlayContext = React2.createContext(null);
|
|
12
|
+
function AntdOverlayProvider({ children }) {
|
|
13
|
+
const [holders, setHolders] = React2.useState([]);
|
|
14
|
+
const addHolder = React2.useCallback((holder) => {
|
|
15
|
+
setHolders((prev) => [...prev, holder]);
|
|
16
|
+
}, []);
|
|
17
|
+
const removeHolder = React2.useCallback((holder) => {
|
|
18
|
+
setHolders((prev) => prev.filter((h) => h !== holder));
|
|
19
|
+
}, []);
|
|
20
|
+
const value = React2.useMemo(
|
|
21
|
+
() => ({ holders, addHolder, removeHolder }),
|
|
22
|
+
[holders, addHolder, removeHolder]
|
|
23
|
+
);
|
|
24
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(AntdOverlayContext.Provider, { value, children: [
|
|
25
|
+
children,
|
|
26
|
+
holders
|
|
27
|
+
] });
|
|
28
|
+
}
|
|
29
|
+
function useAntdOverlayContext() {
|
|
30
|
+
const context = React2.useContext(AntdOverlayContext);
|
|
31
|
+
if (!context) {
|
|
32
|
+
throw new Error(
|
|
33
|
+
"useAntdOverlayContext must be used within an AntdOverlayProvider. Please wrap your application with <AntdOverlayProvider>."
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
return context;
|
|
37
|
+
}
|
|
38
|
+
var defaultPropsAdapter = (props, state) => {
|
|
39
|
+
const result = {
|
|
40
|
+
...props,
|
|
41
|
+
open: state.open,
|
|
42
|
+
customClose: state.onClose
|
|
43
|
+
};
|
|
44
|
+
if (result.customOk) {
|
|
45
|
+
const originalCustomOk = result?.customOk;
|
|
46
|
+
result.customOk = ((value) => {
|
|
47
|
+
originalCustomOk?.(value);
|
|
48
|
+
state.onClose();
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
};
|
|
53
|
+
function useOverlay(OverlayComponent, options = {}) {
|
|
54
|
+
const {
|
|
55
|
+
animation = true,
|
|
56
|
+
keyPrefix = "use-overlay",
|
|
57
|
+
propsAdapter = defaultPropsAdapter
|
|
58
|
+
} = options;
|
|
59
|
+
const id = React2.useId();
|
|
60
|
+
const key = `${keyPrefix}-${id}`;
|
|
61
|
+
const [open, setOpen] = React2.useState(false);
|
|
62
|
+
const [renderEnable, setRenderEnable] = React2.useState(false);
|
|
63
|
+
const [props, setProps] = React2.useState();
|
|
64
|
+
const animationRef = React2.useRef(animation);
|
|
65
|
+
animationRef.current = animation;
|
|
66
|
+
const handleClose = React2.useCallback(() => {
|
|
67
|
+
if (animationRef.current) {
|
|
68
|
+
setOpen(false);
|
|
69
|
+
} else {
|
|
70
|
+
setRenderEnable(false);
|
|
71
|
+
}
|
|
72
|
+
}, []);
|
|
73
|
+
const handleAnimationEnd = React2.useCallback(() => {
|
|
74
|
+
if (animationRef.current) {
|
|
75
|
+
setRenderEnable(false);
|
|
76
|
+
}
|
|
77
|
+
}, []);
|
|
78
|
+
const contextHolder = React2.useMemo(() => {
|
|
79
|
+
if (!renderEnable) return /* @__PURE__ */ jsxRuntime.jsx(React2__default.default.Fragment, {}, key);
|
|
80
|
+
const realProps = propsAdapter(props, {
|
|
81
|
+
open,
|
|
82
|
+
onClose: handleClose,
|
|
83
|
+
onAnimationEnd: handleAnimationEnd
|
|
84
|
+
});
|
|
85
|
+
return /* @__PURE__ */ jsxRuntime.jsx(OverlayComponent, { ...realProps }, key);
|
|
86
|
+
}, [
|
|
87
|
+
renderEnable,
|
|
88
|
+
open,
|
|
89
|
+
props,
|
|
90
|
+
key,
|
|
91
|
+
propsAdapter,
|
|
92
|
+
handleClose,
|
|
93
|
+
handleAnimationEnd,
|
|
94
|
+
OverlayComponent
|
|
95
|
+
]);
|
|
96
|
+
const openOverlay = React2.useCallback(
|
|
97
|
+
(initializeProps) => {
|
|
98
|
+
setRenderEnable(true);
|
|
99
|
+
setOpen(true);
|
|
100
|
+
setProps(initializeProps);
|
|
101
|
+
return {
|
|
102
|
+
/**
|
|
103
|
+
* 更新覆盖层属性
|
|
104
|
+
* 注意:这是完全替换,不是合并
|
|
105
|
+
*/
|
|
106
|
+
update: (newProps) => setProps(newProps),
|
|
107
|
+
/**
|
|
108
|
+
* 关闭覆盖层
|
|
109
|
+
*/
|
|
110
|
+
close: handleClose
|
|
111
|
+
};
|
|
112
|
+
},
|
|
113
|
+
[handleClose]
|
|
114
|
+
);
|
|
115
|
+
return [openOverlay, contextHolder];
|
|
116
|
+
}
|
|
117
|
+
function useGlobalOverlay(OverlayComponent, options) {
|
|
118
|
+
const { addHolder, removeHolder } = useAntdOverlayContext();
|
|
119
|
+
const [openOverlay, contextHolder] = useOverlay(OverlayComponent, options);
|
|
120
|
+
React2.useEffect(() => {
|
|
121
|
+
addHolder(contextHolder);
|
|
122
|
+
return () => removeHolder(contextHolder);
|
|
123
|
+
}, [contextHolder, addHolder, removeHolder]);
|
|
124
|
+
return openOverlay;
|
|
125
|
+
}
|
|
126
|
+
function generateUseOverlayHook(OverlayComponent, defaultOptions) {
|
|
127
|
+
return {
|
|
128
|
+
/**
|
|
129
|
+
* 绑定了特定组件的 useOverlay
|
|
130
|
+
* @param options - 配置选项,会与 defaultOptions 合并
|
|
131
|
+
*/
|
|
132
|
+
useOverlay: (options) => useOverlay(OverlayComponent, { ...defaultOptions, ...options }),
|
|
133
|
+
/**
|
|
134
|
+
* 绑定了特定组件的 useGlobalOverlay
|
|
135
|
+
* @param options - 配置选项,会与 defaultOptions 合并
|
|
136
|
+
*/
|
|
137
|
+
useGlobalOverlay: (options) => useGlobalOverlay(OverlayComponent, { ...defaultOptions, ...options })
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
var createModalPropsAdapter = () => {
|
|
141
|
+
return (props, state) => {
|
|
142
|
+
const result = {
|
|
143
|
+
maskClosable: false,
|
|
144
|
+
// 默认禁止点击遮罩关闭
|
|
145
|
+
...props,
|
|
146
|
+
open: state.open,
|
|
147
|
+
customClose: state.onClose,
|
|
148
|
+
// 在 Modal 关闭动画结束后触发,用于卸载组件
|
|
149
|
+
afterClose: () => {
|
|
150
|
+
props?.afterClose?.();
|
|
151
|
+
state.onAnimationEnd();
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
if (result.customOk) {
|
|
155
|
+
const originalCustomOk = result?.customOk;
|
|
156
|
+
result.customOk = ((value) => {
|
|
157
|
+
originalCustomOk?.(value);
|
|
158
|
+
state.onClose();
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
return result;
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
function useModal(ModalComponent, options) {
|
|
165
|
+
const propsAdapter = React2.useMemo(() => createModalPropsAdapter(), []);
|
|
166
|
+
return useOverlay(ModalComponent, {
|
|
167
|
+
...options,
|
|
168
|
+
keyPrefix: "use-modal",
|
|
169
|
+
propsAdapter
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
function useGlobalModal(ModalComponent, options) {
|
|
173
|
+
const propsAdapter = React2.useMemo(() => createModalPropsAdapter(), []);
|
|
174
|
+
return useGlobalOverlay(ModalComponent, {
|
|
175
|
+
...options,
|
|
176
|
+
keyPrefix: "use-modal",
|
|
177
|
+
propsAdapter
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
function generateUseModalHook(ModalComponent) {
|
|
181
|
+
return {
|
|
182
|
+
useModal: (options) => useModal(ModalComponent, options),
|
|
183
|
+
useGlobalModal: (options) => useGlobalModal(ModalComponent, options)
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
var createDrawerPropsAdapter = () => {
|
|
187
|
+
return (props, state) => {
|
|
188
|
+
const result = {
|
|
189
|
+
maskClosable: false,
|
|
190
|
+
// 默认禁止点击遮罩关闭
|
|
191
|
+
...props,
|
|
192
|
+
open: state.open,
|
|
193
|
+
customClose: state.onClose,
|
|
194
|
+
// Drawer 的动画回调,打开和关闭时都会触发
|
|
195
|
+
afterOpenChange: (open) => {
|
|
196
|
+
props?.afterOpenChange?.(open);
|
|
197
|
+
if (!open) {
|
|
198
|
+
state.onAnimationEnd();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
if (result.customOk) {
|
|
203
|
+
const originalCustomOk = result?.customOk;
|
|
204
|
+
result.customOk = ((value) => {
|
|
205
|
+
originalCustomOk?.(value);
|
|
206
|
+
state.onClose();
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
return result;
|
|
210
|
+
};
|
|
211
|
+
};
|
|
212
|
+
function useDrawer(DrawerComponent, options) {
|
|
213
|
+
const propsAdapter = React2.useMemo(() => createDrawerPropsAdapter(), []);
|
|
214
|
+
return useOverlay(DrawerComponent, {
|
|
215
|
+
...options,
|
|
216
|
+
keyPrefix: "use-drawer",
|
|
217
|
+
propsAdapter
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
function useGlobalDrawer(DrawerComponent, options) {
|
|
221
|
+
const propsAdapter = React2.useMemo(() => createDrawerPropsAdapter(), []);
|
|
222
|
+
return useGlobalOverlay(DrawerComponent, {
|
|
223
|
+
...options,
|
|
224
|
+
keyPrefix: "use-drawer",
|
|
225
|
+
propsAdapter
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
function generateUseDrawerHook(DrawerComponent) {
|
|
229
|
+
return {
|
|
230
|
+
useDrawer: (options) => useDrawer(DrawerComponent, options),
|
|
231
|
+
useGlobalDrawer: (options) => useGlobalDrawer(DrawerComponent, options)
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
exports.AntdOverlayProvider = AntdOverlayProvider;
|
|
236
|
+
exports.generateUseDrawerHook = generateUseDrawerHook;
|
|
237
|
+
exports.generateUseModalHook = generateUseModalHook;
|
|
238
|
+
exports.generateUseOverlayHook = generateUseOverlayHook;
|
|
239
|
+
exports.useAntdOverlayContext = useAntdOverlayContext;
|
|
240
|
+
exports.useDrawer = useDrawer;
|
|
241
|
+
exports.useGlobalDrawer = useGlobalDrawer;
|
|
242
|
+
exports.useGlobalModal = useGlobalModal;
|
|
243
|
+
exports.useGlobalOverlay = useGlobalOverlay;
|
|
244
|
+
exports.useModal = useModal;
|
|
245
|
+
exports.useOverlay = useOverlay;
|
|
246
|
+
//# sourceMappingURL=index.cjs.map
|
|
247
|
+
//# sourceMappingURL=index.cjs.map
|