@agile-team/wl-skills-ui 1.9.8 → 1.9.10

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/CHANGELOG.md CHANGED
@@ -4,6 +4,28 @@ All notable changes to **@agile-team/wl-skills-ui** will be documented in this f
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
 
7
+ ## [1.9.10] - 2026-08-01
8
+
9
+ ### Added
10
+
11
+ - 新增 `@agile-team/wl-skills-ui/runtime/auto` 包级保护入口;Skin 项目一次引入即可获得主题锁和普通表格真实溢出 Tooltip 兜底,Native 项目的 `installCommonPreset()` 自动安装相同保护。
12
+ - 新增长文本 DOM 回归测试,覆盖真实溢出、未溢出、动态/虚拟行、Element 原生 Tooltip 优先以及操作列、Tag、定制区域等排除边界。
13
+
14
+ ### Fixed
15
+
16
+ - 修复平台将 `.ag-cell` 与 `.ag-cell-value` 复用为 flex 节点时 `text-overflow: ellipsis` 只裁切、不绘制省略号的问题。
17
+ - 普通 Element Table、BaseTable 与 AG Grid 不再依赖页面是否调用 `defineColumns()` 才能获得长文本兜底;运行时仅在真实溢出时创建统一提示,不接管已有 Tooltip 或语义组件。
18
+
19
+ ### Changed
20
+
21
+ - SCSS 发布门禁由引用路径检查升级为 full/skin 入口真实编译,避免合法性问题进入 npm 包。
22
+
23
+ ## [1.9.9] - 2026-07-29
24
+
25
+ ### Fixed
26
+
27
+ - 将 Element Table 与 AG Grid 的行 hover/selected 底色统一为品牌色 4%/7% 浅层,并保证 AG Grid 选中态优先于 hover,缓解可编辑控件下方色带过重且不覆盖校验态或业务语义单元格。
28
+
7
29
  ## [1.9.8] - 2026-07-29
8
30
 
9
31
  ### Fixed
package/README.md CHANGED
@@ -103,18 +103,23 @@ wl-skills-ui/
103
103
  │ │ ├── registry.ts # createPreset / installPreset
104
104
  │ │ ├── common.ts # 通用业务预设(enable/audit/verify + 起步包)
105
105
  │ │ └── index.ts
106
+ │ ├── auto.ts # Skin/老项目包级保护自动入口
107
+ │ ├── guards.ts # 主题锁 + 长文本溢出保护聚合
108
+ │ ├── overflow-tooltip.ts # 普通表格真实溢出 Tooltip 兜底
106
109
  │ └── index.ts # 公共 API 入口
107
110
  │
108
111
  ├── scanner/ # 自动化扫描 / 修复
109
112
  │ ├── index.mjs # CLI(含 --layer/--vendor/--mode 过滤)
110
113
  │ ├── rules/ # 规则集
111
114
  │ │ ├── _shared.mjs # 公共工具 + inferMeta(layer/vendor)
112
- │ │ ├── table.mjs # R001 R002 R003 R014
115
+ │ │ ├── table.mjs # R001 R002 R003 R014 R039
113
116
  │ │ ├── form.mjs # R006 R007 R008
114
- │ │ ├── button.mjs # R004 R005 R015
117
+ │ │ ├── button.mjs # R004 R005 R015 R038
115
118
  │ │ ├── tag.mjs # R009 R010 R012
116
119
  │ │ ├── dialog.mjs # R011
117
120
  │ │ ├── color.mjs # R016 R017 R018
121
+ │ │ ├── semantic.mjs # R025 R026 R027
122
+ │ │ ├── componentFamily.mjs # R031 R032 R033 R034 R035 R036 R037
118
123
  │ │ └── index.mjs # 聚合 + addRules() 插件机制
119
124
  │ ├── fix.mjs # 自动修复引擎
120
125
  │ ├── integration.mjs # 接入完整性检查
@@ -134,7 +139,8 @@ wl-skills-ui/
134
139
  │ │ ├── el-table/SKILL.md
135
140
  │ │ ├── el-form/SKILL.md
136
141
  │ │ ├── el-dialog/SKILL.md
137
- │ │ └── el-tag/SKILL.md
142
+ │ │ ├── el-tag/SKILL.md
143
+ │ │ └── component-family/ # 扩展组件族(card/tabs/descriptions/drawer/upload/steps/feedback)
138
144
  │ ├── vendors/ # ⭐ L2 封装识别 SKILL
139
145
  │ │ ├── base-table/SKILL.md # 优先级 #1
140
146
  │ │ ├── jh-components/SKILL.md # 优先级 #2
@@ -149,7 +155,9 @@ wl-skills-ui/
149
155
  │ │ └── migration/SKILL.md
150
156
  │ └── ops/ # 操作类 SKILL
151
157
  │ ├── scan/SKILL.md
152
- │ └── fix/SKILL.md
158
+ │ ├── audit/SKILL.md
159
+ │ ├── fix/SKILL.md
160
+ │ └── migrate/SKILL.md
153
161
  │
154
162
  ├── templates/ # 代码生成模板
155
163
  │ ├── list-page/TPL-LIST.md
@@ -200,7 +208,7 @@ yarn add @agile-team/wl-skills-ui
200
208
  |---|---|---|
201
209
  | `element-plus` | **`2.2.6-prod.3`** | 集团 jh- 定制版;EP 2.3.0 起引入 `.el-input__wrapper`,与 jh-ui 3.x 不兼容 |
202
210
  | `@jhlc/jh-ui` | **`3.1.0`** | SCSS 皮肤包,`.com-text` label 包裹 + `.has-colon` 冒号注入(wl-skills-ui 已统一屏蔽表单冒号) |
203
- | `@agile-team/wl-skills-ui` | `^1.9.8` | 已对齐上述组合的 DOM 假设、客户主题锁、圆角契约与定制页样式边界 |
211
+ | `@agile-team/wl-skills-ui` | `^1.9.10` | 已对齐上述组合的 DOM 假设、客户主题锁、圆角契约、表格长文本兜底与定制页样式边界 |
204
212
 
205
213
  三种识别方式,任选其一:
206
214
 
@@ -214,10 +222,17 @@ yarn add @agile-team/wl-skills-ui
214
222
 
215
223
  ## 版本亮点
216
224
 
217
- 当前 v1.9.8:
225
+ 当前 v1.9.10:
226
+
227
+ - **长文本真正包级闭环**:普通 Element Table、BaseTable 与 AG Grid 即使没有经过 `defineColumns()`,真实超宽时也会稳定显示省略号,并由 `runtime/auto` 在悬停或键盘聚焦时兜底完整文本提示;动态行和虚拟滚动无需额外处理。
228
+ - **严格防污染边界**:已有组件 Tooltip 优先,编辑列、操作列、Tag、复选框、自定义 renderer、主动换行列、登录页及显式皮肤豁免区域均不接管;没有溢出时不创建 Tooltip。
229
+ - **发布验证补强**:新增真实 DOM 行为测试,并将 SCSS 门禁从路径存在检查升级为完整入口编译,防止 flex 省略冲突或无效选择器再次漏发。
230
+
231
+ 上一版 v1.9.9:
218
232
 
219
233
  - **主操作按钮不再漏色**:新增/新建/添加/创建类按钮强制使用客户主题 `primary` 填充样式,扫描器可识别并自动修复漏写 `type` 或误带 `plain` 的存量代码。
220
234
  - **长文本交互统一**:普通数据列在空间不足时单行省略,悬停显示完整内容;Tag、操作列、自定义渲染和主动换行列不被机械覆盖。
235
+ - **表格行状态降噪**:Element Table 与 AG Grid 的 hover/selected 统一为品牌色 4%/7% 浅层,选中态优先于悬停,同时保留编辑控件、校验态、Tag 和业务语义单元格底色。
221
236
  - **紧凑表单字号闭环**:业务表单 label、输入值、选择值、placeholder、textarea 与数字输入统一为 12px;登录页和显式定制区域继续保持项目自身设计。
222
237
  - **输入边框状态闭环**:textarea 聚焦始终显示品牌色边框;数字输入兼容 Element Plus 新旧及混合 wrapper DOM,默认、hover、focus、错误、禁用态均只保留一层正确边框。
223
238
  - **分裂操作保持一体**:BaseToolbar 的主动作与下拉箭头共用外轮廓和状态色,下拉菜单中的业务按钮扁平化为菜单项;规则精准限定在平台工具栏结构,不污染普通按钮组和普通下拉菜单。
@@ -277,7 +292,7 @@ yarn add @agile-team/wl-skills-ui
277
292
  - **R025** 语义合规:`options:[]` 退化检测 → 升级 `renderTagSlot` / `renderDictClassifyTag`
278
293
  - **R026** 原生 HTML 拦截:`<table>/<input>/<select>/<button>/<textarea>` → 替换 el-* 组件
279
294
  - `scan --only/--skip` 规则过滤 + `exempt init` 智能豁免脚手架
280
- - `scan --baseline` 漂移对比 + SCSS 链路检查 + R-rule 单一事实源(32 条)
295
+ - `scan --baseline` 漂移对比 + SCSS 链路检查 + R-rule 单一事实源(35 条)
281
296
 
282
297
  历史亮点(v1.7.1):
283
298
 
@@ -372,6 +387,7 @@ npx wl-ui init --mode native
372
387
  // 4. src/main.ts
373
388
  import { installCommonPreset } from "@agile-team/wl-skills-ui/runtime/common-preset";
374
389
  installCommonPreset();
390
+ // installCommonPreset 已包含主题锁和普通表格长文本包级保护,无需重复引入 runtime/auto。
375
391
  ```
376
392
 
377
393
  ```vue
@@ -411,8 +427,13 @@ npx wl-ui init --mode skin
411
427
  @use "@agile-team/wl-skills-ui/styles/presets/skin" as *;
412
428
  ```
413
429
 
430
+ ```ts
431
+ // 3. src/main.ts:只安装包级保护,不接管页面布局或业务列定义
432
+ import "@agile-team/wl-skills-ui/runtime/auto";
433
+ ```
434
+
414
435
  ```bash
415
- # 3. AI 编辑器中触发:
436
+ # 4. AI 编辑器中触发:
416
437
  # "用 wl-ui 的 legacy-skin-align 流程跑一下当前项目"
417
438
  # → AI 按 _flows/legacy-skin-align.md 顺序执行 6 个 phase
418
439
 
@@ -624,15 +645,19 @@ export const myRules = [
624
645
 
625
646
  ---
626
647
 
627
- ## AI/MCP 智能引导
648
+ ## AI/MCP 智能引导(10 个工具)
628
649
 
629
650
  | MCP Tool | 作用 |
630
651
  | ----------------------- | ---------------------------------------------------------- |
631
652
  | `wl_ui_check` | 检查 tokens/styles/runtime 接入完整性 |
632
653
  | `wl_ui_scan` | 扫描 UI 风格偏差,输出 Markdown 或 JSON |
633
654
  | `wl_ui_fix_dry_run` | 预览自动修复,不实际写入 |
655
+ | `wl_ui_detect_skin` | 检测项目 vendor 版本配对 |
634
656
  | `wl_ui_skill_prompt` | 输出 AI 触发提示 |
635
657
  | `wl_ui_route_intent` | 根据自然语言识别 UI 治理意图并推荐 flow/tool/skill |
658
+ | `wl_ui_list_rules` | 列出全部扫描规则及说明 |
659
+ | `wl_ui_describe_rule` | 查询单条规则详情 |
660
+ | `wl_ui_drift` | 对比基线漂移 |
636
661
  | `wl_ui_recommend_flow` | 根据扫描 JSON 推荐 nextActions 和 `wl-skills-kit` 桥接动作 |
637
662
 
638
663
  推荐智能体流程:
@@ -660,9 +685,14 @@ export const myRules = [
660
685
  | `renderRatingLevel(v)` | 评级颜色 |
661
686
  | `registerColumnAutoMap(field, config)` | 注册新字段自动渲染 |
662
687
  | `installCommonPreset()` | 安装通用业务预设 |
688
+ | `installUiRuntimeGuards()` | 安装主题锁与普通表格长文本包级保护 |
689
+ | `installOverflowTooltipGuard()` | 单独安装真实溢出 Tooltip 兜底 |
663
690
  | `setDictResolver(fn)` | 解耦动态字典查询 |
664
691
  | `createPreset(config)` / `installPreset(config)` | 自定义 preset 工厂 |
665
692
 
693
+ 长文本兜底的接入方式、排除边界和验收方法见
694
+ [表格长文本包级兜底机制](docs/table-overflow-tooltip.md)。
695
+
666
696
  ---
667
697
 
668
698
  ## 设计令牌
package/bin/wl-ui.js CHANGED
@@ -573,7 +573,8 @@ ${
573
573
  installCommonPreset();
574
574
  `
575
575
  : `
576
- ℹ️ skin 模式不需要引入 runtime,页面布局 / 业务代码均保持现状。
576
+ ⚠️ 请手动在 src/main.ts 添加包级保护(不接管页面布局 / 业务列定义):
577
+ import '@agile-team/wl-skills-ui/runtime/auto';
577
578
  `
578
579
  }`);
579
580
  }
@@ -11,7 +11,7 @@
11
11
  | `element-plus` | **`2.2.6-prod.3`** | 集团 jh- 定制版,搭配 `@jhlc/jh-ui` 使用,DOM 仍为 `.el-input > .el-input__inner` 直挂结构(**EP 2.3.0 起才引入 `.el-input__wrapper`**) |
12
12
  | `@jhlc/jh-ui` | **`3.1.0`** | SCSS 皮肤包,`.com-text` label 包裹、`.has-colon ::after` 冒号注入、`.el-form-item--default { margin-bottom: 24px }` 等强约束 |
13
13
  | `@jhlc/common-core` | `3.1.0` 或 `3.1.0-prod.x` | 基础 util/types,`@jhlc/jh-ui` 间接依赖 |
14
- | `@agile-team/wl-skills-ui` | `^1.9.8` | 已对齐 jh-ui 3.1.0 + EP 2.2.6-prod.3 的 DOM 假设、客户主题锁、6px 基础圆角、紧凑表单、分裂按钮、长文本提示、定制页样式边界与 Vite 4 开发转换 |
14
+ | `@agile-team/wl-skills-ui` | `^1.9.10` | 已对齐 jh-ui 3.1.0 + EP 2.2.6-prod.3 的 DOM 假设、客户主题锁、6px 基础圆角、紧凑表单、表格行状态、分裂按钮、包级长文本提示、定制页样式边界与 Vite 4 开发转换 |
15
15
 
16
16
  ## 项目集群当前实测
17
17
 
@@ -35,7 +35,8 @@
35
35
 
36
36
  ## 适配建议
37
37
 
38
- - 集团内项目:**统一锚定 `element-plus@2.2.6-prod.3` + `@jhlc/jh-ui@3.1.0`**,与 wl-skills-ui v1.9.8 三方对齐。
38
+ - 集团内项目:**统一锚定 `element-plus@2.2.6-prod.3` + `@jhlc/jh-ui@3.1.0`**,与 wl-skills-ui v1.9.10 三方对齐。
39
+ - Skin 项目除全局样式外,在 `main.ts` 引入一次 `@agile-team/wl-skills-ui/runtime/auto`;Native 项目的 `installCommonPreset()` 已包含相同包级保护,不要重复安装。
39
40
  - 升级 `element-plus` 到 2.3+ 前,必须同步升级 `@jhlc/jh-ui` 到对应支持版本,否则 `.com-text` / `.el-input__inner` DOM 与 EP `__wrapper` 体系不兼容。
40
41
  - 新项目接入:见 README 「快速接入」章节,默认会按本表声明 peerDependency 范围。
41
42
 
@@ -0,0 +1,66 @@
1
+ # 表格长文本包级兜底机制
2
+
3
+ ## 目标
4
+
5
+ 凡完整接入 `@agile-team/wl-skills-ui` 的普通 Element Table、BaseTable 与 AG Grid,普通文本单元格在空间不足时统一单行省略;鼠标悬停或键盘聚焦后显示完整文本。业务页面不需要逐列补丁,也不依赖列定义是否经过 `defineColumns()`。
6
+
7
+ 该能力只治理普通文本。Tag、操作按钮、编辑控件、复选框、自定义 renderer 和主动换行内容保留业务组件自身行为。
8
+
9
+ ## 接入
10
+
11
+ Native 项目调用 `installCommonPreset()` 时会自动安装包级保护:
12
+
13
+ ```ts
14
+ import { installCommonPreset } from "@agile-team/wl-skills-ui/runtime/common-preset";
15
+
16
+ installCommonPreset();
17
+ ```
18
+
19
+ Skin/老项目在保留 `skin` 样式入口的同时,在启动文件引入一次自动入口:
20
+
21
+ ```ts
22
+ import "@agile-team/wl-skills-ui/runtime/auto";
23
+ ```
24
+
25
+ 不要同时重复调用 `installCommonPreset()` 和引入 `runtime/auto`。内部安装函数具备幂等保护,但项目应保留单一、清晰的启动入口。
26
+
27
+ ## 工作机制
28
+
29
+ 1. 样式层只对没有子元素的普通纯文本单元格修正单行省略,解决 AG Grid 同一节点同时为 flex 容器时省略号不绘制的问题。
30
+ 2. Runtime 在 `document` 上使用事件委托,不扫描整页,也不使用 `MutationObserver` 监听表格结构。
31
+ 3. 用户悬停或键盘聚焦后才计算 `scrollWidth > clientWidth`;没有真实溢出时不创建 Tooltip。
32
+ 4. Element/AG Grid 已有 Tooltip、`title` 或 `aria-describedby` 时由原组件优先处理,兜底不会重复弹出。
33
+ 5. 动态行、Picker 与虚拟滚动复用相同事件入口,新插入的单元格不需要重新注册。
34
+
35
+ ## 防污染边界
36
+
37
+ 以下内容默认排除:
38
+
39
+ - `.editable-cell`、`.always-editable-cell`、`.ag-cell-inline-editing` 等编辑单元格;
40
+ - `.operations-cell`、`.default-slot-cell`、`.ag-cell-wrap-text`;
41
+ - input、textarea、select、button、Tag、Link、Checkbox、Radio、Switch、日期和数字输入;
42
+ - Element Table 已带 `.el-tooltip` 的原生溢出提示列;
43
+ - `.lp-root`、`.session-login`、`.wl-ui-skin-exempt`、`data-wl-ui-skin="off"` 定制区域。
44
+
45
+ 局部显式退出:
46
+
47
+ ```html
48
+ <div data-wl-ui-overflow="off">保持业务自身长文本行为</div>
49
+ ```
50
+
51
+ 自定义纯文本 renderer 确认需要包级提示时,可在实际文本单元格上标记:
52
+
53
+ ```html
54
+ <div data-wl-ui-overflow="on">自定义但仍按普通文本处理</div>
55
+ ```
56
+
57
+ ## 验收
58
+
59
+ - 短文本:无省略号、无兜底 Tooltip。
60
+ - 长文本:单行省略,悬停或键盘聚焦显示完整内容。
61
+ - 选中行/hover 行:省略和 Tooltip 不受行状态底色影响。
62
+ - 动态/虚拟行:滚动复用 DOM 后仍然有效。
63
+ - 操作列、Tag、编辑态、自定义 renderer:布局与交互保持原样。
64
+ - 登录页和显式豁免区域:不增加任何长文本接管行为。
65
+
66
+ 自动回归测试位于 `scanner/__tests__/overflow-tooltip.test.mjs`;发布前 `npm run verify` 会同时执行 DOM 行为、SCSS 实际编译、构建与包导出检查。
package/es/auto.d.ts ADDED
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/es/auto.js ADDED
@@ -0,0 +1,5 @@
1
+ import { installUiRuntimeGuards } from './chunk-Z2OTWMW6.js';
2
+ import './chunk-Q3N5QNRZ.js';
3
+
4
+ // runtime/auto.ts
5
+ installUiRuntimeGuards();
@@ -328,132 +328,4 @@ registerColumnAutoMaps({
328
328
  }
329
329
  });
330
330
 
331
- // runtime/theme-lock.ts
332
- var BRAND_THEME_TOKENS = Object.freeze({
333
- "--el-color-primary": "#002a8f",
334
- "--el-color-primary-rgb": "0, 42, 143",
335
- "--el-color-primary-light-1": "#1a3f9a",
336
- "--el-color-primary-light-2": "#3355a5",
337
- "--el-color-primary-light-3": "#4d6ab1",
338
- "--el-color-primary-light-4": "#667fbc",
339
- "--el-color-primary-light-5": "#8094c7",
340
- "--el-color-primary-light-6": "#99aad2",
341
- "--el-color-primary-light-7": "#b2bfdd",
342
- "--el-color-primary-light-8": "#ccd4e9",
343
- "--el-color-primary-light-9": "#e5eaf4",
344
- "--el-color-primary-dark-1": "#002681",
345
- "--el-color-primary-dark-2": "#002272",
346
- "--el-color-primary-dark-3": "#001d64",
347
- "--el-color-primary-dark-4": "#001956",
348
- "--el-color-success": "#2bb268",
349
- "--el-color-success-light-1": "#40ba77",
350
- "--el-color-success-light-2": "#55c286",
351
- "--el-color-success-light-3": "#6bcb95",
352
- "--el-color-success-light-4": "#80d3a4",
353
- "--el-color-success-light-5": "#95dbb4",
354
- "--el-color-success-light-6": "#aae3c3",
355
- "--el-color-success-light-7": "#bfebd2",
356
- "--el-color-success-light-8": "#d5f4e1",
357
- "--el-color-success-light-9": "#eaf9f0",
358
- "--el-color-success-dark-1": "#229051",
359
- "--el-color-success-dark-2": "#1b733f",
360
- "--el-color-success-dark-3": "#14562f",
361
- "--el-color-success-dark-4": "#0d3a20",
362
- "--el-color-warning": "#ea9a13",
363
- "--el-color-warning-light-1": "#eca42b",
364
- "--el-color-warning-light-2": "#efae42",
365
- "--el-color-warning-light-3": "#f1b85a",
366
- "--el-color-warning-light-4": "#f3c171",
367
- "--el-color-warning-light-5": "#f5cb89",
368
- "--el-color-warning-light-6": "#f7d5a1",
369
- "--el-color-warning-light-7": "#f9dfb8",
370
- "--el-color-warning-light-8": "#fce8d0",
371
- "--el-color-warning-light-9": "#fef2e7",
372
- "--el-color-warning-dark-1": "#c47f0e",
373
- "--el-color-warning-dark-2": "#9d650a",
374
- "--el-color-warning-dark-3": "#754a07",
375
- "--el-color-warning-dark-4": "#4e3004",
376
- "--el-color-danger": "#bb2d3f",
377
- "--el-color-danger-light-1": "#c34253",
378
- "--el-color-danger-light-2": "#ca5766",
379
- "--el-color-danger-light-3": "#d16b78",
380
- "--el-color-danger-light-4": "#d8808b",
381
- "--el-color-danger-light-5": "#dd969f",
382
- "--el-color-danger-light-6": "#e4abb2",
383
- "--el-color-danger-light-7": "#e8c0c5",
384
- "--el-color-danger-light-8": "#f0d5d9",
385
- "--el-color-danger-light-9": "#f7eaec",
386
- "--el-color-danger-dark-1": "#962433",
387
- "--el-color-danger-dark-2": "#711b26",
388
- "--el-color-danger-dark-3": "#4b1219",
389
- "--el-color-danger-dark-4": "#26090d",
390
- "--el-color-error": "#bb2d3f",
391
- "--el-color-error-light-1": "#c34253",
392
- "--el-color-error-light-2": "#ca5766",
393
- "--el-color-error-light-3": "#d16b78",
394
- "--el-color-error-light-4": "#d8808b",
395
- "--el-color-error-light-5": "#dd969f",
396
- "--el-color-error-light-6": "#e4abb2",
397
- "--el-color-error-light-7": "#e8c0c5",
398
- "--el-color-error-light-8": "#f0d5d9",
399
- "--el-color-error-light-9": "#f7eaec",
400
- "--el-color-error-dark-1": "#962433",
401
- "--el-color-error-dark-2": "#711b26",
402
- "--el-color-error-dark-3": "#4b1219",
403
- "--el-color-error-dark-4": "#26090d",
404
- "--el-border-radius-base": "6px",
405
- "--el-border-radius-small": "2px",
406
- "--el-border-radius-round": "20px",
407
- "--el-border-radius-circle": "100%"
408
- });
409
- var observer;
410
- var waitingForBody = false;
411
- function enforceOn(target) {
412
- if (!target) return;
413
- for (const [name, value] of Object.entries(BRAND_THEME_TOKENS)) {
414
- if (target.style.getPropertyValue(name).trim().toLowerCase() !== value || target.style.getPropertyPriority(name) !== "important") {
415
- target.style.setProperty(name, value, "important");
416
- }
417
- }
418
- }
419
- function bindObserver() {
420
- if (typeof document === "undefined") return;
421
- enforceOn(document.documentElement);
422
- enforceOn(document.body);
423
- if (typeof MutationObserver === "undefined") return;
424
- observer ?? (observer = new MutationObserver((mutations) => {
425
- const bodyChanged = mutations.some((mutation) => mutation.type === "childList");
426
- enforceOn(document.documentElement);
427
- enforceOn(document.body);
428
- if (bodyChanged) bindObserver();
429
- }));
430
- observer.disconnect();
431
- observer.observe(document.documentElement, {
432
- attributes: true,
433
- attributeFilter: ["style"],
434
- childList: true
435
- });
436
- if (document.body) {
437
- observer.observe(document.body, {
438
- attributes: true,
439
- attributeFilter: ["style"]
440
- });
441
- }
442
- }
443
- function installBrandThemeLock() {
444
- if (typeof document === "undefined") return;
445
- bindObserver();
446
- if (!document.body && !waitingForBody) {
447
- waitingForBody = true;
448
- document.addEventListener(
449
- "DOMContentLoaded",
450
- () => {
451
- waitingForBody = false;
452
- bindObserver();
453
- },
454
- { once: true }
455
- );
456
- }
457
- }
458
-
459
- export { AUDIT_STATUS_MAP, BRAND_THEME_TOKENS, ENABLE_STATUS_MAP, RATING_LEVEL_COLORS, VERIFY_STATUS_MAP, clearColumnAutoMap, defineColumns, getColumnAutoMap, installBrandThemeLock, registerColumnAutoMap, registerColumnAutoMaps, registerDictColorMap, registerDictColorMaps, renderAuditStatus, renderBadge, renderClassifyTag, renderCountBadge, renderDangerText, renderDictClassifyTag, renderEnableStatus, renderOps, renderRatingLevel, renderTagNode, renderTagSlot, renderVerifyStatus, setDictResolver };
331
+ export { AUDIT_STATUS_MAP, ENABLE_STATUS_MAP, RATING_LEVEL_COLORS, VERIFY_STATUS_MAP, clearColumnAutoMap, defineColumns, getColumnAutoMap, registerColumnAutoMap, registerColumnAutoMaps, registerDictColorMap, registerDictColorMaps, renderAuditStatus, renderBadge, renderClassifyTag, renderCountBadge, renderDangerText, renderDictClassifyTag, renderEnableStatus, renderOps, renderRatingLevel, renderTagNode, renderTagSlot, renderVerifyStatus, setDictResolver };
@@ -0,0 +1,129 @@
1
+ // runtime/theme-lock.ts
2
+ var BRAND_THEME_TOKENS = Object.freeze({
3
+ "--el-color-primary": "#002a8f",
4
+ "--el-color-primary-rgb": "0, 42, 143",
5
+ "--el-color-primary-light-1": "#1a3f9a",
6
+ "--el-color-primary-light-2": "#3355a5",
7
+ "--el-color-primary-light-3": "#4d6ab1",
8
+ "--el-color-primary-light-4": "#667fbc",
9
+ "--el-color-primary-light-5": "#8094c7",
10
+ "--el-color-primary-light-6": "#99aad2",
11
+ "--el-color-primary-light-7": "#b2bfdd",
12
+ "--el-color-primary-light-8": "#ccd4e9",
13
+ "--el-color-primary-light-9": "#e5eaf4",
14
+ "--el-color-primary-dark-1": "#002681",
15
+ "--el-color-primary-dark-2": "#002272",
16
+ "--el-color-primary-dark-3": "#001d64",
17
+ "--el-color-primary-dark-4": "#001956",
18
+ "--el-color-success": "#2bb268",
19
+ "--el-color-success-light-1": "#40ba77",
20
+ "--el-color-success-light-2": "#55c286",
21
+ "--el-color-success-light-3": "#6bcb95",
22
+ "--el-color-success-light-4": "#80d3a4",
23
+ "--el-color-success-light-5": "#95dbb4",
24
+ "--el-color-success-light-6": "#aae3c3",
25
+ "--el-color-success-light-7": "#bfebd2",
26
+ "--el-color-success-light-8": "#d5f4e1",
27
+ "--el-color-success-light-9": "#eaf9f0",
28
+ "--el-color-success-dark-1": "#229051",
29
+ "--el-color-success-dark-2": "#1b733f",
30
+ "--el-color-success-dark-3": "#14562f",
31
+ "--el-color-success-dark-4": "#0d3a20",
32
+ "--el-color-warning": "#ea9a13",
33
+ "--el-color-warning-light-1": "#eca42b",
34
+ "--el-color-warning-light-2": "#efae42",
35
+ "--el-color-warning-light-3": "#f1b85a",
36
+ "--el-color-warning-light-4": "#f3c171",
37
+ "--el-color-warning-light-5": "#f5cb89",
38
+ "--el-color-warning-light-6": "#f7d5a1",
39
+ "--el-color-warning-light-7": "#f9dfb8",
40
+ "--el-color-warning-light-8": "#fce8d0",
41
+ "--el-color-warning-light-9": "#fef2e7",
42
+ "--el-color-warning-dark-1": "#c47f0e",
43
+ "--el-color-warning-dark-2": "#9d650a",
44
+ "--el-color-warning-dark-3": "#754a07",
45
+ "--el-color-warning-dark-4": "#4e3004",
46
+ "--el-color-danger": "#bb2d3f",
47
+ "--el-color-danger-light-1": "#c34253",
48
+ "--el-color-danger-light-2": "#ca5766",
49
+ "--el-color-danger-light-3": "#d16b78",
50
+ "--el-color-danger-light-4": "#d8808b",
51
+ "--el-color-danger-light-5": "#dd969f",
52
+ "--el-color-danger-light-6": "#e4abb2",
53
+ "--el-color-danger-light-7": "#e8c0c5",
54
+ "--el-color-danger-light-8": "#f0d5d9",
55
+ "--el-color-danger-light-9": "#f7eaec",
56
+ "--el-color-danger-dark-1": "#962433",
57
+ "--el-color-danger-dark-2": "#711b26",
58
+ "--el-color-danger-dark-3": "#4b1219",
59
+ "--el-color-danger-dark-4": "#26090d",
60
+ "--el-color-error": "#bb2d3f",
61
+ "--el-color-error-light-1": "#c34253",
62
+ "--el-color-error-light-2": "#ca5766",
63
+ "--el-color-error-light-3": "#d16b78",
64
+ "--el-color-error-light-4": "#d8808b",
65
+ "--el-color-error-light-5": "#dd969f",
66
+ "--el-color-error-light-6": "#e4abb2",
67
+ "--el-color-error-light-7": "#e8c0c5",
68
+ "--el-color-error-light-8": "#f0d5d9",
69
+ "--el-color-error-light-9": "#f7eaec",
70
+ "--el-color-error-dark-1": "#962433",
71
+ "--el-color-error-dark-2": "#711b26",
72
+ "--el-color-error-dark-3": "#4b1219",
73
+ "--el-color-error-dark-4": "#26090d",
74
+ "--el-border-radius-base": "6px",
75
+ "--el-border-radius-small": "2px",
76
+ "--el-border-radius-round": "20px",
77
+ "--el-border-radius-circle": "100%"
78
+ });
79
+ var observer;
80
+ var waitingForBody = false;
81
+ function enforceOn(target) {
82
+ if (!target) return;
83
+ for (const [name, value] of Object.entries(BRAND_THEME_TOKENS)) {
84
+ if (target.style.getPropertyValue(name).trim().toLowerCase() !== value || target.style.getPropertyPriority(name) !== "important") {
85
+ target.style.setProperty(name, value, "important");
86
+ }
87
+ }
88
+ }
89
+ function bindObserver() {
90
+ if (typeof document === "undefined") return;
91
+ enforceOn(document.documentElement);
92
+ enforceOn(document.body);
93
+ if (typeof MutationObserver === "undefined") return;
94
+ observer ?? (observer = new MutationObserver((mutations) => {
95
+ const bodyChanged = mutations.some((mutation) => mutation.type === "childList");
96
+ enforceOn(document.documentElement);
97
+ enforceOn(document.body);
98
+ if (bodyChanged) bindObserver();
99
+ }));
100
+ observer.disconnect();
101
+ observer.observe(document.documentElement, {
102
+ attributes: true,
103
+ attributeFilter: ["style"],
104
+ childList: true
105
+ });
106
+ if (document.body) {
107
+ observer.observe(document.body, {
108
+ attributes: true,
109
+ attributeFilter: ["style"]
110
+ });
111
+ }
112
+ }
113
+ function installBrandThemeLock() {
114
+ if (typeof document === "undefined") return;
115
+ bindObserver();
116
+ if (!document.body && !waitingForBody) {
117
+ waitingForBody = true;
118
+ document.addEventListener(
119
+ "DOMContentLoaded",
120
+ () => {
121
+ waitingForBody = false;
122
+ bindObserver();
123
+ },
124
+ { once: true }
125
+ );
126
+ }
127
+ }
128
+
129
+ export { BRAND_THEME_TOKENS, installBrandThemeLock };
@@ -0,0 +1,241 @@
1
+ import { installBrandThemeLock } from './chunk-Q3N5QNRZ.js';
2
+
3
+ // runtime/overflow-tooltip.ts
4
+ var MANAGED_CELL_SELECTOR = ".ag-root-wrapper .ag-cell-value, .el-table__body .cell";
5
+ var EXEMPT_ROOT_SELECTOR = ".lp-root, .session-login, .wl-ui-skin-exempt, [data-wl-ui-skin='off']";
6
+ var OVERFLOW_OFF_SELECTOR = ".wl-ui-overflow-ignore, [data-wl-ui-overflow='off']";
7
+ var INTERACTIVE_CONTENT_SELECTOR = [
8
+ "input",
9
+ "textarea",
10
+ "select",
11
+ "button",
12
+ "[contenteditable='true']",
13
+ ".el-input",
14
+ ".el-textarea",
15
+ ".el-select",
16
+ ".el-input-number",
17
+ ".el-date-editor",
18
+ ".el-button",
19
+ ".el-link",
20
+ ".el-tag",
21
+ ".el-checkbox",
22
+ ".el-radio",
23
+ ".el-switch",
24
+ ".ag-checkbox",
25
+ ".ag-cell-editor"
26
+ ].join(", ");
27
+ var EXCLUDED_AG_CELL_SELECTOR = [
28
+ ".editable-cell",
29
+ ".always-editable-cell",
30
+ ".default-slot-cell",
31
+ ".operations-cell",
32
+ ".ag-cell-inline-editing",
33
+ ".ag-cell-wrap-text",
34
+ ".ag-checkbox-cell"
35
+ ].join(", ");
36
+ var COMPONENT_TOOLTIP_SELECTOR = ".ag-tooltip, .el-popper[role='tooltip'], .el-tooltip__popper";
37
+ var TOOLTIP_ID = "wl-ui-overflow-tooltip";
38
+ var DEFAULT_OPTIONS = {
39
+ showDelay: 220,
40
+ agGridShowDelay: 900
41
+ };
42
+ var installedDocument;
43
+ var installedOptions = DEFAULT_OPTIONS;
44
+ var pendingCell;
45
+ var visibleCell;
46
+ var showTimer;
47
+ var tooltipElement;
48
+ var previousDescribedBy = null;
49
+ function asElement(target) {
50
+ if (!target || typeof target.closest !== "function") return null;
51
+ return target;
52
+ }
53
+ function isPlainTextCell(cell) {
54
+ if (cell.dataset.wlUiOverflow === "on") return true;
55
+ return cell.childElementCount === 0;
56
+ }
57
+ function resolveManagedCell(target) {
58
+ const element = asElement(target);
59
+ const cell = element?.closest(MANAGED_CELL_SELECTOR);
60
+ if (!cell || !cell.isConnected) return null;
61
+ if (cell.closest(EXEMPT_ROOT_SELECTOR)) return null;
62
+ if (cell.closest(OVERFLOW_OFF_SELECTOR)) return null;
63
+ if (cell.matches(EXCLUDED_AG_CELL_SELECTOR)) return null;
64
+ if (cell.matches(".el-tooltip") || cell.querySelector(INTERACTIVE_CONTENT_SELECTOR)) {
65
+ return null;
66
+ }
67
+ return isPlainTextCell(cell) ? cell : null;
68
+ }
69
+ function hasHorizontalOverflow(cell) {
70
+ return cell.scrollWidth - cell.clientWidth > 1;
71
+ }
72
+ function getCellText(cell) {
73
+ return (cell.textContent ?? "").replace(/\s+/g, " ").trim();
74
+ }
75
+ function hasDeclaredTooltip(cell) {
76
+ return Boolean(
77
+ cell.getAttribute("title")?.trim() || cell.getAttribute("aria-describedby")?.trim() || cell.dataset.tooltip?.trim()
78
+ );
79
+ }
80
+ function hasVisibleComponentTooltip(doc) {
81
+ const view = doc.defaultView;
82
+ const componentTooltips = Array.from(
83
+ doc.querySelectorAll(COMPONENT_TOOLTIP_SELECTOR)
84
+ );
85
+ for (const element of componentTooltips) {
86
+ if (element.id === TOOLTIP_ID || element.hidden) continue;
87
+ if (element.getAttribute("aria-hidden") === "true") continue;
88
+ if (!view) return true;
89
+ const style = view.getComputedStyle(element);
90
+ if (style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0") {
91
+ return true;
92
+ }
93
+ }
94
+ return false;
95
+ }
96
+ function ensureTooltip(doc) {
97
+ if (tooltipElement?.isConnected) return tooltipElement;
98
+ if (!doc.body) return null;
99
+ const tooltip = doc.createElement("div");
100
+ tooltip.id = TOOLTIP_ID;
101
+ tooltip.className = "wl-ui-overflow-tooltip";
102
+ tooltip.setAttribute("role", "tooltip");
103
+ tooltip.hidden = true;
104
+ doc.body.append(tooltip);
105
+ tooltipElement = tooltip;
106
+ return tooltip;
107
+ }
108
+ function positionTooltip(cell, tooltip) {
109
+ const doc = cell.ownerDocument;
110
+ const view = doc.defaultView;
111
+ const viewportWidth = view?.innerWidth ?? doc.documentElement.clientWidth;
112
+ const viewportHeight = view?.innerHeight ?? doc.documentElement.clientHeight;
113
+ const cellRect = cell.getBoundingClientRect();
114
+ const tooltipRect = tooltip.getBoundingClientRect();
115
+ const gap = 8;
116
+ const edge = 12;
117
+ const maxLeft = Math.max(edge, viewportWidth - tooltipRect.width - edge);
118
+ const centeredLeft = cellRect.left + cellRect.width / 2 - tooltipRect.width / 2;
119
+ const left = Math.min(Math.max(edge, centeredLeft), maxLeft);
120
+ const above = cellRect.top - tooltipRect.height - gap;
121
+ const below = Math.min(
122
+ viewportHeight - tooltipRect.height - edge,
123
+ cellRect.bottom + gap
124
+ );
125
+ tooltip.style.left = `${Math.round(left)}px`;
126
+ tooltip.style.top = `${Math.round(above >= edge ? above : below)}px`;
127
+ }
128
+ function restoreDescribedBy() {
129
+ if (!visibleCell) return;
130
+ if (previousDescribedBy === null) visibleCell.removeAttribute("aria-describedby");
131
+ else visibleCell.setAttribute("aria-describedby", previousDescribedBy);
132
+ visibleCell.removeAttribute("data-wl-ui-overflow-active");
133
+ previousDescribedBy = null;
134
+ }
135
+ function hideTooltip() {
136
+ if (showTimer) clearTimeout(showTimer);
137
+ showTimer = void 0;
138
+ pendingCell = void 0;
139
+ restoreDescribedBy();
140
+ visibleCell = void 0;
141
+ if (!tooltipElement) return;
142
+ tooltipElement.classList.remove("is-visible");
143
+ tooltipElement.hidden = true;
144
+ tooltipElement.textContent = "";
145
+ }
146
+ function revealTooltip(cell) {
147
+ const doc = cell.ownerDocument;
148
+ pendingCell = void 0;
149
+ showTimer = void 0;
150
+ if (!cell.isConnected || !hasHorizontalOverflow(cell)) return;
151
+ if (hasDeclaredTooltip(cell) || hasVisibleComponentTooltip(doc)) return;
152
+ const text = getCellText(cell);
153
+ if (!text) return;
154
+ const tooltip = ensureTooltip(doc);
155
+ if (!tooltip) return;
156
+ tooltip.textContent = text;
157
+ tooltip.hidden = false;
158
+ previousDescribedBy = cell.getAttribute("aria-describedby");
159
+ cell.setAttribute("aria-describedby", TOOLTIP_ID);
160
+ cell.setAttribute("data-wl-ui-overflow-active", "true");
161
+ visibleCell = cell;
162
+ positionTooltip(cell, tooltip);
163
+ tooltip.classList.add("is-visible");
164
+ }
165
+ function scheduleTooltip(cell, keyboard = false) {
166
+ hideTooltip();
167
+ if (!hasHorizontalOverflow(cell) || hasDeclaredTooltip(cell)) return;
168
+ pendingCell = cell;
169
+ const delay = keyboard ? 0 : cell.matches(".ag-cell-value") ? installedOptions.agGridShowDelay : installedOptions.showDelay;
170
+ showTimer = setTimeout(() => {
171
+ if (pendingCell === cell) revealTooltip(cell);
172
+ }, delay);
173
+ }
174
+ function onPointerOver(event) {
175
+ const cell = resolveManagedCell(event.target);
176
+ if (!cell || cell === pendingCell || cell === visibleCell) return;
177
+ scheduleTooltip(cell);
178
+ }
179
+ function onPointerOut(event) {
180
+ const pointerEvent = event;
181
+ const fromCell = resolveManagedCell(event.target);
182
+ if (!fromCell) return;
183
+ const toCell = resolveManagedCell(pointerEvent.relatedTarget);
184
+ if (toCell === fromCell) return;
185
+ if (fromCell === pendingCell || fromCell === visibleCell) hideTooltip();
186
+ }
187
+ function onFocusIn(event) {
188
+ const cell = resolveManagedCell(event.target);
189
+ if (cell) scheduleTooltip(cell, true);
190
+ }
191
+ function onFocusOut(event) {
192
+ const fromCell = resolveManagedCell(event.target);
193
+ if (fromCell === pendingCell || fromCell === visibleCell) hideTooltip();
194
+ }
195
+ function onKeyDown(event) {
196
+ if (event.key === "Escape") hideTooltip();
197
+ }
198
+ function bindDocument(doc) {
199
+ doc.addEventListener("pointerover", onPointerOver);
200
+ doc.addEventListener("pointerout", onPointerOut);
201
+ doc.addEventListener("focusin", onFocusIn);
202
+ doc.addEventListener("focusout", onFocusOut);
203
+ doc.addEventListener("keydown", onKeyDown);
204
+ doc.addEventListener("pointerdown", hideTooltip);
205
+ doc.addEventListener("scroll", hideTooltip, true);
206
+ doc.defaultView?.addEventListener("resize", hideTooltip);
207
+ }
208
+ function unbindDocument(doc) {
209
+ doc.removeEventListener("pointerover", onPointerOver);
210
+ doc.removeEventListener("pointerout", onPointerOut);
211
+ doc.removeEventListener("focusin", onFocusIn);
212
+ doc.removeEventListener("focusout", onFocusOut);
213
+ doc.removeEventListener("keydown", onKeyDown);
214
+ doc.removeEventListener("pointerdown", hideTooltip);
215
+ doc.removeEventListener("scroll", hideTooltip, true);
216
+ doc.defaultView?.removeEventListener("resize", hideTooltip);
217
+ }
218
+ function installOverflowTooltipGuard(options = {}) {
219
+ if (typeof document === "undefined") return;
220
+ if (installedDocument === document) return;
221
+ if (installedDocument) unbindDocument(installedDocument);
222
+ installedOptions = { ...DEFAULT_OPTIONS, ...options };
223
+ installedDocument = document;
224
+ bindDocument(document);
225
+ }
226
+ function uninstallOverflowTooltipGuard() {
227
+ if (installedDocument) unbindDocument(installedDocument);
228
+ hideTooltip();
229
+ tooltipElement?.remove();
230
+ tooltipElement = void 0;
231
+ installedDocument = void 0;
232
+ installedOptions = DEFAULT_OPTIONS;
233
+ }
234
+
235
+ // runtime/guards.ts
236
+ function installUiRuntimeGuards() {
237
+ installBrandThemeLock();
238
+ installOverflowTooltipGuard();
239
+ }
240
+
241
+ export { installOverflowTooltipGuard, installUiRuntimeGuards, uninstallOverflowTooltipGuard };
@@ -1,7 +1,7 @@
1
1
  import * as vue from 'vue';
2
2
  import { VNode } from 'vue';
3
- import { T as TagMapItem, J as JhTagNode } from './types-QZ1gy9KX.js';
4
- export { r as registerDictColorMap, a as registerDictColorMaps, g as renderDictClassifyTag, s as setDictResolver } from './renderers-BFRSp2BH.js';
3
+ import { T as TagMapItem, J as JhTagNode } from './types-Dnh4U0hw.js';
4
+ export { r as registerDictColorMap, a as registerDictColorMaps, b as renderDictClassifyTag, s as setDictResolver } from './renderers-B3uUAze8.js';
5
5
 
6
6
  declare const RISK_LEVEL_MAP: Record<string | number, TagMapItem>;
7
7
  declare const renderRiskLevel: (v: string | number | null | undefined) => JhTagNode | null;
@@ -1,5 +1,7 @@
1
- import { renderTagNode, renderClassifyTag, installBrandThemeLock, registerColumnAutoMaps, renderRatingLevel, renderBadge } from './chunk-XDGTJ7LE.js';
2
- export { registerDictColorMap, registerDictColorMaps, renderDictClassifyTag, setDictResolver } from './chunk-XDGTJ7LE.js';
1
+ import { installUiRuntimeGuards } from './chunk-Z2OTWMW6.js';
2
+ import { renderTagNode, renderClassifyTag, registerColumnAutoMaps, renderRatingLevel, renderBadge } from './chunk-4IOYRBW4.js';
3
+ export { registerDictColorMap, registerDictColorMaps, renderDictClassifyTag, setDictResolver } from './chunk-4IOYRBW4.js';
4
+ import './chunk-Q3N5QNRZ.js';
3
5
 
4
6
  // runtime/presets/common.ts
5
7
  var RISK_LEVEL_MAP = {
@@ -94,7 +96,7 @@ var DRILL_TYPE_COLOR_MAP = {
94
96
  "2": "warning"
95
97
  };
96
98
  function installCommonPreset() {
97
- installBrandThemeLock();
99
+ installUiRuntimeGuards();
98
100
  registerColumnAutoMaps({
99
101
  riskLevel: {
100
102
  width: 90,
package/es/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { C as ColumnLike } from './types-QZ1gy9KX.js';
2
- export { E as ElTagType, J as JhTagNode, O as OpChip, a as OpItem, b as OpLink, c as OpPreset, T as TagMapItem } from './types-QZ1gy9KX.js';
3
- export { A as AUDIT_STATUS_MAP, E as ENABLE_STATUS_MAP, R as RATING_LEVEL_COLORS, V as VERIFY_STATUS_MAP, r as registerDictColorMap, a as registerDictColorMaps, b as renderAuditStatus, c as renderBadge, d as renderClassifyTag, e as renderCountBadge, f as renderDangerText, g as renderDictClassifyTag, h as renderEnableStatus, i as renderOps, j as renderRatingLevel, k as renderTagNode, l as renderTagSlot, m as renderVerifyStatus, s as setDictResolver } from './renderers-BFRSp2BH.js';
1
+ import { C as ColumnLike } from './types-Dnh4U0hw.js';
2
+ export { E as ElTagType, J as JhTagNode, a as OpChip, O as OpItem, b as OpLink, c as OpPreset, T as TagMapItem } from './types-Dnh4U0hw.js';
3
+ export { A as AUDIT_STATUS_MAP, E as ENABLE_STATUS_MAP, R as RATING_LEVEL_COLORS, V as VERIFY_STATUS_MAP, r as registerDictColorMap, a as registerDictColorMaps, c as renderAuditStatus, d as renderBadge, e as renderClassifyTag, f as renderCountBadge, g as renderDangerText, b as renderDictClassifyTag, h as renderEnableStatus, i as renderOps, j as renderRatingLevel, k as renderTagNode, l as renderTagSlot, m as renderVerifyStatus, s as setDictResolver } from './renderers-B3uUAze8.js';
4
4
  import 'vue';
5
5
 
6
6
  /**
@@ -160,4 +160,30 @@ declare const BRAND_THEME_TOKENS: Readonly<{
160
160
  */
161
161
  declare function installBrandThemeLock(): void;
162
162
 
163
- export { BRAND_THEME_TOKENS, ColumnLike, type PresetConfig, clearColumnAutoMap, createPreset, defineColumns, getColumnAutoMap, getInstalledPresets, installBrandThemeLock, installPreset, registerColumnAutoMap, registerColumnAutoMaps };
163
+ /**
164
+ * 普通表格长文本兜底。
165
+ *
166
+ * CSS 负责绘制省略号;本模块只在用户悬停或键盘聚焦时按需判断真实溢出,
167
+ * 并为未启用组件原生 tooltip 的普通文本单元格提供完整内容提示。
168
+ * 动态行和虚拟滚动通过事件委托自然覆盖,不需要 MutationObserver。
169
+ */
170
+ interface OverflowTooltipGuardOptions {
171
+ /** 普通 Element Table 单元格的悬停延迟。 */
172
+ showDelay?: number;
173
+ /**
174
+ * AG Grid 兜底延迟。默认略晚于平台的 800ms 原生 tooltip,避免重复提示。
175
+ */
176
+ agGridShowDelay?: number;
177
+ }
178
+ /** 安装普通表格长文本兜底。重复调用安全,SSR 环境自动跳过。 */
179
+ declare function installOverflowTooltipGuard(options?: OverflowTooltipGuardOptions): void;
180
+ /** 卸载兜底监听,主要供微前端销毁和回归测试使用。 */
181
+ declare function uninstallOverflowTooltipGuard(): void;
182
+
183
+ /**
184
+ * 安装不依赖业务页面写法的包级运行时保护。
185
+ * 包含客户主题锁与普通表格长文本溢出提示兜底;重复调用安全。
186
+ */
187
+ declare function installUiRuntimeGuards(): void;
188
+
189
+ export { BRAND_THEME_TOKENS, ColumnLike, type OverflowTooltipGuardOptions, type PresetConfig, clearColumnAutoMap, createPreset, defineColumns, getColumnAutoMap, getInstalledPresets, installBrandThemeLock, installOverflowTooltipGuard, installPreset, installUiRuntimeGuards, registerColumnAutoMap, registerColumnAutoMaps, uninstallOverflowTooltipGuard };
package/es/index.js CHANGED
@@ -1,5 +1,7 @@
1
- import { registerColumnAutoMaps } from './chunk-XDGTJ7LE.js';
2
- export { AUDIT_STATUS_MAP, BRAND_THEME_TOKENS, ENABLE_STATUS_MAP, RATING_LEVEL_COLORS, VERIFY_STATUS_MAP, clearColumnAutoMap, defineColumns, getColumnAutoMap, installBrandThemeLock, registerColumnAutoMap, registerColumnAutoMaps, registerDictColorMap, registerDictColorMaps, renderAuditStatus, renderBadge, renderClassifyTag, renderCountBadge, renderDangerText, renderDictClassifyTag, renderEnableStatus, renderOps, renderRatingLevel, renderTagNode, renderTagSlot, renderVerifyStatus, setDictResolver } from './chunk-XDGTJ7LE.js';
1
+ export { installOverflowTooltipGuard, installUiRuntimeGuards, uninstallOverflowTooltipGuard } from './chunk-Z2OTWMW6.js';
2
+ import { registerColumnAutoMaps } from './chunk-4IOYRBW4.js';
3
+ export { AUDIT_STATUS_MAP, ENABLE_STATUS_MAP, RATING_LEVEL_COLORS, VERIFY_STATUS_MAP, clearColumnAutoMap, defineColumns, getColumnAutoMap, registerColumnAutoMap, registerColumnAutoMaps, registerDictColorMap, registerDictColorMaps, renderAuditStatus, renderBadge, renderClassifyTag, renderCountBadge, renderDangerText, renderDictClassifyTag, renderEnableStatus, renderOps, renderRatingLevel, renderTagNode, renderTagSlot, renderVerifyStatus, setDictResolver } from './chunk-4IOYRBW4.js';
4
+ export { BRAND_THEME_TOKENS, installBrandThemeLock } from './chunk-Q3N5QNRZ.js';
3
5
 
4
6
  // runtime/presets/registry.ts
5
7
  var _installedPresets = /* @__PURE__ */ new Set();
@@ -1,4 +1,4 @@
1
- import { T as TagMapItem, J as JhTagNode } from '../types-QZ1gy9KX.js';
1
+ import { T as TagMapItem, J as JhTagNode } from '../types-Dnh4U0hw.js';
2
2
  import 'vue';
3
3
 
4
4
  declare const VIOLATION_STATUS_MAP: Record<string | number, TagMapItem>;
@@ -1,4 +1,5 @@
1
- import { renderTagNode, installBrandThemeLock, registerDictColorMaps, registerColumnAutoMaps } from '../chunk-XDGTJ7LE.js';
1
+ import { renderTagNode, registerDictColorMaps, registerColumnAutoMaps } from '../chunk-4IOYRBW4.js';
2
+ import { installBrandThemeLock } from '../chunk-Q3N5QNRZ.js';
2
3
 
3
4
  // runtime/presets/security.ts
4
5
  var VIOLATION_STATUS_MAP = {
@@ -1,5 +1,5 @@
1
1
  import { VNode } from 'vue';
2
- import { T as TagMapItem, J as JhTagNode, a as OpItem } from './types-QZ1gy9KX.js';
2
+ import { T as TagMapItem, J as JhTagNode, O as OpItem } from './types-Dnh4U0hw.js';
3
3
 
4
4
  /**
5
5
  * runtime/core/renderers.ts — 通用渲染器 + 通用状态映射
@@ -48,4 +48,4 @@ declare const renderVerifyStatus: (v: string | number | null | undefined) => JhT
48
48
  /** 渲染操作列按钮组(图标 + 胶囊 + 文字链接,自动 stopPropagation) */
49
49
  declare function renderOps(items: OpItem[]): VNode;
50
50
 
51
- export { AUDIT_STATUS_MAP as A, ENABLE_STATUS_MAP as E, RATING_LEVEL_COLORS as R, VERIFY_STATUS_MAP as V, registerDictColorMaps as a, renderAuditStatus as b, renderBadge as c, renderClassifyTag as d, renderCountBadge as e, renderDangerText as f, renderDictClassifyTag as g, renderEnableStatus as h, renderOps as i, renderRatingLevel as j, renderTagNode as k, renderTagSlot as l, renderVerifyStatus as m, registerDictColorMap as r, setDictResolver as s };
51
+ export { AUDIT_STATUS_MAP as A, ENABLE_STATUS_MAP as E, RATING_LEVEL_COLORS as R, VERIFY_STATUS_MAP as V, registerDictColorMaps as a, renderDictClassifyTag as b, renderAuditStatus as c, renderBadge as d, renderClassifyTag as e, renderCountBadge as f, renderDangerText as g, renderEnableStatus as h, renderOps as i, renderRatingLevel as j, renderTagNode as k, renderTagSlot as l, renderVerifyStatus as m, registerDictColorMap as r, setDictResolver as s };
@@ -60,4 +60,4 @@ interface OpLink {
60
60
  }
61
61
  type OpItem = OpPreset | OpChip | OpLink;
62
62
 
63
- export type { ColumnLike as C, ElTagType as E, JhTagNode as J, OpChip as O, TagMapItem as T, OpItem as a, OpLink as b, OpPreset as c };
63
+ export type { ColumnLike as C, ElTagType as E, JhTagNode as J, OpItem as O, TagMapItem as T, OpChip as a, OpLink as b, OpPreset as c };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agile-team/wl-skills-ui",
3
- "version": "1.9.8",
3
+ "version": "1.9.10",
4
4
  "description": "企业级 UI 风格对齐框架 — Vue + Element Plus 项目通用化妆/原生双模式(tokens / element / vendors / layouts / runtime / scanner / fixer / skills)",
5
5
  "type": "module",
6
6
  "main": "./es/index.js",
@@ -14,6 +14,9 @@
14
14
  "import": "./es/index.js",
15
15
  "types": "./es/index.d.ts"
16
16
  },
17
+ "./runtime/auto": {
18
+ "import": "./es/auto.js"
19
+ },
17
20
  "./runtime/common-preset": {
18
21
  "import": "./es/common-preset.js",
19
22
  "types": "./es/common-preset.d.ts"
@@ -82,7 +85,8 @@
82
85
  ],
83
86
  "sideEffects": [
84
87
  "*.css",
85
- "*.scss"
88
+ "*.scss",
89
+ "./es/auto.js"
86
90
  ],
87
91
  "devDependencies": {
88
92
  "@commitlint/cli": "^20.5.3",
@@ -96,8 +100,10 @@
96
100
  "element-plus": "^2.7.0",
97
101
  "eslint": "^10.3.0",
98
102
  "eslint-plugin-vue": "^10.9.0",
103
+ "happy-dom": "20.11.1",
99
104
  "husky": "^9.1.7",
100
105
  "lint-staged": "^16.4.0",
106
+ "sass": "1.77.8",
101
107
  "tsup": "^8.3.0",
102
108
  "typescript": "^5.4.0",
103
109
  "vue": "^3.4.0"
package/scanner/index.mjs CHANGED
@@ -276,9 +276,10 @@ if (subcommand === "init") {
276
276
  @use '@agile-team/wl-skills-ui/styles' as *;
277
277
  // 化妆模式:@use '@agile-team/wl-skills-ui/styles/presets/skin' as *;
278
278
 
279
- 4. 在 src/main.ts 中注册 runtime(可选,仅当业务侧用到 defineColumns):
280
- import { installCommonPreset } from '@agile-team/wl-skills-ui/runtime/common-preset';
281
- installCommonPreset();
279
+ 4. 在 src/main.ts 中安装包级保护:
280
+ // Skin / 老项目:
281
+ import '@agile-team/wl-skills-ui/runtime/auto';
282
+ // Native 项目改为调用 installCommonPreset(),其已包含相同保护。
282
283
 
283
284
  5. 业务列定义改用 defineColumns:
284
285
  import { defineColumns, renderOps } from '@agile-team/wl-skills-ui/runtime';
@@ -128,7 +128,7 @@ export function checkIntegration(projectRoot) {
128
128
  : "未发现 runtime 引入(无 src/util/ag-cell-renders.ts,main.ts 也未 import runtime)",
129
129
  suggestion: runtimeOk
130
130
  ? ""
131
- : '推荐:在 main.ts 中 import { installCommonPreset } from "@agile-team/wl-skills-ui/runtime/common-preset"; installCommonPreset();',
131
+ : 'Skin 项目在 main.ts 中 import "@agile-team/wl-skills-ui/runtime/auto";Native 项目调用 installCommonPreset()(已包含包级保护)。',
132
132
  });
133
133
 
134
134
  // ── I004: element-plus 已安装 ────────────────────────────────────────
@@ -62,7 +62,7 @@ export const tableRules = [
62
62
  "table",
63
63
  "warning",
64
64
  "普通数据列缺少超长省略与悬停完整内容提示",
65
- "添加 show-overflow-tooltip;BaseTable/AG Grid 列统一使用 defineColumns() 自动补齐",
65
+ "添加 show-overflow-tooltip;BaseTable/AG Grid 优先使用 defineColumns(),并在项目启动入口安装 runtime/auto 包级兜底",
66
66
  ),
67
67
  );
68
68
  }
@@ -66,6 +66,16 @@ BaseTable / AG Grid 使用 `defineColumns()` 后由 runtime 自动为普通文
66
66
  `showOverflowTooltip: true`。自定义渲染、结构列、换行列不强制;需要主动关闭时
67
67
  显式声明 `showOverflowTooltip: false`。
68
68
 
69
+ Skin/历史项目还必须在启动入口引入一次
70
+ `@agile-team/wl-skills-ui/runtime/auto`。它为未经过 `defineColumns()` 的动态
71
+ Picker/BaseTable/AG Grid 普通文本提供真实溢出兜底;未溢出、已有 Tooltip、Tag、
72
+ 操作列、编辑列、自定义 renderer 与皮肤豁免区域均不接管。局部可使用
73
+ `data-wl-ui-overflow="off"` 退出。
74
+
75
+ 行 hover/selected 色由包内表格 token 统一管理,业务页面不要重写
76
+ `hover-row`、`current-row` 或直接覆盖 `td.el-table__cell` 背景,以免编辑控件、
77
+ 校验态和语义单元格底色发生冲突。
78
+
69
79
  ---
70
80
 
71
81
  ## 完整标准写法示例
@@ -13,8 +13,17 @@ applyTo: "**/*.{ts,vue}"
13
13
  2. 操作列统一用 `renderOps([...])` — 图标按钮系统,自动分隔线 + stopPropagation
14
14
  3. 状态字段用 `renderTagNode()` / `renderClassifyTag()` — 彩色 Tag,见 tag-status/SKILL.md
15
15
 
16
+ Skin/历史项目必须在 `main.ts` 引入一次
17
+ `@agile-team/wl-skills-ui/runtime/auto`。它修复普通纯文本 flex 单元格的省略号,
18
+ 并在未配置平台原生 Tooltip 且真实溢出时兜底完整内容。编辑列、操作列、Tag、
19
+ 复选框、自定义 renderer、主动换行列和皮肤豁免区域不会被接管。
20
+
16
21
  > 与 `wl-skills-kit` 协同说明:本 Skill 负责 AG Grid/列渲染/操作列 runtime 能力,也要服务非 kit 项目的通用 AG Grid 场景。若扫描发现项目希望升级为团队最佳实践,再提示使用 `wl-skills-kit` 进行页面结构和工作流规范化;在此之前,`wl-skills-ui` 仍应保证样式和渲染能力可独立生效。
17
22
 
23
+ > 行状态由包统一管控:hover 为品牌色 4% 浅底,selected 为 7% 浅底且优先于
24
+ > hover。业务代码不要重写 `.ag-row-hover`、`.ag-row-selected` 或对应 AG
25
+ > Grid 主题变量,也不要为了行状态修改编辑控件、校验态和语义单元格背景。
26
+
18
27
  ---
19
28
 
20
29
  ## 标准列定义写法
@@ -28,7 +28,7 @@ applyTo: "**/*.vue"
28
28
  - ❌ 用 `<el-button type="primary">` 当操作按钮(应用 `is-text` 文字按钮,沿用 R004)
29
29
  - ❌ 列头未居中(同 R001)
30
30
  - ❌ 缺 `empty-text="暂无数据"`(同 R003)
31
- - ❌ 普通文本列未通过 `defineColumns()` 获得超长省略与悬停完整提示(同 R039)
31
+ - ❌ 项目未安装 `runtime/auto` 包级保护,导致动态 Picker/历史列绕过 `defineColumns()` 后没有超长省略与完整提示(同 R039)
32
32
  - ❌ 在 `<BaseTable>` 外层包裹自定义 padding 容器,破坏整体节奏
33
33
 
34
34
  ## Repair(修复)
@@ -36,6 +36,7 @@ applyTo: "**/*.vue"
36
36
  ### A 类(自动修)
37
37
  - 缺失 `empty-text` → 补 `empty-text="暂无数据"`
38
38
  - 普通文本列统一经 `defineColumns()` 自动补 `showOverflowTooltip: true`
39
+ - Skin/历史项目启动入口统一引入 `@agile-team/wl-skills-ui/runtime/auto`,为未经过 `defineColumns()` 的普通文本列提供真实溢出兜底
39
40
  - 操作列按钮 `type="primary"` → 改为 `link` + `is-text`
40
41
  - 内联 hex → CSS 变量
41
42
 
@@ -54,8 +55,10 @@ applyTo: "**/*.vue"
54
55
  ## 全局样式来源
55
56
 
56
57
  `styles/vendors/_base-table.scss` — 已注入容器圆角、表头颜色、操作按钮间距;
57
- `runtime.defineColumns()` 统一控制普通文本列的 overflow tooltip。
58
- 项目侧无需重复写样式,遵循 DOM 约定即可。
58
+ `runtime.defineColumns()` 优先接入平台原生 overflow tooltip;`runtime/auto` 为动态
59
+ Picker 和历史普通文本列提供包级兜底。运行时只在 `scrollWidth > clientWidth` 时工作,
60
+ 并排除 Tag、操作列、编辑器、自定义 renderer、主动换行列和皮肤豁免区域。项目侧
61
+ 不要重复写样式或再注册第二套全局 Tooltip。
59
62
 
60
63
  ## 未来源码迁移
61
64
 
@@ -46,10 +46,21 @@
46
46
  />
47
47
  ```
48
48
 
49
- BaseTable / AG Grid 列必须通过 `defineColumns()` 声明。普通文本列会自动补
50
- `showOverflowTooltip: true`;自定义渲染列、selection/index/expand、`wrapText`
51
- 或 `autoHeight` 列不会被强制。业务可显式设置 `showOverflowTooltip: false`
52
- 退出。
49
+ BaseTable / AG Grid 仍推荐通过 `defineColumns()` 声明,普通文本列会自动补
50
+ `showOverflowTooltip: true` 并优先使用平台原生 Tooltip。对于动态 Picker 或未经过
51
+ `defineColumns()` 的历史列,项目启动入口必须安装 `runtime/auto` 包级保护;其仅在
52
+ 真实溢出时提供兜底。自定义渲染列、selection/index/expand、`wrapText`、`autoHeight`、
53
+ Tag、编辑列和操作列不会被强制。局部可用 `data-wl-ui-overflow="off"` 显式退出。
54
+
55
+ ---
56
+
57
+ ## 行悬停与选中状态
58
+
59
+ - hover 使用客户品牌色 4% 透明度,只提示当前位置,不形成整条亮蓝色块。
60
+ - selected 使用客户品牌色 7% 透明度,并始终优先于 hover。
61
+ - 状态色只作用于数据行背景,不覆盖编辑输入框、校验态、Tag 和业务语义单元格底色。
62
+ - 不在业务页面重写 `.ag-row-hover`、`.ag-row-selected`、`hover-row` 或
63
+ `current-row`;Element Table 与 AG Grid 均由化妆包统一管控。
53
64
 
54
65
  ---
55
66
 
@@ -1,7 +1,16 @@
1
1
  // styles/element/_table.scss — el-table 表头颜色覆盖
2
2
  // jh-ui table.scss 表头颜色为硬编码,此处用 CSS 变量覆盖
3
3
 
4
+ @use "../scope" as skin;
5
+
4
6
  html body .el-table {
7
+ // 与 AG Grid 共用克制的行状态层级;只改表格状态 token,
8
+ // 不强刷 input / 校验 / 业务语义单元格背景。
9
+ --wk-table-row-hover-bg: rgba(var(--el-color-primary-rgb), 0.04);
10
+ --wk-table-row-selected-bg: rgba(var(--el-color-primary-rgb), 0.07);
11
+ --el-table-row-hover-bg-color: var(--wk-table-row-hover-bg) !important;
12
+ --el-table-current-row-bg-color: var(--wk-table-row-selected-bg) !important;
13
+
5
14
  .el-table__header-wrapper th,
6
15
  .el-table__fixed-header-wrapper th {
7
16
  color: var(--el-text-color-primary, #303133);
@@ -38,3 +47,25 @@ html body .el-table {
38
47
  margin: 0 auto;
39
48
  }
40
49
  }
50
+
51
+ // 未显式配置 show-overflow-tooltip 的普通纯文本列也获得视觉省略。
52
+ // :not(:has(> *)) 将 Tag、按钮、复选框、自定义 renderer 和编辑控件排除在外;
53
+ // Tooltip 由 runtime/auto 在真实溢出时按需兜底。
54
+ #{skin.$managed-scope-selector} {
55
+ &.el-table__body
56
+ .cell:not(.el-tooltip):not(
57
+ :where(
58
+ .wl-ui-overflow-ignore,
59
+ .wl-ui-overflow-ignore *,
60
+ [data-wl-ui-overflow="off"],
61
+ [data-wl-ui-overflow="off"] *
62
+ )
63
+ ):not(:has(> *)) {
64
+ display: block !important;
65
+ min-width: 0 !important;
66
+ max-width: 100% !important;
67
+ overflow: hidden !important;
68
+ text-overflow: ellipsis !important;
69
+ white-space: nowrap !important;
70
+ }
71
+ }
@@ -1,3 +1,5 @@
1
+ @use "../scope" as skin;
2
+
1
3
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2
4
  // AG Grid 全局样式 — wl-ui-safe 统一设计规范
3
5
  // 适用:所有使用 BaseTable renderType="agGrid" 的页面
@@ -6,14 +8,18 @@
6
8
 
7
9
  // ── CSS 变量注入(AG Grid 28+ 支持)──────────────────────────────────────────
8
10
  .ag-root-wrapper {
11
+ // 深品牌蓝在大面积行底色中只保留轻提示:hover 4%,selected 7%。
12
+ // 同时回写 AG Grid 变量,避免平台主题继续使用默认亮蓝。
13
+ --wk-grid-row-hover-bg: rgba(var(--el-color-primary-rgb), 0.04);
14
+ --wk-grid-row-selected-bg: rgba(var(--el-color-primary-rgb), 0.07);
9
15
  --ag-background-color: #ffffff;
10
16
  --ag-odd-row-background-color: #ffffff;
11
17
  --ag-header-background-color: #fafafa;
12
18
  --ag-header-foreground-color: #374151;
13
19
  --ag-border-color: rgba(0, 0, 0, 0.06);
14
20
  --ag-row-border-color: rgba(0, 0, 0, 0.06);
15
- --ag-row-hover-color: rgba(var(--el-color-primary-rgb), 0.06);
16
- --ag-selected-row-background-color: rgba(var(--el-color-primary-rgb), 0.1);
21
+ --ag-row-hover-color: var(--wk-grid-row-hover-bg) !important;
22
+ --ag-selected-row-background-color: var(--wk-grid-row-selected-bg) !important;
17
23
  --ag-range-selection-border-color: rgba(var(--el-color-primary-rgb), 0.4);
18
24
  --ag-font-size: 13px;
19
25
  --ag-font-family: inherit;
@@ -88,7 +94,7 @@
88
94
  font-size: 13px !important;
89
95
  color: var(--el-text-color-primary) !important;
90
96
  border-bottom-color: var(--el-border-color-lighter) !important;
91
- transition: background-color 0.15s ease;
97
+ transition: background-color 0.12s ease;
92
98
  }
93
99
 
94
100
  .ag-row-even {
@@ -98,13 +104,21 @@
98
104
  background-color: #ffffff;
99
105
  }
100
106
 
101
- .ag-row:hover,
102
- .ag-row.ag-row-hover {
103
- background-color: rgba(var(--el-color-primary-rgb), 0.06) !important;
107
+ .ag-row:not(.ag-row-selected):hover,
108
+ .ag-row.ag-row-hover:not(.ag-row-selected) {
109
+ background-color: var(
110
+ --wk-grid-row-hover-bg,
111
+ rgba(var(--el-color-primary-rgb), 0.04)
112
+ ) !important;
104
113
  }
105
114
 
106
- .ag-row.ag-row-selected {
107
- background-color: rgba(var(--el-color-primary-rgb), 0.1) !important;
115
+ .ag-row.ag-row-selected,
116
+ .ag-row.ag-row-selected:hover,
117
+ .ag-row.ag-row-selected.ag-row-hover {
118
+ background-color: var(
119
+ --wk-grid-row-selected-bg,
120
+ rgba(var(--el-color-primary-rgb), 0.07)
121
+ ) !important;
108
122
  }
109
123
 
110
124
  // ── 单元格 ────────────────────────────────────────────────────────────────────
@@ -126,6 +140,33 @@
126
140
  max-width: 100%;
127
141
  }
128
142
 
143
+ // 平台把 .ag-cell 与 .ag-cell-value 复用在同一个 flex 节点上;flex 容器的
144
+ // 直接文本不会稳定绘制 text-overflow。仅对没有子元素的普通文本单元格切回
145
+ // block,编辑器、操作列、自定义 renderer、复选框与主动换行列保持原结构。
146
+ #{skin.$managed-scope-selector} {
147
+ &.ag-root-wrapper
148
+ .ag-cell-value:not(.editable-cell):not(.always-editable-cell):not(
149
+ .default-slot-cell
150
+ ):not(.operations-cell):not(.ag-cell-inline-editing):not(
151
+ .ag-cell-wrap-text
152
+ ):not(.ag-checkbox-cell):not(
153
+ :where(
154
+ .wl-ui-overflow-ignore,
155
+ .wl-ui-overflow-ignore *,
156
+ [data-wl-ui-overflow="off"],
157
+ [data-wl-ui-overflow="off"] *
158
+ )
159
+ ):not(:has(> *)) {
160
+ display: block !important;
161
+ min-width: 0 !important;
162
+ max-width: 100% !important;
163
+ overflow: hidden !important;
164
+ line-height: var(--ag-row-height, 26px);
165
+ text-overflow: ellipsis !important;
166
+ white-space: nowrap !important;
167
+ }
168
+ }
169
+
129
170
  // 复选框单元格(header 与 body 使用相同规则,确保视觉对齐)
130
171
  .ag-cell.ag-checkbox-cell {
131
172
  padding: 0 !important;
@@ -0,0 +1,35 @@
1
+ // 普通表格长文本兜底 Tooltip。
2
+ // 仅由 runtime/auto 在真实溢出且组件没有原生 Tooltip 时创建。
3
+
4
+ .wl-ui-overflow-tooltip {
5
+ position: fixed;
6
+ z-index: 2147483000;
7
+ box-sizing: border-box;
8
+ max-width: min(520px, calc(100vw - 24px));
9
+ padding: 7px 10px;
10
+ color: #fff;
11
+ font-size: 12px;
12
+ font-weight: 400;
13
+ line-height: 1.5;
14
+ overflow-wrap: anywhere;
15
+ white-space: normal;
16
+ background: rgba(17, 24, 39, 0.94);
17
+ border: 1px solid rgba(255, 255, 255, 0.12);
18
+ border-radius: 6px;
19
+ box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);
20
+ opacity: 0;
21
+ visibility: hidden;
22
+ pointer-events: none;
23
+ transform: translateY(2px);
24
+ transition:
25
+ opacity 0.12s ease,
26
+ transform 0.12s ease,
27
+ visibility 0.12s ease;
28
+
29
+ &.is-visible {
30
+ opacity: 1;
31
+ visibility: visible;
32
+ transform: translateY(0);
33
+ }
34
+ }
35
+
@@ -6,6 +6,7 @@
6
6
  // → 但 SCSS 加载顺序里我们反过来:兜底先加载,让高优先级覆盖
7
7
 
8
8
  @forward './_portal'; // 弹层/popper 通用(基础设施层)
9
+ @forward './_overflow-tooltip'; // 普通长文本真实溢出 Tooltip 兜底
9
10
  @forward './_ag-grid'; // AG Grid 完整主题
10
11
  @forward './_custom-wrappers'; // 兜底:野路子自封装
11
12
  @forward './_c-components'; // C_/c_ 前缀