antd-overlay 0.1.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +91 -1
- package/dist/index.cjs +205 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +119 -1
- package/dist/index.d.ts +119 -1
- package/dist/index.js +197 -1
- package/dist/index.js.map +1 -1
- package/docs/ai/api-manifest.json +327 -0
- package/docs/ai/constraints.md +83 -0
- package/docs/ai/contracts.json +88 -0
- package/docs/ai/quick-reference.md +112 -0
- package/package.json +9 -3
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# antd-overlay Constraints and Error Semantics
|
|
2
|
+
|
|
3
|
+
本文件定义 AI 调用时应优先遵守的约束,避免生成“看起来正确但运行失败”的代码。
|
|
4
|
+
|
|
5
|
+
## Provider 约束
|
|
6
|
+
|
|
7
|
+
### 约束
|
|
8
|
+
|
|
9
|
+
- `useGlobalOverlay`
|
|
10
|
+
- `useGlobalModal`
|
|
11
|
+
- `useGlobalDrawer`
|
|
12
|
+
|
|
13
|
+
以上 Hook 必须在 `AntdOverlayProvider` 作用域内调用。
|
|
14
|
+
|
|
15
|
+
### 失败语义
|
|
16
|
+
|
|
17
|
+
- 错误语义码:`PROVIDER_REQUIRED`
|
|
18
|
+
- 触发条件:在 Provider 外调用任一全局 Hook
|
|
19
|
+
- 建议修复:将应用入口包裹 `AntdOverlayProvider`
|
|
20
|
+
|
|
21
|
+
## 组件契约约束
|
|
22
|
+
|
|
23
|
+
### 最小必需字段
|
|
24
|
+
|
|
25
|
+
自定义覆盖层组件必须实现 `CustomOverlayProps` 的关键字段:
|
|
26
|
+
|
|
27
|
+
- `open?: boolean`
|
|
28
|
+
- `customClose: () => void`
|
|
29
|
+
- `customOk?: (value) => any | Promise<any>`
|
|
30
|
+
|
|
31
|
+
### 失败语义
|
|
32
|
+
|
|
33
|
+
- 错误语义码:`INVALID_OVERLAY_CONTRACT`
|
|
34
|
+
- 触发条件:组件不消费 `open/customClose`,导致显示或关闭行为异常
|
|
35
|
+
- 建议修复:将 UI 组件的显隐/关闭事件绑定到 `open/customClose`
|
|
36
|
+
|
|
37
|
+
## 行为语义约束
|
|
38
|
+
|
|
39
|
+
### customOk
|
|
40
|
+
|
|
41
|
+
- 同步成功返回:自动关闭
|
|
42
|
+
- Promise resolve:异步完成后自动关闭
|
|
43
|
+
- throw / Promise reject:保持打开并透传错误
|
|
44
|
+
|
|
45
|
+
错误语义码:`CUSTOM_OK_REJECTED`
|
|
46
|
+
|
|
47
|
+
### update
|
|
48
|
+
|
|
49
|
+
- `controller.update(next)` 是浅合并更新,不是深合并
|
|
50
|
+
- 合并优先级:`defaultProps` < 之前 props < 本次 `update`
|
|
51
|
+
|
|
52
|
+
错误语义码:`UPDATE_SHALLOW_MERGE`
|
|
53
|
+
|
|
54
|
+
## Promise 行为语义(usePromiseOverlay / usePromiseModal / usePromiseDrawer)
|
|
55
|
+
|
|
56
|
+
### 解析规则
|
|
57
|
+
|
|
58
|
+
- `customOk(value)` 同步返回 → 外层 Promise resolve **value(入参,非 customOk 返回值)**
|
|
59
|
+
- `customOk(value)` 异步 resolve → 在 customOk 的 Promise 完成后 resolve(value)
|
|
60
|
+
- 任何其他关闭路径(`customClose` / 蒙层 / antd 取消按钮 / 组件卸载 / 同实例再次 `openPromise` 抢占)→ resolve `undefined`
|
|
61
|
+
- `customOk` 抛错或 Promise reject → Promise 以同一错误 **reject**,覆盖层 **保持打开**
|
|
62
|
+
- 单次 `openPromise` 的 Promise 仅结算一次(幂等)
|
|
63
|
+
- 解析时机为决策时刻,不等待关闭动画
|
|
64
|
+
|
|
65
|
+
### 错误语义码
|
|
66
|
+
|
|
67
|
+
- `PROMISE_RESOLVES_WITH_INPUT` — 解析值为 customOk 入参,不是返回值
|
|
68
|
+
- `PROMISE_RESOLVED_ON_CLOSE` — 任意非 OK 关闭 → resolve(undefined),不 reject
|
|
69
|
+
- `PROMISE_PREEMPTED_BY_REOPEN` — 再次 open 抢占式 resolve 前一个 Promise
|
|
70
|
+
- `CUSTOM_OK_REJECTED` — customOk 抛错 / reject 透传,覆盖层不关闭
|
|
71
|
+
|
|
72
|
+
### AI 易错点
|
|
73
|
+
|
|
74
|
+
- 不要假设关闭等同于 reject —— 取消应该用 `if (result === undefined) return;` 判断
|
|
75
|
+
- 不要把 `customOk` 的返回值当成 Promise 的解析值 —— 解析值始终是入参 `value`
|
|
76
|
+
- 不要为了 “等动画完成再继续” 把 `await` 之后的代码放进 `setTimeout` —— Promise 已经在决策时刻 resolve
|
|
77
|
+
|
|
78
|
+
## AI 生成代码建议
|
|
79
|
+
|
|
80
|
+
- 优先生成 `useModal` 或 `useDrawer`,仅在通用组件时使用 `useOverlay`
|
|
81
|
+
- 业务流程中需要 `await` 用户结果时优先生成 `usePromiseModal` / `usePromiseDrawer`
|
|
82
|
+
- 使用全局 Hook 时必须同时输出 Provider 包裹代码
|
|
83
|
+
- 避免在 `customOk` 内重复手动 `close`,除非明确要覆盖默认关闭时机
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "antd-overlay-ai-contracts",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"package": "antd-overlay",
|
|
5
|
+
"capabilities": [
|
|
6
|
+
"imperative-open-close-overlay",
|
|
7
|
+
"update-overlay-props-via-controller",
|
|
8
|
+
"global-overlay-hosting-via-provider",
|
|
9
|
+
"async-custom-ok-auto-close-on-resolve",
|
|
10
|
+
"imperative-await-overlay-result-via-promise"
|
|
11
|
+
],
|
|
12
|
+
"constraints": [
|
|
13
|
+
{
|
|
14
|
+
"code": "PROVIDER_REQUIRED",
|
|
15
|
+
"rule": "useGlobalModal/useGlobalDrawer/useGlobalOverlay 必须在 AntdOverlayProvider 作用域内调用"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"code": "OVERLAY_COMPONENT_CONTRACT",
|
|
19
|
+
"rule": "自定义组件必须消费 open 与 customClose,且 customOk 应由确认行为触发"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"code": "UPDATE_SHALLOW_MERGE",
|
|
23
|
+
"rule": "controller.update 使用浅合并,不进行深层对象合并"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"code": "PROMISE_RESOLVES_WITH_INPUT",
|
|
27
|
+
"rule": "usePromise* 系列:外层 Promise 解析为 customOk 的入参(value),不是 customOk 的返回值"
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
"errorSemantics": [
|
|
31
|
+
{
|
|
32
|
+
"code": "PROVIDER_REQUIRED",
|
|
33
|
+
"type": "runtime-throw",
|
|
34
|
+
"trigger": "全局 Hook 在 Provider 外调用",
|
|
35
|
+
"fix": "在应用入口包裹 AntdOverlayProvider"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"code": "CUSTOM_OK_REJECTED",
|
|
39
|
+
"type": "behavior",
|
|
40
|
+
"trigger": "customOk 抛错或 Promise reject",
|
|
41
|
+
"result": "覆盖层保持打开,错误透传"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"code": "UPDATE_SHALLOW_MERGE",
|
|
45
|
+
"type": "behavior",
|
|
46
|
+
"trigger": "调用 controller.update",
|
|
47
|
+
"result": "defaultProps < prevProps < nextProps(浅合并)"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"code": "PROMISE_RESOLVED_ON_CLOSE",
|
|
51
|
+
"type": "behavior",
|
|
52
|
+
"trigger": "通过 customClose / 蒙层 / antd 取消按钮 / 组件卸载 关闭 usePromise* 系列覆盖层",
|
|
53
|
+
"result": "外层 Promise 以 undefined resolve(不 reject)"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"code": "PROMISE_PREEMPTED_BY_REOPEN",
|
|
57
|
+
"type": "behavior",
|
|
58
|
+
"trigger": "在前一个 Promise 未结算时再次调用同一 hook 实例的 openPromise",
|
|
59
|
+
"result": "前一个 Promise 立即以 undefined resolve,新 Promise 接管"
|
|
60
|
+
}
|
|
61
|
+
],
|
|
62
|
+
"recommendedTemplates": {
|
|
63
|
+
"globalModal": {
|
|
64
|
+
"providerRequired": true,
|
|
65
|
+
"snippet": "const openModal = useGlobalModal(Component); openModal({ ...props });"
|
|
66
|
+
},
|
|
67
|
+
"localModal": {
|
|
68
|
+
"providerRequired": false,
|
|
69
|
+
"snippet": "const [openModal, holder] = useModal(Component); openModal({ ...props });"
|
|
70
|
+
},
|
|
71
|
+
"controllerUpdate": {
|
|
72
|
+
"snippet": "const controller = openModal(init); controller.update(next); controller.close();"
|
|
73
|
+
},
|
|
74
|
+
"promiseModal": {
|
|
75
|
+
"providerRequired": false,
|
|
76
|
+
"snippet": "const [openPromise, holder] = usePromiseModal(Component); const v = await openPromise({ ...props }); if (v === undefined) return; /* 用户取消 */"
|
|
77
|
+
},
|
|
78
|
+
"promiseDrawer": {
|
|
79
|
+
"providerRequired": false,
|
|
80
|
+
"snippet": "const [openPromise, holder] = usePromiseDrawer(Component); const v = await openPromise({ ...props }); if (v === undefined) return; /* 用户取消 */"
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"docs": {
|
|
84
|
+
"quickReference": "docs/ai/quick-reference.md",
|
|
85
|
+
"constraints": "docs/ai/constraints.md",
|
|
86
|
+
"apiManifest": "docs/ai/api-manifest.json"
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# antd-overlay AI Quick Reference
|
|
2
|
+
|
|
3
|
+
本文件面向代码助手与自动化 Agent,提供最短可执行调用路径。
|
|
4
|
+
|
|
5
|
+
## 1) 全局调用(推荐跨组件场景)
|
|
6
|
+
|
|
7
|
+
前置条件:应用根节点已包裹 `AntdOverlayProvider`。
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { AntdOverlayProvider, useGlobalModal, CustomModalProps } from 'antd-overlay';
|
|
11
|
+
import { Modal } from 'antd';
|
|
12
|
+
|
|
13
|
+
interface ConfirmModalProps extends CustomModalProps<void> {
|
|
14
|
+
titleText: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const ConfirmModal: React.FC<ConfirmModalProps> = ({ open, customClose, customOk, titleText }) => (
|
|
18
|
+
<Modal open={open} title={titleText} onCancel={customClose} onOk={() => customOk?.()}>
|
|
19
|
+
Confirm?
|
|
20
|
+
</Modal>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
function AppRoot() {
|
|
24
|
+
return (
|
|
25
|
+
<AntdOverlayProvider>
|
|
26
|
+
<Page />
|
|
27
|
+
</AntdOverlayProvider>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function Page() {
|
|
32
|
+
const openConfirm = useGlobalModal(ConfirmModal);
|
|
33
|
+
return <button onClick={() => openConfirm({ titleText: 'Delete item' })}>Open</button>;
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 2) 局部调用(需要 holder)
|
|
38
|
+
|
|
39
|
+
适用场景:覆盖层只在当前组件内管理,不依赖全局 Provider。
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import { useModal } from 'antd-overlay';
|
|
43
|
+
|
|
44
|
+
function LocalPage() {
|
|
45
|
+
const [openConfirm, holder] = useModal(ConfirmModal);
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<>
|
|
49
|
+
<button onClick={() => openConfirm({ titleText: 'Local confirm' })}>Open</button>
|
|
50
|
+
{holder}
|
|
51
|
+
</>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 3) 控制器模式(update / close)
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
const controller = openConfirm({ titleText: 'Step 1' });
|
|
60
|
+
controller.update({ titleText: 'Step 2' });
|
|
61
|
+
controller.close();
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 4) customOk 语义(必须遵守)
|
|
65
|
+
|
|
66
|
+
- 同步返回(不抛错):自动关闭覆盖层
|
|
67
|
+
- Promise resolve:Promise 完成后自动关闭
|
|
68
|
+
- throw 或 Promise reject:保持打开,错误继续抛给调用方
|
|
69
|
+
|
|
70
|
+
## 5) 最小规则清单
|
|
71
|
+
|
|
72
|
+
- 使用 `useGlobalModal/useGlobalDrawer/useGlobalOverlay` 时,必须存在 `AntdOverlayProvider`
|
|
73
|
+
- 自定义组件需要消费 `open` 与 `customClose`
|
|
74
|
+
- 覆盖层确认动作优先通过 `customOk` 触发,避免自行关闭与业务状态不同步
|
|
75
|
+
|
|
76
|
+
## 6) Promise 模式(await customOk 入参)
|
|
77
|
+
|
|
78
|
+
适用场景:业务方希望在调用处直接 `await` 拿到用户的确认结果。
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
import { usePromiseModal, CustomModalProps } from 'antd-overlay';
|
|
82
|
+
import { Modal } from 'antd';
|
|
83
|
+
|
|
84
|
+
interface ConfirmModalProps extends CustomModalProps<{ value: string }> {
|
|
85
|
+
initialValue?: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const ConfirmModal: React.FC<ConfirmModalProps> = ({ open, customClose, customOk, initialValue }) => (
|
|
89
|
+
<Modal open={open} onCancel={customClose} onOk={() => customOk?.({ value: initialValue ?? '' })}>
|
|
90
|
+
confirm
|
|
91
|
+
</Modal>
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
function Page() {
|
|
95
|
+
const [openConfirm, holder] = usePromiseModal(ConfirmModal);
|
|
96
|
+
|
|
97
|
+
const handle = async () => {
|
|
98
|
+
const result = await openConfirm({ initialValue: 'hello' });
|
|
99
|
+
if (result === undefined) return; // 用户取消 / 关闭
|
|
100
|
+
console.log(result.value); // customOk 入参
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
return <>{holder}<button onClick={handle}>open</button></>;
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
行为契约(同样适用于 `usePromiseDrawer` / `usePromiseOverlay` 与对应的 `useGlobalPromise*` / `generateUsePromise*Hook`):
|
|
108
|
+
|
|
109
|
+
- `customOk(value)` 同步成功 → Promise resolve **value(入参)**;异步 resolve 同理
|
|
110
|
+
- 任意非 OK 关闭路径(`customClose` / 蒙层 / 取消按钮 / 组件卸载 / 同实例再次 open 抢占)→ Promise resolve `undefined`
|
|
111
|
+
- `customOk` 抛错或 Promise reject → Promise 以同一错误 reject,覆盖层保持打开
|
|
112
|
+
- Promise 仅结算一次(幂等);解析时机为决策时刻,不等待关闭动画
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "antd-overlay",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Ant Design Modal/Drawer 命令式调用方案",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -11,10 +11,15 @@
|
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"import": "./dist/index.js",
|
|
13
13
|
"require": "./dist/index.cjs"
|
|
14
|
-
}
|
|
14
|
+
},
|
|
15
|
+
"./ai/api-manifest.json": "./docs/ai/api-manifest.json",
|
|
16
|
+
"./ai/contracts.json": "./docs/ai/contracts.json",
|
|
17
|
+
"./ai/quick-reference.md": "./docs/ai/quick-reference.md",
|
|
18
|
+
"./ai/constraints.md": "./docs/ai/constraints.md"
|
|
15
19
|
},
|
|
16
20
|
"files": [
|
|
17
|
-
"dist"
|
|
21
|
+
"dist",
|
|
22
|
+
"docs/ai"
|
|
18
23
|
],
|
|
19
24
|
"keywords": [
|
|
20
25
|
"antd",
|
|
@@ -65,6 +70,7 @@
|
|
|
65
70
|
"format": "prettier --write .",
|
|
66
71
|
"format:check": "prettier --check .",
|
|
67
72
|
"typecheck": "tsc --noEmit",
|
|
73
|
+
"validate:ai-docs": "node ./scripts/validate-ai-docs.mjs",
|
|
68
74
|
"changeset": "changeset",
|
|
69
75
|
"version-packages": "changeset version",
|
|
70
76
|
"release": "pnpm build && changeset publish"
|