vite-plugin-vue-testid 1.0.6 → 1.0.8
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.en.md +10 -0
- package/README.md +13 -3
- package/dist/runtime.d.ts +12 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +120 -77
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -13,6 +13,7 @@ A Vite plugin that auto-injects `data-testid` into Vue component templates via c
|
|
|
13
13
|
- **Date panel mode awareness** — date / month / year / decade panels are distinguished automatically
|
|
14
14
|
- **MutationObserver re-injection** — New DOM elements from panel switching, tree node expand/collapse are detected and injected automatically
|
|
15
15
|
- **Extensible** — Custom component lists, testId generation rules, and overlay injection strategies are supported
|
|
16
|
+
- **prefixCls compatible** — Supports ant-design-vue global ConfigProvider custom `prefixCls` with auto-detection or manual config
|
|
16
17
|
|
|
17
18
|
---
|
|
18
19
|
|
|
@@ -243,6 +244,14 @@ const cleanup = setupAntDropdownTestIds({
|
|
|
243
244
|
*/
|
|
244
245
|
attributeName: 'data-testid',
|
|
245
246
|
|
|
247
|
+
/**
|
|
248
|
+
* ant-design-vue global CSS class prefix.
|
|
249
|
+
* Required when ConfigProvider prefixCls is set to a non-default value.
|
|
250
|
+
* When not set, auto-detects from DOM (CSS vars → button class → fallback 'ant').
|
|
251
|
+
* @default auto-detect || 'ant'
|
|
252
|
+
*/
|
|
253
|
+
prefixCls: 'myapp',
|
|
254
|
+
|
|
246
255
|
/**
|
|
247
256
|
* Custom panel selector → injection strategy mapping
|
|
248
257
|
* key: CSS selector
|
|
@@ -255,6 +264,7 @@ const cleanup = setupAntDropdownTestIds({
|
|
|
255
264
|
// ctx.trigger — trigger HTMLElement | null
|
|
256
265
|
// ctx.triggerTestId — the trigger's testId value
|
|
257
266
|
// ctx.attrName — testId attribute name
|
|
267
|
+
// ctx.prefixCls — ant-design-vue CSS class prefix
|
|
258
268
|
const prefix = `${ctx.triggerTestId}-dropdown`
|
|
259
269
|
ctx.container.setAttribute(ctx.attrName, prefix)
|
|
260
270
|
// ... custom injection logic
|
package/README.md
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
- **日期面板模式感知** — date / month / year / decade 面板自动区分
|
|
14
14
|
- **MutationObserver 重注入** — 面板切换、树节点展开/折叠时自动检测并注入新 DOM
|
|
15
15
|
- **可扩展** — 支持自定义组件列表、testId 生成规则、弹出面板注入策略
|
|
16
|
+
- **prefixCls 兼容** — 支持 ant-design-vue 全局 ConfigProvider 自定义 `prefixCls`,自动检测或手动配置
|
|
16
17
|
|
|
17
18
|
---
|
|
18
19
|
|
|
@@ -243,6 +244,14 @@ const cleanup = setupAntDropdownTestIds({
|
|
|
243
244
|
*/
|
|
244
245
|
attributeName: 'data-testid',
|
|
245
246
|
|
|
247
|
+
/**
|
|
248
|
+
* ant-design-vue 全局 CSS 类名前缀。
|
|
249
|
+
* 如果通过 ConfigProvider 配置了 prefixCls,必须传入相同值。
|
|
250
|
+
* 未配置时自动从 DOM 检测(扫描 CSS 变量 → button 类名 → 回退 'ant')。
|
|
251
|
+
* @default auto-detect || 'ant'
|
|
252
|
+
*/
|
|
253
|
+
prefixCls: 'myapp',
|
|
254
|
+
|
|
246
255
|
/**
|
|
247
256
|
* 自定义面板选择器 → 注入策略映射
|
|
248
257
|
* key: CSS 选择器
|
|
@@ -251,10 +260,11 @@ const cleanup = setupAntDropdownTestIds({
|
|
|
251
260
|
panels: {
|
|
252
261
|
'.ant-picker-dropdown': undefined, // 禁用内置 Picker 面板注入
|
|
253
262
|
'.my-custom-dropdown': (ctx) => {
|
|
254
|
-
// ctx.container
|
|
255
|
-
// ctx.trigger
|
|
263
|
+
// ctx.container — 面板容器 HTMLElement
|
|
264
|
+
// ctx.trigger — 触发器 HTMLElement | null
|
|
256
265
|
// ctx.triggerTestId — 触发器的 testId 值
|
|
257
|
-
// ctx.attrName
|
|
266
|
+
// ctx.attrName — testId 属性名
|
|
267
|
+
// ctx.prefixCls — ant-design-vue CSS 类名前缀
|
|
258
268
|
const prefix = `${ctx.triggerTestId}-dropdown`
|
|
259
269
|
ctx.container.setAttribute(ctx.attrName, prefix)
|
|
260
270
|
// ... 自定义注入逻辑
|
package/dist/runtime.d.ts
CHANGED
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
* import { setupAntDropdownTestIds } from 'vite-plugin-vue-testid/runtime'
|
|
8
8
|
*
|
|
9
9
|
* setupAntDropdownTestIds()
|
|
10
|
+
*
|
|
11
|
+
* // 如果全局配置了 prefixCls(如 ConfigProvider prefixCls="myapp"):
|
|
12
|
+
* setupAntDropdownTestIds({ prefixCls: 'myapp' })
|
|
10
13
|
* ```
|
|
11
14
|
*/
|
|
12
15
|
export interface RuntimeOptions {
|
|
@@ -15,6 +18,13 @@ export interface RuntimeOptions {
|
|
|
15
18
|
* @default 'data-testid'
|
|
16
19
|
*/
|
|
17
20
|
attributeName?: string;
|
|
21
|
+
/**
|
|
22
|
+
* ant-design-vue 全局 CSS 类名前缀。
|
|
23
|
+
* 如果通过 ConfigProvider 配置了 prefixCls,需要在此传入相同值。
|
|
24
|
+
* 未配置时自动从 DOM 检测,检测失败回退到 'ant'。
|
|
25
|
+
* @default auto-detect || 'ant'
|
|
26
|
+
*/
|
|
27
|
+
prefixCls?: string;
|
|
18
28
|
/**
|
|
19
29
|
* 需要监听的 teleport 面板 CSS 选择器映射
|
|
20
30
|
* key: 面板容器选择器
|
|
@@ -31,6 +41,8 @@ export interface PanelContext {
|
|
|
31
41
|
triggerTestId: string;
|
|
32
42
|
/** testId 属性名 */
|
|
33
43
|
attrName: string;
|
|
44
|
+
/** ant-design-vue 当前生效的 CSS 类名前缀 */
|
|
45
|
+
prefixCls: string;
|
|
34
46
|
}
|
|
35
47
|
export type PanelInjectStrategy = (ctx: PanelContext) => void;
|
|
36
48
|
/**
|
package/dist/runtime.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,GAAG,SAAS,CAAC,CAAA;CACzD;AAED,MAAM,WAAW,YAAY;IAC3B,kBAAkB;IAClB,SAAS,EAAE,WAAW,CAAA;IACtB,iBAAiB;IACjB,OAAO,EAAE,WAAW,GAAG,IAAI,CAAA;IAC3B,oBAAoB;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,YAAY,KAAK,IAAI,CAAA;AA4e7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,GAAE,cAAmB,GAAG,MAAM,IAAI,CAqF7E;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,GAAE,cAAmB,GAAG,IAAI,CAiDtE"}
|
package/dist/runtime.js
CHANGED
|
@@ -1,8 +1,40 @@
|
|
|
1
1
|
// src/runtime.ts
|
|
2
|
-
function
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
function cls(prefix, name) {
|
|
3
|
+
return `.${prefix}-${name}`;
|
|
4
|
+
}
|
|
5
|
+
function detectPrefixCls() {
|
|
6
|
+
try {
|
|
7
|
+
const styles = getComputedStyle(document.documentElement);
|
|
8
|
+
for (let i = 0; i < styles.length; i++) {
|
|
9
|
+
const prop = styles[i];
|
|
10
|
+
const m = prop.match(/^--(ant|[a-z]+)-/);
|
|
11
|
+
if (m && m[1]) return m[1];
|
|
12
|
+
}
|
|
13
|
+
const buttons = document.querySelectorAll('[class*="-btn"]');
|
|
14
|
+
for (const btn of buttons) {
|
|
15
|
+
for (const clsName of btn.classList) {
|
|
16
|
+
if (clsName.endsWith("-btn") && clsName.length > 4) {
|
|
17
|
+
return clsName.slice(0, -4);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const antElements = document.querySelectorAll('[class*="ant-"]');
|
|
22
|
+
if (antElements.length > 0) return "ant";
|
|
23
|
+
} catch {
|
|
24
|
+
}
|
|
25
|
+
return "ant";
|
|
26
|
+
}
|
|
27
|
+
var _cachedPrefixCls = null;
|
|
28
|
+
function resolvePrefixCls(userPrefix) {
|
|
29
|
+
if (userPrefix) return userPrefix;
|
|
30
|
+
if (_cachedPrefixCls !== null) return _cachedPrefixCls;
|
|
31
|
+
_cachedPrefixCls = detectPrefixCls();
|
|
32
|
+
return _cachedPrefixCls;
|
|
33
|
+
}
|
|
34
|
+
function getPanelMode(panel, pfx) {
|
|
35
|
+
if (panel.classList.contains(`${pfx}-picker-month-panel`)) return "month";
|
|
36
|
+
if (panel.classList.contains(`${pfx}-picker-year-panel`)) return "year";
|
|
37
|
+
if (panel.classList.contains(`${pfx}-picker-decade-panel`)) return "decade";
|
|
6
38
|
return "date";
|
|
7
39
|
}
|
|
8
40
|
var MONTH_NAMES = [
|
|
@@ -19,8 +51,8 @@ var MONTH_NAMES = [
|
|
|
19
51
|
"nov",
|
|
20
52
|
"dec"
|
|
21
53
|
];
|
|
22
|
-
function injectHeaderViewButtons(panel, prefix, attrName, suffix) {
|
|
23
|
-
const headerView = panel.querySelector("
|
|
54
|
+
function injectHeaderViewButtons(panel, prefix, attrName, suffix, pfx) {
|
|
55
|
+
const headerView = panel.querySelector(cls(pfx, "picker-header-view"));
|
|
24
56
|
if (!headerView) return;
|
|
25
57
|
const buttons = headerView.querySelectorAll("button");
|
|
26
58
|
buttons.forEach((btn) => {
|
|
@@ -43,25 +75,25 @@ function injectHeaderViewButtons(panel, prefix, attrName, suffix) {
|
|
|
43
75
|
});
|
|
44
76
|
}
|
|
45
77
|
var _observedContainers = /* @__PURE__ */ new WeakSet();
|
|
46
|
-
function injectSinglePanel(panel, prefix, attrName, suffix) {
|
|
47
|
-
const mode = getPanelMode(panel);
|
|
78
|
+
function injectSinglePanel(panel, prefix, attrName, suffix, pfx) {
|
|
79
|
+
const mode = getPanelMode(panel, pfx);
|
|
48
80
|
const setAttr = (selector, name) => {
|
|
49
81
|
const el = panel.querySelector(selector);
|
|
50
82
|
if (el && !el.hasAttribute(attrName)) {
|
|
51
83
|
el.setAttribute(attrName, `${prefix}-${name}${suffix}`);
|
|
52
84
|
}
|
|
53
85
|
};
|
|
54
|
-
setAttr("
|
|
55
|
-
setAttr("
|
|
56
|
-
setAttr("
|
|
57
|
-
setAttr("
|
|
58
|
-
setAttr("
|
|
59
|
-
injectHeaderViewButtons(panel, prefix, attrName, suffix);
|
|
60
|
-
injectPanelCells(panel, prefix, attrName, suffix);
|
|
86
|
+
setAttr(cls(pfx, "picker-header-super-prev-btn"), "super-prev");
|
|
87
|
+
setAttr(cls(pfx, "picker-header-prev-btn"), "prev");
|
|
88
|
+
setAttr(cls(pfx, "picker-header-next-btn"), "next");
|
|
89
|
+
setAttr(cls(pfx, "picker-header-super-next-btn"), "super-next");
|
|
90
|
+
setAttr(cls(pfx, "picker-header-view"), `header-${mode}`);
|
|
91
|
+
injectHeaderViewButtons(panel, prefix, attrName, suffix, pfx);
|
|
92
|
+
injectPanelCells(panel, prefix, attrName, suffix, pfx);
|
|
61
93
|
}
|
|
62
|
-
function injectPanelCells(panel, prefix, attrName, suffix) {
|
|
63
|
-
const mode = getPanelMode(panel);
|
|
64
|
-
const cells = panel.querySelectorAll("
|
|
94
|
+
function injectPanelCells(panel, prefix, attrName, suffix, pfx) {
|
|
95
|
+
const mode = getPanelMode(panel, pfx);
|
|
96
|
+
const cells = panel.querySelectorAll(cls(pfx, "picker-cell-inner"));
|
|
65
97
|
cells.forEach((cell) => {
|
|
66
98
|
const el = cell;
|
|
67
99
|
if (el.hasAttribute(attrName)) return;
|
|
@@ -86,30 +118,29 @@ function injectPanelCells(panel, prefix, attrName, suffix) {
|
|
|
86
118
|
break;
|
|
87
119
|
}
|
|
88
120
|
});
|
|
89
|
-
injectMenuItems(attrName);
|
|
90
121
|
}
|
|
91
122
|
function injectPickerPanel(ctx) {
|
|
92
|
-
const { container, triggerTestId, attrName } = ctx;
|
|
123
|
+
const { container, triggerTestId, attrName, prefixCls: pfx } = ctx;
|
|
93
124
|
const prefix = `${triggerTestId}-dropdown`;
|
|
94
125
|
container.setAttribute(attrName, prefix);
|
|
95
|
-
const isRange = container.classList.contains(
|
|
126
|
+
const isRange = container.classList.contains(`${pfx}-picker-dropdown-range`);
|
|
96
127
|
const injectAllPanels = () => {
|
|
97
|
-
const panels = container.querySelectorAll("
|
|
128
|
+
const panels = container.querySelectorAll(cls(pfx, "picker-panel"));
|
|
98
129
|
if (isRange && panels.length >= 2) {
|
|
99
|
-
injectSinglePanel(panels[0], prefix, attrName, "-left");
|
|
100
|
-
injectSinglePanel(panels[1], prefix, attrName, "-right");
|
|
130
|
+
injectSinglePanel(panels[0], prefix, attrName, "-left", pfx);
|
|
131
|
+
injectSinglePanel(panels[1], prefix, attrName, "-right", pfx);
|
|
101
132
|
} else {
|
|
102
133
|
const panel = panels[0] || container;
|
|
103
|
-
injectSinglePanel(panel, prefix, attrName, "");
|
|
134
|
+
injectSinglePanel(panel, prefix, attrName, "", pfx);
|
|
104
135
|
}
|
|
105
|
-
const presets = container.querySelectorAll("
|
|
136
|
+
const presets = container.querySelectorAll(`${cls(pfx, "picker-presets")} .${pfx}-tag`);
|
|
106
137
|
presets.forEach((tag) => {
|
|
107
138
|
const el = tag;
|
|
108
139
|
if (el.hasAttribute(attrName)) return;
|
|
109
140
|
const text = el.textContent?.trim() || "";
|
|
110
141
|
el.setAttribute(attrName, `${prefix}-preset-${text}`);
|
|
111
142
|
});
|
|
112
|
-
const timeColumns = container.querySelectorAll("
|
|
143
|
+
const timeColumns = container.querySelectorAll(cls(pfx, "picker-time-panel-column"));
|
|
113
144
|
timeColumns.forEach((col, i) => {
|
|
114
145
|
const el = col;
|
|
115
146
|
if (el.hasAttribute(attrName)) return;
|
|
@@ -128,9 +159,9 @@ function injectPickerPanel(ctx) {
|
|
|
128
159
|
btn.setAttribute(attrName, `${prefix}-${name}`);
|
|
129
160
|
}
|
|
130
161
|
};
|
|
131
|
-
setFooterBtn("
|
|
132
|
-
setFooterBtn("
|
|
133
|
-
setFooterBtn("
|
|
162
|
+
setFooterBtn(`${cls(pfx, "picker-ok")} button`, "ok");
|
|
163
|
+
setFooterBtn(`${cls(pfx, "picker-now")} button`, "now");
|
|
164
|
+
setFooterBtn(cls(pfx, "picker-now-btn"), "now");
|
|
134
165
|
};
|
|
135
166
|
injectAllPanels();
|
|
136
167
|
if (!_observedContainers.has(container)) {
|
|
@@ -146,14 +177,14 @@ function injectPickerPanel(ctx) {
|
|
|
146
177
|
}
|
|
147
178
|
}
|
|
148
179
|
function injectCascaderPanel(ctx) {
|
|
149
|
-
const { container, triggerTestId, attrName } = ctx;
|
|
180
|
+
const { container, triggerTestId, attrName, prefixCls: pfx } = ctx;
|
|
150
181
|
const prefix = `${triggerTestId}-dropdown`;
|
|
151
182
|
container.setAttribute(attrName, prefix);
|
|
152
|
-
const menus = container.querySelectorAll("
|
|
183
|
+
const menus = container.querySelectorAll(cls(pfx, "cascader-menu"));
|
|
153
184
|
menus.forEach((menu, i) => {
|
|
154
185
|
const el = menu;
|
|
155
186
|
el.setAttribute(attrName, `${prefix}-menu-${i}`);
|
|
156
|
-
const items = menu.querySelectorAll("
|
|
187
|
+
const items = menu.querySelectorAll(cls(pfx, "cascader-menu-item"));
|
|
157
188
|
items.forEach((item) => {
|
|
158
189
|
const li = item;
|
|
159
190
|
const text = li.textContent?.trim() || "";
|
|
@@ -162,28 +193,28 @@ function injectCascaderPanel(ctx) {
|
|
|
162
193
|
});
|
|
163
194
|
}
|
|
164
195
|
function injectSelectPanel(ctx) {
|
|
165
|
-
const { container, triggerTestId, attrName } = ctx;
|
|
196
|
+
const { container, triggerTestId, attrName, prefixCls: pfx } = ctx;
|
|
166
197
|
const prefix = `${triggerTestId}-dropdown`;
|
|
167
198
|
container.setAttribute(attrName, prefix);
|
|
168
199
|
const injectAllItems = () => {
|
|
169
|
-
const options = container.querySelectorAll("
|
|
200
|
+
const options = container.querySelectorAll(cls(pfx, "select-item-option"));
|
|
170
201
|
options.forEach((opt) => {
|
|
171
202
|
const el = opt;
|
|
172
203
|
if (el.hasAttribute(attrName)) return;
|
|
173
204
|
const title = el.getAttribute("title") || el.textContent?.trim() || "";
|
|
174
205
|
el.setAttribute(attrName, `${prefix}-option-${title}`);
|
|
175
206
|
});
|
|
176
|
-
const treeNodes = container.querySelectorAll("
|
|
207
|
+
const treeNodes = container.querySelectorAll(cls(pfx, "select-tree-treenode"));
|
|
177
208
|
treeNodes.forEach((node) => {
|
|
178
209
|
const el = node;
|
|
179
|
-
const content = el.querySelector("
|
|
210
|
+
const content = el.querySelector(cls(pfx, "select-tree-node-content-wrapper"));
|
|
180
211
|
const title = content?.getAttribute("title") || content?.textContent?.trim() || "";
|
|
181
212
|
if (content && !content.hasAttribute(attrName)) {
|
|
182
213
|
content.setAttribute(attrName, `${prefix}-tree-${title}`);
|
|
183
214
|
}
|
|
184
|
-
const switcher = el.querySelector("
|
|
215
|
+
const switcher = el.querySelector(cls(pfx, "select-tree-switcher"));
|
|
185
216
|
if (switcher && !switcher.hasAttribute(attrName)) {
|
|
186
|
-
const isOpen = switcher.classList.contains(
|
|
217
|
+
const isOpen = switcher.classList.contains(`${pfx}-select-tree-switcher_open`);
|
|
187
218
|
const state = isOpen ? "collapse" : "expand";
|
|
188
219
|
switcher.setAttribute(attrName, `${prefix}-tree-switcher-${state}-${title}`);
|
|
189
220
|
}
|
|
@@ -202,17 +233,19 @@ function injectSelectPanel(ctx) {
|
|
|
202
233
|
observer.observe(container, { childList: true, subtree: true });
|
|
203
234
|
}
|
|
204
235
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
236
|
+
function buildDefaultPanels(pfx) {
|
|
237
|
+
return {
|
|
238
|
+
[cls(pfx, "picker-dropdown")]: injectPickerPanel,
|
|
239
|
+
[cls(pfx, "cascader-dropdown")]: injectCascaderPanel,
|
|
240
|
+
[cls(pfx, "select-dropdown")]: injectSelectPanel
|
|
241
|
+
};
|
|
242
|
+
}
|
|
210
243
|
function getTriggerTestId(trigger, attrName) {
|
|
211
244
|
if (!trigger) return "unknown-picker";
|
|
212
245
|
return trigger.getAttribute(attrName) || trigger.getAttribute("id") || "unknown-picker";
|
|
213
246
|
}
|
|
214
|
-
function findActiveTrigger(attrName) {
|
|
215
|
-
const focused = document.querySelector("
|
|
247
|
+
function findActiveTrigger(attrName, pfx) {
|
|
248
|
+
const focused = document.querySelector(cls(pfx, "picker-focused"));
|
|
216
249
|
if (focused) {
|
|
217
250
|
if (focused.hasAttribute(attrName)) return focused;
|
|
218
251
|
const inner = focused.querySelector(`[${attrName}]`);
|
|
@@ -220,9 +253,9 @@ function findActiveTrigger(attrName) {
|
|
|
220
253
|
const input = focused.querySelector("input[id]");
|
|
221
254
|
if (input) return input;
|
|
222
255
|
}
|
|
223
|
-
const selectOpen = document.querySelector("
|
|
256
|
+
const selectOpen = document.querySelector(cls(pfx, "select-open"));
|
|
224
257
|
if (selectOpen?.hasAttribute(attrName)) return selectOpen;
|
|
225
|
-
const cascader = document.querySelector("
|
|
258
|
+
const cascader = document.querySelector(cls(pfx, "cascader-picker-focused"));
|
|
226
259
|
if (cascader?.hasAttribute(attrName)) return cascader;
|
|
227
260
|
const expanded = document.querySelector(
|
|
228
261
|
`[${attrName}][aria-expanded="true"]`
|
|
@@ -230,33 +263,40 @@ function findActiveTrigger(attrName) {
|
|
|
230
263
|
if (expanded) return expanded;
|
|
231
264
|
return null;
|
|
232
265
|
}
|
|
233
|
-
function injectMenuItems(attrName, root = document) {
|
|
266
|
+
function injectMenuItems(attrName, pfx, root = document) {
|
|
234
267
|
const itemRules = [
|
|
235
|
-
{ selector: "
|
|
236
|
-
{ selector: "
|
|
237
|
-
{ selector: "
|
|
268
|
+
{ selector: cls(pfx, "menu-item"), prefix: "a-menu-item-" },
|
|
269
|
+
{ selector: cls(pfx, "menu-submenu"), textSelector: cls(pfx, "menu-submenu-title"), prefix: "a-sub-menu-" },
|
|
270
|
+
{ selector: cls(pfx, "menu-item-group"), textSelector: cls(pfx, "menu-item-group-title"), prefix: "a-menu-item-group-" }
|
|
238
271
|
];
|
|
272
|
+
const injectSingle = (el, rule) => {
|
|
273
|
+
if (el.hasAttribute(attrName)) return;
|
|
274
|
+
const id = el.getAttribute("id");
|
|
275
|
+
if (id) {
|
|
276
|
+
el.setAttribute(attrName, id);
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
const textTarget = rule.textSelector ? el.querySelector(rule.textSelector) : el;
|
|
280
|
+
const text = (textTarget?.textContent || "").trim().replace(/\s+/g, "-");
|
|
281
|
+
if (text) {
|
|
282
|
+
el.setAttribute(attrName, rule.prefix + text);
|
|
283
|
+
}
|
|
284
|
+
};
|
|
239
285
|
for (const rule of itemRules) {
|
|
286
|
+
if (root instanceof HTMLElement && root.matches(rule.selector)) {
|
|
287
|
+
injectSingle(root, rule);
|
|
288
|
+
}
|
|
240
289
|
const items = root.querySelectorAll(rule.selector);
|
|
241
290
|
items.forEach((item) => {
|
|
242
|
-
|
|
243
|
-
if (el.hasAttribute(attrName)) return;
|
|
244
|
-
const id = el.getAttribute("id");
|
|
245
|
-
if (id) {
|
|
246
|
-
el.setAttribute(attrName, id);
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
const textTarget = rule.textSelector ? el.querySelector(rule.textSelector) : el;
|
|
250
|
-
const text = (textTarget?.textContent || "").trim().replace(/\s+/g, "-");
|
|
251
|
-
if (text) {
|
|
252
|
-
el.setAttribute(attrName, rule.prefix + text);
|
|
253
|
-
}
|
|
291
|
+
injectSingle(item, rule);
|
|
254
292
|
});
|
|
255
293
|
}
|
|
256
294
|
}
|
|
257
295
|
function setupAntDropdownTestIds(opts = {}) {
|
|
258
296
|
const attrName = opts.attributeName ?? "data-testid";
|
|
259
|
-
const
|
|
297
|
+
const pfx = resolvePrefixCls(opts.prefixCls);
|
|
298
|
+
const defaultPanels = buildDefaultPanels(pfx);
|
|
299
|
+
const panels = { ...defaultPanels, ...opts.panels };
|
|
260
300
|
const observer = new MutationObserver((mutations) => {
|
|
261
301
|
for (const mutation of mutations) {
|
|
262
302
|
for (const node of mutation.addedNodes) {
|
|
@@ -268,21 +308,22 @@ function setupAntDropdownTestIds(opts = {}) {
|
|
|
268
308
|
if (container.hasAttribute(attrName)) continue;
|
|
269
309
|
if (strategy) {
|
|
270
310
|
queueMicrotask(() => {
|
|
271
|
-
const trigger = findActiveTrigger(attrName);
|
|
311
|
+
const trigger = findActiveTrigger(attrName, pfx);
|
|
272
312
|
const triggerTestId = getTriggerTestId(trigger, attrName);
|
|
273
313
|
const ctx = {
|
|
274
314
|
container,
|
|
275
315
|
trigger,
|
|
276
316
|
triggerTestId,
|
|
277
|
-
attrName
|
|
317
|
+
attrName,
|
|
318
|
+
prefixCls: pfx
|
|
278
319
|
};
|
|
279
320
|
strategy(ctx);
|
|
280
321
|
});
|
|
281
322
|
}
|
|
282
323
|
}
|
|
283
324
|
}
|
|
284
|
-
const uploadByTestId = node.matches(
|
|
285
|
-
const uploadById = uploadByTestId.length === 0 ? node.matches(
|
|
325
|
+
const uploadByTestId = node.matches(`${cls(pfx, "upload")}[${attrName}]`) ? [node] : Array.from(node.querySelectorAll(`${cls(pfx, "upload")}[${attrName}]`));
|
|
326
|
+
const uploadById = uploadByTestId.length === 0 ? node.matches(`${cls(pfx, "upload")}[id]`) ? [node] : Array.from(node.querySelectorAll(`${cls(pfx, "upload")}[id]`)) : [];
|
|
286
327
|
const uploads = [...uploadByTestId, ...uploadById];
|
|
287
328
|
for (const upload of uploads) {
|
|
288
329
|
if (!(upload instanceof HTMLElement)) continue;
|
|
@@ -296,33 +337,35 @@ function setupAntDropdownTestIds(opts = {}) {
|
|
|
296
337
|
}
|
|
297
338
|
}
|
|
298
339
|
}
|
|
299
|
-
injectMenuItems(attrName, node instanceof HTMLElement ? node : document);
|
|
340
|
+
injectMenuItems(attrName, pfx, node instanceof HTMLElement ? node : document);
|
|
300
341
|
}
|
|
301
342
|
}
|
|
302
343
|
});
|
|
303
344
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
304
345
|
requestAnimationFrame(() => {
|
|
305
|
-
injectMenuItems(attrName);
|
|
346
|
+
injectMenuItems(attrName, pfx);
|
|
306
347
|
});
|
|
307
348
|
return () => observer.disconnect();
|
|
308
349
|
}
|
|
309
350
|
function injectCurrentDropdowns(opts = {}) {
|
|
310
351
|
const attrName = opts.attributeName ?? "data-testid";
|
|
311
|
-
const
|
|
352
|
+
const pfx = resolvePrefixCls(opts.prefixCls);
|
|
353
|
+
const defaultPanels = buildDefaultPanels(pfx);
|
|
354
|
+
const panels = { ...defaultPanels, ...opts.panels };
|
|
312
355
|
for (const [selector, strategy] of Object.entries(panels)) {
|
|
313
356
|
const containers = document.querySelectorAll(selector);
|
|
314
357
|
containers.forEach((container) => {
|
|
315
358
|
if (!(container instanceof HTMLElement)) return;
|
|
316
359
|
if (container.hasAttribute(attrName)) return;
|
|
317
360
|
if (!strategy) return;
|
|
318
|
-
const trigger = findActiveTrigger(attrName);
|
|
361
|
+
const trigger = findActiveTrigger(attrName, pfx);
|
|
319
362
|
const triggerTestId = getTriggerTestId(trigger, attrName);
|
|
320
|
-
strategy({ container, trigger, triggerTestId, attrName });
|
|
363
|
+
strategy({ container, trigger, triggerTestId, attrName, prefixCls: pfx });
|
|
321
364
|
});
|
|
322
365
|
}
|
|
323
366
|
const uploads = [
|
|
324
|
-
...Array.from(document.querySelectorAll(
|
|
325
|
-
...Array.from(document.querySelectorAll(
|
|
367
|
+
...Array.from(document.querySelectorAll(`${cls(pfx, "upload")}[${attrName}]`)),
|
|
368
|
+
...Array.from(document.querySelectorAll(`${cls(pfx, "upload")}[id]`))
|
|
326
369
|
];
|
|
327
370
|
const seen = /* @__PURE__ */ new Set();
|
|
328
371
|
uploads.forEach((upload) => {
|
|
@@ -339,7 +382,7 @@ function injectCurrentDropdowns(opts = {}) {
|
|
|
339
382
|
}
|
|
340
383
|
}
|
|
341
384
|
});
|
|
342
|
-
injectMenuItems(attrName);
|
|
385
|
+
injectMenuItems(attrName, pfx);
|
|
343
386
|
}
|
|
344
387
|
export {
|
|
345
388
|
injectCurrentDropdowns,
|