antd-overlay 0.0.1 → 0.0.3

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 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
@@ -62,19 +62,19 @@ interface MyModalProps extends CustomModalProps<{ result: string }> {
62
62
  }
63
63
 
64
64
  const MyModal: React.FC<MyModalProps> = ({
65
- open,
66
65
  customClose,
67
66
  customOk,
68
67
  initialValue,
68
+ ...props
69
69
  }) => {
70
70
  const [value, setValue] = useState(initialValue || '');
71
71
 
72
72
  return (
73
73
  <Modal
74
74
  title="输入内容"
75
- open={open}
76
75
  onCancel={customClose}
77
76
  onOk={() => customOk?.({ result: value })}
77
+ {...props}
78
78
  >
79
79
  <Input value={value} onChange={(e) => setValue(e.target.value)} />
80
80
  </Modal>
@@ -125,10 +125,23 @@ function GlobalUsage() {
125
125
 
126
126
  全局覆盖层容器,使用 `useGlobalModal`、`useGlobalDrawer`、`useGlobalOverlay` 时需要在应用外层包裹。
127
127
 
128
+ **属性:**
129
+ - `children: React.ReactNode` - 子节点
130
+ - `defaultModalProps?: Partial<ModalProps>` - 默认 Modal 属性,会应用到所有 Modal
131
+ - `defaultDrawerProps?: Partial<DrawerProps>` - 默认 Drawer 属性,会应用到所有 Drawer
132
+
128
133
  ```tsx
129
134
  <AntdOverlayProvider>
130
135
  <App />
131
136
  </AntdOverlayProvider>
137
+
138
+ // 或设置默认属性
139
+ <AntdOverlayProvider
140
+ defaultModalProps={{ centered: true, maskClosable: false }}
141
+ defaultDrawerProps={{ width: 600 }}
142
+ >
143
+ <App />
144
+ </AntdOverlayProvider>
132
145
  ```
133
146
 
134
147
  ### Modal Hooks
@@ -299,22 +312,19 @@ import { CustomModalProps, useGlobalModal } from 'antd-overlay';
299
312
 
300
313
  interface ConfirmDeleteModalProps extends CustomModalProps<void> {
301
314
  itemName: string;
302
- onConfirm: () => Promise<void>;
303
315
  }
304
316
 
305
317
  const ConfirmDeleteModal: React.FC<ConfirmDeleteModalProps> = ({
306
- open,
307
318
  customClose,
308
319
  customOk,
309
320
  itemName,
310
- onConfirm,
321
+ ...props
311
322
  }) => {
312
323
  const [loading, setLoading] = useState(false);
313
324
 
314
325
  const handleOk = async () => {
315
326
  setLoading(true);
316
327
  try {
317
- await onConfirm();
318
328
  message.success('删除成功');
319
329
  customOk?.();
320
330
  } catch (error) {
@@ -327,12 +337,12 @@ const ConfirmDeleteModal: React.FC<ConfirmDeleteModalProps> = ({
327
337
  return (
328
338
  <Modal
329
339
  title="确认删除"
330
- open={open}
331
340
  onCancel={customClose}
332
341
  onOk={handleOk}
333
342
  confirmLoading={loading}
334
343
  okText="删除"
335
344
  okType="danger"
345
+ {...props}
336
346
  >
337
347
  确定要删除 "{itemName}" 吗?此操作不可恢复。
338
348
  </Modal>
@@ -346,7 +356,7 @@ function ItemList() {
346
356
  const handleDelete = (item: Item) => {
347
357
  openConfirm({
348
358
  itemName: item.name,
349
- onConfirm: () => deleteItem(item.id),
359
+ customOk: () => deleteItem(item.id),
350
360
  });
351
361
  };
352
362
 
@@ -380,9 +390,9 @@ interface UserDetailDrawerProps extends CustomDrawerProps {
380
390
  }
381
391
 
382
392
  const UserDetailDrawer: React.FC<UserDetailDrawerProps> = ({
383
- open,
384
393
  customClose,
385
394
  userId,
395
+ ...props
386
396
  }) => {
387
397
  const [user, setUser] = useState<User | null>(null);
388
398
  const [loading, setLoading] = useState(false);
@@ -399,9 +409,9 @@ const UserDetailDrawer: React.FC<UserDetailDrawerProps> = ({
399
409
  return (
400
410
  <Drawer
401
411
  title="用户详情"
402
- open={open}
403
412
  onClose={customClose}
404
413
  width={500}
414
+ {...props}
405
415
  >
406
416
  {loading ? (
407
417
  <Spin />
package/dist/index.cjs CHANGED
@@ -9,7 +9,11 @@ var React2__default = /*#__PURE__*/_interopDefault(React2);
9
9
 
10
10
  // src/AntdOverlayContext.tsx
11
11
  var AntdOverlayContext = React2.createContext(null);
12
- function AntdOverlayProvider({ children }) {
12
+ function AntdOverlayProvider({
13
+ children,
14
+ defaultModalProps,
15
+ defaultDrawerProps
16
+ }) {
13
17
  const [holders, setHolders] = React2.useState([]);
14
18
  const addHolder = React2.useCallback((holder) => {
15
19
  setHolders((prev) => [...prev, holder]);
@@ -18,8 +22,8 @@ function AntdOverlayProvider({ children }) {
18
22
  setHolders((prev) => prev.filter((h) => h !== holder));
19
23
  }, []);
20
24
  const value = React2.useMemo(
21
- () => ({ holders, addHolder, removeHolder }),
22
- [holders, addHolder, removeHolder]
25
+ () => ({ holders, addHolder, removeHolder, defaultModalProps, defaultDrawerProps }),
26
+ [holders, addHolder, removeHolder, defaultModalProps, defaultDrawerProps]
23
27
  );
24
28
  return /* @__PURE__ */ jsxRuntime.jsxs(AntdOverlayContext.Provider, { value, children: [
25
29
  children,
@@ -27,13 +31,7 @@ function AntdOverlayProvider({ children }) {
27
31
  ] });
28
32
  }
29
33
  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;
34
+ return React2.useContext(AntdOverlayContext);
37
35
  }
38
36
  var defaultPropsAdapter = (props, state) => {
39
37
  const result = {
@@ -115,7 +113,13 @@ function useOverlay(OverlayComponent, options = {}) {
115
113
  return [openOverlay, contextHolder];
116
114
  }
117
115
  function useGlobalOverlay(OverlayComponent, options) {
118
- const { addHolder, removeHolder } = useAntdOverlayContext();
116
+ const context = useAntdOverlayContext();
117
+ if (!context) {
118
+ throw new Error(
119
+ "useGlobalOverlay must be used within an AntdOverlayProvider. Please wrap your application with <AntdOverlayProvider>."
120
+ );
121
+ }
122
+ const { addHolder, removeHolder } = context;
119
123
  const [openOverlay, contextHolder] = useOverlay(OverlayComponent, options);
120
124
  React2.useEffect(() => {
121
125
  addHolder(contextHolder);
@@ -137,11 +141,10 @@ function generateUseOverlayHook(OverlayComponent, defaultOptions) {
137
141
  useGlobalOverlay: (options) => useGlobalOverlay(OverlayComponent, { ...defaultOptions, ...options })
138
142
  };
139
143
  }
140
- var createModalPropsAdapter = () => {
144
+ var createModalPropsAdapter = (defaultProps) => {
141
145
  return (props, state) => {
142
146
  const result = {
143
- maskClosable: false,
144
- // 默认禁止点击遮罩关闭
147
+ ...defaultProps,
145
148
  ...props,
146
149
  open: state.open,
147
150
  customClose: state.onClose,
@@ -162,7 +165,11 @@ var createModalPropsAdapter = () => {
162
165
  };
163
166
  };
164
167
  function useModal(ModalComponent, options) {
165
- const propsAdapter = React2.useMemo(() => createModalPropsAdapter(), []);
168
+ const context = useAntdOverlayContext();
169
+ const propsAdapter = React2.useMemo(
170
+ () => createModalPropsAdapter(context?.defaultModalProps),
171
+ [context?.defaultModalProps]
172
+ );
166
173
  return useOverlay(ModalComponent, {
167
174
  ...options,
168
175
  keyPrefix: "use-modal",
@@ -170,7 +177,11 @@ function useModal(ModalComponent, options) {
170
177
  });
171
178
  }
172
179
  function useGlobalModal(ModalComponent, options) {
173
- const propsAdapter = React2.useMemo(() => createModalPropsAdapter(), []);
180
+ const context = useAntdOverlayContext();
181
+ const propsAdapter = React2.useMemo(
182
+ () => createModalPropsAdapter(context?.defaultModalProps),
183
+ [context?.defaultModalProps]
184
+ );
174
185
  return useGlobalOverlay(ModalComponent, {
175
186
  ...options,
176
187
  keyPrefix: "use-modal",
@@ -183,11 +194,10 @@ function generateUseModalHook(ModalComponent) {
183
194
  useGlobalModal: (options) => useGlobalModal(ModalComponent, options)
184
195
  };
185
196
  }
186
- var createDrawerPropsAdapter = () => {
197
+ var createDrawerPropsAdapter = (defaultProps) => {
187
198
  return (props, state) => {
188
199
  const result = {
189
- maskClosable: false,
190
- // 默认禁止点击遮罩关闭
200
+ ...defaultProps,
191
201
  ...props,
192
202
  open: state.open,
193
203
  customClose: state.onClose,
@@ -210,7 +220,11 @@ var createDrawerPropsAdapter = () => {
210
220
  };
211
221
  };
212
222
  function useDrawer(DrawerComponent, options) {
213
- const propsAdapter = React2.useMemo(() => createDrawerPropsAdapter(), []);
223
+ const context = useAntdOverlayContext();
224
+ const propsAdapter = React2.useMemo(
225
+ () => createDrawerPropsAdapter(context?.defaultDrawerProps),
226
+ [context?.defaultDrawerProps]
227
+ );
214
228
  return useOverlay(DrawerComponent, {
215
229
  ...options,
216
230
  keyPrefix: "use-drawer",
@@ -218,7 +232,11 @@ function useDrawer(DrawerComponent, options) {
218
232
  });
219
233
  }
220
234
  function useGlobalDrawer(DrawerComponent, options) {
221
- const propsAdapter = React2.useMemo(() => createDrawerPropsAdapter(), []);
235
+ const context = useAntdOverlayContext();
236
+ const propsAdapter = React2.useMemo(
237
+ () => createDrawerPropsAdapter(context?.defaultDrawerProps),
238
+ [context?.defaultDrawerProps]
239
+ );
222
240
  return useGlobalOverlay(DrawerComponent, {
223
241
  ...options,
224
242
  keyPrefix: "use-drawer",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/AntdOverlayContext.tsx","../src/useOverlay.tsx","../src/useModal.tsx","../src/useDrawer.tsx"],"names":["createContext","useState","useCallback","useMemo","jsxs","useContext","useId","useRef","React","jsx","useEffect"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * @file AntdOverlayContext - 全局覆盖层容器 Context\n * @description\n * 提供全局覆盖层的挂载点管理。所有通过 useGlobalOverlay 系列 Hook\n * 创建的覆盖层都会被挂载到 AntdOverlayProvider 下。\n *\n * 工作原理:\n * 1. AntdOverlayProvider 维护一个 holders 数组\n * 2. useGlobalOverlay 通过 useAntdOverlayContext 获取注册方法\n * 3. 覆盖层的 contextHolder 被添加到 holders 数组\n * 4. Provider 在子节点之后统一渲染所有 holders\n *\n * 这种设计的优势:\n * - 覆盖层与业务组件解耦,可在任意位置调用\n * - 统一的挂载点,避免 z-index 混乱\n * - 组件卸载时自动清理对应的覆盖层\n *\n * @example\n * // 在应用入口包裹 Provider\n * function App() {\n * return (\n * <AntdOverlayProvider>\n * <Router>\n * <Routes />\n * </Router>\n * </AntdOverlayProvider>\n * );\n * }\n */\n\nimport React, { createContext, useCallback, useContext, useMemo, useState } from 'react';\n\n// ============================================================================\n// 类型定义\n// ============================================================================\n\n/**\n * AntdOverlay Context 的值类型\n *\n * @property holders - 当前所有已注册的覆盖层 holder 节点\n * @property addHolder - 注册一个新的 holder 到全局容器\n * @property removeHolder - 从全局容器移除一个已注册的 holder\n */\ninterface AntdOverlayContextValue {\n /** 所有已注册的 holder 节点列表 */\n holders: React.ReactNode[];\n /** 添加 holder 到全局容器 */\n addHolder: (holder: React.ReactNode) => void;\n /** 从全局容器移除 holder */\n removeHolder: (holder: React.ReactNode) => void;\n}\n\n// ============================================================================\n// Context 定义\n// ============================================================================\n\n/**\n * AntdOverlay Context\n *\n * 默认值为 null,使用时必须在 AntdOverlayProvider 内部。\n * 如果在 Provider 外部调用 useAntdOverlayContext,会抛出明确的错误提示。\n */\nconst AntdOverlayContext = createContext<AntdOverlayContextValue | null>(null);\n\n// ============================================================================\n// Provider 组件\n// ============================================================================\n\n/**\n * AntdOverlay 容器提供者组件\n *\n * 用于管理全局覆盖层的挂载点。所有通过 useGlobalOverlay、useGlobalModal、\n * useGlobalDrawer 等 Hook 创建的覆盖层都会被挂载到这个 Provider 下。\n *\n * 渲染结构:\n * ```\n * <AntdOverlayContext.Provider>\n * {children} <- 应用的主要内容\n * {holders[0]} <- 全局覆盖层 1\n * {holders[1]} <- 全局覆盖层 2\n * ...\n * </AntdOverlayContext.Provider>\n * ```\n *\n * @param children - 子节点,通常是整个应用\n *\n * @example\n * // 基础用法 - 在应用入口包裹\n * function App() {\n * return (\n * <AntdOverlayProvider>\n * <Router>\n * <Routes />\n * </Router>\n * </AntdOverlayProvider>\n * );\n * }\n *\n * @example\n * // 与其他 Provider 配合使用\n * function App() {\n * return (\n * <ConfigProvider>\n * <AntdOverlayProvider>\n * <App />\n * </AntdOverlayProvider>\n * </ConfigProvider>\n * );\n * }\n */\nexport function AntdOverlayProvider({ children }: { children: React.ReactNode }) {\n // 存储所有已注册的 holder 节点\n const [holders, setHolders] = useState<React.ReactNode[]>([]);\n\n /**\n * 添加 holder 到全局容器\n *\n * 使用函数式更新确保并发安全,避免闭包陷阱。\n * 新的 holder 会被追加到数组末尾,因此后添加的覆盖层会显示在上层。\n */\n const addHolder = useCallback((holder: React.ReactNode) => {\n setHolders((prev) => [...prev, holder]);\n }, []);\n\n /**\n * 从全局容器移除 holder\n *\n * 通过引用比较(===)找到并移除对应的 holder。\n * 这要求每次传入的 holder 必须是同一个引用。\n */\n const removeHolder = useCallback((holder: React.ReactNode) => {\n setHolders((prev) => prev.filter((h) => h !== holder));\n }, []);\n\n // 使用 useMemo 优化 Context 值,避免不必要的重渲染\n // 只有当 holders、addHolder 或 removeHolder 变化时才会创建新的值对象\n const value = useMemo(\n () => ({ holders, addHolder, removeHolder }),\n [holders, addHolder, removeHolder],\n );\n\n return (\n <AntdOverlayContext.Provider value={value}>\n {children}\n {/* 在 children 之后渲染所有全局覆盖层 */}\n {holders}\n </AntdOverlayContext.Provider>\n );\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * 获取 AntdOverlay Context 的 Hook\n *\n * 返回全局容器的注册和注销方法,供 useGlobalOverlay 系列 Hook 内部使用。\n *\n * 注意事项:\n * - 必须在 AntdOverlayProvider 内部使用\n * - 如果在 Provider 外部调用,会抛出明确的错误\n * - 主要供库内部使用,一般不需要在业务代码中直接调用\n *\n * @returns AntdOverlayContextValue 包含 holders、addHolder、removeHolder\n * @throws Error 如果不在 AntdOverlayProvider 内部使用\n *\n * @example\n * // 库内部使用示例(useGlobalOverlay 的实现)\n * function useGlobalOverlay(Component, options) {\n * const { addHolder, removeHolder } = useAntdOverlayContext();\n * const [open, holder] = useOverlay(Component, options);\n *\n * useEffect(() => {\n * addHolder(holder);\n * return () => removeHolder(holder);\n * }, [holder]);\n *\n * return open;\n * }\n */\nexport function useAntdOverlayContext() {\n const context = useContext(AntdOverlayContext);\n\n if (!context) {\n throw new Error(\n 'useAntdOverlayContext must be used within an AntdOverlayProvider. ' +\n 'Please wrap your application with <AntdOverlayProvider>.',\n );\n }\n\n return context;\n}\n","/**\n * @file useOverlay - 通用覆盖层管理 Hook\n * @description\n * 提供一个与具体 UI 组件无关的覆盖层(Overlay)管理方案。\n * 支持任意满足 CustomOverlayProps 接口的组件,如 Modal、Drawer、Popover 等。\n *\n * 核心设计理念:\n * 1. 命令式调用 - 通过函数调用打开覆盖层,而非声明式管理 open 状态\n * 2. 动画支持 - 正确处理打开/关闭动画,避免动画未完成就卸载组件\n * 3. 全局挂载 - 支持将覆盖层挂载到全局容器,实现跨组件调用\n * 4. 类型安全 - 完整的 TypeScript 类型支持\n *\n * 架构层次:\n * ┌─────────────────────────────────────────────────────────┐\n * │ useModal / useDrawer │ <- 业务层封装\n * ├─────────────────────────────────────────────────────────┤\n * │ useOverlay / useGlobalOverlay │ <- 核心逻辑层\n * ├─────────────────────────────────────────────────────────┤\n * │ GlobalHolderProvider │ <- 全局容器层\n * └─────────────────────────────────────────────────────────┘\n *\n * @example\n * // 直接使用 useOverlay(不推荐,建议使用 useModal/useDrawer)\n * const [openOverlay, holder] = useOverlay(MyOverlayComponent, {\n * propsAdapter: (props, state) => ({ ...props, visible: state.open }),\n * });\n */\n\nimport React, { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';\n\nimport { useAntdOverlayContext } from './AntdOverlayContext';\n\n// ============================================================================\n// 类型定义\n// ============================================================================\n\n/**\n * 自定义覆盖层组件必须实现的属性接口\n *\n * 这是所有覆盖层组件的基础接口,定义了控制覆盖层所需的最小属性集。\n * 具体的 UI 组件(如 Modal、Drawer)应该扩展此接口。\n *\n * @template T - customOk 回调接收的参数类型,用于传递确认操作的数据\n * @template R - customOk 回调的返回类型,通常为 void\n *\n * @property open - 控制覆盖层的显示/隐藏状态\n * @property customClose - 关闭覆盖层的回调函数,由 useOverlay 注入\n * @property customOk - 确认操作的回调函数,调用后会自动关闭覆盖层\n *\n * @example\n * interface MyOverlayProps extends CustomOverlayProps<{ id: number }> {\n * title: string;\n * data: SomeData;\n * }\n *\n * const MyOverlay: React.FC<MyOverlayProps> = ({\n * open,\n * customClose,\n * customOk,\n * title,\n * data,\n * }) => {\n * const handleConfirm = () => {\n * // 调用 customOk 会自动关闭覆盖层\n * customOk?.({ id: data.id });\n * };\n * return (\n * <Modal open={open} onCancel={customClose} onOk={handleConfirm}>\n * {title}\n * </Modal>\n * );\n * };\n */\nexport interface CustomOverlayProps<T = any, R = void> {\n /** 覆盖层的显示状态 */\n open?: boolean;\n /** 关闭覆盖层的回调,由 useOverlay 自动注入 */\n customClose: () => void;\n /** 确认操作回调,调用后自动关闭覆盖层 */\n customOk?: (value: T) => R;\n}\n\n/**\n * 内部使用的属性类型\n * 排除 customClose,因为它由 useOverlay 自动注入,用户无需传递\n */\ntype InternalProps<T extends CustomOverlayProps> = Omit<T, 'customClose'>;\n\n/**\n * 覆盖层控制器接口\n *\n * 打开覆盖层后返回的控制器对象,用于后续操作(更新属性或关闭)。\n * 使用 readonly 确保方法引用稳定,不会被意外修改。\n *\n * @template T - 覆盖层组件的属性类型\n *\n * @example\n * const controller = openModal({ title: '初始标题' });\n *\n * // 动态更新属性\n * controller.update({ title: '新标题', loading: true });\n *\n * // 编程式关闭\n * controller.close();\n */\nexport interface OverlayController<T extends CustomOverlayProps> {\n /**\n * 更新覆盖层的属性\n * @param props - 新的属性对象,会完全替换之前的属性\n */\n readonly update: (props: InternalProps<T>) => void;\n /**\n * 关闭覆盖层\n * 如果启用了动画,会等待动画结束后再卸载组件\n */\n readonly close: () => void;\n}\n\n/**\n * 覆盖层打开函数的类型定义\n *\n * @template T - 覆盖层组件的属性类型\n * @param initialize - 初始化属性,可选\n * @returns 覆盖层控制器,用于后续的更新和关闭操作\n *\n * @example\n * const openModal: OverlayOpener<MyModalProps> = (props) => {\n * // 返回控制器\n * };\n *\n * // 无参数调用\n * const ctrl1 = openModal();\n *\n * // 带初始属性调用\n * const ctrl2 = openModal({ title: '标题', data: someData });\n */\nexport type OverlayOpener<T extends CustomOverlayProps> = (\n initialize?: InternalProps<T>,\n) => OverlayController<T>;\n\n/**\n * useOverlay Hook 的配置选项\n *\n * @template T - 覆盖层组件的属性类型\n *\n * @property animation - 是否启用动画支持,默认 true\n * - true: 关闭时先设置 open=false,等待动画结束后再卸载组件\n * - false: 关闭时直接卸载组件,适用于无动画的覆盖层\n *\n * @property keyPrefix - React key 的前缀,用于区分不同类型的覆盖层\n * - 默认值: 'use-overlay'\n * - useModal 使用 'use-modal'\n * - useDrawer 使用 'use-drawer'\n *\n * @property propsAdapter - 属性适配器函数\n * 用于将内部状态转换为组件实际需要的属性。\n * 不同的 UI 组件(Modal、Drawer)有不同的动画回调机制,\n * 通过适配器实现统一的接口。\n */\nexport interface UseOverlayOptions<T extends CustomOverlayProps> {\n /** 是否启用关闭动画,默认 true */\n animation?: boolean;\n /** React key 前缀,用于标识覆盖层类型 */\n keyPrefix?: string;\n /**\n * 属性适配器函数\n * @param props - 用户传入的属性\n * @param state - 内部状态,包含 open、onClose、onAnimationEnd\n * @returns 传递给组件的最终属性\n */\n propsAdapter?: (\n props: InternalProps<T> | undefined,\n state: {\n /** 当前的打开状态 */\n open: boolean;\n /** 触发关闭的回调 */\n onClose: () => void;\n /** 动画结束后的回调,用于卸载组件 */\n onAnimationEnd: () => void;\n },\n ) => T;\n}\n\n// ============================================================================\n// 默认属性适配器\n// ============================================================================\n\n/**\n * 默认的属性适配器\n *\n * 提供基本的属性转换逻辑:\n * 1. 将用户传入的 props 与内部状态合并\n * 2. 注入 open 和 customClose\n * 3. 包装 customOk 使其调用后自动关闭覆盖层\n *\n * 注意:这是一个简化的适配器,不处理动画。\n * 对于 Modal 和 Drawer,应该使用各自的专用适配器来处理动画回调。\n *\n * @template T - 覆盖层组件的属性类型\n * @param props - 用户传入的属性\n * @param state - 内部状态\n * @returns 最终传递给组件的属性\n */\nconst defaultPropsAdapter = <T extends CustomOverlayProps>(\n props: InternalProps<T> | undefined,\n state: { open: boolean; onClose: () => void; onAnimationEnd: () => void },\n): T => {\n const result = {\n ...props,\n open: state.open,\n customClose: state.onClose,\n } as unknown as T;\n\n // 包装 customOk,使其调用后自动触发关闭\n if (result.customOk) {\n const originalCustomOk = result?.customOk;\n result.customOk = ((value: unknown) => {\n originalCustomOk?.(value);\n state.onClose();\n }) as T['customOk'];\n }\n\n return result;\n};\n\n// ============================================================================\n// 核心 Hook 实现\n// ============================================================================\n\n/**\n * 覆盖层管理核心 Hook\n *\n * 这是整个库的核心,提供覆盖层的生命周期管理:\n * - 挂载/卸载控制\n * - 打开/关闭状态管理\n * - 动画支持\n * - 属性更新\n *\n * 状态机说明:\n * ```\n * [未挂载] --open()--> [已挂载, open=true] --close()--> [已挂载, open=false] --动画结束--> [未挂载]\n * │\n * └── (animation=false) --> [未挂载]\n * ```\n *\n * @template T - 覆盖层组件的属性类型,必须继承 CustomOverlayProps\n *\n * @param OverlayComponent - 覆盖层组件\n * @param options - 配置选项\n *\n * @returns 元组 [openOverlay, contextHolder]\n * - openOverlay: 打开覆盖层的函数,返回控制器\n * - contextHolder: 需要渲染到组件树中的 React 节点\n *\n * @example\n * function MyComponent() {\n * const [openOverlay, holder] = useOverlay(MyOverlay, {\n * animation: true,\n * propsAdapter: (props, state) => ({\n * ...props,\n * visible: state.open,\n * onClose: state.onClose,\n * afterVisibleChange: (visible) => {\n * if (!visible) state.onAnimationEnd();\n * },\n * }),\n * });\n *\n * return (\n * <>\n * <button onClick={() => openOverlay({ title: '标题' })}>打开</button>\n * {holder}\n * </>\n * );\n * }\n */\nexport function useOverlay<T extends CustomOverlayProps>(\n OverlayComponent: React.FC<T>,\n options: UseOverlayOptions<T> = {},\n): [OverlayOpener<T>, React.ReactNode] {\n // 解构配置选项,设置默认值\n const {\n animation = true,\n keyPrefix = 'use-overlay',\n propsAdapter = defaultPropsAdapter,\n } = options;\n\n // 生成唯一 ID,用于 React key\n const id = useId();\n const key = `${keyPrefix}-${id}`;\n\n // ========== 状态管理 ==========\n\n /**\n * open: 控制覆盖层的显示状态(用于动画)\n * - true: 覆盖层显示\n * - false: 覆盖层隐藏(但可能还在播放关闭动画)\n */\n const [open, setOpen] = useState(false);\n\n /**\n * renderEnable: 控制组件是否挂载到 DOM\n * - true: 组件已挂载\n * - false: 组件已卸载\n *\n * 与 open 分离是为了支持关闭动画:\n * 关闭时先设置 open=false 触发动画,动画结束后再设置 renderEnable=false 卸载组件\n */\n const [renderEnable, setRenderEnable] = useState(false);\n\n /**\n * props: 用户传入的属性\n * 存储最近一次 open 或 update 调用时传入的属性\n */\n const [props, setProps] = useState<InternalProps<T> | undefined>();\n\n /**\n * 使用 ref 存储 animation 配置\n * 避免 animation 变化时重新创建回调函数\n */\n const animationRef = useRef(animation);\n animationRef.current = animation;\n\n // ========== 回调函数 ==========\n\n /**\n * 处理关闭操作\n *\n * 根据是否启用动画采取不同策略:\n * - 启用动画: 仅设置 open=false,等待动画结束后再卸载\n * - 禁用动画: 直接卸载组件\n */\n const handleClose = useCallback(() => {\n if (animationRef.current) {\n // 启用动画时,先触发关闭动画\n setOpen(false);\n } else {\n // 禁用动画时,直接卸载\n setRenderEnable(false);\n }\n }, []);\n\n /**\n * 处理动画结束\n *\n * 由属性适配器在关闭动画结束时调用。\n * 仅在启用动画时执行实际的卸载操作。\n */\n const handleAnimationEnd = useCallback(() => {\n if (animationRef.current) {\n setRenderEnable(false);\n }\n }, []);\n\n // ========== 渲染逻辑 ==========\n\n /**\n * contextHolder: 需要渲染到组件树中的节点\n *\n * 使用 useMemo 优化性能:\n * - 未挂载时返回空 Fragment(保持 key 稳定)\n * - 已挂载时渲染实际组件,通过 propsAdapter 转换属性\n */\n const contextHolder = useMemo(() => {\n // 未挂载时返回带 key 的空 Fragment\n // 保持 key 稳定可以避免不必要的 DOM 操作\n if (!renderEnable) return <React.Fragment key={key} />;\n\n // 通过适配器转换属性\n const realProps = propsAdapter(props, {\n open,\n onClose: handleClose,\n onAnimationEnd: handleAnimationEnd,\n });\n\n return <OverlayComponent key={key} {...realProps} />;\n }, [\n renderEnable,\n open,\n props,\n key,\n propsAdapter,\n handleClose,\n handleAnimationEnd,\n OverlayComponent,\n ]);\n\n // ========== 打开函数 ==========\n\n /**\n * 打开覆盖层的函数\n *\n * @param initializeProps - 初始化属性\n * @returns 控制器对象,包含 update 和 close 方法\n */\n const openOverlay = useCallback(\n (initializeProps?: InternalProps<T>) => {\n // 1. 挂载组件\n setRenderEnable(true);\n // 2. 设置为打开状态(触发打开动画)\n setOpen(true);\n // 3. 存储初始属性\n setProps(initializeProps);\n\n // 返回控制器\n return {\n /**\n * 更新覆盖层属性\n * 注意:这是完全替换,不是合并\n */\n update: (newProps: InternalProps<T>) => setProps(newProps),\n /**\n * 关闭覆盖层\n */\n close: handleClose,\n } as const;\n },\n [handleClose],\n );\n\n return [openOverlay, contextHolder];\n}\n\n/**\n * 全局覆盖层管理 Hook\n *\n * 与 useOverlay 的区别:\n * - useOverlay: 需要手动渲染 contextHolder\n * - useGlobalOverlay: 自动挂载到 AntdOverlayProvider\n *\n * 实现原理:\n * 1. 内部调用 useOverlay 获取 openOverlay 和 contextHolder\n * 2. 使用 useEffect 将 contextHolder 注册到全局容器\n * 3. 组件卸载时自动从全局容器移除\n *\n * 使用前提:\n * - 必须在组件树的上层包裹 AntdOverlayProvider\n *\n * @template T - 覆盖层组件的属性类型\n *\n * @param OverlayComponent - 覆盖层组件\n * @param options - 配置选项\n *\n * @returns 打开覆盖层的函数(无需再渲染 holder)\n *\n * @example\n * // 1. 先在应用入口包裹 Provider\n * function App() {\n * return (\n * <AntdOverlayProvider>\n * <YourApp />\n * </AntdOverlayProvider>\n * );\n * }\n *\n * // 2. 在任意组件中使用\n * function AnyComponent() {\n * const openOverlay = useGlobalOverlay(MyOverlay);\n *\n * return (\n * <button onClick={() => openOverlay({ data: someData })}>\n * 打开全局覆盖层\n * </button>\n * );\n * }\n */\nexport function useGlobalOverlay<T extends CustomOverlayProps>(\n OverlayComponent: React.FC<T>,\n options?: UseOverlayOptions<T>,\n): OverlayOpener<T> {\n // 获取全局容器的注册/注销方法\n const { addHolder, removeHolder } = useAntdOverlayContext();\n\n // 使用基础 useOverlay 获取功能\n const [openOverlay, contextHolder] = useOverlay<T>(OverlayComponent, options);\n\n // 将 contextHolder 注册到全局容器\n useEffect(() => {\n addHolder(contextHolder);\n // 清理函数:组件卸载时从全局容器移除\n return () => removeHolder(contextHolder);\n }, [contextHolder, addHolder, removeHolder]);\n\n // 仅返回 openOverlay,holder 已自动挂载\n return openOverlay;\n}\n\n// ============================================================================\n// 工厂函数\n// ============================================================================\n\n/**\n * 生成绑定了特定组件的 Hook 工厂函数\n *\n * 当某个覆盖层组件在多处使用时,可以使用此函数生成专用 Hook,\n * 避免每次使用都需要传入组件引用。\n *\n * @template T - 覆盖层组件的属性类型\n *\n * @param OverlayComponent - 覆盖层组件\n * @param defaultOptions - 默认配置选项,会与调用时的选项合并\n *\n * @returns 包含 useOverlay 和 useGlobalOverlay 的对象\n *\n * @example\n * // 创建专用 Hook\n * const {\n * useOverlay: useMyOverlay,\n * useGlobalOverlay: useGlobalMyOverlay,\n * } = generateUseOverlayHook(MyOverlayComponent, {\n * animation: true,\n * propsAdapter: myAdapter,\n * });\n *\n * // 使用专用 Hook(无需再传组件)\n * function SomeComponent() {\n * const openOverlay = useGlobalMyOverlay();\n * return <button onClick={() => openOverlay()}>打开</button>;\n * }\n */\nexport function generateUseOverlayHook<T extends CustomOverlayProps>(\n OverlayComponent: React.FC<T>,\n defaultOptions?: UseOverlayOptions<T>,\n) {\n return {\n /**\n * 绑定了特定组件的 useOverlay\n * @param options - 配置选项,会与 defaultOptions 合并\n */\n useOverlay: (options?: UseOverlayOptions<T>) =>\n useOverlay(OverlayComponent, { ...defaultOptions, ...options }),\n\n /**\n * 绑定了特定组件的 useGlobalOverlay\n * @param options - 配置选项,会与 defaultOptions 合并\n */\n useGlobalOverlay: (options?: UseOverlayOptions<T>) =>\n useGlobalOverlay(OverlayComponent, { ...defaultOptions, ...options }),\n };\n}\n","/**\n * @file useModal - Ant Design Modal 管理 Hook\n * @description\n * 基于 useOverlay 封装的 Modal 专用管理方案。\n * 提供命令式 API 来控制 Modal 的显示、隐藏和属性更新。\n *\n * 主要特性:\n * - 命令式调用,无需管理 visible 状态\n * - 支持动态更新 Modal 属性\n * - 支持全局挂载,跨组件调用\n * - 正确处理关闭动画(通过 afterClose 回调)\n *\n * @example\n * // 基础用法\n * const [openModal, holder] = useModal(MyModal);\n *\n * // 全局用法\n * const openModal = useGlobalModal(MyModal);\n *\n * // 为特定组件生成专用 Hook\n * const { useGlobalModal: useGlobalMyModal } = generateUseModalHook(MyModal);\n */\n\nimport { ModalProps } from 'antd';\nimport { useMemo } from 'react';\n\nimport {\n CustomOverlayProps,\n OverlayOpener,\n useGlobalOverlay,\n useOverlay,\n UseOverlayOptions,\n} from './useOverlay';\n\n/**\n * 自定义 Modal 组件的属性接口\n * 继承 Ant Design ModalProps 并添加自定义属性\n *\n * @template T - customOk 回调的参数类型\n * @template R - customOk 回调的返回类型\n *\n * @example\n * const MyModal: React.FC<CustomModalProps<{ name: string }>> = ({\n * open,\n * customClose,\n * customOk,\n * }) => {\n * return (\n * <Modal open={open} onCancel={customClose} onOk={() => customOk?.({ name: 'test' })}>\n * 内容\n * </Modal>\n * );\n * };\n */\nexport interface CustomModalProps<T = any, R = void> extends ModalProps, CustomOverlayProps<T, R> {}\n\n/**\n * useModal Hook 的配置选项\n * 排除了 propsAdapter 和 keyPrefix,这些由内部自动处理\n */\nexport type UseModalOptions = Omit<\n UseOverlayOptions<CustomModalProps>,\n 'propsAdapter' | 'keyPrefix'\n>;\n\n/**\n * 创建 Modal 专用的属性适配器\n *\n * 主要职责:\n * 1. 注入 open 和 customClose\n * 2. 包装 afterClose 以处理动画结束\n * 3. 包装 customOk 以实现自动关闭\n *\n * @template T - Modal 组件的属性类型\n * @returns 属性适配器函数\n */\nconst createModalPropsAdapter = <T extends CustomModalProps>() => {\n return (\n props: Omit<T, 'customClose'> | undefined,\n state: { open: boolean; onClose: () => void; onAnimationEnd: () => void },\n ): T => {\n const result = {\n maskClosable: false, // 默认禁止点击遮罩关闭\n ...props,\n open: state.open,\n customClose: state.onClose,\n // 在 Modal 关闭动画结束后触发,用于卸载组件\n afterClose: () => {\n props?.afterClose?.();\n state.onAnimationEnd();\n },\n } as unknown as T;\n\n // 包装 customOk,调用后自动关闭 Modal\n if (result.customOk) {\n const originalCustomOk = result?.customOk;\n result.customOk = ((value: unknown) => {\n originalCustomOk?.(value);\n state.onClose();\n }) as T['customOk'];\n }\n\n return result;\n };\n};\n\n/**\n * Modal 管理 Hook\n *\n * @template T - Modal 组件的属性类型,必须继承 CustomModalProps\n *\n * @param ModalComponent - Modal 组件\n * @param options - 配置选项\n *\n * @returns 元组 [openModal, contextHolder]\n * - openModal: 打开 Modal 的函数\n * - contextHolder: 需要渲染到组件树中的 React 节点\n *\n * @example\n * function MyPage() {\n * const [openModal, modalHolder] = useModal(ConfirmModal);\n *\n * const handleDelete = () => {\n * openModal({\n * title: '确认删除',\n * content: '删除后无法恢复',\n * });\n * };\n *\n * return (\n * <>\n * <button onClick={handleDelete}>删除</button>\n * {modalHolder}\n * </>\n * );\n * }\n */\nexport function useModal<T extends CustomModalProps>(\n ModalComponent: React.FC<T>,\n options?: UseModalOptions,\n): [OverlayOpener<T>, React.ReactNode] {\n const propsAdapter = useMemo(() => createModalPropsAdapter<T>(), []);\n return useOverlay(ModalComponent, {\n ...options,\n keyPrefix: 'use-modal',\n propsAdapter,\n });\n}\n\n/**\n * 全局 Modal 管理 Hook\n *\n * 与 useModal 的区别:\n * - 无需手动渲染 contextHolder\n * - Modal 会自动挂载到全局容器\n * - 适合需要跨组件调用的场景\n *\n * @template T - Modal 组件的属性类型\n *\n * @param ModalComponent - Modal 组件\n * @param options - 配置选项\n *\n * @returns 打开 Modal 的函数\n *\n * @example\n * function DeleteButton() {\n * const openConfirm = useGlobalModal(ConfirmModal);\n *\n * return (\n * <button onClick={() => openConfirm({ title: '确认删除?' })}>\n * 删除\n * </button>\n * );\n * }\n */\nexport function useGlobalModal<T extends CustomModalProps>(\n ModalComponent: React.FC<T>,\n options?: UseModalOptions,\n): OverlayOpener<T> {\n const propsAdapter = useMemo(() => createModalPropsAdapter<T>(), []);\n return useGlobalOverlay(ModalComponent, {\n ...options,\n keyPrefix: 'use-modal',\n propsAdapter,\n });\n}\n\n/**\n * 生成绑定了特定 Modal 组件的 Hook 工厂函数\n *\n * 适用场景:\n * - 某个 Modal 在多处使用\n * - 希望简化调用代码\n * - 需要统一管理某个 Modal 的默认配置\n *\n * @template T - Modal 组件的属性类型\n *\n * @param ModalComponent - Modal 组件\n *\n * @returns 包含 useModal 和 useGlobalModal 的对象\n *\n * @example\n * // 在 Modal 组件文件中导出专用 Hook\n * const ConfirmModal: React.FC<CustomModalProps> = (props) => {\n * // ...\n * };\n *\n * export const {\n * useModal: useConfirmModal,\n * useGlobalModal: useGlobalConfirmModal,\n * } = generateUseModalHook(ConfirmModal);\n *\n * // 在其他组件中使用\n * function MyPage() {\n * const openConfirm = useGlobalConfirmModal();\n * return <button onClick={() => openConfirm()}>确认</button>;\n * }\n */\nexport function generateUseModalHook<T extends CustomModalProps>(ModalComponent: React.FC<T>) {\n return {\n useModal: (options?: UseModalOptions) => useModal(ModalComponent, options),\n useGlobalModal: (options?: UseModalOptions) => useGlobalModal(ModalComponent, options),\n };\n}\n\nexport default useModal;\n","/**\n * @file useDrawer - Ant Design Drawer 管理 Hook\n * @description\n * 基于 useOverlay 封装的 Drawer 专用管理方案。\n * 提供命令式 API 来控制 Drawer 的显示、隐藏和属性更新。\n *\n * 主要特性:\n * - 命令式调用,无需管理 open 状态\n * - 支持动态更新 Drawer 属性\n * - 支持全局挂载,跨组件调用\n * - 正确处理关闭动画(通过 afterOpenChange 回调)\n *\n * @example\n * // 基础用法\n * const [openDrawer, holder] = useDrawer(MyDrawer);\n *\n * // 全局用法\n * const openDrawer = useGlobalDrawer(MyDrawer);\n *\n * // 为特定组件生成专用 Hook\n * const { useGlobalDrawer: useGlobalMyDrawer } = generateUseDrawerHook(MyDrawer);\n */\n\nimport { DrawerProps } from 'antd';\nimport { useMemo } from 'react';\n\nimport {\n CustomOverlayProps,\n OverlayOpener,\n useGlobalOverlay,\n useOverlay,\n UseOverlayOptions,\n} from './useOverlay';\n\n/**\n * 自定义 Drawer 组件的属性接口\n * 继承 Ant Design DrawerProps 并添加自定义属性\n *\n * @template T - customOk 回调的参数类型\n * @template R - customOk 回调的返回类型\n *\n * @example\n * const MyDrawer: React.FC<CustomDrawerProps<{ id: number }>> = ({\n * open,\n * customClose,\n * customOk,\n * }) => {\n * return (\n * <Drawer open={open} onClose={customClose}>\n * <Button onClick={() => customOk?.({ id: 1 })}>确认</Button>\n * </Drawer>\n * );\n * };\n */\nexport interface CustomDrawerProps<T = any, R = void>\n extends DrawerProps, CustomOverlayProps<T, R> {}\n\n/**\n * useDrawer Hook 的配置选项\n * 排除了 propsAdapter 和 keyPrefix,这些由内部自动处理\n */\nexport type UseDrawerOptions = Omit<\n UseOverlayOptions<CustomDrawerProps>,\n 'propsAdapter' | 'keyPrefix'\n>;\n\n/**\n * 创建 Drawer 专用的属性适配器\n *\n * 主要职责:\n * 1. 注入 open 和 customClose\n * 2. 包装 afterOpenChange 以处理动画结束\n * 3. 包装 customOk 以实现自动关闭\n *\n * 与 Modal 的区别:\n * - Modal 使用 afterClose 回调(仅在关闭后触发)\n * - Drawer 使用 afterOpenChange 回调(打开和关闭都会触发,需要判断状态)\n *\n * @template T - Drawer 组件的属性类型\n * @returns 属性适配器函数\n */\nconst createDrawerPropsAdapter = <T extends CustomDrawerProps>() => {\n return (\n props: Omit<T, 'customClose'> | undefined,\n state: { open: boolean; onClose: () => void; onAnimationEnd: () => void },\n ): T => {\n const result = {\n maskClosable: false, // 默认禁止点击遮罩关闭\n ...props,\n open: state.open,\n customClose: state.onClose,\n // Drawer 的动画回调,打开和关闭时都会触发\n afterOpenChange: (open: boolean) => {\n props?.afterOpenChange?.(open);\n // 仅在关闭动画结束时触发卸载\n if (!open) {\n state.onAnimationEnd();\n }\n },\n } as unknown as T;\n\n // 包装 customOk,调用后自动关闭 Drawer\n if (result.customOk) {\n const originalCustomOk = result?.customOk;\n result.customOk = ((value: unknown) => {\n originalCustomOk?.(value);\n state.onClose();\n }) as T['customOk'];\n }\n\n return result;\n };\n};\n\n/**\n * Drawer 管理 Hook\n *\n * @template T - Drawer 组件的属性类型,必须继承 CustomDrawerProps\n *\n * @param DrawerComponent - Drawer 组件\n * @param options - 配置选项\n *\n * @returns 元组 [openDrawer, contextHolder]\n * - openDrawer: 打开 Drawer 的函数\n * - contextHolder: 需要渲染到组件树中的 React 节点\n *\n * @example\n * function MyPage() {\n * const [openDrawer, drawerHolder] = useDrawer(UserDetailDrawer);\n *\n * const handleViewUser = (userId: number) => {\n * openDrawer({ userId, title: '用户详情' });\n * };\n *\n * return (\n * <>\n * <button onClick={() => handleViewUser(1)}>查看用户</button>\n * {drawerHolder}\n * </>\n * );\n * }\n */\nexport function useDrawer<T extends CustomDrawerProps>(\n DrawerComponent: React.FC<T>,\n options?: UseDrawerOptions,\n): [OverlayOpener<T>, React.ReactNode] {\n const propsAdapter = useMemo(() => createDrawerPropsAdapter<T>(), []);\n return useOverlay(DrawerComponent, {\n ...options,\n keyPrefix: 'use-drawer',\n propsAdapter,\n });\n}\n\n/**\n * 全局 Drawer 管理 Hook\n *\n * 与 useDrawer 的区别:\n * - 无需手动渲染 contextHolder\n * - Drawer 会自动挂载到全局容器\n * - 适合需要跨组件调用的场景\n *\n * @template T - Drawer 组件的属性类型\n *\n * @param DrawerComponent - Drawer 组件\n * @param options - 配置选项\n *\n * @returns 打开 Drawer 的函数\n *\n * @example\n * function UserCard({ userId }: { userId: number }) {\n * const openDetail = useGlobalDrawer(UserDetailDrawer);\n *\n * return (\n * <Card onClick={() => openDetail({ userId })}>\n * 查看详情\n * </Card>\n * );\n * }\n */\nexport function useGlobalDrawer<T extends CustomDrawerProps>(\n DrawerComponent: React.FC<T>,\n options?: UseDrawerOptions,\n): OverlayOpener<T> {\n const propsAdapter = useMemo(() => createDrawerPropsAdapter<T>(), []);\n return useGlobalOverlay(DrawerComponent, {\n ...options,\n keyPrefix: 'use-drawer',\n propsAdapter,\n });\n}\n\n/**\n * 生成绑定了特定 Drawer 组件的 Hook 工厂函数\n *\n * 适用场景:\n * - 某个 Drawer 在多处使用\n * - 希望简化调用代码\n * - 需要统一管理某个 Drawer 的默认配置\n *\n * @template T - Drawer 组件的属性类型\n *\n * @param DrawerComponent - Drawer 组件\n *\n * @returns 包含 useDrawer 和 useGlobalDrawer 的对象\n *\n * @example\n * // 在 Drawer 组件文件中导出专用 Hook\n * const ProjectMemberDrawer: React.FC<CustomDrawerProps> = (props) => {\n * // ...\n * };\n *\n * export const {\n * useDrawer: useProjectMemberDrawer,\n * useGlobalDrawer: useGlobalProjectMemberDrawer,\n * } = generateUseDrawerHook(ProjectMemberDrawer);\n *\n * // 在其他组件中使用\n * function ProjectPage() {\n * const openMemberDrawer = useGlobalProjectMemberDrawer();\n * return <button onClick={() => openMemberDrawer()}>管理成员</button>;\n * }\n */\nexport function generateUseDrawerHook<T extends CustomDrawerProps>(DrawerComponent: React.FC<T>) {\n return {\n useDrawer: (options?: UseDrawerOptions) => useDrawer(DrawerComponent, options),\n useGlobalDrawer: (options?: UseDrawerOptions) => useGlobalDrawer(DrawerComponent, options),\n };\n}\n\nexport default useDrawer;\n"]}
1
+ {"version":3,"sources":["../src/AntdOverlayContext.tsx","../src/useOverlay.tsx","../src/useModal.tsx","../src/useDrawer.tsx"],"names":["createContext","useState","useCallback","useMemo","jsxs","useContext","useId","useRef","React","jsx","useEffect"],"mappings":";;;;;;;;;;AAsEA,IAAM,kBAAA,GAAqBA,qBAA8C,IAAI,CAAA;AAiEtE,SAAS,mBAAA,CAAoB;AAAA,EAClC,QAAA;AAAA,EACA,iBAAA;AAAA,EACA;AACF,CAAA,EAA6B;AAE3B,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIC,eAAA,CAA4B,EAAE,CAAA;AAQ5D,EAAA,MAAM,SAAA,GAAYC,kBAAA,CAAY,CAAC,MAAA,KAA4B;AACzD,IAAA,UAAA,CAAW,CAAC,IAAA,KAAS,CAAC,GAAG,IAAA,EAAM,MAAM,CAAC,CAAA;AAAA,EACxC,CAAA,EAAG,EAAE,CAAA;AAQL,EAAA,MAAM,YAAA,GAAeA,kBAAA,CAAY,CAAC,MAAA,KAA4B;AAC5D,IAAA,UAAA,CAAW,CAAC,SAAS,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,KAAM,MAAM,CAAC,CAAA;AAAA,EACvD,CAAA,EAAG,EAAE,CAAA;AAIL,EAAA,MAAM,KAAA,GAAQC,cAAA;AAAA,IACZ,OAAO,EAAE,OAAA,EAAS,SAAA,EAAW,YAAA,EAAc,mBAAmB,kBAAA,EAAmB,CAAA;AAAA,IACjF,CAAC,OAAA,EAAS,SAAA,EAAW,YAAA,EAAc,mBAAmB,kBAAkB;AAAA,GAC1E;AAEA,EAAA,uBACEC,eAAA,CAAC,kBAAA,CAAmB,QAAA,EAAnB,EAA4B,KAAA,EAC1B,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,IAEA;AAAA,GAAA,EACH,CAAA;AAEJ;AAqCO,SAAS,qBAAA,GAAwB;AACtC,EAAA,OAAOC,kBAAW,kBAAkB,CAAA;AACtC;ACbA,IAAM,mBAAA,GAAsB,CAC1B,KAAA,EACA,KAAA,KACM;AACN,EAAA,MAAM,MAAA,GAAS;AAAA,IACb,GAAG,KAAA;AAAA,IACH,MAAM,KAAA,CAAM,IAAA;AAAA,IACZ,aAAa,KAAA,CAAM;AAAA,GACrB;AAGA,EAAA,IAAI,OAAO,QAAA,EAAU;AACnB,IAAA,MAAM,mBAAmB,MAAA,EAAQ,QAAA;AACjC,IAAA,MAAA,CAAO,QAAA,IAAY,CAAC,KAAA,KAAmB;AACrC,MAAA,gBAAA,GAAmB,KAAK,CAAA;AACxB,MAAA,KAAA,CAAM,OAAA,EAAQ;AAAA,IAChB,CAAA,CAAA;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT,CAAA;AAqDO,SAAS,UAAA,CACd,gBAAA,EACA,OAAA,GAAgC,EAAC,EACI;AAErC,EAAA,MAAM;AAAA,IACJ,SAAA,GAAY,IAAA;AAAA,IACZ,SAAA,GAAY,aAAA;AAAA,IACZ,YAAA,GAAe;AAAA,GACjB,GAAI,OAAA;AAGJ,EAAA,MAAM,KAAKC,YAAA,EAAM;AACjB,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA;AAS9B,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIL,gBAAS,KAAK,CAAA;AAUtC,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAIA,gBAAS,KAAK,CAAA;AAMtD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,eAAAA,EAAuC;AAMjE,EAAA,MAAM,YAAA,GAAeM,cAAO,SAAS,CAAA;AACrC,EAAA,YAAA,CAAa,OAAA,GAAU,SAAA;AAWvB,EAAA,MAAM,WAAA,GAAcL,mBAAY,MAAM;AACpC,IAAA,IAAI,aAAa,OAAA,EAAS;AAExB,MAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,IACf,CAAA,MAAO;AAEL,MAAA,eAAA,CAAgB,KAAK,CAAA;AAAA,IACvB;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAQL,EAAA,MAAM,kBAAA,GAAqBA,mBAAY,MAAM;AAC3C,IAAA,IAAI,aAAa,OAAA,EAAS;AACxB,MAAA,eAAA,CAAgB,KAAK,CAAA;AAAA,IACvB;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAWL,EAAA,MAAM,aAAA,GAAgBC,eAAQ,MAAM;AAGlC,IAAA,IAAI,CAAC,YAAA,EAAc,sCAAQK,uBAAAA,CAAM,QAAA,EAAN,IAAoB,GAAK,CAAA;AAGpD,IAAA,MAAM,SAAA,GAAY,aAAa,KAAA,EAAO;AAAA,MACpC,IAAA;AAAA,MACA,OAAA,EAAS,WAAA;AAAA,MACT,cAAA,EAAgB;AAAA,KACjB,CAAA;AAED,IAAA,uBAAOC,cAAA,CAAC,gBAAA,EAAA,EAA4B,GAAG,SAAA,EAAA,EAAT,GAAoB,CAAA;AAAA,EACpD,CAAA,EAAG;AAAA,IACD,YAAA;AAAA,IACA,IAAA;AAAA,IACA,KAAA;AAAA,IACA,GAAA;AAAA,IACA,YAAA;AAAA,IACA,WAAA;AAAA,IACA,kBAAA;AAAA,IACA;AAAA,GACD,CAAA;AAUD,EAAA,MAAM,WAAA,GAAcP,kBAAAA;AAAA,IAClB,CAAC,eAAA,KAAuC;AAEtC,MAAA,eAAA,CAAgB,IAAI,CAAA;AAEpB,MAAA,OAAA,CAAQ,IAAI,CAAA;AAEZ,MAAA,QAAA,CAAS,eAAe,CAAA;AAGxB,MAAA,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,QAKL,MAAA,EAAQ,CAAC,QAAA,KAA+B,QAAA,CAAS,QAAQ,CAAA;AAAA;AAAA;AAAA;AAAA,QAIzD,KAAA,EAAO;AAAA,OACT;AAAA,IACF,CAAA;AAAA,IACA,CAAC,WAAW;AAAA,GACd;AAEA,EAAA,OAAO,CAAC,aAAa,aAAa,CAAA;AACpC;AA6CO,SAAS,gBAAA,CACd,kBACA,OAAA,EACkB;AAElB,EAAA,MAAM,UAAU,qBAAA,EAAsB;AAEtC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KAEF;AAAA,EACF;AAEA,EAAA,MAAM,EAAE,SAAA,EAAW,YAAA,EAAa,GAAI,OAAA;AAGpC,EAAA,MAAM,CAAC,WAAA,EAAa,aAAa,CAAA,GAAI,UAAA,CAAc,kBAAkB,OAAO,CAAA;AAG5E,EAAAQ,gBAAA,CAAU,MAAM;AACd,IAAA,SAAA,CAAU,aAAa,CAAA;AAEvB,IAAA,OAAO,MAAM,aAAa,aAAa,CAAA;AAAA,EACzC,CAAA,EAAG,CAAC,aAAA,EAAe,SAAA,EAAW,YAAY,CAAC,CAAA;AAG3C,EAAA,OAAO,WAAA;AACT;AAmCO,SAAS,sBAAA,CACd,kBACA,cAAA,EACA;AACA,EAAA,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,IAKL,UAAA,EAAY,CAAC,OAAA,KACX,UAAA,CAAW,gBAAA,EAAkB,EAAE,GAAG,cAAA,EAAgB,GAAG,OAAA,EAAS,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMhE,gBAAA,EAAkB,CAAC,OAAA,KACjB,gBAAA,CAAiB,gBAAA,EAAkB,EAAE,GAAG,cAAA,EAAgB,GAAG,OAAA,EAAS;AAAA,GACxE;AACF;ACtdA,IAAM,uBAAA,GAA0B,CAC9B,YAAA,KACG;AACH,EAAA,OAAO,CACL,OACA,KAAA,KACM;AACN,IAAA,MAAM,MAAA,GAAS;AAAA,MACb,GAAG,YAAA;AAAA,MACH,GAAG,KAAA;AAAA,MACH,MAAM,KAAA,CAAM,IAAA;AAAA,MACZ,aAAa,KAAA,CAAM,OAAA;AAAA;AAAA,MAEnB,YAAY,MAAM;AAChB,QAAA,KAAA,EAAO,UAAA,IAAa;AACpB,QAAA,KAAA,CAAM,cAAA,EAAe;AAAA,MACvB;AAAA,KACF;AAGA,IAAA,IAAI,OAAO,QAAA,EAAU;AACnB,MAAA,MAAM,mBAAmB,MAAA,EAAQ,QAAA;AACjC,MAAA,MAAA,CAAO,QAAA,IAAY,CAAC,KAAA,KAAmB;AACrC,QAAA,gBAAA,GAAmB,KAAK,CAAA;AACxB,QAAA,KAAA,CAAM,OAAA,EAAQ;AAAA,MAChB,CAAA,CAAA;AAAA,IACF;AAEA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACF,CAAA;AAiCO,SAAS,QAAA,CACd,gBACA,OAAA,EACqC;AACrC,EAAA,MAAM,UAAU,qBAAA,EAAsB;AACtC,EAAA,MAAM,YAAA,GAAeP,cAAAA;AAAA,IACnB,MAAM,uBAAA,CAA2B,OAAA,EAAS,iBAAiB,CAAA;AAAA,IAC3D,CAAC,SAAS,iBAAiB;AAAA,GAC7B;AACA,EAAA,OAAO,WAAW,cAAA,EAAgB;AAAA,IAChC,GAAG,OAAA;AAAA,IACH,SAAA,EAAW,WAAA;AAAA,IACX;AAAA,GACD,CAAA;AACH;AA4BO,SAAS,cAAA,CACd,gBACA,OAAA,EACkB;AAClB,EAAA,MAAM,UAAU,qBAAA,EAAsB;AACtC,EAAA,MAAM,YAAA,GAAeA,cAAAA;AAAA,IACnB,MAAM,uBAAA,CAA2B,OAAA,EAAS,iBAAiB,CAAA;AAAA,IAC3D,CAAC,SAAS,iBAAiB;AAAA,GAC7B;AACA,EAAA,OAAO,iBAAiB,cAAA,EAAgB;AAAA,IACtC,GAAG,OAAA;AAAA,IACH,SAAA,EAAW,WAAA;AAAA,IACX;AAAA,GACD,CAAA;AACH;AAiCO,SAAS,qBAAiD,cAAA,EAA6B;AAC5F,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,CAAC,OAAA,KAA8B,QAAA,CAAS,gBAAgB,OAAO,CAAA;AAAA,IACzE,cAAA,EAAgB,CAAC,OAAA,KAA8B,cAAA,CAAe,gBAAgB,OAAO;AAAA,GACvF;AACF;AC5JA,IAAM,wBAAA,GAA2B,CAC/B,YAAA,KACG;AACH,EAAA,OAAO,CACL,OACA,KAAA,KACM;AACN,IAAA,MAAM,MAAA,GAAS;AAAA,MACb,GAAG,YAAA;AAAA,MACH,GAAG,KAAA;AAAA,MACH,MAAM,KAAA,CAAM,IAAA;AAAA,MACZ,aAAa,KAAA,CAAM,OAAA;AAAA;AAAA,MAEnB,eAAA,EAAiB,CAAC,IAAA,KAAkB;AAClC,QAAA,KAAA,EAAO,kBAAkB,IAAI,CAAA;AAE7B,QAAA,IAAI,CAAC,IAAA,EAAM;AACT,UAAA,KAAA,CAAM,cAAA,EAAe;AAAA,QACvB;AAAA,MACF;AAAA,KACF;AAGA,IAAA,IAAI,OAAO,QAAA,EAAU;AACnB,MAAA,MAAM,mBAAmB,MAAA,EAAQ,QAAA;AACjC,MAAA,MAAA,CAAO,QAAA,IAAY,CAAC,KAAA,KAAmB;AACrC,QAAA,gBAAA,GAAmB,KAAK,CAAA;AACxB,QAAA,KAAA,CAAM,OAAA,EAAQ;AAAA,MAChB,CAAA,CAAA;AAAA,IACF;AAEA,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACF,CAAA;AA8BO,SAAS,SAAA,CACd,iBACA,OAAA,EACqC;AACrC,EAAA,MAAM,UAAU,qBAAA,EAAsB;AACtC,EAAA,MAAM,YAAA,GAAeA,cAAAA;AAAA,IACnB,MAAM,wBAAA,CAA4B,OAAA,EAAS,kBAAkB,CAAA;AAAA,IAC7D,CAAC,SAAS,kBAAkB;AAAA,GAC9B;AACA,EAAA,OAAO,WAAW,eAAA,EAAiB;AAAA,IACjC,GAAG,OAAA;AAAA,IACH,SAAA,EAAW,YAAA;AAAA,IACX;AAAA,GACD,CAAA;AACH;AA4BO,SAAS,eAAA,CACd,iBACA,OAAA,EACkB;AAClB,EAAA,MAAM,UAAU,qBAAA,EAAsB;AACtC,EAAA,MAAM,YAAA,GAAeA,cAAAA;AAAA,IACnB,MAAM,wBAAA,CAA4B,OAAA,EAAS,kBAAkB,CAAA;AAAA,IAC7D,CAAC,SAAS,kBAAkB;AAAA,GAC9B;AACA,EAAA,OAAO,iBAAiB,eAAA,EAAiB;AAAA,IACvC,GAAG,OAAA;AAAA,IACH,SAAA,EAAW,YAAA;AAAA,IACX;AAAA,GACD,CAAA;AACH;AAiCO,SAAS,sBAAmD,eAAA,EAA8B;AAC/F,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,CAAC,OAAA,KAA+B,SAAA,CAAU,iBAAiB,OAAO,CAAA;AAAA,IAC7E,eAAA,EAAiB,CAAC,OAAA,KAA+B,eAAA,CAAgB,iBAAiB,OAAO;AAAA,GAC3F;AACF","file":"index.cjs","sourcesContent":["/**\n * @file AntdOverlayContext - 全局覆盖层容器 Context\n * @description\n * 提供全局覆盖层的挂载点管理。所有通过 useGlobalOverlay 系列 Hook\n * 创建的覆盖层都会被挂载到 AntdOverlayProvider 下。\n *\n * 工作原理:\n * 1. AntdOverlayProvider 维护一个 holders 数组\n * 2. useGlobalOverlay 通过 useAntdOverlayContext 获取注册方法\n * 3. 覆盖层的 contextHolder 被添加到 holders 数组\n * 4. Provider 在子节点之后统一渲染所有 holders\n *\n * 这种设计的优势:\n * - 覆盖层与业务组件解耦,可在任意位置调用\n * - 统一的挂载点,避免 z-index 混乱\n * - 组件卸载时自动清理对应的覆盖层\n *\n * @example\n * // 在应用入口包裹 Provider\n * function App() {\n * return (\n * <AntdOverlayProvider>\n * <Router>\n * <Routes />\n * </Router>\n * </AntdOverlayProvider>\n * );\n * }\n */\n\nimport { DrawerProps, ModalProps } from 'antd';\nimport React, { createContext, useCallback, useContext, useMemo, useState } from 'react';\n\n// ============================================================================\n// 类型定义\n// ============================================================================\n\nexport type DefaultModalProps = Partial<ModalProps>;\nexport type DefaultDrawerProps = Partial<DrawerProps>;\n\n/**\n * AntdOverlay Context 的值类型\n *\n * @property holders - 当前所有已注册的覆盖层 holder 节点\n * @property addHolder - 注册一个新的 holder 到全局容器\n * @property removeHolder - 从全局容器移除一个已注册的 holder\n */\ninterface AntdOverlayContextValue {\n /** 所有已注册的 holder 节点列表 */\n holders: React.ReactNode[];\n /** 添加 holder 到全局容器 */\n addHolder: (holder: React.ReactNode) => void;\n /** 从全局容器移除 holder */\n removeHolder: (holder: React.ReactNode) => void;\n /** 默认 Modal 属性 */\n defaultModalProps?: DefaultModalProps;\n /** 默认 Drawer 属性 */\n defaultDrawerProps?: DefaultDrawerProps;\n}\n\n// ============================================================================\n// Context 定义\n// ============================================================================\n\n/**\n * AntdOverlay Context\n *\n * 默认值为 null,使用时必须在 AntdOverlayProvider 内部。\n * 如果在 Provider 外部调用 useAntdOverlayContext,会抛出明确的错误提示。\n */\nconst AntdOverlayContext = createContext<AntdOverlayContextValue | null>(null);\n\n// ============================================================================\n// Provider 组件\n// ============================================================================\n\n/**\n * AntdOverlay 容器提供者组件\n *\n * 用于管理全局覆盖层的挂载点。所有通过 useGlobalOverlay、useGlobalModal、\n * useGlobalDrawer 等 Hook 创建的覆盖层都会被挂载到这个 Provider 下。\n *\n * 渲染结构:\n * ```\n * <AntdOverlayContext.Provider>\n * {children} <- 应用的主要内容\n * {holders[0]} <- 全局覆盖层 1\n * {holders[1]} <- 全局覆盖层 2\n * ...\n * </AntdOverlayContext.Provider>\n * ```\n *\n * @param children - 子节点,通常是整个应用\n *\n * @example\n * // 基础用法 - 在应用入口包裹\n * function App() {\n * return (\n * <AntdOverlayProvider>\n * <Router>\n * <Routes />\n * </Router>\n * </AntdOverlayProvider>\n * );\n * }\n *\n * @example\n * // 与其他 Provider 配合使用\n * function App() {\n * return (\n * <ConfigProvider>\n * <AntdOverlayProvider>\n * <App />\n * </AntdOverlayProvider>\n * </ConfigProvider>\n * );\n * }\n */\nexport interface AntdOverlayProviderProps {\n /** 子节点 */\n children: React.ReactNode;\n /** 默认 Modal 属性 */\n defaultModalProps?: DefaultModalProps;\n /** 默认 Drawer 属性 */\n defaultDrawerProps?: DefaultDrawerProps;\n}\n\n\n/**\n * AntdOverlayProvider 组件\n * @param children - 子节点\n * @param defaultModalProps - 默认 Modal 属性\n * @param defaultDrawerProps - 默认 Drawer 属性\n * @returns React.ReactNode\n */\nexport function AntdOverlayProvider({\n children,\n defaultModalProps,\n defaultDrawerProps,\n}: AntdOverlayProviderProps) {\n // 存储所有已注册的 holder 节点\n const [holders, setHolders] = useState<React.ReactNode[]>([]);\n\n /**\n * 添加 holder 到全局容器\n *\n * 使用函数式更新确保并发安全,避免闭包陷阱。\n * 新的 holder 会被追加到数组末尾,因此后添加的覆盖层会显示在上层。\n */\n const addHolder = useCallback((holder: React.ReactNode) => {\n setHolders((prev) => [...prev, holder]);\n }, []);\n\n /**\n * 从全局容器移除 holder\n *\n * 通过引用比较(===)找到并移除对应的 holder。\n * 这要求每次传入的 holder 必须是同一个引用。\n */\n const removeHolder = useCallback((holder: React.ReactNode) => {\n setHolders((prev) => prev.filter((h) => h !== holder));\n }, []);\n\n // 使用 useMemo 优化 Context 值,避免不必要的重渲染\n // 只有当 holders、addHolder 或 removeHolder 变化时才会创建新的值对象\n const value = useMemo(\n () => ({ holders, addHolder, removeHolder, defaultModalProps, defaultDrawerProps }),\n [holders, addHolder, removeHolder, defaultModalProps, defaultDrawerProps],\n );\n\n return (\n <AntdOverlayContext.Provider value={value}>\n {children}\n {/* 在 children 之后渲染所有全局覆盖层 */}\n {holders}\n </AntdOverlayContext.Provider>\n );\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * 获取 AntdOverlay Context 的 Hook\n *\n * 返回全局容器的注册和注销方法,供 useGlobalOverlay 系列 Hook 内部使用。\n *\n * 注意事项:\n * - 必须在 AntdOverlayProvider 内部使用\n * - 如果在 Provider 外部调用,会抛出明确的错误\n * - 主要供库内部使用,一般不需要在业务代码中直接调用\n *\n * @returns AntdOverlayContextValue 包含 holders、addHolder、removeHolder\n * @throws Error 如果不在 AntdOverlayProvider 内部使用\n *\n * @example\n * // 库内部使用示例(useGlobalOverlay 的实现)\n * function useGlobalOverlay(Component, options) {\n * const context = useAntdOverlayContext();\n * if (!context) {\n * throw new Error('useGlobalOverlay must be used within an AntdOverlayProvider. Please wrap your application with <AntdOverlayProvider>.');\n * }\n * const { addHolder, removeHolder } = context;\n * const [open, holder] = useOverlay(Component, options);\n *\n * useEffect(() => {\n * addHolder(holder);\n * return () => removeHolder(holder);\n * }, [holder]);\n *\n * return open;\n * }\n */\nexport function useAntdOverlayContext() {\n return useContext(AntdOverlayContext);\n}\n","/**\n * @file useOverlay - 通用覆盖层管理 Hook\n * @description\n * 提供一个与具体 UI 组件无关的覆盖层(Overlay)管理方案。\n * 支持任意满足 CustomOverlayProps 接口的组件,如 Modal、Drawer、Popover 等。\n *\n * 核心设计理念:\n * 1. 命令式调用 - 通过函数调用打开覆盖层,而非声明式管理 open 状态\n * 2. 动画支持 - 正确处理打开/关闭动画,避免动画未完成就卸载组件\n * 3. 全局挂载 - 支持将覆盖层挂载到全局容器,实现跨组件调用\n * 4. 类型安全 - 完整的 TypeScript 类型支持\n *\n * 架构层次:\n * ┌─────────────────────────────────────────────────────────┐\n * │ useModal / useDrawer │ <- 业务层封装\n * ├─────────────────────────────────────────────────────────┤\n * │ useOverlay / useGlobalOverlay │ <- 核心逻辑层\n * ├─────────────────────────────────────────────────────────┤\n * │ GlobalHolderProvider │ <- 全局容器层\n * └─────────────────────────────────────────────────────────┘\n *\n * @example\n * // 直接使用 useOverlay(不推荐,建议使用 useModal/useDrawer)\n * const [openOverlay, holder] = useOverlay(MyOverlayComponent, {\n * propsAdapter: (props, state) => ({ ...props, visible: state.open }),\n * });\n */\n\nimport React, { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';\n\nimport { useAntdOverlayContext } from './AntdOverlayContext';\n\n// ============================================================================\n// 类型定义\n// ============================================================================\n\n/**\n * 自定义覆盖层组件必须实现的属性接口\n *\n * 这是所有覆盖层组件的基础接口,定义了控制覆盖层所需的最小属性集。\n * 具体的 UI 组件(如 Modal、Drawer)应该扩展此接口。\n *\n * @template T - customOk 回调接收的参数类型,用于传递确认操作的数据\n * @template R - customOk 回调的返回类型,通常为 void\n *\n * @property open - 控制覆盖层的显示/隐藏状态\n * @property customClose - 关闭覆盖层的回调函数,由 useOverlay 注入\n * @property customOk - 确认操作的回调函数,调用后会自动关闭覆盖层\n *\n * @example\n * interface MyOverlayProps extends CustomOverlayProps<{ id: number }> {\n * title: string;\n * data: SomeData;\n * }\n *\n * const MyOverlay: React.FC<MyOverlayProps> = ({\n * open,\n * customClose,\n * customOk,\n * title,\n * data,\n * }) => {\n * const handleConfirm = () => {\n * // 调用 customOk 会自动关闭覆盖层\n * customOk?.({ id: data.id });\n * };\n * return (\n * <Modal open={open} onCancel={customClose} onOk={handleConfirm}>\n * {title}\n * </Modal>\n * );\n * };\n */\nexport interface CustomOverlayProps<T = any, R = void> {\n /** 覆盖层的显示状态 */\n open?: boolean;\n /** 关闭覆盖层的回调,由 useOverlay 自动注入 */\n customClose: () => void;\n /** 确认操作回调,调用后自动关闭覆盖层 */\n customOk?: (value: T) => R;\n}\n\n/**\n * 内部使用的属性类型\n * 排除 customClose,因为它由 useOverlay 自动注入,用户无需传递\n */\ntype InternalProps<T extends CustomOverlayProps> = Omit<T, 'customClose'>;\n\n/**\n * 覆盖层控制器接口\n *\n * 打开覆盖层后返回的控制器对象,用于后续操作(更新属性或关闭)。\n * 使用 readonly 确保方法引用稳定,不会被意外修改。\n *\n * @template T - 覆盖层组件的属性类型\n *\n * @example\n * const controller = openModal({ title: '初始标题' });\n *\n * // 动态更新属性\n * controller.update({ title: '新标题', loading: true });\n *\n * // 编程式关闭\n * controller.close();\n */\nexport interface OverlayController<T extends CustomOverlayProps> {\n /**\n * 更新覆盖层的属性\n * @param props - 新的属性对象,会完全替换之前的属性\n */\n readonly update: (props: InternalProps<T>) => void;\n /**\n * 关闭覆盖层\n * 如果启用了动画,会等待动画结束后再卸载组件\n */\n readonly close: () => void;\n}\n\n/**\n * 覆盖层打开函数的类型定义\n *\n * @template T - 覆盖层组件的属性类型\n * @param initialize - 初始化属性,可选\n * @returns 覆盖层控制器,用于后续的更新和关闭操作\n *\n * @example\n * const openModal: OverlayOpener<MyModalProps> = (props) => {\n * // 返回控制器\n * };\n *\n * // 无参数调用\n * const ctrl1 = openModal();\n *\n * // 带初始属性调用\n * const ctrl2 = openModal({ title: '标题', data: someData });\n */\nexport type OverlayOpener<T extends CustomOverlayProps> = (\n initialize?: InternalProps<T>,\n) => OverlayController<T>;\n\n/**\n * useOverlay Hook 的配置选项\n *\n * @template T - 覆盖层组件的属性类型\n *\n * @property animation - 是否启用动画支持,默认 true\n * - true: 关闭时先设置 open=false,等待动画结束后再卸载组件\n * - false: 关闭时直接卸载组件,适用于无动画的覆盖层\n *\n * @property keyPrefix - React key 的前缀,用于区分不同类型的覆盖层\n * - 默认值: 'use-overlay'\n * - useModal 使用 'use-modal'\n * - useDrawer 使用 'use-drawer'\n *\n * @property propsAdapter - 属性适配器函数\n * 用于将内部状态转换为组件实际需要的属性。\n * 不同的 UI 组件(Modal、Drawer)有不同的动画回调机制,\n * 通过适配器实现统一的接口。\n */\nexport interface UseOverlayOptions<T extends CustomOverlayProps> {\n /** 是否启用关闭动画,默认 true */\n animation?: boolean;\n /** React key 前缀,用于标识覆盖层类型 */\n keyPrefix?: string;\n /**\n * 属性适配器函数\n * @param props - 用户传入的属性\n * @param state - 内部状态,包含 open、onClose、onAnimationEnd\n * @returns 传递给组件的最终属性\n */\n propsAdapter?: (\n props: InternalProps<T> | undefined,\n state: {\n /** 当前的打开状态 */\n open: boolean;\n /** 触发关闭的回调 */\n onClose: () => void;\n /** 动画结束后的回调,用于卸载组件 */\n onAnimationEnd: () => void;\n },\n ) => T;\n}\n\n// ============================================================================\n// 默认属性适配器\n// ============================================================================\n\n/**\n * 默认的属性适配器\n *\n * 提供基本的属性转换逻辑:\n * 1. 将用户传入的 props 与内部状态合并\n * 2. 注入 open 和 customClose\n * 3. 包装 customOk 使其调用后自动关闭覆盖层\n *\n * 注意:这是一个简化的适配器,不处理动画。\n * 对于 Modal 和 Drawer,应该使用各自的专用适配器来处理动画回调。\n *\n * @template T - 覆盖层组件的属性类型\n * @param props - 用户传入的属性\n * @param state - 内部状态\n * @returns 最终传递给组件的属性\n */\nconst defaultPropsAdapter = <T extends CustomOverlayProps>(\n props: InternalProps<T> | undefined,\n state: { open: boolean; onClose: () => void; onAnimationEnd: () => void },\n): T => {\n const result = {\n ...props,\n open: state.open,\n customClose: state.onClose,\n } as unknown as T;\n\n // 包装 customOk,使其调用后自动触发关闭\n if (result.customOk) {\n const originalCustomOk = result?.customOk;\n result.customOk = ((value: unknown) => {\n originalCustomOk?.(value);\n state.onClose();\n }) as T['customOk'];\n }\n\n return result;\n};\n\n// ============================================================================\n// 核心 Hook 实现\n// ============================================================================\n\n/**\n * 覆盖层管理核心 Hook\n *\n * 这是整个库的核心,提供覆盖层的生命周期管理:\n * - 挂载/卸载控制\n * - 打开/关闭状态管理\n * - 动画支持\n * - 属性更新\n *\n * 状态机说明:\n * ```\n * [未挂载] --open()--> [已挂载, open=true] --close()--> [已挂载, open=false] --动画结束--> [未挂载]\n * │\n * └── (animation=false) --> [未挂载]\n * ```\n *\n * @template T - 覆盖层组件的属性类型,必须继承 CustomOverlayProps\n *\n * @param OverlayComponent - 覆盖层组件\n * @param options - 配置选项\n *\n * @returns 元组 [openOverlay, contextHolder]\n * - openOverlay: 打开覆盖层的函数,返回控制器\n * - contextHolder: 需要渲染到组件树中的 React 节点\n *\n * @example\n * function MyComponent() {\n * const [openOverlay, holder] = useOverlay(MyOverlay, {\n * animation: true,\n * propsAdapter: (props, state) => ({\n * ...props,\n * visible: state.open,\n * onClose: state.onClose,\n * afterVisibleChange: (visible) => {\n * if (!visible) state.onAnimationEnd();\n * },\n * }),\n * });\n *\n * return (\n * <>\n * <button onClick={() => openOverlay({ title: '标题' })}>打开</button>\n * {holder}\n * </>\n * );\n * }\n */\nexport function useOverlay<T extends CustomOverlayProps>(\n OverlayComponent: React.FC<T>,\n options: UseOverlayOptions<T> = {},\n): [OverlayOpener<T>, React.ReactNode] {\n // 解构配置选项,设置默认值\n const {\n animation = true,\n keyPrefix = 'use-overlay',\n propsAdapter = defaultPropsAdapter,\n } = options;\n\n // 生成唯一 ID,用于 React key\n const id = useId();\n const key = `${keyPrefix}-${id}`;\n\n // ========== 状态管理 ==========\n\n /**\n * open: 控制覆盖层的显示状态(用于动画)\n * - true: 覆盖层显示\n * - false: 覆盖层隐藏(但可能还在播放关闭动画)\n */\n const [open, setOpen] = useState(false);\n\n /**\n * renderEnable: 控制组件是否挂载到 DOM\n * - true: 组件已挂载\n * - false: 组件已卸载\n *\n * 与 open 分离是为了支持关闭动画:\n * 关闭时先设置 open=false 触发动画,动画结束后再设置 renderEnable=false 卸载组件\n */\n const [renderEnable, setRenderEnable] = useState(false);\n\n /**\n * props: 用户传入的属性\n * 存储最近一次 open 或 update 调用时传入的属性\n */\n const [props, setProps] = useState<InternalProps<T> | undefined>();\n\n /**\n * 使用 ref 存储 animation 配置\n * 避免 animation 变化时重新创建回调函数\n */\n const animationRef = useRef(animation);\n animationRef.current = animation;\n\n // ========== 回调函数 ==========\n\n /**\n * 处理关闭操作\n *\n * 根据是否启用动画采取不同策略:\n * - 启用动画: 仅设置 open=false,等待动画结束后再卸载\n * - 禁用动画: 直接卸载组件\n */\n const handleClose = useCallback(() => {\n if (animationRef.current) {\n // 启用动画时,先触发关闭动画\n setOpen(false);\n } else {\n // 禁用动画时,直接卸载\n setRenderEnable(false);\n }\n }, []);\n\n /**\n * 处理动画结束\n *\n * 由属性适配器在关闭动画结束时调用。\n * 仅在启用动画时执行实际的卸载操作。\n */\n const handleAnimationEnd = useCallback(() => {\n if (animationRef.current) {\n setRenderEnable(false);\n }\n }, []);\n\n // ========== 渲染逻辑 ==========\n\n /**\n * contextHolder: 需要渲染到组件树中的节点\n *\n * 使用 useMemo 优化性能:\n * - 未挂载时返回空 Fragment(保持 key 稳定)\n * - 已挂载时渲染实际组件,通过 propsAdapter 转换属性\n */\n const contextHolder = useMemo(() => {\n // 未挂载时返回带 key 的空 Fragment\n // 保持 key 稳定可以避免不必要的 DOM 操作\n if (!renderEnable) return <React.Fragment key={key} />;\n\n // 通过适配器转换属性\n const realProps = propsAdapter(props, {\n open,\n onClose: handleClose,\n onAnimationEnd: handleAnimationEnd,\n });\n\n return <OverlayComponent key={key} {...realProps} />;\n }, [\n renderEnable,\n open,\n props,\n key,\n propsAdapter,\n handleClose,\n handleAnimationEnd,\n OverlayComponent,\n ]);\n\n // ========== 打开函数 ==========\n\n /**\n * 打开覆盖层的函数\n *\n * @param initializeProps - 初始化属性\n * @returns 控制器对象,包含 update 和 close 方法\n */\n const openOverlay = useCallback(\n (initializeProps?: InternalProps<T>) => {\n // 1. 挂载组件\n setRenderEnable(true);\n // 2. 设置为打开状态(触发打开动画)\n setOpen(true);\n // 3. 存储初始属性\n setProps(initializeProps);\n\n // 返回控制器\n return {\n /**\n * 更新覆盖层属性\n * 注意:这是完全替换,不是合并\n */\n update: (newProps: InternalProps<T>) => setProps(newProps),\n /**\n * 关闭覆盖层\n */\n close: handleClose,\n } as const;\n },\n [handleClose],\n );\n\n return [openOverlay, contextHolder];\n}\n\n/**\n * 全局覆盖层管理 Hook\n *\n * 与 useOverlay 的区别:\n * - useOverlay: 需要手动渲染 contextHolder\n * - useGlobalOverlay: 自动挂载到 AntdOverlayProvider\n *\n * 实现原理:\n * 1. 内部调用 useOverlay 获取 openOverlay 和 contextHolder\n * 2. 使用 useEffect 将 contextHolder 注册到全局容器\n * 3. 组件卸载时自动从全局容器移除\n *\n * 使用前提:\n * - 必须在组件树的上层包裹 AntdOverlayProvider\n *\n * @template T - 覆盖层组件的属性类型\n *\n * @param OverlayComponent - 覆盖层组件\n * @param options - 配置选项\n *\n * @returns 打开覆盖层的函数(无需再渲染 holder)\n *\n * @example\n * // 1. 先在应用入口包裹 Provider\n * function App() {\n * return (\n * <AntdOverlayProvider>\n * <YourApp />\n * </AntdOverlayProvider>\n * );\n * }\n *\n * // 2. 在任意组件中使用\n * function AnyComponent() {\n * const openOverlay = useGlobalOverlay(MyOverlay);\n *\n * return (\n * <button onClick={() => openOverlay({ data: someData })}>\n * 打开全局覆盖层\n * </button>\n * );\n * }\n */\nexport function useGlobalOverlay<T extends CustomOverlayProps>(\n OverlayComponent: React.FC<T>,\n options?: UseOverlayOptions<T>,\n): OverlayOpener<T> {\n // 获取全局容器的注册/注销方法\n const context = useAntdOverlayContext();\n\n if (!context) {\n throw new Error(\n 'useGlobalOverlay must be used within an AntdOverlayProvider. ' +\n 'Please wrap your application with <AntdOverlayProvider>.'\n );\n }\n\n const { addHolder, removeHolder } = context;\n\n // 使用基础 useOverlay 获取功能\n const [openOverlay, contextHolder] = useOverlay<T>(OverlayComponent, options);\n\n // 将 contextHolder 注册到全局容器\n useEffect(() => {\n addHolder(contextHolder);\n // 清理函数:组件卸载时从全局容器移除\n return () => removeHolder(contextHolder);\n }, [contextHolder, addHolder, removeHolder]);\n\n // 仅返回 openOverlay,holder 已自动挂载\n return openOverlay;\n}\n\n// ============================================================================\n// 工厂函数\n// ============================================================================\n\n/**\n * 生成绑定了特定组件的 Hook 工厂函数\n *\n * 当某个覆盖层组件在多处使用时,可以使用此函数生成专用 Hook,\n * 避免每次使用都需要传入组件引用。\n *\n * @template T - 覆盖层组件的属性类型\n *\n * @param OverlayComponent - 覆盖层组件\n * @param defaultOptions - 默认配置选项,会与调用时的选项合并\n *\n * @returns 包含 useOverlay 和 useGlobalOverlay 的对象\n *\n * @example\n * // 创建专用 Hook\n * const {\n * useOverlay: useMyOverlay,\n * useGlobalOverlay: useGlobalMyOverlay,\n * } = generateUseOverlayHook(MyOverlayComponent, {\n * animation: true,\n * propsAdapter: myAdapter,\n * });\n *\n * // 使用专用 Hook(无需再传组件)\n * function SomeComponent() {\n * const openOverlay = useGlobalMyOverlay();\n * return <button onClick={() => openOverlay()}>打开</button>;\n * }\n */\nexport function generateUseOverlayHook<T extends CustomOverlayProps>(\n OverlayComponent: React.FC<T>,\n defaultOptions?: UseOverlayOptions<T>,\n) {\n return {\n /**\n * 绑定了特定组件的 useOverlay\n * @param options - 配置选项,会与 defaultOptions 合并\n */\n useOverlay: (options?: UseOverlayOptions<T>) =>\n useOverlay(OverlayComponent, { ...defaultOptions, ...options }),\n\n /**\n * 绑定了特定组件的 useGlobalOverlay\n * @param options - 配置选项,会与 defaultOptions 合并\n */\n useGlobalOverlay: (options?: UseOverlayOptions<T>) =>\n useGlobalOverlay(OverlayComponent, { ...defaultOptions, ...options }),\n };\n}\n","/**\n * @file useModal - Ant Design Modal 管理 Hook\n * @description\n * 基于 useOverlay 封装的 Modal 专用管理方案。\n * 提供命令式 API 来控制 Modal 的显示、隐藏和属性更新。\n *\n * 主要特性:\n * - 命令式调用,无需管理 visible 状态\n * - 支持动态更新 Modal 属性\n * - 支持全局挂载,跨组件调用\n * - 正确处理关闭动画(通过 afterClose 回调)\n *\n * @example\n * // 基础用法\n * const [openModal, holder] = useModal(MyModal);\n *\n * // 全局用法\n * const openModal = useGlobalModal(MyModal);\n *\n * // 为特定组件生成专用 Hook\n * const { useGlobalModal: useGlobalMyModal } = generateUseModalHook(MyModal);\n */\n\nimport { ModalProps } from 'antd';\nimport { useMemo } from 'react';\n\nimport { useAntdOverlayContext, DefaultModalProps } from './AntdOverlayContext';\nimport {\n CustomOverlayProps,\n OverlayOpener,\n useGlobalOverlay,\n useOverlay,\n UseOverlayOptions,\n} from './useOverlay';\n\n/**\n * 自定义 Modal 组件的属性接口\n * 继承 Ant Design ModalProps 并添加自定义属性\n *\n * @template T - customOk 回调的参数类型\n * @template R - customOk 回调的返回类型\n *\n * @example\n * const MyModal: React.FC<CustomModalProps<{ name: string }>> = ({\n * open,\n * customClose,\n * customOk,\n * }) => {\n * return (\n * <Modal open={open} onCancel={customClose} onOk={() => customOk?.({ name: 'test' })}>\n * 内容\n * </Modal>\n * );\n * };\n */\nexport interface CustomModalProps<T = any, R = void> extends ModalProps, CustomOverlayProps<T, R> {}\n\n/**\n * useModal Hook 的配置选项\n * 排除了 propsAdapter 和 keyPrefix,这些由内部自动处理\n */\nexport type UseModalOptions = Omit<\n UseOverlayOptions<CustomModalProps>,\n 'propsAdapter' | 'keyPrefix'\n>;\n\n/**\n * 创建 Modal 专用的属性适配器\n *\n * 主要职责:\n * 1. 注入 open 和 customClose\n * 2. 包装 afterClose 以处理动画结束\n * 3. 包装 customOk 以实现自动关闭\n *\n * @template T - Modal 组件的属性类型\n * @param defaultProps - 默认 Modal 属性\n * @returns 属性适配器函数\n */\nconst createModalPropsAdapter = <T extends CustomModalProps>(\n defaultProps?: DefaultModalProps,\n) => {\n return (\n props: Omit<T, 'customClose'> | undefined,\n state: { open: boolean; onClose: () => void; onAnimationEnd: () => void },\n ): T => {\n const result = {\n ...defaultProps,\n ...props,\n open: state.open,\n customClose: state.onClose,\n // 在 Modal 关闭动画结束后触发,用于卸载组件\n afterClose: () => {\n props?.afterClose?.();\n state.onAnimationEnd();\n },\n } as unknown as T;\n\n // 包装 customOk,调用后自动关闭 Modal\n if (result.customOk) {\n const originalCustomOk = result?.customOk;\n result.customOk = ((value: unknown) => {\n originalCustomOk?.(value);\n state.onClose();\n }) as T['customOk'];\n }\n\n return result;\n };\n};\n\n/**\n * Modal 管理 Hook\n *\n * @template T - Modal 组件的属性类型,必须继承 CustomModalProps\n *\n * @param ModalComponent - Modal 组件\n * @param options - 配置选项\n *\n * @returns 元组 [openModal, contextHolder]\n * - openModal: 打开 Modal 的函数\n * - contextHolder: 需要渲染到组件树中的 React 节点\n *\n * @example\n * function MyPage() {\n * const [openModal, modalHolder] = useModal(ConfirmModal);\n *\n * const handleDelete = () => {\n * openModal({\n * title: '确认删除',\n * content: '删除后无法恢复',\n * });\n * };\n *\n * return (\n * <>\n * <button onClick={handleDelete}>删除</button>\n * {modalHolder}\n * </>\n * );\n * }\n */\nexport function useModal<T extends CustomModalProps>(\n ModalComponent: React.FC<T>,\n options?: UseModalOptions,\n): [OverlayOpener<T>, React.ReactNode] {\n const context = useAntdOverlayContext();\n const propsAdapter = useMemo(\n () => createModalPropsAdapter<T>(context?.defaultModalProps),\n [context?.defaultModalProps],\n );\n return useOverlay(ModalComponent, {\n ...options,\n keyPrefix: 'use-modal',\n propsAdapter,\n });\n}\n\n/**\n * 全局 Modal 管理 Hook\n *\n * 与 useModal 的区别:\n * - 无需手动渲染 contextHolder\n * - Modal 会自动挂载到全局容器\n * - 适合需要跨组件调用的场景\n *\n * @template T - Modal 组件的属性类型\n *\n * @param ModalComponent - Modal 组件\n * @param options - 配置选项\n *\n * @returns 打开 Modal 的函数\n *\n * @example\n * function DeleteButton() {\n * const openConfirm = useGlobalModal(ConfirmModal);\n *\n * return (\n * <button onClick={() => openConfirm({ title: '确认删除?' })}>\n * 删除\n * </button>\n * );\n * }\n */\nexport function useGlobalModal<T extends CustomModalProps>(\n ModalComponent: React.FC<T>,\n options?: UseModalOptions,\n): OverlayOpener<T> {\n const context = useAntdOverlayContext();\n const propsAdapter = useMemo(\n () => createModalPropsAdapter<T>(context?.defaultModalProps),\n [context?.defaultModalProps],\n );\n return useGlobalOverlay(ModalComponent, {\n ...options,\n keyPrefix: 'use-modal',\n propsAdapter,\n });\n}\n\n/**\n * 生成绑定了特定 Modal 组件的 Hook 工厂函数\n *\n * 适用场景:\n * - 某个 Modal 在多处使用\n * - 希望简化调用代码\n * - 需要统一管理某个 Modal 的默认配置\n *\n * @template T - Modal 组件的属性类型\n *\n * @param ModalComponent - Modal 组件\n *\n * @returns 包含 useModal 和 useGlobalModal 的对象\n *\n * @example\n * // 在 Modal 组件文件中导出专用 Hook\n * const ConfirmModal: React.FC<CustomModalProps> = (props) => {\n * // ...\n * };\n *\n * export const {\n * useModal: useConfirmModal,\n * useGlobalModal: useGlobalConfirmModal,\n * } = generateUseModalHook(ConfirmModal);\n *\n * // 在其他组件中使用\n * function MyPage() {\n * const openConfirm = useGlobalConfirmModal();\n * return <button onClick={() => openConfirm()}>确认</button>;\n * }\n */\nexport function generateUseModalHook<T extends CustomModalProps>(ModalComponent: React.FC<T>) {\n return {\n useModal: (options?: UseModalOptions) => useModal(ModalComponent, options),\n useGlobalModal: (options?: UseModalOptions) => useGlobalModal(ModalComponent, options),\n };\n}\n\nexport default useModal;\n","/**\n * @file useDrawer - Ant Design Drawer 管理 Hook\n * @description\n * 基于 useOverlay 封装的 Drawer 专用管理方案。\n * 提供命令式 API 来控制 Drawer 的显示、隐藏和属性更新。\n *\n * 主要特性:\n * - 命令式调用,无需管理 open 状态\n * - 支持动态更新 Drawer 属性\n * - 支持全局挂载,跨组件调用\n * - 正确处理关闭动画(通过 afterOpenChange 回调)\n *\n * @example\n * // 基础用法\n * const [openDrawer, holder] = useDrawer(MyDrawer);\n *\n * // 全局用法\n * const openDrawer = useGlobalDrawer(MyDrawer);\n *\n * // 为特定组件生成专用 Hook\n * const { useGlobalDrawer: useGlobalMyDrawer } = generateUseDrawerHook(MyDrawer);\n */\n\nimport { DrawerProps } from 'antd';\nimport { useMemo } from 'react';\n\nimport { useAntdOverlayContext, DefaultDrawerProps } from './AntdOverlayContext';\nimport {\n CustomOverlayProps,\n OverlayOpener,\n useGlobalOverlay,\n useOverlay,\n UseOverlayOptions,\n} from './useOverlay';\n\n/**\n * 自定义 Drawer 组件的属性接口\n * 继承 Ant Design DrawerProps 并添加自定义属性\n *\n * @template T - customOk 回调的参数类型\n * @template R - customOk 回调的返回类型\n *\n * @example\n * const MyDrawer: React.FC<CustomDrawerProps<{ id: number }>> = ({\n * open,\n * customClose,\n * customOk,\n * }) => {\n * return (\n * <Drawer open={open} onClose={customClose}>\n * <Button onClick={() => customOk?.({ id: 1 })}>确认</Button>\n * </Drawer>\n * );\n * };\n */\nexport interface CustomDrawerProps<T = any, R = void>\n extends DrawerProps, CustomOverlayProps<T, R> {}\n\n/**\n * useDrawer Hook 的配置选项\n * 排除了 propsAdapter 和 keyPrefix,这些由内部自动处理\n */\nexport type UseDrawerOptions = Omit<\n UseOverlayOptions<CustomDrawerProps>,\n 'propsAdapter' | 'keyPrefix'\n>;\n\n/**\n * 创建 Drawer 专用的属性适配器\n *\n * 主要职责:\n * 1. 注入 open 和 customClose\n * 2. 包装 afterOpenChange 以处理动画结束\n * 3. 包装 customOk 以实现自动关闭\n *\n * @template T - Drawer 组件的属性类型\n * @param defaultProps - 默认 Drawer 属性\n * @returns 属性适配器函数\n */\nconst createDrawerPropsAdapter = <T extends CustomDrawerProps>(\n defaultProps?: DefaultDrawerProps,\n) => {\n return (\n props: Omit<T, 'customClose'> | undefined,\n state: { open: boolean; onClose: () => void; onAnimationEnd: () => void },\n ): T => {\n const result = {\n ...defaultProps,\n ...props,\n open: state.open,\n customClose: state.onClose,\n // Drawer 的动画回调,打开和关闭时都会触发\n afterOpenChange: (open: boolean) => {\n props?.afterOpenChange?.(open);\n // 仅在关闭动画结束时触发卸载\n if (!open) {\n state.onAnimationEnd();\n }\n },\n } as unknown as T;\n\n // 包装 customOk,调用后自动关闭 Drawer\n if (result.customOk) {\n const originalCustomOk = result?.customOk;\n result.customOk = ((value: unknown) => {\n originalCustomOk?.(value);\n state.onClose();\n }) as T['customOk'];\n }\n\n return result;\n };\n};\n\n/**\n * Drawer 管理 Hook\n *\n * @template T - Drawer 组件的属性类型,必须继承 CustomDrawerProps\n *\n * @param DrawerComponent - Drawer 组件\n * @param options - 配置选项\n *\n * @returns 元组 [openDrawer, contextHolder]\n * - openDrawer: 打开 Drawer 的函数\n * - contextHolder: 需要渲染到组件树中的 React 节点\n *\n * @example\n * function MyPage() {\n * const [openDrawer, drawerHolder] = useDrawer(UserDetailDrawer);\n *\n * const handleViewUser = (userId: number) => {\n * openDrawer({ userId, title: '用户详情' });\n * };\n *\n * return (\n * <>\n * <button onClick={() => handleViewUser(1)}>查看用户</button>\n * {drawerHolder}\n * </>\n * );\n * }\n */\nexport function useDrawer<T extends CustomDrawerProps>(\n DrawerComponent: React.FC<T>,\n options?: UseDrawerOptions,\n): [OverlayOpener<T>, React.ReactNode] {\n const context = useAntdOverlayContext();\n const propsAdapter = useMemo(\n () => createDrawerPropsAdapter<T>(context?.defaultDrawerProps),\n [context?.defaultDrawerProps],\n );\n return useOverlay(DrawerComponent, {\n ...options,\n keyPrefix: 'use-drawer',\n propsAdapter,\n });\n}\n\n/**\n * 全局 Drawer 管理 Hook\n *\n * 与 useDrawer 的区别:\n * - 无需手动渲染 contextHolder\n * - Drawer 会自动挂载到全局容器\n * - 适合需要跨组件调用的场景\n *\n * @template T - Drawer 组件的属性类型\n *\n * @param DrawerComponent - Drawer 组件\n * @param options - 配置选项\n *\n * @returns 打开 Drawer 的函数\n *\n * @example\n * function UserCard({ userId }: { userId: number }) {\n * const openDetail = useGlobalDrawer(UserDetailDrawer);\n *\n * return (\n * <Card onClick={() => openDetail({ userId })}>\n * 查看详情\n * </Card>\n * );\n * }\n */\nexport function useGlobalDrawer<T extends CustomDrawerProps>(\n DrawerComponent: React.FC<T>,\n options?: UseDrawerOptions,\n): OverlayOpener<T> {\n const context = useAntdOverlayContext();\n const propsAdapter = useMemo(\n () => createDrawerPropsAdapter<T>(context?.defaultDrawerProps),\n [context?.defaultDrawerProps],\n );\n return useGlobalOverlay(DrawerComponent, {\n ...options,\n keyPrefix: 'use-drawer',\n propsAdapter,\n });\n}\n\n/**\n * 生成绑定了特定 Drawer 组件的 Hook 工厂函数\n *\n * 适用场景:\n * - 某个 Drawer 在多处使用\n * - 希望简化调用代码\n * - 需要统一管理某个 Drawer 的默认配置\n *\n * @template T - Drawer 组件的属性类型\n *\n * @param DrawerComponent - Drawer 组件\n *\n * @returns 包含 useDrawer 和 useGlobalDrawer 的对象\n *\n * @example\n * // 在 Drawer 组件文件中导出专用 Hook\n * const ProjectMemberDrawer: React.FC<CustomDrawerProps> = (props) => {\n * // ...\n * };\n *\n * export const {\n * useDrawer: useProjectMemberDrawer,\n * useGlobalDrawer: useGlobalProjectMemberDrawer,\n * } = generateUseDrawerHook(ProjectMemberDrawer);\n *\n * // 在其他组件中使用\n * function ProjectPage() {\n * const openMemberDrawer = useGlobalProjectMemberDrawer();\n * return <button onClick={() => openMemberDrawer()}>管理成员</button>;\n * }\n */\nexport function generateUseDrawerHook<T extends CustomDrawerProps>(DrawerComponent: React.FC<T>) {\n return {\n useDrawer: (options?: UseDrawerOptions) => useDrawer(DrawerComponent, options),\n useGlobalDrawer: (options?: UseDrawerOptions) => useGlobalDrawer(DrawerComponent, options),\n };\n}\n\nexport default useDrawer;\n"]}
package/dist/index.d.cts CHANGED
@@ -1,8 +1,10 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ModalProps, DrawerProps } from 'antd';
2
3
  import * as React$1 from 'react';
3
4
  import React__default from 'react';
4
- import { ModalProps, DrawerProps } from 'antd';
5
5
 
6
+ type DefaultModalProps = Partial<ModalProps>;
7
+ type DefaultDrawerProps = Partial<DrawerProps>;
6
8
  /**
7
9
  * AntdOverlay Context 的值类型
8
10
  *
@@ -17,6 +19,10 @@ interface AntdOverlayContextValue {
17
19
  addHolder: (holder: React__default.ReactNode) => void;
18
20
  /** 从全局容器移除 holder */
19
21
  removeHolder: (holder: React__default.ReactNode) => void;
22
+ /** 默认 Modal 属性 */
23
+ defaultModalProps?: DefaultModalProps;
24
+ /** 默认 Drawer 属性 */
25
+ defaultDrawerProps?: DefaultDrawerProps;
20
26
  }
21
27
  /**
22
28
  * AntdOverlay 容器提供者组件
@@ -60,9 +66,22 @@ interface AntdOverlayContextValue {
60
66
  * );
61
67
  * }
62
68
  */
63
- declare function AntdOverlayProvider({ children }: {
69
+ interface AntdOverlayProviderProps {
70
+ /** 子节点 */
64
71
  children: React__default.ReactNode;
65
- }): react_jsx_runtime.JSX.Element;
72
+ /** 默认 Modal 属性 */
73
+ defaultModalProps?: DefaultModalProps;
74
+ /** 默认 Drawer 属性 */
75
+ defaultDrawerProps?: DefaultDrawerProps;
76
+ }
77
+ /**
78
+ * AntdOverlayProvider 组件
79
+ * @param children - 子节点
80
+ * @param defaultModalProps - 默认 Modal 属性
81
+ * @param defaultDrawerProps - 默认 Drawer 属性
82
+ * @returns React.ReactNode
83
+ */
84
+ declare function AntdOverlayProvider({ children, defaultModalProps, defaultDrawerProps, }: AntdOverlayProviderProps): react_jsx_runtime.JSX.Element;
66
85
  /**
67
86
  * 获取 AntdOverlay Context 的 Hook
68
87
  *
@@ -79,7 +98,11 @@ declare function AntdOverlayProvider({ children }: {
79
98
  * @example
80
99
  * // 库内部使用示例(useGlobalOverlay 的实现)
81
100
  * function useGlobalOverlay(Component, options) {
82
- * const { addHolder, removeHolder } = useAntdOverlayContext();
101
+ * const context = useAntdOverlayContext();
102
+ * if (!context) {
103
+ * throw new Error('useGlobalOverlay must be used within an AntdOverlayProvider. Please wrap your application with <AntdOverlayProvider>.');
104
+ * }
105
+ * const { addHolder, removeHolder } = context;
83
106
  * const [open, holder] = useOverlay(Component, options);
84
107
  *
85
108
  * useEffect(() => {
@@ -90,7 +113,7 @@ declare function AntdOverlayProvider({ children }: {
90
113
  * return open;
91
114
  * }
92
115
  */
93
- declare function useAntdOverlayContext(): AntdOverlayContextValue;
116
+ declare function useAntdOverlayContext(): AntdOverlayContextValue | null;
94
117
 
95
118
  /**
96
119
  * @file useOverlay - 通用覆盖层管理 Hook
@@ -632,4 +655,4 @@ declare function generateUseDrawerHook<T extends CustomDrawerProps>(DrawerCompon
632
655
  useGlobalDrawer: (options?: UseDrawerOptions) => OverlayOpener<T>;
633
656
  };
634
657
 
635
- export { AntdOverlayProvider, type CustomDrawerProps, type CustomModalProps, type CustomOverlayProps, type OverlayController, type OverlayOpener, type UseDrawerOptions, type UseModalOptions, type UseOverlayOptions, generateUseDrawerHook, generateUseModalHook, generateUseOverlayHook, useAntdOverlayContext, useDrawer, useGlobalDrawer, useGlobalModal, useGlobalOverlay, useModal, useOverlay };
658
+ export { AntdOverlayProvider, type AntdOverlayProviderProps, type CustomDrawerProps, type CustomModalProps, type CustomOverlayProps, type DefaultDrawerProps, type DefaultModalProps, type OverlayController, type OverlayOpener, type UseDrawerOptions, type UseModalOptions, type UseOverlayOptions, generateUseDrawerHook, generateUseModalHook, generateUseOverlayHook, useAntdOverlayContext, useDrawer, useGlobalDrawer, useGlobalModal, useGlobalOverlay, useModal, useOverlay };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ModalProps, DrawerProps } from 'antd';
2
3
  import * as React$1 from 'react';
3
4
  import React__default from 'react';
4
- import { ModalProps, DrawerProps } from 'antd';
5
5
 
6
+ type DefaultModalProps = Partial<ModalProps>;
7
+ type DefaultDrawerProps = Partial<DrawerProps>;
6
8
  /**
7
9
  * AntdOverlay Context 的值类型
8
10
  *
@@ -17,6 +19,10 @@ interface AntdOverlayContextValue {
17
19
  addHolder: (holder: React__default.ReactNode) => void;
18
20
  /** 从全局容器移除 holder */
19
21
  removeHolder: (holder: React__default.ReactNode) => void;
22
+ /** 默认 Modal 属性 */
23
+ defaultModalProps?: DefaultModalProps;
24
+ /** 默认 Drawer 属性 */
25
+ defaultDrawerProps?: DefaultDrawerProps;
20
26
  }
21
27
  /**
22
28
  * AntdOverlay 容器提供者组件
@@ -60,9 +66,22 @@ interface AntdOverlayContextValue {
60
66
  * );
61
67
  * }
62
68
  */
63
- declare function AntdOverlayProvider({ children }: {
69
+ interface AntdOverlayProviderProps {
70
+ /** 子节点 */
64
71
  children: React__default.ReactNode;
65
- }): react_jsx_runtime.JSX.Element;
72
+ /** 默认 Modal 属性 */
73
+ defaultModalProps?: DefaultModalProps;
74
+ /** 默认 Drawer 属性 */
75
+ defaultDrawerProps?: DefaultDrawerProps;
76
+ }
77
+ /**
78
+ * AntdOverlayProvider 组件
79
+ * @param children - 子节点
80
+ * @param defaultModalProps - 默认 Modal 属性
81
+ * @param defaultDrawerProps - 默认 Drawer 属性
82
+ * @returns React.ReactNode
83
+ */
84
+ declare function AntdOverlayProvider({ children, defaultModalProps, defaultDrawerProps, }: AntdOverlayProviderProps): react_jsx_runtime.JSX.Element;
66
85
  /**
67
86
  * 获取 AntdOverlay Context 的 Hook
68
87
  *
@@ -79,7 +98,11 @@ declare function AntdOverlayProvider({ children }: {
79
98
  * @example
80
99
  * // 库内部使用示例(useGlobalOverlay 的实现)
81
100
  * function useGlobalOverlay(Component, options) {
82
- * const { addHolder, removeHolder } = useAntdOverlayContext();
101
+ * const context = useAntdOverlayContext();
102
+ * if (!context) {
103
+ * throw new Error('useGlobalOverlay must be used within an AntdOverlayProvider. Please wrap your application with <AntdOverlayProvider>.');
104
+ * }
105
+ * const { addHolder, removeHolder } = context;
83
106
  * const [open, holder] = useOverlay(Component, options);
84
107
  *
85
108
  * useEffect(() => {
@@ -90,7 +113,7 @@ declare function AntdOverlayProvider({ children }: {
90
113
  * return open;
91
114
  * }
92
115
  */
93
- declare function useAntdOverlayContext(): AntdOverlayContextValue;
116
+ declare function useAntdOverlayContext(): AntdOverlayContextValue | null;
94
117
 
95
118
  /**
96
119
  * @file useOverlay - 通用覆盖层管理 Hook
@@ -632,4 +655,4 @@ declare function generateUseDrawerHook<T extends CustomDrawerProps>(DrawerCompon
632
655
  useGlobalDrawer: (options?: UseDrawerOptions) => OverlayOpener<T>;
633
656
  };
634
657
 
635
- export { AntdOverlayProvider, type CustomDrawerProps, type CustomModalProps, type CustomOverlayProps, type OverlayController, type OverlayOpener, type UseDrawerOptions, type UseModalOptions, type UseOverlayOptions, generateUseDrawerHook, generateUseModalHook, generateUseOverlayHook, useAntdOverlayContext, useDrawer, useGlobalDrawer, useGlobalModal, useGlobalOverlay, useModal, useOverlay };
658
+ export { AntdOverlayProvider, type AntdOverlayProviderProps, type CustomDrawerProps, type CustomModalProps, type CustomOverlayProps, type DefaultDrawerProps, type DefaultModalProps, type OverlayController, type OverlayOpener, type UseDrawerOptions, type UseModalOptions, type UseOverlayOptions, generateUseDrawerHook, generateUseModalHook, generateUseOverlayHook, useAntdOverlayContext, useDrawer, useGlobalDrawer, useGlobalModal, useGlobalOverlay, useModal, useOverlay };
package/dist/index.js CHANGED
@@ -3,7 +3,11 @@ import { jsxs, jsx } from 'react/jsx-runtime';
3
3
 
4
4
  // src/AntdOverlayContext.tsx
5
5
  var AntdOverlayContext = createContext(null);
6
- function AntdOverlayProvider({ children }) {
6
+ function AntdOverlayProvider({
7
+ children,
8
+ defaultModalProps,
9
+ defaultDrawerProps
10
+ }) {
7
11
  const [holders, setHolders] = useState([]);
8
12
  const addHolder = useCallback((holder) => {
9
13
  setHolders((prev) => [...prev, holder]);
@@ -12,8 +16,8 @@ function AntdOverlayProvider({ children }) {
12
16
  setHolders((prev) => prev.filter((h) => h !== holder));
13
17
  }, []);
14
18
  const value = useMemo(
15
- () => ({ holders, addHolder, removeHolder }),
16
- [holders, addHolder, removeHolder]
19
+ () => ({ holders, addHolder, removeHolder, defaultModalProps, defaultDrawerProps }),
20
+ [holders, addHolder, removeHolder, defaultModalProps, defaultDrawerProps]
17
21
  );
18
22
  return /* @__PURE__ */ jsxs(AntdOverlayContext.Provider, { value, children: [
19
23
  children,
@@ -21,13 +25,7 @@ function AntdOverlayProvider({ children }) {
21
25
  ] });
22
26
  }
23
27
  function useAntdOverlayContext() {
24
- const context = useContext(AntdOverlayContext);
25
- if (!context) {
26
- throw new Error(
27
- "useAntdOverlayContext must be used within an AntdOverlayProvider. Please wrap your application with <AntdOverlayProvider>."
28
- );
29
- }
30
- return context;
28
+ return useContext(AntdOverlayContext);
31
29
  }
32
30
  var defaultPropsAdapter = (props, state) => {
33
31
  const result = {
@@ -109,7 +107,13 @@ function useOverlay(OverlayComponent, options = {}) {
109
107
  return [openOverlay, contextHolder];
110
108
  }
111
109
  function useGlobalOverlay(OverlayComponent, options) {
112
- const { addHolder, removeHolder } = useAntdOverlayContext();
110
+ const context = useAntdOverlayContext();
111
+ if (!context) {
112
+ throw new Error(
113
+ "useGlobalOverlay must be used within an AntdOverlayProvider. Please wrap your application with <AntdOverlayProvider>."
114
+ );
115
+ }
116
+ const { addHolder, removeHolder } = context;
113
117
  const [openOverlay, contextHolder] = useOverlay(OverlayComponent, options);
114
118
  useEffect(() => {
115
119
  addHolder(contextHolder);
@@ -131,11 +135,10 @@ function generateUseOverlayHook(OverlayComponent, defaultOptions) {
131
135
  useGlobalOverlay: (options) => useGlobalOverlay(OverlayComponent, { ...defaultOptions, ...options })
132
136
  };
133
137
  }
134
- var createModalPropsAdapter = () => {
138
+ var createModalPropsAdapter = (defaultProps) => {
135
139
  return (props, state) => {
136
140
  const result = {
137
- maskClosable: false,
138
- // 默认禁止点击遮罩关闭
141
+ ...defaultProps,
139
142
  ...props,
140
143
  open: state.open,
141
144
  customClose: state.onClose,
@@ -156,7 +159,11 @@ var createModalPropsAdapter = () => {
156
159
  };
157
160
  };
158
161
  function useModal(ModalComponent, options) {
159
- const propsAdapter = useMemo(() => createModalPropsAdapter(), []);
162
+ const context = useAntdOverlayContext();
163
+ const propsAdapter = useMemo(
164
+ () => createModalPropsAdapter(context?.defaultModalProps),
165
+ [context?.defaultModalProps]
166
+ );
160
167
  return useOverlay(ModalComponent, {
161
168
  ...options,
162
169
  keyPrefix: "use-modal",
@@ -164,7 +171,11 @@ function useModal(ModalComponent, options) {
164
171
  });
165
172
  }
166
173
  function useGlobalModal(ModalComponent, options) {
167
- const propsAdapter = useMemo(() => createModalPropsAdapter(), []);
174
+ const context = useAntdOverlayContext();
175
+ const propsAdapter = useMemo(
176
+ () => createModalPropsAdapter(context?.defaultModalProps),
177
+ [context?.defaultModalProps]
178
+ );
168
179
  return useGlobalOverlay(ModalComponent, {
169
180
  ...options,
170
181
  keyPrefix: "use-modal",
@@ -177,11 +188,10 @@ function generateUseModalHook(ModalComponent) {
177
188
  useGlobalModal: (options) => useGlobalModal(ModalComponent, options)
178
189
  };
179
190
  }
180
- var createDrawerPropsAdapter = () => {
191
+ var createDrawerPropsAdapter = (defaultProps) => {
181
192
  return (props, state) => {
182
193
  const result = {
183
- maskClosable: false,
184
- // 默认禁止点击遮罩关闭
194
+ ...defaultProps,
185
195
  ...props,
186
196
  open: state.open,
187
197
  customClose: state.onClose,
@@ -204,7 +214,11 @@ var createDrawerPropsAdapter = () => {
204
214
  };
205
215
  };
206
216
  function useDrawer(DrawerComponent, options) {
207
- const propsAdapter = useMemo(() => createDrawerPropsAdapter(), []);
217
+ const context = useAntdOverlayContext();
218
+ const propsAdapter = useMemo(
219
+ () => createDrawerPropsAdapter(context?.defaultDrawerProps),
220
+ [context?.defaultDrawerProps]
221
+ );
208
222
  return useOverlay(DrawerComponent, {
209
223
  ...options,
210
224
  keyPrefix: "use-drawer",
@@ -212,7 +226,11 @@ function useDrawer(DrawerComponent, options) {
212
226
  });
213
227
  }
214
228
  function useGlobalDrawer(DrawerComponent, options) {
215
- const propsAdapter = useMemo(() => createDrawerPropsAdapter(), []);
229
+ const context = useAntdOverlayContext();
230
+ const propsAdapter = useMemo(
231
+ () => createDrawerPropsAdapter(context?.defaultDrawerProps),
232
+ [context?.defaultDrawerProps]
233
+ );
216
234
  return useGlobalOverlay(DrawerComponent, {
217
235
  ...options,
218
236
  keyPrefix: "use-drawer",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/AntdOverlayContext.tsx","../src/useOverlay.tsx","../src/useModal.tsx","../src/useDrawer.tsx"],"names":["useState","useCallback","useMemo","React"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @file AntdOverlayContext - 全局覆盖层容器 Context\n * @description\n * 提供全局覆盖层的挂载点管理。所有通过 useGlobalOverlay 系列 Hook\n * 创建的覆盖层都会被挂载到 AntdOverlayProvider 下。\n *\n * 工作原理:\n * 1. AntdOverlayProvider 维护一个 holders 数组\n * 2. useGlobalOverlay 通过 useAntdOverlayContext 获取注册方法\n * 3. 覆盖层的 contextHolder 被添加到 holders 数组\n * 4. Provider 在子节点之后统一渲染所有 holders\n *\n * 这种设计的优势:\n * - 覆盖层与业务组件解耦,可在任意位置调用\n * - 统一的挂载点,避免 z-index 混乱\n * - 组件卸载时自动清理对应的覆盖层\n *\n * @example\n * // 在应用入口包裹 Provider\n * function App() {\n * return (\n * <AntdOverlayProvider>\n * <Router>\n * <Routes />\n * </Router>\n * </AntdOverlayProvider>\n * );\n * }\n */\n\nimport React, { createContext, useCallback, useContext, useMemo, useState } from 'react';\n\n// ============================================================================\n// 类型定义\n// ============================================================================\n\n/**\n * AntdOverlay Context 的值类型\n *\n * @property holders - 当前所有已注册的覆盖层 holder 节点\n * @property addHolder - 注册一个新的 holder 到全局容器\n * @property removeHolder - 从全局容器移除一个已注册的 holder\n */\ninterface AntdOverlayContextValue {\n /** 所有已注册的 holder 节点列表 */\n holders: React.ReactNode[];\n /** 添加 holder 到全局容器 */\n addHolder: (holder: React.ReactNode) => void;\n /** 从全局容器移除 holder */\n removeHolder: (holder: React.ReactNode) => void;\n}\n\n// ============================================================================\n// Context 定义\n// ============================================================================\n\n/**\n * AntdOverlay Context\n *\n * 默认值为 null,使用时必须在 AntdOverlayProvider 内部。\n * 如果在 Provider 外部调用 useAntdOverlayContext,会抛出明确的错误提示。\n */\nconst AntdOverlayContext = createContext<AntdOverlayContextValue | null>(null);\n\n// ============================================================================\n// Provider 组件\n// ============================================================================\n\n/**\n * AntdOverlay 容器提供者组件\n *\n * 用于管理全局覆盖层的挂载点。所有通过 useGlobalOverlay、useGlobalModal、\n * useGlobalDrawer 等 Hook 创建的覆盖层都会被挂载到这个 Provider 下。\n *\n * 渲染结构:\n * ```\n * <AntdOverlayContext.Provider>\n * {children} <- 应用的主要内容\n * {holders[0]} <- 全局覆盖层 1\n * {holders[1]} <- 全局覆盖层 2\n * ...\n * </AntdOverlayContext.Provider>\n * ```\n *\n * @param children - 子节点,通常是整个应用\n *\n * @example\n * // 基础用法 - 在应用入口包裹\n * function App() {\n * return (\n * <AntdOverlayProvider>\n * <Router>\n * <Routes />\n * </Router>\n * </AntdOverlayProvider>\n * );\n * }\n *\n * @example\n * // 与其他 Provider 配合使用\n * function App() {\n * return (\n * <ConfigProvider>\n * <AntdOverlayProvider>\n * <App />\n * </AntdOverlayProvider>\n * </ConfigProvider>\n * );\n * }\n */\nexport function AntdOverlayProvider({ children }: { children: React.ReactNode }) {\n // 存储所有已注册的 holder 节点\n const [holders, setHolders] = useState<React.ReactNode[]>([]);\n\n /**\n * 添加 holder 到全局容器\n *\n * 使用函数式更新确保并发安全,避免闭包陷阱。\n * 新的 holder 会被追加到数组末尾,因此后添加的覆盖层会显示在上层。\n */\n const addHolder = useCallback((holder: React.ReactNode) => {\n setHolders((prev) => [...prev, holder]);\n }, []);\n\n /**\n * 从全局容器移除 holder\n *\n * 通过引用比较(===)找到并移除对应的 holder。\n * 这要求每次传入的 holder 必须是同一个引用。\n */\n const removeHolder = useCallback((holder: React.ReactNode) => {\n setHolders((prev) => prev.filter((h) => h !== holder));\n }, []);\n\n // 使用 useMemo 优化 Context 值,避免不必要的重渲染\n // 只有当 holders、addHolder 或 removeHolder 变化时才会创建新的值对象\n const value = useMemo(\n () => ({ holders, addHolder, removeHolder }),\n [holders, addHolder, removeHolder],\n );\n\n return (\n <AntdOverlayContext.Provider value={value}>\n {children}\n {/* 在 children 之后渲染所有全局覆盖层 */}\n {holders}\n </AntdOverlayContext.Provider>\n );\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * 获取 AntdOverlay Context 的 Hook\n *\n * 返回全局容器的注册和注销方法,供 useGlobalOverlay 系列 Hook 内部使用。\n *\n * 注意事项:\n * - 必须在 AntdOverlayProvider 内部使用\n * - 如果在 Provider 外部调用,会抛出明确的错误\n * - 主要供库内部使用,一般不需要在业务代码中直接调用\n *\n * @returns AntdOverlayContextValue 包含 holders、addHolder、removeHolder\n * @throws Error 如果不在 AntdOverlayProvider 内部使用\n *\n * @example\n * // 库内部使用示例(useGlobalOverlay 的实现)\n * function useGlobalOverlay(Component, options) {\n * const { addHolder, removeHolder } = useAntdOverlayContext();\n * const [open, holder] = useOverlay(Component, options);\n *\n * useEffect(() => {\n * addHolder(holder);\n * return () => removeHolder(holder);\n * }, [holder]);\n *\n * return open;\n * }\n */\nexport function useAntdOverlayContext() {\n const context = useContext(AntdOverlayContext);\n\n if (!context) {\n throw new Error(\n 'useAntdOverlayContext must be used within an AntdOverlayProvider. ' +\n 'Please wrap your application with <AntdOverlayProvider>.',\n );\n }\n\n return context;\n}\n","/**\n * @file useOverlay - 通用覆盖层管理 Hook\n * @description\n * 提供一个与具体 UI 组件无关的覆盖层(Overlay)管理方案。\n * 支持任意满足 CustomOverlayProps 接口的组件,如 Modal、Drawer、Popover 等。\n *\n * 核心设计理念:\n * 1. 命令式调用 - 通过函数调用打开覆盖层,而非声明式管理 open 状态\n * 2. 动画支持 - 正确处理打开/关闭动画,避免动画未完成就卸载组件\n * 3. 全局挂载 - 支持将覆盖层挂载到全局容器,实现跨组件调用\n * 4. 类型安全 - 完整的 TypeScript 类型支持\n *\n * 架构层次:\n * ┌─────────────────────────────────────────────────────────┐\n * │ useModal / useDrawer │ <- 业务层封装\n * ├─────────────────────────────────────────────────────────┤\n * │ useOverlay / useGlobalOverlay │ <- 核心逻辑层\n * ├─────────────────────────────────────────────────────────┤\n * │ GlobalHolderProvider │ <- 全局容器层\n * └─────────────────────────────────────────────────────────┘\n *\n * @example\n * // 直接使用 useOverlay(不推荐,建议使用 useModal/useDrawer)\n * const [openOverlay, holder] = useOverlay(MyOverlayComponent, {\n * propsAdapter: (props, state) => ({ ...props, visible: state.open }),\n * });\n */\n\nimport React, { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';\n\nimport { useAntdOverlayContext } from './AntdOverlayContext';\n\n// ============================================================================\n// 类型定义\n// ============================================================================\n\n/**\n * 自定义覆盖层组件必须实现的属性接口\n *\n * 这是所有覆盖层组件的基础接口,定义了控制覆盖层所需的最小属性集。\n * 具体的 UI 组件(如 Modal、Drawer)应该扩展此接口。\n *\n * @template T - customOk 回调接收的参数类型,用于传递确认操作的数据\n * @template R - customOk 回调的返回类型,通常为 void\n *\n * @property open - 控制覆盖层的显示/隐藏状态\n * @property customClose - 关闭覆盖层的回调函数,由 useOverlay 注入\n * @property customOk - 确认操作的回调函数,调用后会自动关闭覆盖层\n *\n * @example\n * interface MyOverlayProps extends CustomOverlayProps<{ id: number }> {\n * title: string;\n * data: SomeData;\n * }\n *\n * const MyOverlay: React.FC<MyOverlayProps> = ({\n * open,\n * customClose,\n * customOk,\n * title,\n * data,\n * }) => {\n * const handleConfirm = () => {\n * // 调用 customOk 会自动关闭覆盖层\n * customOk?.({ id: data.id });\n * };\n * return (\n * <Modal open={open} onCancel={customClose} onOk={handleConfirm}>\n * {title}\n * </Modal>\n * );\n * };\n */\nexport interface CustomOverlayProps<T = any, R = void> {\n /** 覆盖层的显示状态 */\n open?: boolean;\n /** 关闭覆盖层的回调,由 useOverlay 自动注入 */\n customClose: () => void;\n /** 确认操作回调,调用后自动关闭覆盖层 */\n customOk?: (value: T) => R;\n}\n\n/**\n * 内部使用的属性类型\n * 排除 customClose,因为它由 useOverlay 自动注入,用户无需传递\n */\ntype InternalProps<T extends CustomOverlayProps> = Omit<T, 'customClose'>;\n\n/**\n * 覆盖层控制器接口\n *\n * 打开覆盖层后返回的控制器对象,用于后续操作(更新属性或关闭)。\n * 使用 readonly 确保方法引用稳定,不会被意外修改。\n *\n * @template T - 覆盖层组件的属性类型\n *\n * @example\n * const controller = openModal({ title: '初始标题' });\n *\n * // 动态更新属性\n * controller.update({ title: '新标题', loading: true });\n *\n * // 编程式关闭\n * controller.close();\n */\nexport interface OverlayController<T extends CustomOverlayProps> {\n /**\n * 更新覆盖层的属性\n * @param props - 新的属性对象,会完全替换之前的属性\n */\n readonly update: (props: InternalProps<T>) => void;\n /**\n * 关闭覆盖层\n * 如果启用了动画,会等待动画结束后再卸载组件\n */\n readonly close: () => void;\n}\n\n/**\n * 覆盖层打开函数的类型定义\n *\n * @template T - 覆盖层组件的属性类型\n * @param initialize - 初始化属性,可选\n * @returns 覆盖层控制器,用于后续的更新和关闭操作\n *\n * @example\n * const openModal: OverlayOpener<MyModalProps> = (props) => {\n * // 返回控制器\n * };\n *\n * // 无参数调用\n * const ctrl1 = openModal();\n *\n * // 带初始属性调用\n * const ctrl2 = openModal({ title: '标题', data: someData });\n */\nexport type OverlayOpener<T extends CustomOverlayProps> = (\n initialize?: InternalProps<T>,\n) => OverlayController<T>;\n\n/**\n * useOverlay Hook 的配置选项\n *\n * @template T - 覆盖层组件的属性类型\n *\n * @property animation - 是否启用动画支持,默认 true\n * - true: 关闭时先设置 open=false,等待动画结束后再卸载组件\n * - false: 关闭时直接卸载组件,适用于无动画的覆盖层\n *\n * @property keyPrefix - React key 的前缀,用于区分不同类型的覆盖层\n * - 默认值: 'use-overlay'\n * - useModal 使用 'use-modal'\n * - useDrawer 使用 'use-drawer'\n *\n * @property propsAdapter - 属性适配器函数\n * 用于将内部状态转换为组件实际需要的属性。\n * 不同的 UI 组件(Modal、Drawer)有不同的动画回调机制,\n * 通过适配器实现统一的接口。\n */\nexport interface UseOverlayOptions<T extends CustomOverlayProps> {\n /** 是否启用关闭动画,默认 true */\n animation?: boolean;\n /** React key 前缀,用于标识覆盖层类型 */\n keyPrefix?: string;\n /**\n * 属性适配器函数\n * @param props - 用户传入的属性\n * @param state - 内部状态,包含 open、onClose、onAnimationEnd\n * @returns 传递给组件的最终属性\n */\n propsAdapter?: (\n props: InternalProps<T> | undefined,\n state: {\n /** 当前的打开状态 */\n open: boolean;\n /** 触发关闭的回调 */\n onClose: () => void;\n /** 动画结束后的回调,用于卸载组件 */\n onAnimationEnd: () => void;\n },\n ) => T;\n}\n\n// ============================================================================\n// 默认属性适配器\n// ============================================================================\n\n/**\n * 默认的属性适配器\n *\n * 提供基本的属性转换逻辑:\n * 1. 将用户传入的 props 与内部状态合并\n * 2. 注入 open 和 customClose\n * 3. 包装 customOk 使其调用后自动关闭覆盖层\n *\n * 注意:这是一个简化的适配器,不处理动画。\n * 对于 Modal 和 Drawer,应该使用各自的专用适配器来处理动画回调。\n *\n * @template T - 覆盖层组件的属性类型\n * @param props - 用户传入的属性\n * @param state - 内部状态\n * @returns 最终传递给组件的属性\n */\nconst defaultPropsAdapter = <T extends CustomOverlayProps>(\n props: InternalProps<T> | undefined,\n state: { open: boolean; onClose: () => void; onAnimationEnd: () => void },\n): T => {\n const result = {\n ...props,\n open: state.open,\n customClose: state.onClose,\n } as unknown as T;\n\n // 包装 customOk,使其调用后自动触发关闭\n if (result.customOk) {\n const originalCustomOk = result?.customOk;\n result.customOk = ((value: unknown) => {\n originalCustomOk?.(value);\n state.onClose();\n }) as T['customOk'];\n }\n\n return result;\n};\n\n// ============================================================================\n// 核心 Hook 实现\n// ============================================================================\n\n/**\n * 覆盖层管理核心 Hook\n *\n * 这是整个库的核心,提供覆盖层的生命周期管理:\n * - 挂载/卸载控制\n * - 打开/关闭状态管理\n * - 动画支持\n * - 属性更新\n *\n * 状态机说明:\n * ```\n * [未挂载] --open()--> [已挂载, open=true] --close()--> [已挂载, open=false] --动画结束--> [未挂载]\n * │\n * └── (animation=false) --> [未挂载]\n * ```\n *\n * @template T - 覆盖层组件的属性类型,必须继承 CustomOverlayProps\n *\n * @param OverlayComponent - 覆盖层组件\n * @param options - 配置选项\n *\n * @returns 元组 [openOverlay, contextHolder]\n * - openOverlay: 打开覆盖层的函数,返回控制器\n * - contextHolder: 需要渲染到组件树中的 React 节点\n *\n * @example\n * function MyComponent() {\n * const [openOverlay, holder] = useOverlay(MyOverlay, {\n * animation: true,\n * propsAdapter: (props, state) => ({\n * ...props,\n * visible: state.open,\n * onClose: state.onClose,\n * afterVisibleChange: (visible) => {\n * if (!visible) state.onAnimationEnd();\n * },\n * }),\n * });\n *\n * return (\n * <>\n * <button onClick={() => openOverlay({ title: '标题' })}>打开</button>\n * {holder}\n * </>\n * );\n * }\n */\nexport function useOverlay<T extends CustomOverlayProps>(\n OverlayComponent: React.FC<T>,\n options: UseOverlayOptions<T> = {},\n): [OverlayOpener<T>, React.ReactNode] {\n // 解构配置选项,设置默认值\n const {\n animation = true,\n keyPrefix = 'use-overlay',\n propsAdapter = defaultPropsAdapter,\n } = options;\n\n // 生成唯一 ID,用于 React key\n const id = useId();\n const key = `${keyPrefix}-${id}`;\n\n // ========== 状态管理 ==========\n\n /**\n * open: 控制覆盖层的显示状态(用于动画)\n * - true: 覆盖层显示\n * - false: 覆盖层隐藏(但可能还在播放关闭动画)\n */\n const [open, setOpen] = useState(false);\n\n /**\n * renderEnable: 控制组件是否挂载到 DOM\n * - true: 组件已挂载\n * - false: 组件已卸载\n *\n * 与 open 分离是为了支持关闭动画:\n * 关闭时先设置 open=false 触发动画,动画结束后再设置 renderEnable=false 卸载组件\n */\n const [renderEnable, setRenderEnable] = useState(false);\n\n /**\n * props: 用户传入的属性\n * 存储最近一次 open 或 update 调用时传入的属性\n */\n const [props, setProps] = useState<InternalProps<T> | undefined>();\n\n /**\n * 使用 ref 存储 animation 配置\n * 避免 animation 变化时重新创建回调函数\n */\n const animationRef = useRef(animation);\n animationRef.current = animation;\n\n // ========== 回调函数 ==========\n\n /**\n * 处理关闭操作\n *\n * 根据是否启用动画采取不同策略:\n * - 启用动画: 仅设置 open=false,等待动画结束后再卸载\n * - 禁用动画: 直接卸载组件\n */\n const handleClose = useCallback(() => {\n if (animationRef.current) {\n // 启用动画时,先触发关闭动画\n setOpen(false);\n } else {\n // 禁用动画时,直接卸载\n setRenderEnable(false);\n }\n }, []);\n\n /**\n * 处理动画结束\n *\n * 由属性适配器在关闭动画结束时调用。\n * 仅在启用动画时执行实际的卸载操作。\n */\n const handleAnimationEnd = useCallback(() => {\n if (animationRef.current) {\n setRenderEnable(false);\n }\n }, []);\n\n // ========== 渲染逻辑 ==========\n\n /**\n * contextHolder: 需要渲染到组件树中的节点\n *\n * 使用 useMemo 优化性能:\n * - 未挂载时返回空 Fragment(保持 key 稳定)\n * - 已挂载时渲染实际组件,通过 propsAdapter 转换属性\n */\n const contextHolder = useMemo(() => {\n // 未挂载时返回带 key 的空 Fragment\n // 保持 key 稳定可以避免不必要的 DOM 操作\n if (!renderEnable) return <React.Fragment key={key} />;\n\n // 通过适配器转换属性\n const realProps = propsAdapter(props, {\n open,\n onClose: handleClose,\n onAnimationEnd: handleAnimationEnd,\n });\n\n return <OverlayComponent key={key} {...realProps} />;\n }, [\n renderEnable,\n open,\n props,\n key,\n propsAdapter,\n handleClose,\n handleAnimationEnd,\n OverlayComponent,\n ]);\n\n // ========== 打开函数 ==========\n\n /**\n * 打开覆盖层的函数\n *\n * @param initializeProps - 初始化属性\n * @returns 控制器对象,包含 update 和 close 方法\n */\n const openOverlay = useCallback(\n (initializeProps?: InternalProps<T>) => {\n // 1. 挂载组件\n setRenderEnable(true);\n // 2. 设置为打开状态(触发打开动画)\n setOpen(true);\n // 3. 存储初始属性\n setProps(initializeProps);\n\n // 返回控制器\n return {\n /**\n * 更新覆盖层属性\n * 注意:这是完全替换,不是合并\n */\n update: (newProps: InternalProps<T>) => setProps(newProps),\n /**\n * 关闭覆盖层\n */\n close: handleClose,\n } as const;\n },\n [handleClose],\n );\n\n return [openOverlay, contextHolder];\n}\n\n/**\n * 全局覆盖层管理 Hook\n *\n * 与 useOverlay 的区别:\n * - useOverlay: 需要手动渲染 contextHolder\n * - useGlobalOverlay: 自动挂载到 AntdOverlayProvider\n *\n * 实现原理:\n * 1. 内部调用 useOverlay 获取 openOverlay 和 contextHolder\n * 2. 使用 useEffect 将 contextHolder 注册到全局容器\n * 3. 组件卸载时自动从全局容器移除\n *\n * 使用前提:\n * - 必须在组件树的上层包裹 AntdOverlayProvider\n *\n * @template T - 覆盖层组件的属性类型\n *\n * @param OverlayComponent - 覆盖层组件\n * @param options - 配置选项\n *\n * @returns 打开覆盖层的函数(无需再渲染 holder)\n *\n * @example\n * // 1. 先在应用入口包裹 Provider\n * function App() {\n * return (\n * <AntdOverlayProvider>\n * <YourApp />\n * </AntdOverlayProvider>\n * );\n * }\n *\n * // 2. 在任意组件中使用\n * function AnyComponent() {\n * const openOverlay = useGlobalOverlay(MyOverlay);\n *\n * return (\n * <button onClick={() => openOverlay({ data: someData })}>\n * 打开全局覆盖层\n * </button>\n * );\n * }\n */\nexport function useGlobalOverlay<T extends CustomOverlayProps>(\n OverlayComponent: React.FC<T>,\n options?: UseOverlayOptions<T>,\n): OverlayOpener<T> {\n // 获取全局容器的注册/注销方法\n const { addHolder, removeHolder } = useAntdOverlayContext();\n\n // 使用基础 useOverlay 获取功能\n const [openOverlay, contextHolder] = useOverlay<T>(OverlayComponent, options);\n\n // 将 contextHolder 注册到全局容器\n useEffect(() => {\n addHolder(contextHolder);\n // 清理函数:组件卸载时从全局容器移除\n return () => removeHolder(contextHolder);\n }, [contextHolder, addHolder, removeHolder]);\n\n // 仅返回 openOverlay,holder 已自动挂载\n return openOverlay;\n}\n\n// ============================================================================\n// 工厂函数\n// ============================================================================\n\n/**\n * 生成绑定了特定组件的 Hook 工厂函数\n *\n * 当某个覆盖层组件在多处使用时,可以使用此函数生成专用 Hook,\n * 避免每次使用都需要传入组件引用。\n *\n * @template T - 覆盖层组件的属性类型\n *\n * @param OverlayComponent - 覆盖层组件\n * @param defaultOptions - 默认配置选项,会与调用时的选项合并\n *\n * @returns 包含 useOverlay 和 useGlobalOverlay 的对象\n *\n * @example\n * // 创建专用 Hook\n * const {\n * useOverlay: useMyOverlay,\n * useGlobalOverlay: useGlobalMyOverlay,\n * } = generateUseOverlayHook(MyOverlayComponent, {\n * animation: true,\n * propsAdapter: myAdapter,\n * });\n *\n * // 使用专用 Hook(无需再传组件)\n * function SomeComponent() {\n * const openOverlay = useGlobalMyOverlay();\n * return <button onClick={() => openOverlay()}>打开</button>;\n * }\n */\nexport function generateUseOverlayHook<T extends CustomOverlayProps>(\n OverlayComponent: React.FC<T>,\n defaultOptions?: UseOverlayOptions<T>,\n) {\n return {\n /**\n * 绑定了特定组件的 useOverlay\n * @param options - 配置选项,会与 defaultOptions 合并\n */\n useOverlay: (options?: UseOverlayOptions<T>) =>\n useOverlay(OverlayComponent, { ...defaultOptions, ...options }),\n\n /**\n * 绑定了特定组件的 useGlobalOverlay\n * @param options - 配置选项,会与 defaultOptions 合并\n */\n useGlobalOverlay: (options?: UseOverlayOptions<T>) =>\n useGlobalOverlay(OverlayComponent, { ...defaultOptions, ...options }),\n };\n}\n","/**\n * @file useModal - Ant Design Modal 管理 Hook\n * @description\n * 基于 useOverlay 封装的 Modal 专用管理方案。\n * 提供命令式 API 来控制 Modal 的显示、隐藏和属性更新。\n *\n * 主要特性:\n * - 命令式调用,无需管理 visible 状态\n * - 支持动态更新 Modal 属性\n * - 支持全局挂载,跨组件调用\n * - 正确处理关闭动画(通过 afterClose 回调)\n *\n * @example\n * // 基础用法\n * const [openModal, holder] = useModal(MyModal);\n *\n * // 全局用法\n * const openModal = useGlobalModal(MyModal);\n *\n * // 为特定组件生成专用 Hook\n * const { useGlobalModal: useGlobalMyModal } = generateUseModalHook(MyModal);\n */\n\nimport { ModalProps } from 'antd';\nimport { useMemo } from 'react';\n\nimport {\n CustomOverlayProps,\n OverlayOpener,\n useGlobalOverlay,\n useOverlay,\n UseOverlayOptions,\n} from './useOverlay';\n\n/**\n * 自定义 Modal 组件的属性接口\n * 继承 Ant Design ModalProps 并添加自定义属性\n *\n * @template T - customOk 回调的参数类型\n * @template R - customOk 回调的返回类型\n *\n * @example\n * const MyModal: React.FC<CustomModalProps<{ name: string }>> = ({\n * open,\n * customClose,\n * customOk,\n * }) => {\n * return (\n * <Modal open={open} onCancel={customClose} onOk={() => customOk?.({ name: 'test' })}>\n * 内容\n * </Modal>\n * );\n * };\n */\nexport interface CustomModalProps<T = any, R = void> extends ModalProps, CustomOverlayProps<T, R> {}\n\n/**\n * useModal Hook 的配置选项\n * 排除了 propsAdapter 和 keyPrefix,这些由内部自动处理\n */\nexport type UseModalOptions = Omit<\n UseOverlayOptions<CustomModalProps>,\n 'propsAdapter' | 'keyPrefix'\n>;\n\n/**\n * 创建 Modal 专用的属性适配器\n *\n * 主要职责:\n * 1. 注入 open 和 customClose\n * 2. 包装 afterClose 以处理动画结束\n * 3. 包装 customOk 以实现自动关闭\n *\n * @template T - Modal 组件的属性类型\n * @returns 属性适配器函数\n */\nconst createModalPropsAdapter = <T extends CustomModalProps>() => {\n return (\n props: Omit<T, 'customClose'> | undefined,\n state: { open: boolean; onClose: () => void; onAnimationEnd: () => void },\n ): T => {\n const result = {\n maskClosable: false, // 默认禁止点击遮罩关闭\n ...props,\n open: state.open,\n customClose: state.onClose,\n // 在 Modal 关闭动画结束后触发,用于卸载组件\n afterClose: () => {\n props?.afterClose?.();\n state.onAnimationEnd();\n },\n } as unknown as T;\n\n // 包装 customOk,调用后自动关闭 Modal\n if (result.customOk) {\n const originalCustomOk = result?.customOk;\n result.customOk = ((value: unknown) => {\n originalCustomOk?.(value);\n state.onClose();\n }) as T['customOk'];\n }\n\n return result;\n };\n};\n\n/**\n * Modal 管理 Hook\n *\n * @template T - Modal 组件的属性类型,必须继承 CustomModalProps\n *\n * @param ModalComponent - Modal 组件\n * @param options - 配置选项\n *\n * @returns 元组 [openModal, contextHolder]\n * - openModal: 打开 Modal 的函数\n * - contextHolder: 需要渲染到组件树中的 React 节点\n *\n * @example\n * function MyPage() {\n * const [openModal, modalHolder] = useModal(ConfirmModal);\n *\n * const handleDelete = () => {\n * openModal({\n * title: '确认删除',\n * content: '删除后无法恢复',\n * });\n * };\n *\n * return (\n * <>\n * <button onClick={handleDelete}>删除</button>\n * {modalHolder}\n * </>\n * );\n * }\n */\nexport function useModal<T extends CustomModalProps>(\n ModalComponent: React.FC<T>,\n options?: UseModalOptions,\n): [OverlayOpener<T>, React.ReactNode] {\n const propsAdapter = useMemo(() => createModalPropsAdapter<T>(), []);\n return useOverlay(ModalComponent, {\n ...options,\n keyPrefix: 'use-modal',\n propsAdapter,\n });\n}\n\n/**\n * 全局 Modal 管理 Hook\n *\n * 与 useModal 的区别:\n * - 无需手动渲染 contextHolder\n * - Modal 会自动挂载到全局容器\n * - 适合需要跨组件调用的场景\n *\n * @template T - Modal 组件的属性类型\n *\n * @param ModalComponent - Modal 组件\n * @param options - 配置选项\n *\n * @returns 打开 Modal 的函数\n *\n * @example\n * function DeleteButton() {\n * const openConfirm = useGlobalModal(ConfirmModal);\n *\n * return (\n * <button onClick={() => openConfirm({ title: '确认删除?' })}>\n * 删除\n * </button>\n * );\n * }\n */\nexport function useGlobalModal<T extends CustomModalProps>(\n ModalComponent: React.FC<T>,\n options?: UseModalOptions,\n): OverlayOpener<T> {\n const propsAdapter = useMemo(() => createModalPropsAdapter<T>(), []);\n return useGlobalOverlay(ModalComponent, {\n ...options,\n keyPrefix: 'use-modal',\n propsAdapter,\n });\n}\n\n/**\n * 生成绑定了特定 Modal 组件的 Hook 工厂函数\n *\n * 适用场景:\n * - 某个 Modal 在多处使用\n * - 希望简化调用代码\n * - 需要统一管理某个 Modal 的默认配置\n *\n * @template T - Modal 组件的属性类型\n *\n * @param ModalComponent - Modal 组件\n *\n * @returns 包含 useModal 和 useGlobalModal 的对象\n *\n * @example\n * // 在 Modal 组件文件中导出专用 Hook\n * const ConfirmModal: React.FC<CustomModalProps> = (props) => {\n * // ...\n * };\n *\n * export const {\n * useModal: useConfirmModal,\n * useGlobalModal: useGlobalConfirmModal,\n * } = generateUseModalHook(ConfirmModal);\n *\n * // 在其他组件中使用\n * function MyPage() {\n * const openConfirm = useGlobalConfirmModal();\n * return <button onClick={() => openConfirm()}>确认</button>;\n * }\n */\nexport function generateUseModalHook<T extends CustomModalProps>(ModalComponent: React.FC<T>) {\n return {\n useModal: (options?: UseModalOptions) => useModal(ModalComponent, options),\n useGlobalModal: (options?: UseModalOptions) => useGlobalModal(ModalComponent, options),\n };\n}\n\nexport default useModal;\n","/**\n * @file useDrawer - Ant Design Drawer 管理 Hook\n * @description\n * 基于 useOverlay 封装的 Drawer 专用管理方案。\n * 提供命令式 API 来控制 Drawer 的显示、隐藏和属性更新。\n *\n * 主要特性:\n * - 命令式调用,无需管理 open 状态\n * - 支持动态更新 Drawer 属性\n * - 支持全局挂载,跨组件调用\n * - 正确处理关闭动画(通过 afterOpenChange 回调)\n *\n * @example\n * // 基础用法\n * const [openDrawer, holder] = useDrawer(MyDrawer);\n *\n * // 全局用法\n * const openDrawer = useGlobalDrawer(MyDrawer);\n *\n * // 为特定组件生成专用 Hook\n * const { useGlobalDrawer: useGlobalMyDrawer } = generateUseDrawerHook(MyDrawer);\n */\n\nimport { DrawerProps } from 'antd';\nimport { useMemo } from 'react';\n\nimport {\n CustomOverlayProps,\n OverlayOpener,\n useGlobalOverlay,\n useOverlay,\n UseOverlayOptions,\n} from './useOverlay';\n\n/**\n * 自定义 Drawer 组件的属性接口\n * 继承 Ant Design DrawerProps 并添加自定义属性\n *\n * @template T - customOk 回调的参数类型\n * @template R - customOk 回调的返回类型\n *\n * @example\n * const MyDrawer: React.FC<CustomDrawerProps<{ id: number }>> = ({\n * open,\n * customClose,\n * customOk,\n * }) => {\n * return (\n * <Drawer open={open} onClose={customClose}>\n * <Button onClick={() => customOk?.({ id: 1 })}>确认</Button>\n * </Drawer>\n * );\n * };\n */\nexport interface CustomDrawerProps<T = any, R = void>\n extends DrawerProps, CustomOverlayProps<T, R> {}\n\n/**\n * useDrawer Hook 的配置选项\n * 排除了 propsAdapter 和 keyPrefix,这些由内部自动处理\n */\nexport type UseDrawerOptions = Omit<\n UseOverlayOptions<CustomDrawerProps>,\n 'propsAdapter' | 'keyPrefix'\n>;\n\n/**\n * 创建 Drawer 专用的属性适配器\n *\n * 主要职责:\n * 1. 注入 open 和 customClose\n * 2. 包装 afterOpenChange 以处理动画结束\n * 3. 包装 customOk 以实现自动关闭\n *\n * 与 Modal 的区别:\n * - Modal 使用 afterClose 回调(仅在关闭后触发)\n * - Drawer 使用 afterOpenChange 回调(打开和关闭都会触发,需要判断状态)\n *\n * @template T - Drawer 组件的属性类型\n * @returns 属性适配器函数\n */\nconst createDrawerPropsAdapter = <T extends CustomDrawerProps>() => {\n return (\n props: Omit<T, 'customClose'> | undefined,\n state: { open: boolean; onClose: () => void; onAnimationEnd: () => void },\n ): T => {\n const result = {\n maskClosable: false, // 默认禁止点击遮罩关闭\n ...props,\n open: state.open,\n customClose: state.onClose,\n // Drawer 的动画回调,打开和关闭时都会触发\n afterOpenChange: (open: boolean) => {\n props?.afterOpenChange?.(open);\n // 仅在关闭动画结束时触发卸载\n if (!open) {\n state.onAnimationEnd();\n }\n },\n } as unknown as T;\n\n // 包装 customOk,调用后自动关闭 Drawer\n if (result.customOk) {\n const originalCustomOk = result?.customOk;\n result.customOk = ((value: unknown) => {\n originalCustomOk?.(value);\n state.onClose();\n }) as T['customOk'];\n }\n\n return result;\n };\n};\n\n/**\n * Drawer 管理 Hook\n *\n * @template T - Drawer 组件的属性类型,必须继承 CustomDrawerProps\n *\n * @param DrawerComponent - Drawer 组件\n * @param options - 配置选项\n *\n * @returns 元组 [openDrawer, contextHolder]\n * - openDrawer: 打开 Drawer 的函数\n * - contextHolder: 需要渲染到组件树中的 React 节点\n *\n * @example\n * function MyPage() {\n * const [openDrawer, drawerHolder] = useDrawer(UserDetailDrawer);\n *\n * const handleViewUser = (userId: number) => {\n * openDrawer({ userId, title: '用户详情' });\n * };\n *\n * return (\n * <>\n * <button onClick={() => handleViewUser(1)}>查看用户</button>\n * {drawerHolder}\n * </>\n * );\n * }\n */\nexport function useDrawer<T extends CustomDrawerProps>(\n DrawerComponent: React.FC<T>,\n options?: UseDrawerOptions,\n): [OverlayOpener<T>, React.ReactNode] {\n const propsAdapter = useMemo(() => createDrawerPropsAdapter<T>(), []);\n return useOverlay(DrawerComponent, {\n ...options,\n keyPrefix: 'use-drawer',\n propsAdapter,\n });\n}\n\n/**\n * 全局 Drawer 管理 Hook\n *\n * 与 useDrawer 的区别:\n * - 无需手动渲染 contextHolder\n * - Drawer 会自动挂载到全局容器\n * - 适合需要跨组件调用的场景\n *\n * @template T - Drawer 组件的属性类型\n *\n * @param DrawerComponent - Drawer 组件\n * @param options - 配置选项\n *\n * @returns 打开 Drawer 的函数\n *\n * @example\n * function UserCard({ userId }: { userId: number }) {\n * const openDetail = useGlobalDrawer(UserDetailDrawer);\n *\n * return (\n * <Card onClick={() => openDetail({ userId })}>\n * 查看详情\n * </Card>\n * );\n * }\n */\nexport function useGlobalDrawer<T extends CustomDrawerProps>(\n DrawerComponent: React.FC<T>,\n options?: UseDrawerOptions,\n): OverlayOpener<T> {\n const propsAdapter = useMemo(() => createDrawerPropsAdapter<T>(), []);\n return useGlobalOverlay(DrawerComponent, {\n ...options,\n keyPrefix: 'use-drawer',\n propsAdapter,\n });\n}\n\n/**\n * 生成绑定了特定 Drawer 组件的 Hook 工厂函数\n *\n * 适用场景:\n * - 某个 Drawer 在多处使用\n * - 希望简化调用代码\n * - 需要统一管理某个 Drawer 的默认配置\n *\n * @template T - Drawer 组件的属性类型\n *\n * @param DrawerComponent - Drawer 组件\n *\n * @returns 包含 useDrawer 和 useGlobalDrawer 的对象\n *\n * @example\n * // 在 Drawer 组件文件中导出专用 Hook\n * const ProjectMemberDrawer: React.FC<CustomDrawerProps> = (props) => {\n * // ...\n * };\n *\n * export const {\n * useDrawer: useProjectMemberDrawer,\n * useGlobalDrawer: useGlobalProjectMemberDrawer,\n * } = generateUseDrawerHook(ProjectMemberDrawer);\n *\n * // 在其他组件中使用\n * function ProjectPage() {\n * const openMemberDrawer = useGlobalProjectMemberDrawer();\n * return <button onClick={() => openMemberDrawer()}>管理成员</button>;\n * }\n */\nexport function generateUseDrawerHook<T extends CustomDrawerProps>(DrawerComponent: React.FC<T>) {\n return {\n useDrawer: (options?: UseDrawerOptions) => useDrawer(DrawerComponent, options),\n useGlobalDrawer: (options?: UseDrawerOptions) => useGlobalDrawer(DrawerComponent, options),\n };\n}\n\nexport default useDrawer;\n"]}
1
+ {"version":3,"sources":["../src/AntdOverlayContext.tsx","../src/useOverlay.tsx","../src/useModal.tsx","../src/useDrawer.tsx"],"names":["useState","useCallback","useMemo","React"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @file AntdOverlayContext - 全局覆盖层容器 Context\n * @description\n * 提供全局覆盖层的挂载点管理。所有通过 useGlobalOverlay 系列 Hook\n * 创建的覆盖层都会被挂载到 AntdOverlayProvider 下。\n *\n * 工作原理:\n * 1. AntdOverlayProvider 维护一个 holders 数组\n * 2. useGlobalOverlay 通过 useAntdOverlayContext 获取注册方法\n * 3. 覆盖层的 contextHolder 被添加到 holders 数组\n * 4. Provider 在子节点之后统一渲染所有 holders\n *\n * 这种设计的优势:\n * - 覆盖层与业务组件解耦,可在任意位置调用\n * - 统一的挂载点,避免 z-index 混乱\n * - 组件卸载时自动清理对应的覆盖层\n *\n * @example\n * // 在应用入口包裹 Provider\n * function App() {\n * return (\n * <AntdOverlayProvider>\n * <Router>\n * <Routes />\n * </Router>\n * </AntdOverlayProvider>\n * );\n * }\n */\n\nimport { DrawerProps, ModalProps } from 'antd';\nimport React, { createContext, useCallback, useContext, useMemo, useState } from 'react';\n\n// ============================================================================\n// 类型定义\n// ============================================================================\n\nexport type DefaultModalProps = Partial<ModalProps>;\nexport type DefaultDrawerProps = Partial<DrawerProps>;\n\n/**\n * AntdOverlay Context 的值类型\n *\n * @property holders - 当前所有已注册的覆盖层 holder 节点\n * @property addHolder - 注册一个新的 holder 到全局容器\n * @property removeHolder - 从全局容器移除一个已注册的 holder\n */\ninterface AntdOverlayContextValue {\n /** 所有已注册的 holder 节点列表 */\n holders: React.ReactNode[];\n /** 添加 holder 到全局容器 */\n addHolder: (holder: React.ReactNode) => void;\n /** 从全局容器移除 holder */\n removeHolder: (holder: React.ReactNode) => void;\n /** 默认 Modal 属性 */\n defaultModalProps?: DefaultModalProps;\n /** 默认 Drawer 属性 */\n defaultDrawerProps?: DefaultDrawerProps;\n}\n\n// ============================================================================\n// Context 定义\n// ============================================================================\n\n/**\n * AntdOverlay Context\n *\n * 默认值为 null,使用时必须在 AntdOverlayProvider 内部。\n * 如果在 Provider 外部调用 useAntdOverlayContext,会抛出明确的错误提示。\n */\nconst AntdOverlayContext = createContext<AntdOverlayContextValue | null>(null);\n\n// ============================================================================\n// Provider 组件\n// ============================================================================\n\n/**\n * AntdOverlay 容器提供者组件\n *\n * 用于管理全局覆盖层的挂载点。所有通过 useGlobalOverlay、useGlobalModal、\n * useGlobalDrawer 等 Hook 创建的覆盖层都会被挂载到这个 Provider 下。\n *\n * 渲染结构:\n * ```\n * <AntdOverlayContext.Provider>\n * {children} <- 应用的主要内容\n * {holders[0]} <- 全局覆盖层 1\n * {holders[1]} <- 全局覆盖层 2\n * ...\n * </AntdOverlayContext.Provider>\n * ```\n *\n * @param children - 子节点,通常是整个应用\n *\n * @example\n * // 基础用法 - 在应用入口包裹\n * function App() {\n * return (\n * <AntdOverlayProvider>\n * <Router>\n * <Routes />\n * </Router>\n * </AntdOverlayProvider>\n * );\n * }\n *\n * @example\n * // 与其他 Provider 配合使用\n * function App() {\n * return (\n * <ConfigProvider>\n * <AntdOverlayProvider>\n * <App />\n * </AntdOverlayProvider>\n * </ConfigProvider>\n * );\n * }\n */\nexport interface AntdOverlayProviderProps {\n /** 子节点 */\n children: React.ReactNode;\n /** 默认 Modal 属性 */\n defaultModalProps?: DefaultModalProps;\n /** 默认 Drawer 属性 */\n defaultDrawerProps?: DefaultDrawerProps;\n}\n\n\n/**\n * AntdOverlayProvider 组件\n * @param children - 子节点\n * @param defaultModalProps - 默认 Modal 属性\n * @param defaultDrawerProps - 默认 Drawer 属性\n * @returns React.ReactNode\n */\nexport function AntdOverlayProvider({\n children,\n defaultModalProps,\n defaultDrawerProps,\n}: AntdOverlayProviderProps) {\n // 存储所有已注册的 holder 节点\n const [holders, setHolders] = useState<React.ReactNode[]>([]);\n\n /**\n * 添加 holder 到全局容器\n *\n * 使用函数式更新确保并发安全,避免闭包陷阱。\n * 新的 holder 会被追加到数组末尾,因此后添加的覆盖层会显示在上层。\n */\n const addHolder = useCallback((holder: React.ReactNode) => {\n setHolders((prev) => [...prev, holder]);\n }, []);\n\n /**\n * 从全局容器移除 holder\n *\n * 通过引用比较(===)找到并移除对应的 holder。\n * 这要求每次传入的 holder 必须是同一个引用。\n */\n const removeHolder = useCallback((holder: React.ReactNode) => {\n setHolders((prev) => prev.filter((h) => h !== holder));\n }, []);\n\n // 使用 useMemo 优化 Context 值,避免不必要的重渲染\n // 只有当 holders、addHolder 或 removeHolder 变化时才会创建新的值对象\n const value = useMemo(\n () => ({ holders, addHolder, removeHolder, defaultModalProps, defaultDrawerProps }),\n [holders, addHolder, removeHolder, defaultModalProps, defaultDrawerProps],\n );\n\n return (\n <AntdOverlayContext.Provider value={value}>\n {children}\n {/* 在 children 之后渲染所有全局覆盖层 */}\n {holders}\n </AntdOverlayContext.Provider>\n );\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * 获取 AntdOverlay Context 的 Hook\n *\n * 返回全局容器的注册和注销方法,供 useGlobalOverlay 系列 Hook 内部使用。\n *\n * 注意事项:\n * - 必须在 AntdOverlayProvider 内部使用\n * - 如果在 Provider 外部调用,会抛出明确的错误\n * - 主要供库内部使用,一般不需要在业务代码中直接调用\n *\n * @returns AntdOverlayContextValue 包含 holders、addHolder、removeHolder\n * @throws Error 如果不在 AntdOverlayProvider 内部使用\n *\n * @example\n * // 库内部使用示例(useGlobalOverlay 的实现)\n * function useGlobalOverlay(Component, options) {\n * const context = useAntdOverlayContext();\n * if (!context) {\n * throw new Error('useGlobalOverlay must be used within an AntdOverlayProvider. Please wrap your application with <AntdOverlayProvider>.');\n * }\n * const { addHolder, removeHolder } = context;\n * const [open, holder] = useOverlay(Component, options);\n *\n * useEffect(() => {\n * addHolder(holder);\n * return () => removeHolder(holder);\n * }, [holder]);\n *\n * return open;\n * }\n */\nexport function useAntdOverlayContext() {\n return useContext(AntdOverlayContext);\n}\n","/**\n * @file useOverlay - 通用覆盖层管理 Hook\n * @description\n * 提供一个与具体 UI 组件无关的覆盖层(Overlay)管理方案。\n * 支持任意满足 CustomOverlayProps 接口的组件,如 Modal、Drawer、Popover 等。\n *\n * 核心设计理念:\n * 1. 命令式调用 - 通过函数调用打开覆盖层,而非声明式管理 open 状态\n * 2. 动画支持 - 正确处理打开/关闭动画,避免动画未完成就卸载组件\n * 3. 全局挂载 - 支持将覆盖层挂载到全局容器,实现跨组件调用\n * 4. 类型安全 - 完整的 TypeScript 类型支持\n *\n * 架构层次:\n * ┌─────────────────────────────────────────────────────────┐\n * │ useModal / useDrawer │ <- 业务层封装\n * ├─────────────────────────────────────────────────────────┤\n * │ useOverlay / useGlobalOverlay │ <- 核心逻辑层\n * ├─────────────────────────────────────────────────────────┤\n * │ GlobalHolderProvider │ <- 全局容器层\n * └─────────────────────────────────────────────────────────┘\n *\n * @example\n * // 直接使用 useOverlay(不推荐,建议使用 useModal/useDrawer)\n * const [openOverlay, holder] = useOverlay(MyOverlayComponent, {\n * propsAdapter: (props, state) => ({ ...props, visible: state.open }),\n * });\n */\n\nimport React, { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';\n\nimport { useAntdOverlayContext } from './AntdOverlayContext';\n\n// ============================================================================\n// 类型定义\n// ============================================================================\n\n/**\n * 自定义覆盖层组件必须实现的属性接口\n *\n * 这是所有覆盖层组件的基础接口,定义了控制覆盖层所需的最小属性集。\n * 具体的 UI 组件(如 Modal、Drawer)应该扩展此接口。\n *\n * @template T - customOk 回调接收的参数类型,用于传递确认操作的数据\n * @template R - customOk 回调的返回类型,通常为 void\n *\n * @property open - 控制覆盖层的显示/隐藏状态\n * @property customClose - 关闭覆盖层的回调函数,由 useOverlay 注入\n * @property customOk - 确认操作的回调函数,调用后会自动关闭覆盖层\n *\n * @example\n * interface MyOverlayProps extends CustomOverlayProps<{ id: number }> {\n * title: string;\n * data: SomeData;\n * }\n *\n * const MyOverlay: React.FC<MyOverlayProps> = ({\n * open,\n * customClose,\n * customOk,\n * title,\n * data,\n * }) => {\n * const handleConfirm = () => {\n * // 调用 customOk 会自动关闭覆盖层\n * customOk?.({ id: data.id });\n * };\n * return (\n * <Modal open={open} onCancel={customClose} onOk={handleConfirm}>\n * {title}\n * </Modal>\n * );\n * };\n */\nexport interface CustomOverlayProps<T = any, R = void> {\n /** 覆盖层的显示状态 */\n open?: boolean;\n /** 关闭覆盖层的回调,由 useOverlay 自动注入 */\n customClose: () => void;\n /** 确认操作回调,调用后自动关闭覆盖层 */\n customOk?: (value: T) => R;\n}\n\n/**\n * 内部使用的属性类型\n * 排除 customClose,因为它由 useOverlay 自动注入,用户无需传递\n */\ntype InternalProps<T extends CustomOverlayProps> = Omit<T, 'customClose'>;\n\n/**\n * 覆盖层控制器接口\n *\n * 打开覆盖层后返回的控制器对象,用于后续操作(更新属性或关闭)。\n * 使用 readonly 确保方法引用稳定,不会被意外修改。\n *\n * @template T - 覆盖层组件的属性类型\n *\n * @example\n * const controller = openModal({ title: '初始标题' });\n *\n * // 动态更新属性\n * controller.update({ title: '新标题', loading: true });\n *\n * // 编程式关闭\n * controller.close();\n */\nexport interface OverlayController<T extends CustomOverlayProps> {\n /**\n * 更新覆盖层的属性\n * @param props - 新的属性对象,会完全替换之前的属性\n */\n readonly update: (props: InternalProps<T>) => void;\n /**\n * 关闭覆盖层\n * 如果启用了动画,会等待动画结束后再卸载组件\n */\n readonly close: () => void;\n}\n\n/**\n * 覆盖层打开函数的类型定义\n *\n * @template T - 覆盖层组件的属性类型\n * @param initialize - 初始化属性,可选\n * @returns 覆盖层控制器,用于后续的更新和关闭操作\n *\n * @example\n * const openModal: OverlayOpener<MyModalProps> = (props) => {\n * // 返回控制器\n * };\n *\n * // 无参数调用\n * const ctrl1 = openModal();\n *\n * // 带初始属性调用\n * const ctrl2 = openModal({ title: '标题', data: someData });\n */\nexport type OverlayOpener<T extends CustomOverlayProps> = (\n initialize?: InternalProps<T>,\n) => OverlayController<T>;\n\n/**\n * useOverlay Hook 的配置选项\n *\n * @template T - 覆盖层组件的属性类型\n *\n * @property animation - 是否启用动画支持,默认 true\n * - true: 关闭时先设置 open=false,等待动画结束后再卸载组件\n * - false: 关闭时直接卸载组件,适用于无动画的覆盖层\n *\n * @property keyPrefix - React key 的前缀,用于区分不同类型的覆盖层\n * - 默认值: 'use-overlay'\n * - useModal 使用 'use-modal'\n * - useDrawer 使用 'use-drawer'\n *\n * @property propsAdapter - 属性适配器函数\n * 用于将内部状态转换为组件实际需要的属性。\n * 不同的 UI 组件(Modal、Drawer)有不同的动画回调机制,\n * 通过适配器实现统一的接口。\n */\nexport interface UseOverlayOptions<T extends CustomOverlayProps> {\n /** 是否启用关闭动画,默认 true */\n animation?: boolean;\n /** React key 前缀,用于标识覆盖层类型 */\n keyPrefix?: string;\n /**\n * 属性适配器函数\n * @param props - 用户传入的属性\n * @param state - 内部状态,包含 open、onClose、onAnimationEnd\n * @returns 传递给组件的最终属性\n */\n propsAdapter?: (\n props: InternalProps<T> | undefined,\n state: {\n /** 当前的打开状态 */\n open: boolean;\n /** 触发关闭的回调 */\n onClose: () => void;\n /** 动画结束后的回调,用于卸载组件 */\n onAnimationEnd: () => void;\n },\n ) => T;\n}\n\n// ============================================================================\n// 默认属性适配器\n// ============================================================================\n\n/**\n * 默认的属性适配器\n *\n * 提供基本的属性转换逻辑:\n * 1. 将用户传入的 props 与内部状态合并\n * 2. 注入 open 和 customClose\n * 3. 包装 customOk 使其调用后自动关闭覆盖层\n *\n * 注意:这是一个简化的适配器,不处理动画。\n * 对于 Modal 和 Drawer,应该使用各自的专用适配器来处理动画回调。\n *\n * @template T - 覆盖层组件的属性类型\n * @param props - 用户传入的属性\n * @param state - 内部状态\n * @returns 最终传递给组件的属性\n */\nconst defaultPropsAdapter = <T extends CustomOverlayProps>(\n props: InternalProps<T> | undefined,\n state: { open: boolean; onClose: () => void; onAnimationEnd: () => void },\n): T => {\n const result = {\n ...props,\n open: state.open,\n customClose: state.onClose,\n } as unknown as T;\n\n // 包装 customOk,使其调用后自动触发关闭\n if (result.customOk) {\n const originalCustomOk = result?.customOk;\n result.customOk = ((value: unknown) => {\n originalCustomOk?.(value);\n state.onClose();\n }) as T['customOk'];\n }\n\n return result;\n};\n\n// ============================================================================\n// 核心 Hook 实现\n// ============================================================================\n\n/**\n * 覆盖层管理核心 Hook\n *\n * 这是整个库的核心,提供覆盖层的生命周期管理:\n * - 挂载/卸载控制\n * - 打开/关闭状态管理\n * - 动画支持\n * - 属性更新\n *\n * 状态机说明:\n * ```\n * [未挂载] --open()--> [已挂载, open=true] --close()--> [已挂载, open=false] --动画结束--> [未挂载]\n * │\n * └── (animation=false) --> [未挂载]\n * ```\n *\n * @template T - 覆盖层组件的属性类型,必须继承 CustomOverlayProps\n *\n * @param OverlayComponent - 覆盖层组件\n * @param options - 配置选项\n *\n * @returns 元组 [openOverlay, contextHolder]\n * - openOverlay: 打开覆盖层的函数,返回控制器\n * - contextHolder: 需要渲染到组件树中的 React 节点\n *\n * @example\n * function MyComponent() {\n * const [openOverlay, holder] = useOverlay(MyOverlay, {\n * animation: true,\n * propsAdapter: (props, state) => ({\n * ...props,\n * visible: state.open,\n * onClose: state.onClose,\n * afterVisibleChange: (visible) => {\n * if (!visible) state.onAnimationEnd();\n * },\n * }),\n * });\n *\n * return (\n * <>\n * <button onClick={() => openOverlay({ title: '标题' })}>打开</button>\n * {holder}\n * </>\n * );\n * }\n */\nexport function useOverlay<T extends CustomOverlayProps>(\n OverlayComponent: React.FC<T>,\n options: UseOverlayOptions<T> = {},\n): [OverlayOpener<T>, React.ReactNode] {\n // 解构配置选项,设置默认值\n const {\n animation = true,\n keyPrefix = 'use-overlay',\n propsAdapter = defaultPropsAdapter,\n } = options;\n\n // 生成唯一 ID,用于 React key\n const id = useId();\n const key = `${keyPrefix}-${id}`;\n\n // ========== 状态管理 ==========\n\n /**\n * open: 控制覆盖层的显示状态(用于动画)\n * - true: 覆盖层显示\n * - false: 覆盖层隐藏(但可能还在播放关闭动画)\n */\n const [open, setOpen] = useState(false);\n\n /**\n * renderEnable: 控制组件是否挂载到 DOM\n * - true: 组件已挂载\n * - false: 组件已卸载\n *\n * 与 open 分离是为了支持关闭动画:\n * 关闭时先设置 open=false 触发动画,动画结束后再设置 renderEnable=false 卸载组件\n */\n const [renderEnable, setRenderEnable] = useState(false);\n\n /**\n * props: 用户传入的属性\n * 存储最近一次 open 或 update 调用时传入的属性\n */\n const [props, setProps] = useState<InternalProps<T> | undefined>();\n\n /**\n * 使用 ref 存储 animation 配置\n * 避免 animation 变化时重新创建回调函数\n */\n const animationRef = useRef(animation);\n animationRef.current = animation;\n\n // ========== 回调函数 ==========\n\n /**\n * 处理关闭操作\n *\n * 根据是否启用动画采取不同策略:\n * - 启用动画: 仅设置 open=false,等待动画结束后再卸载\n * - 禁用动画: 直接卸载组件\n */\n const handleClose = useCallback(() => {\n if (animationRef.current) {\n // 启用动画时,先触发关闭动画\n setOpen(false);\n } else {\n // 禁用动画时,直接卸载\n setRenderEnable(false);\n }\n }, []);\n\n /**\n * 处理动画结束\n *\n * 由属性适配器在关闭动画结束时调用。\n * 仅在启用动画时执行实际的卸载操作。\n */\n const handleAnimationEnd = useCallback(() => {\n if (animationRef.current) {\n setRenderEnable(false);\n }\n }, []);\n\n // ========== 渲染逻辑 ==========\n\n /**\n * contextHolder: 需要渲染到组件树中的节点\n *\n * 使用 useMemo 优化性能:\n * - 未挂载时返回空 Fragment(保持 key 稳定)\n * - 已挂载时渲染实际组件,通过 propsAdapter 转换属性\n */\n const contextHolder = useMemo(() => {\n // 未挂载时返回带 key 的空 Fragment\n // 保持 key 稳定可以避免不必要的 DOM 操作\n if (!renderEnable) return <React.Fragment key={key} />;\n\n // 通过适配器转换属性\n const realProps = propsAdapter(props, {\n open,\n onClose: handleClose,\n onAnimationEnd: handleAnimationEnd,\n });\n\n return <OverlayComponent key={key} {...realProps} />;\n }, [\n renderEnable,\n open,\n props,\n key,\n propsAdapter,\n handleClose,\n handleAnimationEnd,\n OverlayComponent,\n ]);\n\n // ========== 打开函数 ==========\n\n /**\n * 打开覆盖层的函数\n *\n * @param initializeProps - 初始化属性\n * @returns 控制器对象,包含 update 和 close 方法\n */\n const openOverlay = useCallback(\n (initializeProps?: InternalProps<T>) => {\n // 1. 挂载组件\n setRenderEnable(true);\n // 2. 设置为打开状态(触发打开动画)\n setOpen(true);\n // 3. 存储初始属性\n setProps(initializeProps);\n\n // 返回控制器\n return {\n /**\n * 更新覆盖层属性\n * 注意:这是完全替换,不是合并\n */\n update: (newProps: InternalProps<T>) => setProps(newProps),\n /**\n * 关闭覆盖层\n */\n close: handleClose,\n } as const;\n },\n [handleClose],\n );\n\n return [openOverlay, contextHolder];\n}\n\n/**\n * 全局覆盖层管理 Hook\n *\n * 与 useOverlay 的区别:\n * - useOverlay: 需要手动渲染 contextHolder\n * - useGlobalOverlay: 自动挂载到 AntdOverlayProvider\n *\n * 实现原理:\n * 1. 内部调用 useOverlay 获取 openOverlay 和 contextHolder\n * 2. 使用 useEffect 将 contextHolder 注册到全局容器\n * 3. 组件卸载时自动从全局容器移除\n *\n * 使用前提:\n * - 必须在组件树的上层包裹 AntdOverlayProvider\n *\n * @template T - 覆盖层组件的属性类型\n *\n * @param OverlayComponent - 覆盖层组件\n * @param options - 配置选项\n *\n * @returns 打开覆盖层的函数(无需再渲染 holder)\n *\n * @example\n * // 1. 先在应用入口包裹 Provider\n * function App() {\n * return (\n * <AntdOverlayProvider>\n * <YourApp />\n * </AntdOverlayProvider>\n * );\n * }\n *\n * // 2. 在任意组件中使用\n * function AnyComponent() {\n * const openOverlay = useGlobalOverlay(MyOverlay);\n *\n * return (\n * <button onClick={() => openOverlay({ data: someData })}>\n * 打开全局覆盖层\n * </button>\n * );\n * }\n */\nexport function useGlobalOverlay<T extends CustomOverlayProps>(\n OverlayComponent: React.FC<T>,\n options?: UseOverlayOptions<T>,\n): OverlayOpener<T> {\n // 获取全局容器的注册/注销方法\n const context = useAntdOverlayContext();\n\n if (!context) {\n throw new Error(\n 'useGlobalOverlay must be used within an AntdOverlayProvider. ' +\n 'Please wrap your application with <AntdOverlayProvider>.'\n );\n }\n\n const { addHolder, removeHolder } = context;\n\n // 使用基础 useOverlay 获取功能\n const [openOverlay, contextHolder] = useOverlay<T>(OverlayComponent, options);\n\n // 将 contextHolder 注册到全局容器\n useEffect(() => {\n addHolder(contextHolder);\n // 清理函数:组件卸载时从全局容器移除\n return () => removeHolder(contextHolder);\n }, [contextHolder, addHolder, removeHolder]);\n\n // 仅返回 openOverlay,holder 已自动挂载\n return openOverlay;\n}\n\n// ============================================================================\n// 工厂函数\n// ============================================================================\n\n/**\n * 生成绑定了特定组件的 Hook 工厂函数\n *\n * 当某个覆盖层组件在多处使用时,可以使用此函数生成专用 Hook,\n * 避免每次使用都需要传入组件引用。\n *\n * @template T - 覆盖层组件的属性类型\n *\n * @param OverlayComponent - 覆盖层组件\n * @param defaultOptions - 默认配置选项,会与调用时的选项合并\n *\n * @returns 包含 useOverlay 和 useGlobalOverlay 的对象\n *\n * @example\n * // 创建专用 Hook\n * const {\n * useOverlay: useMyOverlay,\n * useGlobalOverlay: useGlobalMyOverlay,\n * } = generateUseOverlayHook(MyOverlayComponent, {\n * animation: true,\n * propsAdapter: myAdapter,\n * });\n *\n * // 使用专用 Hook(无需再传组件)\n * function SomeComponent() {\n * const openOverlay = useGlobalMyOverlay();\n * return <button onClick={() => openOverlay()}>打开</button>;\n * }\n */\nexport function generateUseOverlayHook<T extends CustomOverlayProps>(\n OverlayComponent: React.FC<T>,\n defaultOptions?: UseOverlayOptions<T>,\n) {\n return {\n /**\n * 绑定了特定组件的 useOverlay\n * @param options - 配置选项,会与 defaultOptions 合并\n */\n useOverlay: (options?: UseOverlayOptions<T>) =>\n useOverlay(OverlayComponent, { ...defaultOptions, ...options }),\n\n /**\n * 绑定了特定组件的 useGlobalOverlay\n * @param options - 配置选项,会与 defaultOptions 合并\n */\n useGlobalOverlay: (options?: UseOverlayOptions<T>) =>\n useGlobalOverlay(OverlayComponent, { ...defaultOptions, ...options }),\n };\n}\n","/**\n * @file useModal - Ant Design Modal 管理 Hook\n * @description\n * 基于 useOverlay 封装的 Modal 专用管理方案。\n * 提供命令式 API 来控制 Modal 的显示、隐藏和属性更新。\n *\n * 主要特性:\n * - 命令式调用,无需管理 visible 状态\n * - 支持动态更新 Modal 属性\n * - 支持全局挂载,跨组件调用\n * - 正确处理关闭动画(通过 afterClose 回调)\n *\n * @example\n * // 基础用法\n * const [openModal, holder] = useModal(MyModal);\n *\n * // 全局用法\n * const openModal = useGlobalModal(MyModal);\n *\n * // 为特定组件生成专用 Hook\n * const { useGlobalModal: useGlobalMyModal } = generateUseModalHook(MyModal);\n */\n\nimport { ModalProps } from 'antd';\nimport { useMemo } from 'react';\n\nimport { useAntdOverlayContext, DefaultModalProps } from './AntdOverlayContext';\nimport {\n CustomOverlayProps,\n OverlayOpener,\n useGlobalOverlay,\n useOverlay,\n UseOverlayOptions,\n} from './useOverlay';\n\n/**\n * 自定义 Modal 组件的属性接口\n * 继承 Ant Design ModalProps 并添加自定义属性\n *\n * @template T - customOk 回调的参数类型\n * @template R - customOk 回调的返回类型\n *\n * @example\n * const MyModal: React.FC<CustomModalProps<{ name: string }>> = ({\n * open,\n * customClose,\n * customOk,\n * }) => {\n * return (\n * <Modal open={open} onCancel={customClose} onOk={() => customOk?.({ name: 'test' })}>\n * 内容\n * </Modal>\n * );\n * };\n */\nexport interface CustomModalProps<T = any, R = void> extends ModalProps, CustomOverlayProps<T, R> {}\n\n/**\n * useModal Hook 的配置选项\n * 排除了 propsAdapter 和 keyPrefix,这些由内部自动处理\n */\nexport type UseModalOptions = Omit<\n UseOverlayOptions<CustomModalProps>,\n 'propsAdapter' | 'keyPrefix'\n>;\n\n/**\n * 创建 Modal 专用的属性适配器\n *\n * 主要职责:\n * 1. 注入 open 和 customClose\n * 2. 包装 afterClose 以处理动画结束\n * 3. 包装 customOk 以实现自动关闭\n *\n * @template T - Modal 组件的属性类型\n * @param defaultProps - 默认 Modal 属性\n * @returns 属性适配器函数\n */\nconst createModalPropsAdapter = <T extends CustomModalProps>(\n defaultProps?: DefaultModalProps,\n) => {\n return (\n props: Omit<T, 'customClose'> | undefined,\n state: { open: boolean; onClose: () => void; onAnimationEnd: () => void },\n ): T => {\n const result = {\n ...defaultProps,\n ...props,\n open: state.open,\n customClose: state.onClose,\n // 在 Modal 关闭动画结束后触发,用于卸载组件\n afterClose: () => {\n props?.afterClose?.();\n state.onAnimationEnd();\n },\n } as unknown as T;\n\n // 包装 customOk,调用后自动关闭 Modal\n if (result.customOk) {\n const originalCustomOk = result?.customOk;\n result.customOk = ((value: unknown) => {\n originalCustomOk?.(value);\n state.onClose();\n }) as T['customOk'];\n }\n\n return result;\n };\n};\n\n/**\n * Modal 管理 Hook\n *\n * @template T - Modal 组件的属性类型,必须继承 CustomModalProps\n *\n * @param ModalComponent - Modal 组件\n * @param options - 配置选项\n *\n * @returns 元组 [openModal, contextHolder]\n * - openModal: 打开 Modal 的函数\n * - contextHolder: 需要渲染到组件树中的 React 节点\n *\n * @example\n * function MyPage() {\n * const [openModal, modalHolder] = useModal(ConfirmModal);\n *\n * const handleDelete = () => {\n * openModal({\n * title: '确认删除',\n * content: '删除后无法恢复',\n * });\n * };\n *\n * return (\n * <>\n * <button onClick={handleDelete}>删除</button>\n * {modalHolder}\n * </>\n * );\n * }\n */\nexport function useModal<T extends CustomModalProps>(\n ModalComponent: React.FC<T>,\n options?: UseModalOptions,\n): [OverlayOpener<T>, React.ReactNode] {\n const context = useAntdOverlayContext();\n const propsAdapter = useMemo(\n () => createModalPropsAdapter<T>(context?.defaultModalProps),\n [context?.defaultModalProps],\n );\n return useOverlay(ModalComponent, {\n ...options,\n keyPrefix: 'use-modal',\n propsAdapter,\n });\n}\n\n/**\n * 全局 Modal 管理 Hook\n *\n * 与 useModal 的区别:\n * - 无需手动渲染 contextHolder\n * - Modal 会自动挂载到全局容器\n * - 适合需要跨组件调用的场景\n *\n * @template T - Modal 组件的属性类型\n *\n * @param ModalComponent - Modal 组件\n * @param options - 配置选项\n *\n * @returns 打开 Modal 的函数\n *\n * @example\n * function DeleteButton() {\n * const openConfirm = useGlobalModal(ConfirmModal);\n *\n * return (\n * <button onClick={() => openConfirm({ title: '确认删除?' })}>\n * 删除\n * </button>\n * );\n * }\n */\nexport function useGlobalModal<T extends CustomModalProps>(\n ModalComponent: React.FC<T>,\n options?: UseModalOptions,\n): OverlayOpener<T> {\n const context = useAntdOverlayContext();\n const propsAdapter = useMemo(\n () => createModalPropsAdapter<T>(context?.defaultModalProps),\n [context?.defaultModalProps],\n );\n return useGlobalOverlay(ModalComponent, {\n ...options,\n keyPrefix: 'use-modal',\n propsAdapter,\n });\n}\n\n/**\n * 生成绑定了特定 Modal 组件的 Hook 工厂函数\n *\n * 适用场景:\n * - 某个 Modal 在多处使用\n * - 希望简化调用代码\n * - 需要统一管理某个 Modal 的默认配置\n *\n * @template T - Modal 组件的属性类型\n *\n * @param ModalComponent - Modal 组件\n *\n * @returns 包含 useModal 和 useGlobalModal 的对象\n *\n * @example\n * // 在 Modal 组件文件中导出专用 Hook\n * const ConfirmModal: React.FC<CustomModalProps> = (props) => {\n * // ...\n * };\n *\n * export const {\n * useModal: useConfirmModal,\n * useGlobalModal: useGlobalConfirmModal,\n * } = generateUseModalHook(ConfirmModal);\n *\n * // 在其他组件中使用\n * function MyPage() {\n * const openConfirm = useGlobalConfirmModal();\n * return <button onClick={() => openConfirm()}>确认</button>;\n * }\n */\nexport function generateUseModalHook<T extends CustomModalProps>(ModalComponent: React.FC<T>) {\n return {\n useModal: (options?: UseModalOptions) => useModal(ModalComponent, options),\n useGlobalModal: (options?: UseModalOptions) => useGlobalModal(ModalComponent, options),\n };\n}\n\nexport default useModal;\n","/**\n * @file useDrawer - Ant Design Drawer 管理 Hook\n * @description\n * 基于 useOverlay 封装的 Drawer 专用管理方案。\n * 提供命令式 API 来控制 Drawer 的显示、隐藏和属性更新。\n *\n * 主要特性:\n * - 命令式调用,无需管理 open 状态\n * - 支持动态更新 Drawer 属性\n * - 支持全局挂载,跨组件调用\n * - 正确处理关闭动画(通过 afterOpenChange 回调)\n *\n * @example\n * // 基础用法\n * const [openDrawer, holder] = useDrawer(MyDrawer);\n *\n * // 全局用法\n * const openDrawer = useGlobalDrawer(MyDrawer);\n *\n * // 为特定组件生成专用 Hook\n * const { useGlobalDrawer: useGlobalMyDrawer } = generateUseDrawerHook(MyDrawer);\n */\n\nimport { DrawerProps } from 'antd';\nimport { useMemo } from 'react';\n\nimport { useAntdOverlayContext, DefaultDrawerProps } from './AntdOverlayContext';\nimport {\n CustomOverlayProps,\n OverlayOpener,\n useGlobalOverlay,\n useOverlay,\n UseOverlayOptions,\n} from './useOverlay';\n\n/**\n * 自定义 Drawer 组件的属性接口\n * 继承 Ant Design DrawerProps 并添加自定义属性\n *\n * @template T - customOk 回调的参数类型\n * @template R - customOk 回调的返回类型\n *\n * @example\n * const MyDrawer: React.FC<CustomDrawerProps<{ id: number }>> = ({\n * open,\n * customClose,\n * customOk,\n * }) => {\n * return (\n * <Drawer open={open} onClose={customClose}>\n * <Button onClick={() => customOk?.({ id: 1 })}>确认</Button>\n * </Drawer>\n * );\n * };\n */\nexport interface CustomDrawerProps<T = any, R = void>\n extends DrawerProps, CustomOverlayProps<T, R> {}\n\n/**\n * useDrawer Hook 的配置选项\n * 排除了 propsAdapter 和 keyPrefix,这些由内部自动处理\n */\nexport type UseDrawerOptions = Omit<\n UseOverlayOptions<CustomDrawerProps>,\n 'propsAdapter' | 'keyPrefix'\n>;\n\n/**\n * 创建 Drawer 专用的属性适配器\n *\n * 主要职责:\n * 1. 注入 open 和 customClose\n * 2. 包装 afterOpenChange 以处理动画结束\n * 3. 包装 customOk 以实现自动关闭\n *\n * @template T - Drawer 组件的属性类型\n * @param defaultProps - 默认 Drawer 属性\n * @returns 属性适配器函数\n */\nconst createDrawerPropsAdapter = <T extends CustomDrawerProps>(\n defaultProps?: DefaultDrawerProps,\n) => {\n return (\n props: Omit<T, 'customClose'> | undefined,\n state: { open: boolean; onClose: () => void; onAnimationEnd: () => void },\n ): T => {\n const result = {\n ...defaultProps,\n ...props,\n open: state.open,\n customClose: state.onClose,\n // Drawer 的动画回调,打开和关闭时都会触发\n afterOpenChange: (open: boolean) => {\n props?.afterOpenChange?.(open);\n // 仅在关闭动画结束时触发卸载\n if (!open) {\n state.onAnimationEnd();\n }\n },\n } as unknown as T;\n\n // 包装 customOk,调用后自动关闭 Drawer\n if (result.customOk) {\n const originalCustomOk = result?.customOk;\n result.customOk = ((value: unknown) => {\n originalCustomOk?.(value);\n state.onClose();\n }) as T['customOk'];\n }\n\n return result;\n };\n};\n\n/**\n * Drawer 管理 Hook\n *\n * @template T - Drawer 组件的属性类型,必须继承 CustomDrawerProps\n *\n * @param DrawerComponent - Drawer 组件\n * @param options - 配置选项\n *\n * @returns 元组 [openDrawer, contextHolder]\n * - openDrawer: 打开 Drawer 的函数\n * - contextHolder: 需要渲染到组件树中的 React 节点\n *\n * @example\n * function MyPage() {\n * const [openDrawer, drawerHolder] = useDrawer(UserDetailDrawer);\n *\n * const handleViewUser = (userId: number) => {\n * openDrawer({ userId, title: '用户详情' });\n * };\n *\n * return (\n * <>\n * <button onClick={() => handleViewUser(1)}>查看用户</button>\n * {drawerHolder}\n * </>\n * );\n * }\n */\nexport function useDrawer<T extends CustomDrawerProps>(\n DrawerComponent: React.FC<T>,\n options?: UseDrawerOptions,\n): [OverlayOpener<T>, React.ReactNode] {\n const context = useAntdOverlayContext();\n const propsAdapter = useMemo(\n () => createDrawerPropsAdapter<T>(context?.defaultDrawerProps),\n [context?.defaultDrawerProps],\n );\n return useOverlay(DrawerComponent, {\n ...options,\n keyPrefix: 'use-drawer',\n propsAdapter,\n });\n}\n\n/**\n * 全局 Drawer 管理 Hook\n *\n * 与 useDrawer 的区别:\n * - 无需手动渲染 contextHolder\n * - Drawer 会自动挂载到全局容器\n * - 适合需要跨组件调用的场景\n *\n * @template T - Drawer 组件的属性类型\n *\n * @param DrawerComponent - Drawer 组件\n * @param options - 配置选项\n *\n * @returns 打开 Drawer 的函数\n *\n * @example\n * function UserCard({ userId }: { userId: number }) {\n * const openDetail = useGlobalDrawer(UserDetailDrawer);\n *\n * return (\n * <Card onClick={() => openDetail({ userId })}>\n * 查看详情\n * </Card>\n * );\n * }\n */\nexport function useGlobalDrawer<T extends CustomDrawerProps>(\n DrawerComponent: React.FC<T>,\n options?: UseDrawerOptions,\n): OverlayOpener<T> {\n const context = useAntdOverlayContext();\n const propsAdapter = useMemo(\n () => createDrawerPropsAdapter<T>(context?.defaultDrawerProps),\n [context?.defaultDrawerProps],\n );\n return useGlobalOverlay(DrawerComponent, {\n ...options,\n keyPrefix: 'use-drawer',\n propsAdapter,\n });\n}\n\n/**\n * 生成绑定了特定 Drawer 组件的 Hook 工厂函数\n *\n * 适用场景:\n * - 某个 Drawer 在多处使用\n * - 希望简化调用代码\n * - 需要统一管理某个 Drawer 的默认配置\n *\n * @template T - Drawer 组件的属性类型\n *\n * @param DrawerComponent - Drawer 组件\n *\n * @returns 包含 useDrawer 和 useGlobalDrawer 的对象\n *\n * @example\n * // 在 Drawer 组件文件中导出专用 Hook\n * const ProjectMemberDrawer: React.FC<CustomDrawerProps> = (props) => {\n * // ...\n * };\n *\n * export const {\n * useDrawer: useProjectMemberDrawer,\n * useGlobalDrawer: useGlobalProjectMemberDrawer,\n * } = generateUseDrawerHook(ProjectMemberDrawer);\n *\n * // 在其他组件中使用\n * function ProjectPage() {\n * const openMemberDrawer = useGlobalProjectMemberDrawer();\n * return <button onClick={() => openMemberDrawer()}>管理成员</button>;\n * }\n */\nexport function generateUseDrawerHook<T extends CustomDrawerProps>(DrawerComponent: React.FC<T>) {\n return {\n useDrawer: (options?: UseDrawerOptions) => useDrawer(DrawerComponent, options),\n useGlobalDrawer: (options?: UseDrawerOptions) => useGlobalDrawer(DrawerComponent, options),\n };\n}\n\nexport default useDrawer;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antd-overlay",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Ant Design Modal/Drawer 命令式调用方案",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -8,14 +8,9 @@
8
8
  "types": "./dist/index.d.ts",
9
9
  "exports": {
10
10
  ".": {
11
- "import": {
12
- "types": "./dist/index.d.ts",
13
- "default": "./dist/index.js"
14
- },
15
- "require": {
16
- "types": "./dist/index.d.cts",
17
- "default": "./dist/index.cjs"
18
- }
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
19
14
  }
20
15
  },
21
16
  "files": [
@@ -36,6 +31,9 @@
36
31
  "type": "git",
37
32
  "url": "https://github.com/RaineySpace/antd-overlay"
38
33
  },
34
+ "publishConfig": {
35
+ "registry": "https://registry.npmjs.org"
36
+ },
39
37
  "peerDependencies": {
40
38
  "antd": ">=5.0.0",
41
39
  "react": ">=18.0.0"
@@ -44,7 +42,7 @@
44
42
  "@changesets/cli": "^2.27.10",
45
43
  "@eslint/js": "^9.17.0",
46
44
  "@types/react": "^19.2.7",
47
- "antd": "^6.1.1",
45
+ "antd": "^6.2.2",
48
46
  "eslint": "^9.17.0",
49
47
  "eslint-config-prettier": "^10.0.1",
50
48
  "eslint-plugin-react-hooks": "^5.1.0",