@icen.ai/ui 0.8.1 → 0.10.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/AGENTS.md +176 -75
- package/README.md +66 -88
- package/dist/base.css +208 -179
- package/dist/behaviors/accordion.mjs +8 -8
- package/dist/behaviors/ai-branch.d.mts +19 -0
- package/dist/behaviors/ai-branch.mjs +1133 -0
- package/dist/behaviors/ai-chat.d.mts +12 -10
- package/dist/behaviors/ai-chat.mjs +1125 -155
- package/dist/behaviors/ai-composer.d.mts +44 -12
- package/dist/behaviors/ai-composer.mjs +2084 -523
- package/dist/behaviors/ai-core.d.mts +1 -1
- package/dist/behaviors/ai-core.mjs +1016 -107
- package/dist/behaviors/ai-diff.mjs +1019 -127
- package/dist/behaviors/ai-feedback.d.mts +26 -0
- package/dist/behaviors/ai-feedback.mjs +1212 -0
- package/dist/behaviors/ai-panel.d.mts +21 -7
- package/dist/behaviors/ai-panel.mjs +1308 -264
- package/dist/behaviors/ai-provider.mjs +1003 -101
- package/dist/behaviors/ai-threads.d.mts +38 -0
- package/dist/behaviors/ai-threads.mjs +1233 -0
- package/dist/behaviors/ai-tool.d.mts +2 -2
- package/dist/behaviors/ai-tool.mjs +2042 -396
- package/dist/behaviors/ai-tools.d.mts +89 -16
- package/dist/behaviors/ai-tools.mjs +4453 -372
- package/dist/behaviors/autocomplete.d.mts +53 -0
- package/dist/behaviors/autocomplete.mjs +1600 -0
- package/dist/behaviors/back-top.d.mts +1 -1
- package/dist/behaviors/back-top.mjs +951 -14
- package/dist/behaviors/carousel.d.mts +1 -1
- package/dist/behaviors/carousel.mjs +906 -11
- package/dist/behaviors/cascader.d.mts +48 -0
- package/dist/behaviors/cascader.mjs +1853 -0
- package/dist/behaviors/charts.d.mts +174 -8
- package/dist/behaviors/charts.mjs +2632 -192
- package/dist/behaviors/code-block.d.mts +36 -0
- package/dist/behaviors/code-block.mjs +1611 -0
- package/dist/behaviors/command-palette.d.mts +9 -6
- package/dist/behaviors/command-palette.mjs +161 -59
- package/dist/behaviors/context-menu.d.mts +9 -8
- package/dist/behaviors/context-menu.mjs +1112 -44
- package/dist/behaviors/controls.d.mts +13 -13
- package/dist/behaviors/controls.mjs +989 -130
- package/dist/behaviors/copy.d.mts +21 -2
- package/dist/behaviors/copy.mjs +1206 -42
- package/dist/behaviors/datatable.d.mts +53 -3
- package/dist/behaviors/datatable.mjs +1963 -207
- package/dist/behaviors/date-picker.d.mts +0 -1
- package/dist/behaviors/date-picker.mjs +1340 -293
- package/dist/behaviors/design.d.mts +54 -0
- package/dist/behaviors/design.mjs +109 -0
- package/dist/behaviors/dropdown.d.mts +5 -6
- package/dist/behaviors/dropdown.mjs +262 -110
- package/dist/behaviors/events.d.mts +313 -3
- package/dist/behaviors/events.mjs +47 -2
- package/dist/behaviors/feedback.d.mts +30 -0
- package/dist/behaviors/feedback.mjs +296 -0
- package/dist/behaviors/focus.d.mts +8 -0
- package/dist/behaviors/focus.mjs +24 -0
- package/dist/behaviors/form-validate.d.mts +102 -0
- package/dist/behaviors/form-validate.mjs +6091 -0
- package/dist/behaviors/i18n.d.mts +789 -0
- package/dist/behaviors/i18n.mjs +1711 -0
- package/dist/behaviors/icons.d.mts +93 -0
- package/dist/behaviors/icons.mjs +113 -0
- package/dist/behaviors/input.d.mts +9 -1
- package/dist/behaviors/input.mjs +1056 -60
- package/dist/behaviors/kb-access.d.mts +34 -0
- package/dist/behaviors/kb-access.mjs +2459 -0
- package/dist/behaviors/kb-acl.d.mts +50 -0
- package/dist/behaviors/kb-acl.mjs +1345 -0
- package/dist/behaviors/kb-answer.d.mts +38 -0
- package/dist/behaviors/kb-answer.mjs +3707 -0
- package/dist/behaviors/kb-audit.d.mts +23 -0
- package/dist/behaviors/kb-audit.mjs +1297 -0
- package/dist/behaviors/kb-canvas.d.mts +44 -0
- package/dist/behaviors/kb-canvas.mjs +1512 -0
- package/dist/behaviors/kb-chain.d.mts +15 -0
- package/dist/behaviors/kb-chain.mjs +1192 -0
- package/dist/behaviors/kb-checkpoint.d.mts +16 -0
- package/dist/behaviors/kb-checkpoint.mjs +1492 -0
- package/dist/behaviors/kb-chunks.d.mts +31 -0
- package/dist/behaviors/kb-chunks.mjs +1414 -0
- package/dist/behaviors/kb-citation.d.mts +38 -0
- package/dist/behaviors/kb-citation.mjs +1699 -0
- package/dist/behaviors/kb-clarify.d.mts +20 -0
- package/dist/behaviors/kb-clarify.mjs +1176 -0
- package/dist/behaviors/kb-conflict.d.mts +22 -0
- package/dist/behaviors/kb-conflict.mjs +1206 -0
- package/dist/behaviors/kb-connector.d.mts +17 -0
- package/dist/behaviors/kb-connector.mjs +1303 -0
- package/dist/behaviors/kb-core.d.mts +534 -0
- package/dist/behaviors/kb-core.mjs +1805 -0
- package/dist/behaviors/kb-eval.d.mts +22 -0
- package/dist/behaviors/kb-eval.mjs +2235 -0
- package/dist/behaviors/kb-explain.d.mts +11 -0
- package/dist/behaviors/kb-explain.mjs +1165 -0
- package/dist/behaviors/kb-filter.d.mts +31 -0
- package/dist/behaviors/kb-filter.mjs +2417 -0
- package/dist/behaviors/kb-gap.d.mts +27 -0
- package/dist/behaviors/kb-gap.mjs +1195 -0
- package/dist/behaviors/kb-hittest.d.mts +34 -0
- package/dist/behaviors/kb-hittest.mjs +1352 -0
- package/dist/behaviors/kb-metadata.d.mts +29 -0
- package/dist/behaviors/kb-metadata.mjs +1248 -0
- package/dist/behaviors/kb-passage.d.mts +41 -0
- package/dist/behaviors/kb-passage.mjs +1469 -0
- package/dist/behaviors/kb-pipeline.d.mts +18 -0
- package/dist/behaviors/kb-pipeline.mjs +1301 -0
- package/dist/behaviors/kb-qa.d.mts +26 -0
- package/dist/behaviors/kb-qa.mjs +1260 -0
- package/dist/behaviors/kb-rerank.d.mts +20 -0
- package/dist/behaviors/kb-rerank.mjs +1248 -0
- package/dist/behaviors/kb-retrieval.d.mts +49 -0
- package/dist/behaviors/kb-retrieval.mjs +2585 -0
- package/dist/behaviors/kb-review.d.mts +44 -0
- package/dist/behaviors/kb-review.mjs +2282 -0
- package/dist/behaviors/kb-sandbox.d.mts +33 -0
- package/dist/behaviors/kb-sandbox.mjs +1247 -0
- package/dist/behaviors/kb-segment.d.mts +32 -0
- package/dist/behaviors/kb-segment.mjs +1431 -0
- package/dist/behaviors/kb-select.d.mts +24 -0
- package/dist/behaviors/kb-select.mjs +1989 -0
- package/dist/behaviors/kb-sources.d.mts +27 -0
- package/dist/behaviors/kb-sources.mjs +1287 -0
- package/dist/behaviors/kb-sql.d.mts +43 -0
- package/dist/behaviors/kb-sql.mjs +1865 -0
- package/dist/behaviors/kb-trace.d.mts +16 -0
- package/dist/behaviors/kb-trace.mjs +1328 -0
- package/dist/behaviors/kb-visibility.d.mts +44 -0
- package/dist/behaviors/kb-visibility.mjs +1331 -0
- package/dist/behaviors/kb-who-can.d.mts +32 -0
- package/dist/behaviors/kb-who-can.mjs +2216 -0
- package/dist/behaviors/mentions.d.mts +93 -0
- package/dist/behaviors/mentions.mjs +2152 -0
- package/dist/behaviors/modal.d.mts +4 -3
- package/dist/behaviors/modal.mjs +1055 -33
- package/dist/behaviors/nav.d.mts +1 -1
- package/dist/behaviors/nav.mjs +6 -6
- package/dist/behaviors/notification.d.mts +16 -8
- package/dist/behaviors/notification.mjs +1615 -265
- package/dist/behaviors/panel.d.mts +4 -0
- package/dist/behaviors/panel.mjs +994 -0
- package/dist/behaviors/popover.d.mts +28 -5
- package/dist/behaviors/popover.mjs +225 -24
- package/dist/behaviors/select.d.mts +5 -2
- package/dist/behaviors/select.mjs +1410 -117
- package/dist/behaviors/sidebar.d.mts +1 -1
- package/dist/behaviors/sidebar.mjs +13 -13
- package/dist/behaviors/slider.d.mts +1 -1
- package/dist/behaviors/slider.mjs +9 -9
- package/dist/behaviors/split-pane.d.mts +1 -1
- package/dist/behaviors/split-pane.mjs +7 -7
- package/dist/behaviors/suggestions.d.mts +27 -0
- package/dist/behaviors/suggestions.mjs +1089 -0
- package/dist/behaviors/svg-parse.d.mts +14 -0
- package/dist/behaviors/svg-parse.mjs +37 -0
- package/dist/behaviors/tabs.d.mts +2 -2
- package/dist/behaviors/tabs.mjs +25 -25
- package/dist/behaviors/tag-input.d.mts +23 -5
- package/dist/behaviors/tag-input.mjs +1359 -104
- package/dist/behaviors/theme-switcher.d.mts +24 -0
- package/dist/behaviors/theme-switcher.mjs +1981 -0
- package/dist/behaviors/theme.d.mts +15 -8
- package/dist/behaviors/theme.mjs +390 -28
- package/dist/behaviors/toast.d.mts +24 -25
- package/dist/behaviors/toast.mjs +1266 -88
- package/dist/behaviors/tooltip.d.mts +4 -0
- package/dist/behaviors/tooltip.mjs +378 -0
- package/dist/behaviors/tree-select.d.mts +69 -0
- package/dist/behaviors/tree-select.mjs +1907 -0
- package/dist/behaviors/tree.d.mts +1 -1
- package/dist/behaviors/tree.mjs +15 -15
- package/dist/behaviors/upload.d.mts +3 -2
- package/dist/behaviors/upload.mjs +1076 -66
- package/dist/cli.mjs +5 -6
- package/dist/components/ai-branch.mjs +3 -0
- package/dist/components/ai-chat.css +846 -458
- package/dist/components/ai-diff.css +153 -132
- package/dist/components/ai-feedback.mjs +3 -0
- package/dist/components/ai-panel.css +495 -270
- package/dist/components/ai-threads.mjs +3 -0
- package/dist/components/ai-tool.css +393 -238
- package/dist/components/autocomplete.css +61 -0
- package/dist/components/autocomplete.mjs +3 -0
- package/dist/components/back-top.css +34 -31
- package/dist/components/badge.css +44 -41
- package/dist/components/breadcrumb.css +67 -46
- package/dist/components/btn.css +80 -74
- package/dist/components/card.css +117 -106
- package/dist/components/cascader.css +311 -0
- package/dist/components/cascader.mjs +3 -0
- package/dist/components/chart-area.css +8 -2
- package/dist/components/chart-bar.css +95 -33
- package/dist/components/chart-gauge.css +14 -11
- package/dist/components/chart-graph.css +60 -0
- package/dist/components/chart-graph.mjs +4 -0
- package/dist/components/chart-heatmap.css +96 -90
- package/dist/components/chart-line.css +8 -3
- package/dist/components/chart-map.mjs +3 -0
- package/dist/components/chart-pie.css +9 -6
- package/dist/components/chart-radar.css +8 -5
- package/dist/components/chart-scatter.css +9 -6
- package/dist/components/chart-scatter.mjs +1 -1
- package/dist/components/chart-sparkline.css +5 -2
- package/dist/components/chart-stack.css +14 -11
- package/dist/components/charts.css +190 -67
- package/dist/components/charts.mjs +1 -0
- package/dist/components/code-block.css +418 -0
- package/dist/components/code-block.mjs +4 -0
- package/dist/components/command-palette.css +138 -117
- package/dist/components/content.css +257 -251
- package/dist/components/copy.css +72 -44
- package/dist/components/datatable.css +423 -181
- package/dist/components/date-picker.css +135 -104
- package/dist/components/empty.css +68 -65
- package/dist/components/feedback.css +201 -183
- package/dist/components/form-validate.css +120 -0
- package/dist/components/form-validate.mjs +3 -0
- package/dist/components/form.css +150 -127
- package/dist/components/icon.css +102 -0
- package/dist/components/icon.mjs +3 -0
- package/dist/components/input.css +159 -104
- package/dist/components/kb-access.mjs +4 -0
- package/dist/components/kb-acl.mjs +4 -0
- package/dist/components/kb-agent.css +496 -0
- package/dist/components/kb-answer.mjs +4 -0
- package/dist/components/kb-audit.mjs +4 -0
- package/dist/components/kb-canvas.mjs +4 -0
- package/dist/components/kb-chain.mjs +4 -0
- package/dist/components/kb-checkpoint.mjs +4 -0
- package/dist/components/kb-chunks.mjs +4 -0
- package/dist/components/kb-citation.mjs +4 -0
- package/dist/components/kb-clarify.mjs +4 -0
- package/dist/components/kb-conflict.mjs +4 -0
- package/dist/components/kb-connector.mjs +4 -0
- package/dist/components/kb-data.css +653 -0
- package/dist/components/kb-eval.mjs +4 -0
- package/dist/components/kb-explain.mjs +4 -0
- package/dist/components/kb-filter.mjs +4 -0
- package/dist/components/kb-gap.mjs +4 -0
- package/dist/components/kb-ground.css +578 -0
- package/dist/components/kb-hittest.mjs +4 -0
- package/dist/components/kb-ingest.css +882 -0
- package/dist/components/kb-metadata.mjs +4 -0
- package/dist/components/kb-ops.css +554 -0
- package/dist/components/kb-passage.mjs +4 -0
- package/dist/components/kb-perm.css +433 -0
- package/dist/components/kb-pipeline.mjs +4 -0
- package/dist/components/kb-qa.mjs +4 -0
- package/dist/components/kb-rerank.mjs +4 -0
- package/dist/components/kb-retrieval.mjs +4 -0
- package/dist/components/kb-review.mjs +4 -0
- package/dist/components/kb-sandbox.mjs +4 -0
- package/dist/components/kb-search.css +897 -0
- package/dist/components/kb-segment.mjs +4 -0
- package/dist/components/kb-sources.mjs +4 -0
- package/dist/components/kb-sql.mjs +4 -0
- package/dist/components/kb-trace.mjs +4 -0
- package/dist/components/kb-visibility.mjs +4 -0
- package/dist/components/kb-who-can.mjs +4 -0
- package/dist/components/kb.css +263 -0
- package/dist/components/kb.mjs +9 -0
- package/dist/components/layout.css +85 -82
- package/dist/components/material-chinese.css +73 -0
- package/dist/components/material-soviet.css +76 -0
- package/dist/components/material.css +275 -0
- package/dist/components/media.css +220 -166
- package/dist/components/mentions.css +189 -0
- package/dist/components/mentions.mjs +3 -0
- package/dist/components/menu.css +113 -105
- package/dist/components/modal.css +107 -112
- package/dist/components/nav.css +118 -115
- package/dist/components/notification.css +238 -174
- package/dist/components/pagination.css +56 -53
- package/dist/components/panel.css +66 -63
- package/dist/components/panel.mjs +1 -0
- package/dist/components/pill.css +81 -71
- package/dist/components/popover.css +67 -53
- package/dist/components/scroll-area.css +113 -110
- package/dist/components/segmented.css +146 -143
- package/dist/components/select.css +206 -186
- package/dist/components/sidebar.css +137 -127
- package/dist/components/slider.css +117 -114
- package/dist/components/split-pane.css +112 -109
- package/dist/components/stat.css +112 -106
- package/dist/components/steps.css +109 -103
- package/dist/components/switch.css +138 -134
- package/dist/components/table.css +131 -107
- package/dist/components/tabs.css +114 -108
- package/dist/components/tag-input.css +48 -133
- package/dist/components/tag.css +81 -71
- package/dist/components/theme-switcher.css +105 -0
- package/dist/components/theme-switcher.mjs +3 -0
- package/dist/components/toast.css +100 -86
- package/dist/components/toolbar.css +45 -42
- package/dist/components/tooltip.css +102 -43
- package/dist/components/tooltip.mjs +1 -0
- package/dist/components/tree-select.css +416 -0
- package/dist/components/tree-select.mjs +3 -0
- package/dist/components/upload.css +135 -92
- package/dist/fonts/LICENSES/ark-pixel/OFL.txt +96 -0
- package/dist/fonts/LICENSES/cubic-11/OFL.txt +108 -0
- package/dist/fonts/LICENSES/galmuri/LICENSE.txt +93 -0
- package/dist/fonts/OFL.txt +96 -0
- package/dist/fonts/README.md +14 -0
- package/dist/fonts/fusion-pixel-12px-zh-hans.woff2 +0 -0
- package/dist/index.d.mts +64 -15
- package/dist/index.mjs +28049 -8595
- package/dist/react.d.mts +91 -0
- package/dist/react.mjs +8208 -0
- package/dist/registry.json +454 -15
- package/dist/tokens/chinese.css +44 -0
- package/dist/tokens/colors.css +365 -1222
- package/dist/tokens/design.css +109 -0
- package/dist/tokens/dtcg.json +11198 -0
- package/dist/tokens/figma.variables.json +7017 -0
- package/dist/tokens/icon-masks.css +78 -0
- package/dist/tokens/pixel.css +50 -0
- package/dist/tokens/soviet.css +44 -0
- package/dist/tokens/style-profiles.css +36 -547
- package/dist/tokens/themes.json +308 -0
- package/dist/tokens/tokens-studio.json +6728 -0
- package/dist/tokens/typography.css +21 -18
- package/dist/tokens.css +1555 -1801
- package/dist/ui.css +16147 -8597
- package/dist/vue.d.mts +344 -0
- package/dist/vue.mjs +7781 -0
- package/docs/spec/ai-input-experience.md +75 -0
- package/docs/spec/ai-native.md +238 -147
- package/docs/spec/design-philosophy.md +189 -0
- package/docs/spec/design-primitives.md +196 -0
- package/docs/spec/kb-family.md +475 -0
- package/package.json +42 -7
- package/dist/retro-effects.css +0 -255
- package/dist/tokens/retro-effects.css +0 -255
package/AGENTS.md
CHANGED
|
@@ -6,15 +6,27 @@
|
|
|
6
6
|
|
|
7
7
|
# 第一段 · 消费方速查(在用户项目里用 @icen.ai/ui)
|
|
8
8
|
|
|
9
|
-
完整类型签名看包内 `dist/*.d.ts`;交互式文档 <https://ui.icen.ai>;AI 能力规格 `docs/spec/ai-native.md
|
|
9
|
+
完整类型签名看包内 `dist/*.d.ts`;交互式文档 <https://ui.icen.ai>;AI 能力规格 `docs/spec/ai-native.md`;知识库族规格 `docs/spec/kb-family.md`;最佳实践成品页 <https://ui.icen.ai/kb/>;文档全文(喂模型)<https://ui.icen.ai/llms-full.txt>。
|
|
10
10
|
|
|
11
11
|
## 形态约束(先读,避免生成跑不通的代码)
|
|
12
12
|
|
|
13
13
|
- 零依赖纯 ESM + TypeScript;组件 = CSS + 行为 JS,**不绑定框架**(React/Vue 在 effect/mounted 里调行为函数即可)。
|
|
14
|
-
- 先引 tokens 再引组件:`@import '@icen.ai/ui/tokens.css';`(组件 CSS 全部消费 `--token-*` 变量)。
|
|
14
|
+
- 先引 tokens 再引组件:`@import '@icen.ai/ui/tokens.css';`(组件 CSS 全部消费 `--icen-token-*` 变量)。
|
|
15
15
|
- **Astro 陷阱**:kit 入口的 css import 在页面 `<script>`(client bundle)里会被摇掉——Astro 项目必须在布局 frontmatter 引组件 CSS;Vite SPA / webpack 无此问题。
|
|
16
16
|
- 行为函数全部**幂等**且 **SSR 安全**(`window` 未定义静默返回);渲染只写 `textContent`,绝不 innerHTML。
|
|
17
|
-
- 自定义事件统一 `icen:` 前缀(图表 `icen:chart-*`,AI 族 `icen:ai-*`)。明暗 = html `data-theme="dark"`;密度 = 容器 `data-density`。
|
|
17
|
+
- 自定义事件统一 `icen:` 前缀(图表 `icen:chart-*`,AI 族 `icen:ai-*`)。明暗 = html `data-icen-theme="dark"`;密度 = 容器 `data-icen-density`。
|
|
18
|
+
|
|
19
|
+
## 命名空间契约(类名防冲突——与任何第三方 CSS 共存零冲突)
|
|
20
|
+
|
|
21
|
+
- **类名一律 `icen-` 前缀**(`.icen-btn` / `.icen-modal` / `.icen-kb-citation`…);唯一例外是状态类 `.is-*`——纪律是 `.is-*` 永不单独出现在选择器里,永远与根类复合(`.icen-tab.is-active`),因此天然隔离。
|
|
22
|
+
- **主题层是 data 属性,不是类**:`<html data-icen-preset="piano" data-icen-theme="dark" data-icen-style="pixel">`。自建预设 = 写 `[data-icen-preset="<name>"]` 与 `[data-icen-preset="<name>"][data-icen-theme="dark"]` 两块完整 token 面。
|
|
23
|
+
- **库 data 钩子一律 `data-icen-*`**(`[data-icen-tabs]`、`data-icen-copy`、`data-icen-panel-width`…235 个全量);**全局 CSS 变量七族一律 `--icen-*`**(`--icen-token-*/--icen-density-*/--icen-radius-*/--icen-duration-*/--icen-ease-*/--icen-z-*/--icen-font-*`);组件作用域变量(`--btn-*`/`--ai-*`/`--kb-*`)不前缀——它们只随根类作用于子树,根类已前缀即继承链已隔离。
|
|
24
|
+
- **cascade layers**:全部产物 CSS 包在 `@layer icen.tokens / icen.base / icen.components`——消费方自己的无层样式永远赢库样式(放心覆盖);层序由 tokens.css 顶部声明锚定。
|
|
25
|
+
|
|
26
|
+
## RTL 与逻辑属性
|
|
27
|
+
|
|
28
|
+
- **消费方零成本**:全套组件使用 CSS 逻辑属性(`margin/padding/border-inline-*`、`inset-inline-*`、`text-align: start/end`、逻辑角半径),`<html dir="rtl">` 即整体镜像;方向性图标(轮播箭头 / 面包屑分隔符 › → / 折叠 chevron / kb caret / 抽屉滑出)在 `[dir="rtl"]` 下自动翻转。
|
|
29
|
+
- **新增组件的 RTL 纪律**(`bun run guard` 第 7 项强制):流向布局一律逻辑属性优先;物理方向只允许给真正的视口物理坐标——JS 计算的浮层定位(popover/tooltip/select panel)、图表坐标系(chart-*.css)、物理侧边变体名(`--sheet-left` / `data-icen-side='left'` / `--right` 时间线)、开关类物理隐喻控件(Material 惯例不镜像)、数字列物理对齐(Excel 惯例);以上物理保留必须行尾 `/* guard:allow-physical 理由 */` 或进 `scripts/guard/rtl.ts` 的 PHYSICAL_FILES 文件级白名单(理由同步写进文件头注释)。
|
|
18
30
|
|
|
19
31
|
## 安装颗粒度
|
|
20
32
|
|
|
@@ -50,7 +62,7 @@ c.destroy();
|
|
|
50
62
|
```
|
|
51
63
|
|
|
52
64
|
- 省略 `type` 时 `inferChartType` 自动选型(ISO 日期/年月/周几/版本号 v0.8/纯年份等时序标签 → line)。
|
|
53
|
-
- 事件:`icen:chart-hover`(detail.phase ∈ enter/move/leave)/ `-click / -dblclick / -contextmenu / -legend-toggle / -legend-visibility`;内置 tooltip 门户(`tooltip:false` 关闭只派事件),tooltip 最大宽吃图表根 `data-panel-max`;图表头统一带**图例眼睛**(隐藏/显示全部指标)。直调底层渲染器同样有交互委托(`bindChartEvents`)。
|
|
65
|
+
- 事件:`icen:chart-hover`(detail.phase ∈ enter/move/leave)/ `-click / -dblclick / -contextmenu / -legend-toggle / -legend-visibility`;内置 tooltip 门户(`tooltip:false` 关闭只派事件),tooltip 最大宽吃图表根 `data-icen-panel-max`;图表头统一带**图例眼睛**(隐藏/显示全部指标)。直调底层渲染器同样有交互委托(`bindChartEvents`)。
|
|
54
66
|
- 底层渲染器(同 chrome,非 AI 场景直用):`renderVBar/renderHBar/renderStack/renderDonut/renderLine/renderArea/renderRadar/renderHeatmap/renderCalendar/renderSparkline/renderGauge/renderScatter`。
|
|
55
67
|
|
|
56
68
|
## AI 原生族 — 7 态状态机 + kind 注册表
|
|
@@ -79,11 +91,13 @@ initAiTool(); initAiSubagent(); // 事件委托,页面级一次
|
|
|
79
91
|
|
|
80
92
|
- 线格式归一 `normalizeContentParts`(OpenAI/Anthropic/MCP 通吃);取纯文本 `contentToText`;资源 URL `aiContentUrl`。
|
|
81
93
|
- kind 可扩展:`registerAiKind({ label, icon, tint, summarize })`;工具卡输入 JSON 默认折叠,`chart`/`error`/`approval`/多模态输出默认展开。
|
|
82
|
-
- 推理块 `.ai-reasoning` + `createAiStream(host)` 流入(host 在 `.ai-reasoning` 内时完成自动折叠并回填耗时)。
|
|
94
|
+
- 推理块 `.icen-ai-reasoning` + `createAiStream(host)` 流入(host 在 `.icen-ai-reasoning` 内时完成自动折叠并回填耗时)。
|
|
83
95
|
- 面板:`renderAiTodo/renderAiUsage/renderAiContext/renderAiAudit`(ai-panel)、`parseUnifiedDiff/renderAiDiff`(ai-diff)。
|
|
84
96
|
|
|
85
97
|
## 输入台 + 零接线绑定
|
|
86
98
|
|
|
99
|
+
输入台资源目录与兼容契约见 `docs/spec/ai-input-experience.md`。`setComposerRefs` 内置 skill/tool/file/folder/doc/agent,可选 description/icon/keywords/disabled;配置后自动出现 +。`openComposerLibrary(el, kind?)` 可从任意入口打开,命令在目录中仅填入草稿,`/` 快捷入口仍执行。`getComposerDraft` / send / queue 快照携带 refs?/files?;移除附件必须改真实状态并派 attachment-remove。`bindComposer.prepareMessage(draft,{signal})` 由宿主处理上传与授权资源,不能猜服务端或静默丢文件;未接适配器的附件给可重试错误。client 模式用量按本请求更新,纯事件多会话传 eventTarget 隔离。
|
|
100
|
+
|
|
87
101
|
```ts
|
|
88
102
|
import { initAiComposer, bindComposer, setComposerTodo, setComposerModels } from '@icen.ai/ui/behaviors/ai-composer';
|
|
89
103
|
|
|
@@ -113,7 +127,7 @@ const auditor = createAiAuditor(); // log() 条目含 cost(定价表估算
|
|
|
113
127
|
## 工具体系(behaviors/ai-tools)— 把 UI 能力注册成模型可调用工具
|
|
114
128
|
|
|
115
129
|
```ts
|
|
116
|
-
import { createAiToolArea, aiToolsToOpenAI, aiToolsToMcp, aiToolsManifest, parseAiToolArgs }
|
|
130
|
+
import { createAiToolArea, aiToolsToOpenAI, aiToolsToAnthropic, aiToolsToMcp, aiToolsToAiSdk, aiToolsManifest, parseAiToolArgs, validateToolArgs }
|
|
117
131
|
from '@icen.ai/ui/behaviors/ai-tools';
|
|
118
132
|
|
|
119
133
|
const area = createAiToolArea(mountEl, {
|
|
@@ -121,26 +135,74 @@ const area = createAiToolArea(mountEl, {
|
|
|
121
135
|
max: 4, // 挂载上限,LRU 淘汰
|
|
122
136
|
});
|
|
123
137
|
area.call('render_chart', { type: 'line', labels, series }); // 宿主手动/模型触发
|
|
138
|
+
area.call('risky_tool', args, { validate: false }); // call opts:校验默认开,可关
|
|
124
139
|
area.setTools(['render_chart']); area.setMax(2); area.onChange(cb);
|
|
125
140
|
|
|
126
|
-
aiToolsToOpenAI();
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
141
|
+
aiToolsToOpenAI(); // → OpenAI tools 数组(function.parameters)
|
|
142
|
+
aiToolsToAnthropic(); // → Anthropic tools 数组(input_schema)
|
|
143
|
+
aiToolsToMcp(); // → MCP tools/list 形态
|
|
144
|
+
aiToolsToAiSdk(); // → Vercel AI SDK v5 tool() 描述表(不 execute,宿主侧挂载执行)
|
|
145
|
+
aiToolsManifest(); // → 自描述 manifest
|
|
146
|
+
parseAiToolArgs(raw); // 模型回包解析(容错 JSON 字符串/对象,坏 JSON→{})
|
|
147
|
+
validateToolArgs(schema, args); // 参数校验:不支持的关键字进 unvalidated 清单,不猜
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
自定义工具:`registerAiTool({ name, description, inputSchema, run, present?, timeoutMs?, requiresApproval?, idempotent? })`;
|
|
151
|
+
`run(input, mount, ctx)` 第三参 `ctx: { signal: AbortSignal, progress(line) }`,允许返回
|
|
152
|
+
Promise(落定后写结果);`timeoutMs` 超时 → `{ ok:false, error:{ code:'timeout' } }`;
|
|
153
|
+
`requiresApproval` → 挂载卡先呈审批区(批准派 `icen:ai-tool-approve` 才执行,拒绝派
|
|
154
|
+
`icen:ai-tool-reject` 置 `.is-cancelled`);`idempotent` → 同名同输入在途调用复用同一条
|
|
155
|
+
记录。内置 `render_chart` 与 `render_datatable`。挂载区条目可折叠/移除,超限 LRU 自动回收。
|
|
156
|
+
|
|
157
|
+
## i18n 本地化(behaviors/i18n)
|
|
158
|
+
|
|
159
|
+
- 全库行为层面向用户文案的唯一事实源:扁平 key 注册表(默认 zh-CN,附完整 en-US)。组件渲染时经 `t(key)` 取值——`setIcenLocale(ICEN_LOCALE_EN_US)` 一键切英文,或传 `Partial<IcenLocale>` 逐 key 合并覆盖(不清表),`resetIcenLocale()` 回默认。
|
|
160
|
+
- 切换后自 document 派 `icen:locale-change` 广播(detail `{ changed: string[] }`,见 events.ts 广播约定)——组件监听后可重渲染;`getIcenLocale()` 返回冻结浅快照(改它不影响内部)。
|
|
161
|
+
- 数组型 key(`datePicker.weekdays`)`t()` 返回 `string[]`;插值 `t(key, { p0 })` 以 `{p0}` 占位符替换;模块级注册表(kind 标签/工具 schema)在导入时按当时语言快照。
|
|
162
|
+
|
|
163
|
+
## 知识库族(kb-*)— 证据层组件
|
|
164
|
+
|
|
165
|
+
**ai 族描述思考(过程),kb 族呈现证据(知识从哪来 / 可信吗 / 怎么用);权限域呈现边界(谁能看到什么,以及为什么)**。32 个 slug 七域,CSS 根类 `.kb-*`,事件统一 `icen:kb-*`(56 个全类型登记)。规格唯一事实源 `docs/spec/kb-family.md`(§9 为权限域);最佳实践成品页 <https://ui.icen.ai/kb/>(八标签工作台 + 参考文献锚点)。
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
import { renderCitationText, initKbCitation } from '@icen.ai/ui/behaviors/kb-citation';
|
|
169
|
+
import { createKbRetrieval, scorePercent } from '@icen.ai/ui/behaviors/kb-retrieval';
|
|
170
|
+
import { createKbFilter } from '@icen.ai/ui/behaviors/kb-filter';
|
|
171
|
+
import { parseInlineCitations } from '@icen.ai/ui/behaviors/kb-core';
|
|
172
|
+
|
|
173
|
+
// 角标:文本里的 [1][2] → renderCitationText(el, text, sources)(initKbCitation() 页面级事件委托)
|
|
174
|
+
// 引用三型定位(Anthropic 同款):location: {type:'char',start,end,unit:'char'} | {type:'page',page} | {type:'block',blockId}——unit 写死不猜
|
|
175
|
+
// 检索 playground:混合权重 / 阈值 / topK 即调即得,事件 icen:kb-retrieval-run
|
|
176
|
+
// 过滤器:树形规则 → serialize('mongo'|'odata') 双 DSL;无效规则不镜像(诚实纪律)
|
|
177
|
+
const filter = createKbFilter(el, { node, fields, onChange: (node, valid) => {...} });
|
|
130
178
|
```
|
|
131
179
|
|
|
132
|
-
|
|
180
|
+
- **分数纪律(全族统一)**:score 必带 metric 与 higherIsBetter(l2 距离自动反转);null / 缺失渲染「—」不猜;条形轨道定宽,长度严格按 scorePercent 比例。
|
|
181
|
+
- **诚实呈现**:行数截断要声明、权限缺失打码并给「申请访问」、重排关闭后列压淡不隐藏、检查点回滚范围显式(只回滚文件保留对话)。
|
|
182
|
+
- 契约层 `kb-core.ts`(`import ... from '@icen.ai/ui/behaviors/kb-core'`):KbCitation / KbChunk / KbRunStatus / KbConnector / KbRetrievalParams / KbFilterNode / KbEvalRow 等 40+ normalize 与格式化函数,业务数据一律先过 normalize 再喂组件。
|
|
183
|
+
- 域文件映射:证据 kb-citation·kb-sources·kb-passage·kb-conflict → kb-ground.css;摄取 kb-pipeline·kb-chunks·kb-segment·kb-connector·kb-metadata·kb-qa → kb-ingest.css;检索 kb-retrieval·kb-filter·kb-rerank·kb-hittest → kb-search.css;问数 kb-sql·kb-answer·kb-clarify → kb-data.css;治理 kb-explain·kb-trace·kb-review·kb-gap·kb-eval → kb-ops.css;工作台 kb-canvas·kb-checkpoint·kb-sandbox·kb-chain → kb-agent.css;**权限 kb-acl·kb-who-can·kb-access·kb-audit·kb-visibility → kb-perm.css**;全部组件 kit 自动带 kb.css 基座。
|
|
184
|
+
|
|
185
|
+
**权限域安全纪律(spec §9.0,评审必查)**:
|
|
186
|
+
|
|
187
|
+
- 检索期隔离唯一安全基线 = **query-time pre-filter**(ANN 与 BM25 两侧);post-filter / generation / presentation 都不是边界。
|
|
188
|
+
- **对授权侧诚实,对受限侧沉默**:被裁条数 / 标题 / 分数 / 「若权限不同」对照不出现在普通用户视图(kb-visibility 的 admin 对照是唯一例外,组件自带警示条)。
|
|
189
|
+
- 「不知道」与「不能说」不可区分:无权限文档在检索/列表/计数/引用中 = 不存在;唯一允许的裁剪提示是与命中无关的恒定文案。
|
|
190
|
+
- 求值语义:`evaluateAcl(entries, identity)` 纯函数 = **先显式 deny → allow 并集 → 默认拒绝(fail-closed)**;身份来自服务端固定身份集,不接受自由输入。
|
|
191
|
+
- 引用白名单:citation 只能生成自过滤后集合;revoked 历史引用呈中性 `.is-revoked`;每条 grant 可带 `expiresAt`(到期三态:永不过期 / 倒计时+续期 / 已过期+重交)。
|
|
192
|
+
- 组件速用:`renderKbAcl(el, model)`(继承四件套 + Direct/Links 双区 + deny 置顶);`renderKbWhoCan(el, {identities, entries})`(view-as 原因链,业界唯一全实现是 SharePoint Check Permissions——差异化件);`createKbAccess(el, {request, mode})`(被拒五件套 + 九态状态机 + 路由明示);`renderKbAudit(el, {entries, hygiene})` + `initKbAudit()`(三通道 + break-glass 警示 + 六类异味);`renderKbVisibility(el, opts)`(admin 对照器 + 过滤层三态徽标 `.icen-kb-layer-chip` pre✓/post⚠/none✕)。
|
|
133
193
|
|
|
134
194
|
## 深挖索引(复杂模块不设单独 AGENTS.md,类型真相在 .d.mts)
|
|
135
195
|
|
|
136
|
-
每个 behavior 的完整接口/类型/字段约束都随包发布在 `dist/behaviors/<模块>.d.mts`(JSDoc 注释含行为约束,如「el 传容器或内部任意元素,就近解析 `[data-ai-composer]`」)。**不建议也不需要按组件再写深层 AGENTS.md**——复制必漂移;读类型面即读文档:
|
|
196
|
+
每个 behavior 的完整接口/类型/字段约束都随包发布在 `dist/behaviors/<模块>.d.mts`(JSDoc 注释含行为约束,如「el 传容器或内部任意元素,就近解析 `[data-icen-ai-composer]`」)。**不建议也不需要按组件再写深层 AGENTS.md**——复制必漂移;读类型面即读文档:
|
|
137
197
|
|
|
138
198
|
| 深挖什么 | 去哪读 |
|
|
139
199
|
| --- | --- |
|
|
140
|
-
| AI 族全部签名与字段约束 | 包内 `dist/behaviors/ai-{core,chat,composer,tool,panel,diff,provider,tools}.d.mts` |
|
|
200
|
+
| AI 族全部签名与字段约束 | 包内 `dist/behaviors/ai-{core,chat,composer,tool,panel,diff,provider,tools,threads,feedback,branch}.d.mts` |
|
|
201
|
+
| 知识库族全部签名与字段约束 | 包内 `dist/behaviors/kb-*.d.mts`(契约层 `kb-core.d.mts`) |
|
|
141
202
|
| 图表 ChartSpec 全字段 + 各类型 options | `dist/behaviors/charts.d.mts` |
|
|
142
203
|
| 上述类型面 + JSDoc 的纯文本快照 | <https://ui.icen.ai/llms-full.txt>(「API 类型面」节,构建期自动内嵌) |
|
|
143
204
|
| 设计动机 / 状态机语义 / 口径取舍 | `docs/spec/ai-native.md`(包内随发) |
|
|
205
|
+
| **设计哲学全文(几何/色彩/动效/密度/预设人格/对标矩阵/覆盖架构/红线)** | `docs/spec/design-philosophy.md` |
|
|
144
206
|
| DOM 契约 / CSS 类名 | 各组件文档页 <https://ui.icen.ai/components/<slug>/,kit 入口同款 CSS 头注释 |
|
|
145
207
|
| 场景配方(选图决策树 / 聊天五步 / 主题切换) | skill `icen-ui`(skill.icen.ai,`curl -sL https://skill.icen.ai/install/ui.sh \| bash`)——按需触发的流程层,与本手册(事实层)互补 |
|
|
146
208
|
|
|
@@ -148,35 +210,51 @@ parseAiToolArgs('render_chart', raw); // 模型回包解析(容错 JSON 字
|
|
|
148
210
|
|
|
149
211
|
# 第二段 · 本仓库开发约定
|
|
150
212
|
|
|
213
|
+
## 完整设计原语(现代 / 中式 / 苏式 / 像素)
|
|
214
|
+
|
|
215
|
+
- 默认主题与默认原语均为现代。主题走 `data-icen-preset`(现代+另外五个主题);原语走 `data-icen-style`(现代/中式/苏式/像素)。两轴独立;没有第四条 design 轴。
|
|
216
|
+
- 配色目录唯一事实源:`src/tokens/themes.json`;colors.css 由 `bun run colors`(scripts/theme-colors.mjs)生成,禁止手改。六套主题:现代/东韵/巨构/钢琴/莫奈/梵高。运行时、文档站、导出均直接消费目录。
|
|
217
|
+
- 单一事实源:`src/tokens/design.css`(作者种子→语义角色映射),`src/components/material.css`(三类材料与组件适配),`src/behaviors/design.ts`(可选 `createDesign/mountDesign/setDesign`)。材料适配随 tokens.css 分发,kit 单独引入同样成立。
|
|
218
|
+
- 品牌作者优先修改 `--icen-design-*` 少量种子,避免复制组件 CSS。完整规则与明暗品牌示例见 `docs/spec/design-primitives.md`;交互工作室 `/modern/`。
|
|
219
|
+
- 材料 API:`data-icen-material="content|chrome|floating"`。内容面不透明;操作/临时面条件启用磨砂,提供 reduced-transparency 与 forced-colors 降级。密度变化不缩小文字,触摸目标至少 44px。
|
|
220
|
+
- 验证原语变更:`bun run verify` + 文档站构建 + `bunx playwright test tests/e2e/design.pw.ts`(真实产物、定制、portal、明暗、移动与 axe)。
|
|
221
|
+
|
|
151
222
|
## 项目概览
|
|
152
223
|
|
|
153
224
|
`@icen.ai/ui` = Icen Design System 的单一事实源:设计 tokens + 无框架组件 CSS + 行为 JS。生态内所有前端(accounts / skill / editor / 未来 `*.icen.ai`)从这里取设计资产,**不允许在消费项目里另起一套样式**。
|
|
154
225
|
|
|
155
226
|
三层正交架构(移植自 opengal,见其 `docs/spec/theme-system.md`):
|
|
156
|
-
- **色彩预设**(`src/tokens/colors.css`):`
|
|
157
|
-
-
|
|
158
|
-
-
|
|
227
|
+
- **色彩预设**(`src/tokens/colors.css`):`modern`(默认)/ `dongyun` / `jugou` / `piano` / `monet` / `vangogh`,各含 `[data-icen-theme="dark"]`;以 `data-icen-preset` 挂在 `<html>` 上,现代是默认
|
|
228
|
+
- **原语**(`src/tokens/design.css` / `chinese.css` / `soviet.css` / `pixel.css`):现代 modern(默认)、中式 chinese、苏式 soviet、像素 pixel,控制几何、字体、材料、节奏与反馈;不覆盖选中的配色主题。
|
|
229
|
+
- **明暗**:`data-icen-theme="dark"` 属性,与预设和原语自由组合;亮色时移除该属性。
|
|
230
|
+
|
|
231
|
+
icen 默认:现代主题(瓷白+冷蓝)+现代原语。
|
|
159
232
|
|
|
160
|
-
icen
|
|
233
|
+
**accent 明度三档契约(WCAG AA 硬达标)**:`--icen-token-accent`(亮档,品牌色——图标/边框/数据可视化等纯图形面)/ `--icen-token-accent-strong`(**承文本填充档**——实心按钮/选中态/徽标等 accent 底承 on-accent 文字的面一律用它,12 面实测 4.79–10.84 全过 AA)/ `--icen-token-accent-text`(浅底上的文字橙——链接/弱强调文本)。`--icen-token-on-accent` 是 accent 填充上的文字色:亮底深字(monet dark/vangogh/piano 的「亮填充+深字」Material You 惯例)或深底白字。新增承文本填充面禁止直接消费 accent 亮档。
|
|
161
234
|
|
|
162
235
|
## 构建
|
|
163
236
|
|
|
164
237
|
```bash
|
|
165
238
|
bun install
|
|
166
|
-
bun run build # tsup(src/behaviors/*.ts
|
|
239
|
+
bun run build # tsup(src/behaviors/*.ts + src/react/index.tsx + src/vue/index.ts → dist/*.mjs
|
|
240
|
+
# + dist/behaviors/*.mjs + .d.mts 类型面;react/react-dom/vue 为 external peer)
|
|
241
|
+
# + bun scripts/react-use-client.mjs(dist/react.mjs 补 'use client' banner)
|
|
167
242
|
# + bun scripts/dts-ext.mjs(.d.ts 改名 .d.mts:.mjs 的声明必须同名 .d.mts)
|
|
168
243
|
# + bun scripts/build-css.ts(css → dist/:tokens.css/ui.css/base.css/
|
|
169
|
-
#
|
|
244
|
+
# tokens/*/components/*/registry.json)
|
|
245
|
+
# + bun scripts/dtcg.mjs + design-tokens.mjs(设计 token 导出:
|
|
246
|
+
# dist/tokens/dtcg.json + tokens-studio.json + figma.variables.json)
|
|
170
247
|
```
|
|
171
248
|
|
|
172
|
-
|
|
249
|
+
测试基座 = bun test + happy-dom(`tests/setup.ts` preload 注册 DOM 全局;`tests/helpers/dom.ts` 提供 mount/nextTick/fire;kb 族诚实呈现一致性套件 `tests/kb-conformance.test.ts` + 求值语义 `tests/unit/kb-acl.test.ts`,映射表见 spec §9.9)。验证 = `bunx tsc --noEmit` + `bun run guard` + `bun test` 全绿 + `bun run build` 通过 + `site/` 文档站目视(`cd site && bun install && bun run build`)。
|
|
173
250
|
|
|
174
251
|
## 规模
|
|
175
252
|
|
|
176
|
-
- **
|
|
177
|
-
- **
|
|
178
|
-
- **
|
|
179
|
-
-
|
|
253
|
+
- **69 个组件 CSS**(charts 基座 + 13 个细分图表 CSS + copy/tag/badge/scroll-area/notification/back-top/command-palette/date-picker/toolbar/split-pane + 4 个 AI 族合并文件:ai-chat/ai-tool/ai-diff/ai-panel + kb.css 基座 + 7 个 kb 域文件(ground/ingest/search/data/ops/agent/perm)+ form-validate.css 校验层 + mentions/autocomplete.css + theme-switcher.css 外观切换)
|
|
254
|
+
- **85 个 behaviors TS**(ai-threads/ai-feedback/ai-branch + kb-core 契约层 + 31 个 kb-*——含权限域 kb-acl/kb-who-can/kb-access/kb-audit/kb-visibility;form-validate 校验层 + mentions/autocomplete + i18n 文案注册表;theme-switcher 外观切换、icons 共享图形、focus 原生焦点契约、feedback 计时与异步动作、suggestions 可取消查询等基础模块)
|
|
255
|
+
- **122 个组件 slug**(kit 一行入口 / CLI / 文档站侧栏共用 SLUGS 清单)
|
|
256
|
+
- **测试与守卫**:`bun run verify` = tsc + guard + test + build;800+ 测试(bun test + happy-dom,tests/unit 纯契约 + tests/dom 委托行为 + tests/kb-conformance 权限诚实呈现 + tests/{unit,dom}/i18n 本地化契约与零 CJK 渲染验收);10 项纪律守卫(CSS/registry/事件/行为/命名空间/权限域/RTL 逻辑属性/类名同步/操作图标),CI 全挂
|
|
257
|
+
- **8 个 token 文件**:colors.css、style-profiles.css(公共兜底)、typography.css、design.css(现代与共享配方)、pixel.css(像素)、chinese.css(中式)、soviet.css(苏式)、icon-masks.css(共享 SVG 路径生成的静态图形)。
|
|
180
258
|
|
|
181
259
|
## 发布(OIDC Trusted Publishing,已配好)
|
|
182
260
|
|
|
@@ -186,77 +264,100 @@ bun run build # tsup(src/behaviors/*.ts → dist/behaviors/*.mjs + index.m
|
|
|
186
264
|
|
|
187
265
|
## 约定
|
|
188
266
|
|
|
189
|
-
- **组件只消费 `--token-*`,不写死颜色/圆角/阴影/字体/时长/间距**(radius 用 `--radius-*`、阴影用 `--token-shadow-*`、动效用 `--duration-*`/`--ease-*`、间距用 `--density-*`、字号用 `--density-font-size-*`、控件高度用 `--density-input-height-*`)。
|
|
190
|
-
-
|
|
191
|
-
-
|
|
192
|
-
|
|
193
|
-
-
|
|
194
|
-
-
|
|
195
|
-
- tabs.css 的 `--scroll` 变体已删除(违反「tab 条永不滚动」纪律)。
|
|
267
|
+
- **组件只消费 `--icen-token-*`,不写死颜色/圆角/阴影/字体/时长/间距**(radius 用 `--icen-radius-*`、阴影用 `--icen-token-shadow-*`、动效用 `--icen-duration-*`/`--icen-ease-*`、间距用 `--icen-density-*`、字号用 `--icen-density-font-size-*`、控件高度用 `--icen-density-input-height-*`)。
|
|
268
|
+
- **圆角几何契约(guard 第 1 项强制,哲学全文在 `docs/spec/design-philosophy.md` §2)**:六档职责 xs 微件内角 / sm 控件 / md 默认容器 / lg 卡片面板 / xl 页面级 / full 胶囊。**同心圆法则**:嵌套圆角共圆心,`R_inner = R_outer − gap`,写 `calc(var(--icen-radius-<外档>) - <间距>)`;同心结果 <0 时内层直角,禁止 1–3px 近似圆角差。**`full`(跑道形)只给胶囊语义件**(pill/badge/chip/switch/进度轨道),容器永不用 full;**`50%` 只给几何正圆**(avatar/状态点/图标底)。禁裸 999px、禁撞档裸值 6/8/10/12/16px;bar/dot/track 等图形级微构件的 1–5px 裸值须行尾 `/* guard:allow-radius 理由 */` 登记。像素原语把六档归零——正交归零依赖组件零物理值。
|
|
269
|
+
- 语义色纪律:仅绿 `--icen-token-success` / 黄 `--icen-token-warning` / 红 `--icen-token-error` / 信息 `--icen-token-info` + 品牌 `--icen-token-accent`。
|
|
270
|
+
- **类名规范**:
|
|
271
|
+
- 语义修饰符只认 `--success/--warning/--error/--info`(`.icen-pill--success` / `.icen-toast--error` / `.icen-icon--warning` 等)。
|
|
272
|
+
- 状态类一律 `.is-*`(如 `.icen-page-tab.is-active`、toast/notification 的 `.is-leaving`、`.icen-copy-btn.is-done`)。
|
|
196
273
|
- 滚动条纪律:全局细薄无上下箭头(`base.css` 统一负责,组件不再写滚动条样式);tab 条类组件**永不滚动**(`flex-wrap: wrap`)。
|
|
197
|
-
- **交互基元**:`base.css` 提供 6 个组件地基 `.pressable` / `.control` / `.field` / `.lift` / `.surface-elevated` / `.focus-ring
|
|
198
|
-
- **z-index 标尺**:浮层一律 portal 到 body,z-index 取 `--z-base/raised/sticky/chrome/toast/banner/dialog/popover/tooltip/fx
|
|
199
|
-
- **浮层 portal 家族**:popover / dropdown / context-menu / command-palette / date-picker / **select**(
|
|
200
|
-
- **凹槽 × 尺寸 ×
|
|
201
|
-
- **凹槽(内容)**:标记驱动组件 = 任意 HTML 凹槽(契约在各组件 CSS 头注释,如 modal 的 `.modal-body`、select 的 `.select-option` 内可写色卡/图标/多行);函数渲染组件 = 类型化 model(一律 `textContent` 防 XSS)+ 指定挂载点(`renderAiMessage` 的 `handle.body`、datatable 的 `columns.render → Node`)。toast / notification 保持纯文本是安全纪律,不开 HTML 口子。
|
|
202
|
-
- **尺寸(PanelSizing)**:所有浮层面板共享 `behaviors/popover.ts` 的 `PanelSizing` 类型(`width 固定(最高优先)/ minWidth / maxWidth / maxHeight`)与同名 data 属性 `data-panel-width / data-panel-min / data-panel-max / data-panel-max-height`(挂组件根;context-menu 等无宿主面板的走 `opts.sizing` 程序面,datatable 右键自动从宿主读)。共享解析 `readPanelSizing(el)` / `resolvePanelSizing(el, overrides)`(程序面 > 属性面)+ `sizingToLayout`(锚定布局)/ `applyPanelSizing(panel, sizing | null)`(自建面板内联;固定宽连带盖掉 CSS 侧 max-width;**带视口夹取**——宽一律夹到视口 −24px;**传 null 复位全部内联尺寸**,单例面板跨实例复用防串味,date-picker 即此用法)。布局侧 `side` 支持 `top/bottom/left/right`(左右侧自动翻转)。已接入:select / popover(openPopover) / dropdown / context-menu / date-picker / command-palette / modal / ai-composer 三弹层(`popoverSizing` opts > composer 根 data-panel-* > 内置默认)/ datatable 筛选与列显隐面板。新增浮层组件必须走此契约,禁止再写死宽高。
|
|
203
|
-
- **事件(三层体系,`behaviors/events.ts`)**:①手势层——任意容器挂 `data-gestures="click dblclick contextmenu longpress text-select"`(空格分隔)即开通归一化 `icen:` 手势事件(click 与 dblclick 同开时单击延迟 220ms,双击到达即取消;位移 >5px
|
|
204
|
-
- **控件族(`behaviors/controls.ts`)**:纯 CSS 控件的行为承载统一在此(switch/checkbox/radio 三态、stepper、segmented、steps、rating、pagination、静态表 th[data-sort] 排序),七 init 全部「document 委托 + 幂等 + 返回销毁」同款骨架;事件 `icen:switch-change / check-change / stepper-change / segmented-change / step-change / rating-change / page-change / sort-change`。slugs 映射走 SLUG_BEHAVIOR(segmented 同时带 input 的 initInput,kit 由 SLUG_EXPORTS 三项并存解决;controls 内转发 initInput 仅为 kit 服务,**根入口 index.ts 对 controls 用具名导出**——export * 会与 input 的 initInput 构成 ESM 歧义名被静默剔除)。
|
|
205
|
-
- **事件前缀纪律**:behavior 派发的自定义事件统一 `icen:` 前缀(如 tabs 的 `icen:tab-change`、upload 的 `icen:upload`)。
|
|
274
|
+
- **交互基元**:`base.css` 提供 6 个组件地基 `.icen-pressable` / `.icen-control` / `.icen-field` / `.icen-lift` / `.icen-surface-elevated` / `.icen-focus-ring`。原语适配集中在 material.css 与 material-{chinese,soviet}.css,原语参数分别位于 design.css、pixel.css、chinese.css、soviet.css。共享 keyframes(`icen-pop-in` / `icen-spin` / `icen-skeleton-pulse`)也在 base.css,组件动画复用、不各自重定义。
|
|
275
|
+
- **z-index 标尺**:浮层一律 portal 到 body,z-index 取 `--icen-z-base/raised/sticky/chrome/toast/banner/dialog/popover/tooltip/fx`。
|
|
276
|
+
- **浮层 portal 家族**:popover / dropdown / context-menu / command-palette / date-picker / **select**(panel 也 portal 到 body,与 popover 共用定位模式)/ **tooltip**(initTooltip 把 data-icen-tooltip 气泡 portal 增强,CSS ::after 仅作无 JS 回退;overflow 裁切对 z-index 无解,portal 是唯一根治)。
|
|
277
|
+
- **凹槽 × 尺寸 × 事件三契约(全库统一心智模型)**:
|
|
278
|
+
- **凹槽(内容)**:标记驱动组件 = 任意 HTML 凹槽(契约在各组件 CSS 头注释,如 modal 的 `.icen-modal-body`、select 的 `.icen-select-option` 内可写色卡/图标/多行);函数渲染组件 = 类型化 model(一律 `textContent` 防 XSS)+ 指定挂载点(`renderAiMessage` 的 `handle.body`、datatable 的 `columns.render → Node`)。toast / notification 保持纯文本是安全纪律,不开 HTML 口子。
|
|
279
|
+
- **尺寸(PanelSizing)**:所有浮层面板共享 `behaviors/popover.ts` 的 `PanelSizing` 类型(`width 固定(最高优先)/ minWidth / maxWidth / maxHeight`)与同名 data 属性 `data-icen-panel-width / data-icen-panel-min / data-icen-panel-max / data-icen-panel-max-height`(挂组件根;context-menu 等无宿主面板的走 `opts.sizing` 程序面,datatable 右键自动从宿主读)。共享解析 `readPanelSizing(el)` / `resolvePanelSizing(el, overrides)`(程序面 > 属性面)+ `sizingToLayout`(锚定布局)/ `applyPanelSizing(panel, sizing | null)`(自建面板内联;固定宽连带盖掉 CSS 侧 max-width;**带视口夹取**——宽一律夹到视口 −24px;**传 null 复位全部内联尺寸**,单例面板跨实例复用防串味,date-picker 即此用法)。布局侧 `side` 支持 `top/bottom/left/right`(左右侧自动翻转)。已接入:select / popover(openPopover) / dropdown / context-menu / date-picker / command-palette / modal / ai-composer 三弹层(`popoverSizing` opts > composer 根 data-panel-* > 内置默认)/ datatable 筛选与列显隐面板。新增浮层组件必须走此契约,禁止再写死宽高。
|
|
280
|
+
- **事件(三层体系,`behaviors/events.ts`)**:①手势层——任意容器挂 `data-icen-gestures="click dblclick contextmenu longpress text-select swipe"`(空格分隔)即开通归一化 `icen:` 手势事件(click 与 dblclick 同开时单击延迟 220ms,双击到达即取消;位移 >5px 视为拖拽不派发;`swipe` = 滑动:icen-down→icen-up 位移 ≥48px 且主轴明确〔次轴 < 主轴 1/2〕派 `icen:swipe-left/right/up/down`,detail = 手势包络 + `{dx,dy}`,move 期判垂直滚动脉络〔次轴先行 12px〕则抬手不派横向,全程不 preventDefault,`pointercancel` 中止);②协议层——全部 CustomEvent,`bubbles + composed + cancelable`;detail 契约全量登记在 `IcenEventMap`(onIcen 推断 / emitIcen 校验双侧同表,新增事件必须登记,拼错或 detail 不符编译期报错);从 document 派发(如 `icen:ai-done`/`icen:ai-usage`)= 全局广播——传播路径只经 [document, window],只有全局形态能收到(`within` 为普通元素时路径不经过它,收不到,要收广播用全局形态);③策略层——`setEventPolicy(type, fn|null)` 只收五种手势事件(编译期收死),给事件注册全站默认行为,一处赋予/覆盖/禁用,`getEventPolicy`/`resetEventPolicies` 为对称读取/清空口(调试与热重载)。绑定层 `onIcen`:类型推断 + 选择器委托 + `{ within, signal, once }`,返回解绑函数;派生口 `emitIcen`(勿裸写 new CustomEvent);`initGestures()` 幂等并返回销毁函数(`destroyGestures()` 同效),组件作者派发领域事件同样必须先在 `IcenEventMap` 登记。拖拽不在手势层(文件走 upload,排序/分割走组件自带)。
|
|
281
|
+
- **控件族(`behaviors/controls.ts`)**:纯 CSS 控件的行为承载统一在此(switch/checkbox/radio 三态、stepper、segmented、steps、rating、pagination、静态表 th[data-icen-sort] 排序),七 init 全部「document 委托 + 幂等 + 返回销毁」同款骨架;事件 `icen:switch-change / check-change / stepper-change / segmented-change / step-change / rating-change / page-change / sort-change`。slugs 映射走 SLUG_BEHAVIOR(segmented 同时带 input 的 initInput,kit 由 SLUG_EXPORTS 三项并存解决;controls 内转发 initInput 仅为 kit 服务,**根入口 index.ts 对 controls 用具名导出**——export * 会与 input 的 initInput 构成 ESM 歧义名被静默剔除)。
|
|
282
|
+
- **事件前缀纪律**:behavior 派发的自定义事件统一 `icen:` 前缀(如 tabs 的 `icen:tab-change`、upload 的 `icen:upload`)。
|
|
206
283
|
- **a11y**:所有可聚焦元素必须有 `:focus-visible` 环;状态变化必须同步 `aria-*`;modal/dialog 必须有 focus trap + ESC 关闭 + 焦点还原。
|
|
207
284
|
- **动效守卫**:所有动画/过渡在 `@media (prefers-reduced-motion: reduce)` 下压缩为 ~0ms;触屏(`pointer: coarse`)关闭 `:hover` 抬升;高对比度模式(`forced-colors: active`)保留焦点环。
|
|
208
|
-
- 新组件 = `src/components/<name>.css` 一个文件 + 文档站 components 页加一节;交互行为放 `src/behaviors/<name>.ts` 并配套 CSS 类契约。每个 CSS 头注释必须列出完整 DOM
|
|
285
|
+
- 新组件 = `src/components/<name>.css` 一个文件 + 文档站 components 页加一节;交互行为放 `src/behaviors/<name>.ts` 并配套 CSS 类契约。每个 CSS 头注释必须列出完整 DOM 契约。**新类名一律 `icen-` 前缀、新 data 钩子一律 `data-icen-*`、新事件一律 `icen:*` 并登记 IcenEventMap**——命名空间/事件/CSS 纪律由 `bun run guard` 强制(CI 红绿),新增违规无法合入。
|
|
209
286
|
- behaviors 全部 SSR 守卫(`typeof document === 'undefined'`),文本赋值用 `textContent`(禁 innerHTML),init 函数全部幂等(重复调用安全,通过 WeakSet/MarkedElement.__icen*Init 标记)。initTabs/initNav/initBackTop 等返回**销毁函数**(移除监听 + 复位幂等标记,销毁后可重新 init)。
|
|
210
287
|
- 函数式组件族(charts / datatable / ai 族 render*):不写类契约,导出 `createX(el, opts) → handle`;render* 一律返回挂载元素(有生命周期的图表返回 ChartHandle)——「有生命周期返 handle、静态返容器元素」,写文档示例时勿再写 void。同样一文件 CSS + 文档页一节 + slugs.mjs 登记。datatable 右键菜单复用 context-menu,其依赖的额外 CSS 走 slugs.mjs 的 EXTRA_CSS(kit 入口自动带上)。
|
|
211
|
-
- **图表按需安装**:charts 细分为 11 个独立可安装的 kit 入口(`chart-line` / `chart-bar` / `chart-pie` / `chart-radar` / `chart-heatmap` / `chart-area` / `chart-stack` / `chart-gauge` / `chart-sparkline` / `chart-scatter` / `chart-calendar`)+ umbrella `charts`(一条 import
|
|
288
|
+
- **图表按需安装**:charts 细分为 11 个独立可安装的 kit 入口(`chart-line` / `chart-bar` / `chart-pie` / `chart-radar` / `chart-heatmap` / `chart-area` / `chart-stack` / `chart-gauge` / `chart-sparkline` / `chart-scatter` / `chart-calendar`)+ umbrella `charts`(一条 import 全拿)。**通用层**:`renderChart(el, spec)` 单一入口吃纯 JSON ChartSpec(type 别名归一 `normalizeChartSpec` / 自动选型 `inferChartType` / `data[]+dims` 任意维度 pivot / `format` 描述符替代回调——AI 调用层的直接底座);交互委托 `icen:chart-hover(enter/move/leave)/click/dblclick/contextmenu`(detail 含 index/seriesIndex/seriesName/label/value/指针坐标,右键默认 preventDefault)+ 内置 tooltip(portal,`tooltip:false` 关)+ 图例点击切换系列(`icen:chart-legend-toggle`);图例可见性统一由 renderChart 头部行(.icen-chart-head = 标题 + 小眼睛)控制——根 `data-icen-legend-hidden` 容器级 CSS 隐藏全部图型图例(`spec.legend=false` 定初值,事件 `icen:chart-legend-visibility`),图表体渲染进内层 .chart-body(底层渲染器按契约清空传入 el,头部不能同层);多系列 line(调色盘)/ vbar(分组 `stacked` 堆叠)已内建,标记统一 `data-icen-chart-mark` + `data-icen-chart-*` 数据位。共享基座在 `charts.css`(.icen-chart / .icen-chart-legend / .icen-chart-labels / 调色盘),各类型专属样式在独立 `chart-<type>.css`;所有渲染函数仍在 `behaviors/charts.ts` 一个文件(tree-shake 友好);调色盘扩展口 `registerChartTone(name, cssVar)`(注册第 7+ 档自定义 tone,主题层/消费方用,内置六档之外时必走它)。子类型 slug → charts 行为模块的映射走 slugs.mjs 的 **`SLUG_BEHAVIOR`**(key=子类型 slug,value='charts'),kit 入口按 `SLUG_EXPORTS` 只 re-export 该类型的渲染函数。
|
|
212
289
|
- 组件 slug 映射(css 合并文件 / init 函数名 / behavior 模块名)的单一事实源是 `scripts/slugs.mjs`——新组件必须在此登记;`scripts/build-css.ts` 据此生成 kit 一行入口(`dist/components/<slug>.mjs` = import css + re-export behavior,消费侧 `@icen.ai/ui/kit/<slug>`)与 registry.json 的 slugs 面,CLI(`dist/cli.mjs`,`bunx @icen.ai/ui add <slug>` 打印引入行,不拷贝源码)与文档站都消费它。`slugs.mjs` 的类型声明在 `slugs.d.mts`,加导出成员时两处同步改。behavior 与 slug 不同名的(如 segmented 的 OTP 由 input.ts 的 initInput 提供)在 `SLUG_BEHAVIOR` 登记映射、在 `SLUG_EXPORTS` 登记 re-export,kit 入口才能正确带出。
|
|
213
290
|
- **kit 的 Astro 陷阱**:kit 入口里的 css import 在 Astro 页面 `<script>`(client bundle)里会被摇掉——Astro 项目必须在布局 frontmatter 里引组件 CSS(accounts 已踩过);Vite SPA / webpack 无此问题。文档站安装段已带此提示。
|
|
214
291
|
- **文档站客户端换页(ClientRouter)**:Docs 布局挂 `<ClientRouter prefetch />`,组件↔原语↔色彩↔各组件页之间为客户端换页(首页走 Base 布局,进出仍整页加载)。两条硬约定:① 页头/页脚 `transition:persist` 常驻,页头脚本经 `astro:after-swap` 对齐新页 active 并滑移导航墨条;② **页面级模块脚本(同 src 只评估一次)一律 `astro:page-load` 驱动**(首载 + 每次换页都触发),全局监听(onIcen 等)重入前先退订上一代;Docs 侧栏内联脚本用 `data-astro-rerun` 强制重跑(组开合记忆存 window 内存——客户端换页保留手动展开、真刷新归零回「全收 + 深链开组」)。新增页面脚本必须遵守,否则换页后接线断线。
|
|
215
292
|
- 文档站(`site/`):站壳/代码块样式集中在 `site/src/styles/site.css`;可复用展示件在 `site/src/components/`(SiteHeader / SiteFooter / CodeBlock / PmInstall / ThemeRestore 防闪烁);轻量语法高亮在 `site/src/lib/highlight.ts`(单行 token 化,`.tok-*` 颜色消费语义 token)。站顶 ⌘K 全站搜索 = 自家 command-palette 组件直出(条目由 `COMPONENTS` 生成),既是功能也是门面条 demo。
|
|
216
293
|
- **skill `icen-ui` 源在本仓库**(`skill/icen-ui/`,SKILL.md + 中英产品页):只写 WHEN/WHICH 场景配方,不抄 API 签名(事实层在 AGENTS.md/.d.mts)。改完跑 `bun scripts/sync-skill.mjs` 单向同步到兄弟仓库 `../skill/skills/icen-ui/`(skill 仓库那份是产物,勿手改),在该仓库提交 push 后 CI 自动上 skill.icen.ai;`--check` 可挂 CI 防漂移。
|
|
217
|
-
- 文档站字体体系(site.css 顶部):prose/站壳 = `--site-font-sans`(系统无衬线),demo 区 = `--site-font-mono`(Plex Mono + CJK 无衬线回退),展示级大标题才用 `--font-heading` 宋体——小字号中文一律不走宋体/通用 monospace 回退。
|
|
218
|
-
- CSS 产物由 `scripts/build-css.ts` 生成,**不要手改 dist/**。`tokensExtras
|
|
219
|
-
-
|
|
220
|
-
- 文档分组(`site/src/lib/components.ts` 的 `GROUPS`)= 侧栏顺序 = 索引页分组顺序:基础 / AI 原生 / 表单 / 数据展示 / 图表 / 浮层 / 反馈 /
|
|
221
|
-
- **反馈三件正交**:`toast`(瞬时 2.6s 右下角)/ `alert`(内嵌页面流)/ `notification`(持久右上角栈,工程级——进度通知/confirm Promise/多按钮/hover 暂停/倒计时/优先级置顶/已读未读/持久化/多容器 createNotificationCenter)——三者各司其职不互相替代;`copy` 是原地按钮反馈(区别于 toast 的全局通知)。JS
|
|
294
|
+
- 文档站字体体系(site.css 顶部):prose/站壳 = `--site-font-sans`(系统无衬线),demo 区 = `--site-font-mono`(Plex Mono + CJK 无衬线回退),展示级大标题才用 `--icen-font-heading` 宋体——小字号中文一律不走宋体/通用 monospace 回退。
|
|
295
|
+
- CSS 产物由 `scripts/build-css.ts` 生成,**不要手改 dist/**。`tokensExtras` 单独拷贝、暴露 exports,**不**进 `tokens.css`/`ui.css` 默认拼合。
|
|
296
|
+
- 内置主题的 12 基值 token 改动属于品牌级变更;新增内置主题 = 编辑 themes.json,再运行 bun run colors;运行时和站点自动读取目录,不维护重复名单。外部品牌仍可通过 createDesign 编译 CSS 或覆盖语义 token。
|
|
297
|
+
- 文档分组(`site/src/lib/components.ts` 的 `GROUPS`)= 侧栏顺序 = 索引页分组顺序:基础 / AI 原生 / 知识库 / 表单 / 数据展示 / 图表 / 浮层 / 反馈 / 导航。侧栏分组为 `<details>` 折叠(可多开,首访全开,localStorage `icen.docs.icen-nav.groups` 记忆,深链自动展开当前组)。kb 族文档数据在 `site/src/lib/kb-docs-{ground-ingest,search-data,ops-agent,perm}.ts` 四片段(避免巨文件冲突),`components.ts` 统一 push 进 COMPONENTS;`/kb` 的参考标签数据在 `site/src/lib/kb-references.ts`(32 条文献锚点 + 发表时间——设计决策可回溯,升级时先回源头)。
|
|
298
|
+
- **反馈三件正交**:`toast`(瞬时 2.6s 右下角)/ `alert`(内嵌页面流)/ `notification`(持久右上角栈,工程级——进度通知/confirm Promise/多按钮/hover 暂停/倒计时/优先级置顶/已读未读/持久化/多容器 createNotificationCenter)——三者各司其职不互相替代;`copy` 是原地按钮反馈(区别于 toast 的全局通知)。JS 词表 `toast.success/error`
|
|
222
299
|
- **徽章三件正交**:`pill`(行内状态徽章,语义色)/ `tag`(中性展示标签,可选关闭按钮与选中态)/ `badge`(角标式数字/圆点,挂外层元素角上,外层需 `position: relative`)。
|
|
223
|
-
-
|
|
224
|
-
- **select**:`data-select-search` 可搜索过滤(支持 `data-keywords` 辅助关键字 + 分组自动隐藏)、`data-select-multiple` 多选(chips 显示 + `data-select-max` 上限 + `.select-clear` 清除钮)、`.select-group` / `.select-group-label` 分组、`.select-empty` 无结果态。
|
|
225
|
-
- **input**:`maxlength`/`data-count` 字符计数器(接近上限转 warn、到顶转 error)、`data-mask="###-####-####"` 输入掩码(`#` 数字 / `A` 字母 / `*` 任意,原始值存 `data-raw-value`)、`data-trim` blur 去空白、全局 IME 组合态安全(compositionstart/end 挂起处理)。OTP 单元格(segmented 族)的跳格/粘贴分摊也由 initInput 接管。
|
|
226
|
-
- **upload**:`data-upload-list` 开启文件列表(图片自动缩略图、大小格式化、单文件 × 移除)、`data-max-size` / `data-max-files` 校验、accept 类型校验、事件 `icen:upload` / `icen:upload-error` / `icen:upload-remove`。
|
|
227
|
-
- **table**(静态表):`--zebra` 斑马纹、`caption` 标题、`--sticky-col` + `.col-fixed` 首列粘滞、`.row-expand` 展开行、行状态色(`row-success` / `row-warning` / `row-error`)、列宽工具类(`.col-narrow` / `.col-wide` / `.col-action`)。
|
|
228
|
-
- **stat**:横向布局(`--horizontal`)、迷你 sparkline 槽(`.stat-spark`)、SVG 进度环(`.stat-ring`)、加载骨架态(`.is-loading`)、图标语义色变体(`.icon--success/warning/error/info`)。
|
|
300
|
+
- **组件增强**:所有基础组件均为工程级深度——
|
|
301
|
+
- **select**:`data-icen-select-search` 可搜索过滤(支持 `data-icen-keywords` 辅助关键字 + 分组自动隐藏)、`data-icen-select-multiple` 多选(chips 显示 + `data-icen-select-max` 上限 + `.icen-select-clear` 清除钮)、`.icen-select-group` / `.icen-select-group-label` 分组、`.icen-select-empty` 无结果态。
|
|
302
|
+
- **input**:`maxlength`/`data-icen-count` 字符计数器(接近上限转 warn、到顶转 error)、`data-icen-mask="###-####-####"` 输入掩码(`#` 数字 / `A` 字母 / `*` 任意,原始值存 `data-icen-raw-value`)、`data-icen-trim` blur 去空白、全局 IME 组合态安全(compositionstart/end 挂起处理)。OTP 单元格(segmented 族)的跳格/粘贴分摊也由 initInput 接管。
|
|
303
|
+
- **upload**:`data-icen-upload-list` 开启文件列表(图片自动缩略图、大小格式化、单文件 × 移除)、`data-icen-max-size` / `data-icen-max-files` 校验、accept 类型校验、事件 `icen:upload` / `icen:upload-error` / `icen:upload-remove`。
|
|
304
|
+
- **table**(静态表):`--zebra` 斑马纹、`caption` 标题、`--sticky-col` + `.icen-col-fixed` 首列粘滞、`.icen-row-expand` 展开行、行状态色(`row-success` / `row-warning` / `row-error`)、列宽工具类(`.icen-col-narrow` / `.icen-col-wide` / `.icen-col-action`)。
|
|
305
|
+
- **stat**:横向布局(`--horizontal`)、迷你 sparkline 槽(`.icen-stat-spark`)、SVG 进度环(`.icen-stat-ring`)、加载骨架态(`.is-loading`)、图标语义色变体(`.icen-icon--success/warning/error/info`)。
|
|
229
306
|
- **empty**:类型预设(`--error` / `--404` / `--search` / `--maintenance` / `--network`)、`--illustrated` 渐变背景、`--inline` 内嵌模式。
|
|
230
|
-
- **panel**:可折叠(`--collapsible` + `.is-collapsed`)、副标题(`.panel-subtitle`)、平面变体(`--flat`)、强调变体(`--accent`)。
|
|
231
|
-
- **slider**:带标签刻度(`.slider-marks` + `.slider-mark`)、拖拽值提示气泡(`.slider-tooltip`)、渐变填充(`--gradient`)。
|
|
232
|
-
- **card**:封面比例变体(`.card-media--square/tall/wide`)、卡片网格(`.card-group`)、卡片列表(`.card-list`)、状态色边(`--success/warning/error`)、角标位(`.card-badge`)。
|
|
233
|
-
- **feedback**:环形进度(`.progress-ring`)、条纹/渐变进度条(`--striped` / `--gradient`)、点阵/条形 spinner(`--dots` / `--bars`)、全屏遮罩(`.spinner-overlay`)、骨架组合体(`.skeleton-text-group` / `.skeleton-media` / `.skeleton-table`)、shimmer 波纹(`--shimmer`)、alert 增强(`.alert-actions` / `--banner` / `--inline`)。
|
|
234
|
-
- **switch**:色彩变体(`--success/warning/danger`)、带文字开关(`--text`)、开关行(`.switch-row`)、单选卡片(`.radio-card` + `.radio-card-grid`)、复选网格(`.checkbox-grid`)。
|
|
235
|
-
- **tabs**:可关闭 tab(`.page-tab-close`)、徽标(`.page-tab-badge`)、图标(`.page-tab-icon`)、分段式(`--segment`)、垂直(`--vertical`)、尺寸(`--sm/lg`)。
|
|
236
|
-
- **nav**:搜索槽(`.nav-search`)、通知徽标(`.nav-btn-badge`)、链接式(`.nav-link`)、用户区(`.nav-user`)。
|
|
237
|
-
- **sidebar**:头部/底部槽(`.sidebar-header` / `.sidebar-footer`)、折叠/轨道模式(`--collapsed`)、激活指示条、分隔线、徽章变体色。
|
|
238
|
-
- **content**:列表增强(`.list-item-leading/meta/trailing` + 选中/斑马)、时间线变体(右侧/交替/自定义尺寸/扩展内容槽)、描述列表变体(行内/垂直/可复制)、树增强(连接线 `.tree--lined` + 搜索高亮)、代码块(`.code-block`)、kbd 大号/按下态。
|
|
307
|
+
- **panel**:可折叠(`--collapsible` + `.is-collapsed`)、副标题(`.icen-panel-subtitle`)、平面变体(`--flat`)、强调变体(`--accent`)。
|
|
308
|
+
- **slider**:带标签刻度(`.icen-slider-marks` + `.icen-slider-mark`)、拖拽值提示气泡(`.icen-slider-tooltip`)、渐变填充(`--gradient`)。
|
|
309
|
+
- **card**:封面比例变体(`.icen-card-media--square/tall/wide`)、卡片网格(`.icen-card-group`)、卡片列表(`.icen-card-list`)、状态色边(`--success/warning/error`)、角标位(`.icen-card-badge`)。
|
|
310
|
+
- **feedback**:环形进度(`.icen-progress-ring`)、条纹/渐变进度条(`--striped` / `--gradient`)、点阵/条形 spinner(`--dots` / `--bars`)、全屏遮罩(`.icen-spinner-overlay`)、骨架组合体(`.icen-skeleton-text-group` / `.icen-skeleton-media` / `.icen-skeleton-table`)、shimmer 波纹(`--shimmer`)、alert 增强(`.icen-alert-actions` / `--banner` / `--inline`)。
|
|
311
|
+
- **switch**:色彩变体(`--success/warning/danger`)、带文字开关(`--text`)、开关行(`.icen-switch-row`)、单选卡片(`.icen-radio-card` + `.icen-radio-card-grid`)、复选网格(`.icen-checkbox-grid`)。
|
|
312
|
+
- **tabs**:可关闭 tab(`.icen-page-tab-close`)、徽标(`.icen-page-tab-badge`)、图标(`.icen-page-tab-icon`)、分段式(`--segment`)、垂直(`--vertical`)、尺寸(`--sm/lg`)。
|
|
313
|
+
- **nav**:搜索槽(`.icen-nav-search`)、通知徽标(`.icen-nav-btn-badge`)、链接式(`.icen-nav-link`)、用户区(`.icen-nav-user`)。
|
|
314
|
+
- **sidebar**:头部/底部槽(`.icen-sidebar-header` / `.icen-sidebar-footer`)、折叠/轨道模式(`--collapsed`)、激活指示条、分隔线、徽章变体色。
|
|
315
|
+
- **content**:列表增强(`.icen-list-item-leading/meta/trailing` + 选中/斑马)、时间线变体(右侧/交替/自定义尺寸/扩展内容槽)、描述列表变体(行内/垂直/可复制)、树增强(连接线 `.icen-tree--lined` + 搜索高亮)、代码块(`.icen-code-block`)、kbd 大号/按下态。
|
|
239
316
|
- **media**:头像变体(语义色/渐变/方形/通知环)、头像组溢出计数、评分只读/清除/计数/摘要、轮播缩略图/索引/渐入。
|
|
240
317
|
- **toast**:语义图标、关闭钮、富内容(标题+正文)、超时进度条、6 种容器定位。
|
|
241
|
-
- **pill**:可关闭(`.pill-close`)、图标、实时脉冲(`--live`)、纯数字(`--count`)、渐变(`--gradient`)。
|
|
242
|
-
- **form**:水平字段布局(`--horizontal`)、表单区块(`.form-section`)、操作区(`.form-actions`)、行内表单(`--inline`)、字段网格(`.form-grid`)、加载遮罩(`.form-loading`)、label 帮助图标 / 可选标记。
|
|
243
|
-
- layout.css 已 token
|
|
318
|
+
- **pill**:可关闭(`.icen-pill-close`)、图标、实时脉冲(`--live`)、纯数字(`--count`)、渐变(`--gradient`)。
|
|
319
|
+
- **form**:水平字段布局(`--horizontal`)、表单区块(`.icen-form-section`)、操作区(`.icen-form-actions`)、行内表单(`--inline`)、字段网格(`.icen-form-grid`)、加载遮罩(`.icen-form-loading`)、label 帮助图标 / 可选标记。
|
|
320
|
+
- layout.css 已 token 化:stack / divider / surface / grid 等布局工具类的间距全部消费 `--icen-density-space-*`,无写死 px。
|
|
244
321
|
|
|
245
|
-
## AI
|
|
322
|
+
## AI 组件族
|
|
246
323
|
|
|
247
324
|
规格唯一事实源:`docs/spec/ai-native.md`(类名 / 导出签名 / 事件名以它为准)。11 个 slug 在文档站侧栏单列「AI」分组,排在导航之后:
|
|
248
325
|
|
|
249
326
|
- **清单与 CSS 合并**:ai-chat / ai-message / ai-reasoning / ai-composer → `ai-chat.css`;ai-tool-call / ai-subagent → `ai-tool.css`;ai-diff / ai-files → `ai-diff.css`;ai-todo / ai-context / ai-usage → `ai-panel.css`。6 个 behavior:ai-core(状态机 / 注册表 / 适配器 / 格式化 / svgIcon)、ai-chat、ai-composer、ai-tool、ai-diff、ai-panel,全部经 `src/index.ts` `export *`。
|
|
250
|
-
- **`.ai-item` 基元**:行式 AI 条目的"基类"(icon / main / side 状态点+meta / detail),kind 与变体只覆盖局部变量 `--ai-item-tint` 等槽位、不改结构(`--btn-*` 继承模式的推广);第三方 kind 的 tint 由 behavior 内联 `--ai-item-tint: var(--token-<tint>)` 兜底。
|
|
251
|
-
- **7 态状态机**(一切 AI 条目共享,语义色与动画全库一致):`.is-pending / running / streaming / approval / done / error / cancelled`;状态点 `.ai-item-status` 纯 CSS 由 `.is-*` 驱动;**默认展开集**:chart kind / error / approval / 多模态回执首渲染自动展开,其余 kind 默认折叠(用户手动切换后策略不干预,data-ai-user-toggled)。
|
|
327
|
+
- **`.icen-ai-item` 基元**:行式 AI 条目的"基类"(icon / main / side 状态点+meta / detail),kind 与变体只覆盖局部变量 `--ai-item-tint` 等槽位、不改结构(`--btn-*` 继承模式的推广);第三方 kind 的 tint 由 behavior 内联 `--ai-item-tint: var(--icen-token-<tint>)` 兜底。
|
|
328
|
+
- **7 态状态机**(一切 AI 条目共享,语义色与动画全库一致):`.is-pending / running / streaming / approval / done / error / cancelled`;状态点 `.icen-ai-item-status` 纯 CSS 由 `.is-*` 驱动;**默认展开集**:chart kind / error / approval / 多模态回执首渲染自动展开,其余 kind 默认折叠(用户手动切换后策略不干预,data-ai-user-toggled)。
|
|
252
329
|
- **kind 注册表与 normalize 适配层**:组件只消费归一化 `AiToolCallModel` / `AiUsage` / `AiContentPart`,业界格式(OpenAI / Anthropic / AI SDK / AG-UI / MCP / 素朴)由 `normalizeToolCall` / `normalizeUsage` / `normalizeContentParts` 翻译;内置 kinds(shell/read/edit/write/rm/grep/glob/browser/search/fetch/mcp/skill/todo/plan/subagent/note),第三方 `registerAiKind()` 扩展;`inferKind` 从工具名推断。
|
|
253
|
-
- **标准化内容模型 `AiContent`**(
|
|
330
|
+
- **标准化内容模型 `AiContent`**(spec §10):`string | AiContentPart[]`,部件族 text / image / audio / video / file / resource-link(url XOR data+base64 约定);一套 parts 三处共用——renderAiMessage 消息渲染(多模态 + `.icen-ai-msg--error` 错误变体 + `stream()` 流式节点)、ai-tool 的 IO 区(MCP content 数组零改动进卡片,`normalizeContentParts` 兼容 MCP 的 `resource_link` 下划线形态)、ai-provider 传输(两族 wire 映射 + anthropic `cache_control` + role 'tool' 回灌)。估算器 `estimateTokens`(CJK ×0.6 + 其余 ÷4 + 媒体经验值)与 `contextEstimate`(下一轮上下文口径)在 ai-core;**`contextEstimate`(环口径)与 `auditor.summary()`(累计计费口径)语义不同,禁止混喂同一个环**。
|
|
254
331
|
- **事件族 `icen:ai-*`**(全部 bubbles):send / stop / queue / dequeue / attach(钮选/粘贴/拖放三入口)/ copy / retry / approve / reject / diff-accept / diff-reject / todo-toggle / toggle / model-change / command / ref / usage(请求归一 usage)/ done(请求收尾:status/provider/model/usage/cost/error/durationMs/ttftMs——绑定层驱动事件)/ audit-clear;detail 见规格 §5。
|
|
255
|
-
- **`data-density` 三档**:verbose / normal / summary(summary 隐藏 meta、默认折叠 reasoning、压淡 tool/system 消息,纯 CSS)。
|
|
256
|
-
- **ai-usage 双形态**:分段条 `renderAiUsage` + 上下文窗口环形指示器 `renderAiUsageRing`(点击弹出完整分解,弹层复用 popover;状态档 <60% accent / 60–85% warning / >85% error+脉冲)。配套 `renderAiAudit` 审计面板(totals + byModel + 最近条目,清除钮派 `icen:ai-audit-clear`);`ai-context` 抽屉的 `model.audit` 自动渲染审计节(紧凑形态)。
|
|
257
|
-
- **ai-composer
|
|
258
|
-
- **绑定层 `bindComposer`**(
|
|
332
|
+
- **`data-icen-density` 三档**:verbose / normal / summary(summary 隐藏 meta、默认折叠 reasoning、压淡 tool/system 消息,纯 CSS)。
|
|
333
|
+
- **ai-usage 双形态**:分段条 `renderAiUsage` + 上下文窗口环形指示器 `renderAiUsageRing`(点击弹出完整分解,弹层复用 icen-popover;状态档 <60% icen-accent / 60–85% warning / >85% error+脉冲)。配套 `renderAiAudit` 审计面板(totals + byModel + 最近条目,清除钮派 `icen:ai-audit-clear`);`ai-context` 抽屉的 `model.audit` 自动渲染审计节(紧凑形态)。
|
|
334
|
+
- **ai-composer**(业界集大成):底部工具条 = 模型切换(多 provider 分组 + 搜索 + 缓存失效提示,选中模型 context 自动喂给环的 total;无 context 显式清除不留陈旧值)+ 上下文环挂载点 + 附件 + 发送/停止;`/` 命令弹层(拦截执行不进消息流);`@` 引用弹层(chip 分离渲染,textarea 不嵌 chip);空输入 `↑` 取回历史,运行中 `↑` 取回排队消息。附件三入口:钮选 / textarea 粘贴文件 / box 拖放(`.is-dragover` 高亮)。API:setComposerModels / setComposerCommands / setComposerRefs / setComposerUsage / bindComposer。
|
|
335
|
+
- **绑定层 `bindComposer`**(spec §11,「零接线全链路」):事件驱动把 composer ↔ 消息区(renderAiMessage)↔ client(stream + 停止 + 排队自动续发 + 错误 → setError/fail)↔ 用量环(`usage.from: 'context'` 默认正确口径 | `'billing'` | AiAuditor)接成闭环;运行态自动管理(send→running / icen:ai-done→解除);不传 client 为纯状态绑定(渐进采用);重复绑定 WeakSet 防护,unbind 解绑。
|
|
259
336
|
- **ai-provider 适配层**(`src/behaviors/ai-provider.ts`,无 UI 不占 slug):注册表内置 openai/claude/deepseek/glm/kimi 五家(`registerAiProvider`/`getAiProvider` 注册与读取第三方/自建网关;baseURL 可自定义,models 携带定价表——`estimateCost` 未命中返回 undefined 不猜价),`createAiClient` 填 key 即用(chat + stream 双族线协议,多模态 parts 传输:openai 族 image_url/input_audio/file_id、anthropic 族 image/audio/document(pdf) + `cacheControl` 断点 + role 'tool' 的 tool_result 回灌;video 两族诚实报 unsupported),usage 走 normalizeUsage 归一(含各家缓存字段),`createAiAuditor` 环形审计(条目含 cost 定价估算 + ttftMs 首 token 延迟;`summary()` 喂环 / `totals()` 喂审计面板 / `byModel()` 分组),每次请求派 `icen:ai-usage` 与 `icen:ai-done` 事件。浏览器直连:claude 官方支持(自动带直连头),openai 官方禁止,其余三家建议代理(browserDirect 字段诚实标注)。
|
|
260
|
-
- **AI
|
|
337
|
+
- **AI 工具体系(`src/behaviors/ai-tools.ts`,不绑定 slug)**:UI 能力注册为模型可调用的 AiToolDef(内置 render_chart(inputSchema=ChartSpec)与 render_datatable(columns+rows → createTable 可搜索/分页/可导出));createAiToolArea 挂载区三层控制(不 import=无 / 白名单+max LRU 淘汰最旧挂载 / 运行时 setTools·setMax·clear);`AiToolDef.present: 'mount'|'data'`(data=不占挂载位,记录与事件照常,run 返回值即结果);执行契约 `run(input, mount, ctx)`:`ctx:{signal,progress(line)}`、允许 Promise 结果、`timeoutMs`(超时→`{ok:false,error:{code:'timeout'}}`,只作用 Promise 型 run)、`requiresApproval`(审批区→icen:ai-tool-approve 才执行 / -reject 置 .is-cancelled)、`idempotent`(同名同输入在途复用同一记录);`validateToolArgs` 诚实校验(不支持的关键字进 unvalidated 清单,不猜不静默),area.call 的 `validate` 默认开;注册面 `registerAiTool`·`unregisterAiTool`(联动摘除各区域已挂载卡)·`getAiTool`·`listAiTools`;模型侧导出四族共享归一管线 aiToolsToOpenAI/aiToolsToAnthropic/aiToolsToMcp/aiToolsToAiSdk(不 execute,宿主侧挂载)+ aiToolsManifest + parseAiToolArgs;失败统一信封 `record.icen-result={ok:false,error:{code}}`,事件 error 字段保持 string 契约;工具回执内嵌图(**仅 output**;input 是机器参数保持 JSON)→ renderAiToolCall IO 区直接 renderChart;待办业界模式:TodoWrite 折叠卡(todo kind summarize x/y)+ `setComposerTodo` 输入区实时 chip(全完成/有失败图标反馈,点击弹层看清单);事件 icen:ai-tool-call/-result/-evict/-approve/-reject。规格 §13。
|
|
261
338
|
- **ai-core 不绑定任何 slug**:demo/消费方要用 `normalizeToolCall` 等时,在该页 behaviors 数组里显式加 `'ai-core'`(boot 的 glob 会加载并注入 `aiCoreMod` 参数)。
|
|
262
|
-
- **宽度自稳定契约**:所有 AI 输出容器根(`.ai-chat/.ai-reasoning/.ai-composer/.ai-item/.ai-tool/.ai-subagent/.ai-diff/.ai-files/.ai-todo/.ai-usage`)声明 `align-self: stretch`——在 flex/grid 居中宿主(shrink-wrap 上下文,如文档站 `.demo-stage`)里不随内容多少改变宽度,流式内容只允许纵向生长。**禁用 `width: 100%`** 做这件事(在 shrink-wrap 父级下会塌成 min-content)。消费方给组件包一层自己的布局 wrapper 时,wrapper 的宽度由消费方负责(demo 里直接 `style="width:100%"`)。
|
|
339
|
+
- **宽度自稳定契约**:所有 AI 输出容器根(`.icen-ai-chat/.icen-ai-reasoning/.icen-ai-composer/.icen-ai-item/.icen-ai-tool/.icen-ai-subagent/.icen-ai-diff/.icen-ai-files/.icen-ai-todo/.icen-ai-usage`)声明 `align-self: stretch`——在 flex/grid 居中宿主(shrink-wrap 上下文,如文档站 `.demo-stage`)里不随内容多少改变宽度,流式内容只允许纵向生长。**禁用 `width: 100%`** 做这件事(在 shrink-wrap 父级下会塌成 min-content)。消费方给组件包一层自己的布局 wrapper 时,wrapper 的宽度由消费方负责(demo 里直接 `style="width:100%"`)。
|
|
340
|
+
|
|
341
|
+
## 知识库族
|
|
342
|
+
|
|
343
|
+
规格唯一事实源:`docs/spec/kb-family.md`(顶层设计 / 类名 / 导出签名 / 事件名以它为准;调研底稿 `docs/research/2026-10-03-ai-kb-components.md` + `2026-10-03-kb-permissions.md`)。32 个 slug 在文档站侧栏「知识库」分组(第三位);旗舰成品页 `/kb`(八标签工作台全真接线 + 参考文献锚点)。
|
|
344
|
+
|
|
345
|
+
- **心法**:ai 族描述思考(过程),kb 族呈现证据(知识从哪来 / 可信吗 / 怎么用)。CSS 根类 `.kb-*`,行为文件 `kb-*.ts`,事件 `icen:kb-*`(45 个全量登记 `IcenEventMap`,detail 契约编译期校验)。
|
|
346
|
+
- **契约层 `kb-core.ts`(无 UI 不占 slug)**:KbCitation(三型定位 char/page/block,unit 写死)/ KB_SCORE_KINDS + scoreHigherIsBetter + scorePercent(l2 自动反转,null→「—」)/ KbChunk / KbRunStatus 管线五态 / normalizeConnector + connectorHealth(4 离散信号,enabled≠healthy)/ segmentText + segmentStats / normalizeRetrievalParams / KbFilterNode + filterToMongo/filterToOData / KbEvalRow + evalGrade(improvement/regression/tradeoff/tie)/ KbCheckpoint + scope / KbSandboxMessage 等 40+ normalize 与格式化函数。**业务数据一律先过 normalize 再喂组件**;demo / 消费方要用契约时在该页 behaviors 数组显式加 `'kb-core'`。
|
|
347
|
+
- **CSS 布局**:共享基座 `kb.css`(.icen-kb-row 28/24 双密度、.icen-kb-num/.icen-kb-meta、.icen-kb-dot 四态、.icen-kb-score bar、.icen-kb-quote 证据线 + mark 分色 data-icen-hit 0/1/2、.icen-kb-badge 族、.icen-kb-chip、.kb-fold、.icen-kb-key、.icen-kb-empty、.icen-kb-notice、.icen-kb-layer-chip 过滤层徽标三态)+ 七域文件 kb-{ground,ingest,search,data,ops,agent,perm}.css。slugs.mjs 的 EXTRA_CSS 把每个 kb-* slug 映射到 `['kb.css', '<域>.css']`(kit 入口自动带上);`kb` 总集 slug 带全部七域。新组件先进规格冻结 DOM 骨架再动手(权限域冻结在 §9)。
|
|
348
|
+
- **诚实呈现纪律(kb 族特有,评审必查,已由测试+守卫强制执行——spec §9.9 映射表)**:分数 null →「—」不猜;行数截断必须声明(「前 200 行」);权限缺失打码 + 「申请访问」入口;重排关闭后列压淡不隐藏(显式禁用 > 静默消失);检查点回滚范围显式(只回滚文件保留对话);DSL 镜像只镜像可发送规则(无效规则不进 DSL);`仅本次会话生效 / 入库` 二选一显式承诺。改行为先改 `tests/kb-conformance.test.ts` 预期;泄露文案模式由 `scripts/guard/kb-honesty.ts` 扫 `kb-*.ts` + `site/src/lib/kb-*.ts`(豁免:行尾 `guard:allow-honesty 理由`)。
|
|
349
|
+
- **分数条纪律**:`.icen-kb-score-bar` 是定宽轨道(域 CSS 内 `flex: 0 0 64px` 量级)+ `i` inline width 百分比——禁止让轨道随数值文本伸缩(曾导致 0.49 与 0.13 等长的失真)。
|
|
350
|
+
- **DOM 骨架与事件**:每个组件的冻结骨架与函数名在规格 §4/§5;`createX(el, opts) → handle`(含 destroy)、`renderX(el, data)` 快照渲染、`initX(root?)` document 委托幂等——与全库三契约(凹槽/尺寸/事件)同一心智。
|
|
351
|
+
- **/kb 工作台**(`site/src/pages/kb.astro` + `site/src/lib/kb-showcase.ts`):mock 数据与接线全在 showcase 模块;八标签 = 问答 / 摄取 / 检索 / 问数 / 观测 / 权限 / Agent / 参考(参考为静态 SSR,数据在 kb-references.ts)。改 mock 数据只动 kb-showcase.ts;页面脚本遵守 `astro:page-load` 驱动约定。
|
|
352
|
+
|
|
353
|
+
## 图标与次要操作
|
|
354
|
+
|
|
355
|
+
- **AI 托管会话连续性**:`bindComposer` 返回 `retry(): boolean` 与 `unbind()`。成功后续发队列;停止或失败暂停队列,空输入框 ↑ 可取回待发消息。最近失败/停止的回答可由 `retry()` 或消息继续钮原位重试,保留当前草稿且不重复用户消息;更早或成功回答的重试由宿主处理。`unbind()` 必须在页面/组件卸载时调用,迟到的 chunk/done 不得改动新会话。
|
|
356
|
+
|
|
357
|
+
- **选中态纪律(用户明确要求)**:所有选择组件与菜单不使用 ✓、check SVG 或 check mask 表示选中,也不替换为「已选」等文字标记。选项共用 material.css 的轻底色 + 内描边;复选框用实心几何内核,半选用 CSS 短横,保留真实 checked/indeterminate/aria-*。弹出式选择器、主题/原语切换、模型选择和下拉触发器不展示上下箭头;树内层级导航及前后翻页仍可保留方向图形。完成/成功反馈与选中不同,状态 check 图标仍可按语义使用。
|
|
358
|
+
|
|
359
|
+
- `behaviors/icons.ts` 是界面操作符号的唯一几何源:`createIcon` 返回真实 SVG DOM,`iconHTML` 输出安全 SSR 标记;消费方一行入口 `kit/icon`,不使用图标字体或 Unicode 字形代替操作图标。CSS 指示器用 `--icen-token-icon-*` masks,由 `scripts/icon-masks.ts` 同源生成,构建会重算。
|
|
360
|
+
- 所有图形采用 20×20 光学网格、1.6 线宽;图标默认 decorative,独立图标传 label。方向镜像由具体组件决定。自定义路径走 registerIcon,不允许覆盖内置符号。
|
|
361
|
+
- 次要操作可用 `.icen-icon-action[data-icen-reveal]`:固定槽位,父级 hover/focus-within 显现,触屏常显。不要隐藏主入口或重要状态;避免用宽度从 0 展开挤动正文。
|
|
362
|
+
- 可折叠面板用 `initPanel`,程序化更新用 `setPanelExpanded`;用户操作派 `icen:panel-toggle`。标题区保留真正的原生 button,其他标题操作不触发折叠。
|
|
363
|
+
- 全站文档基础巡检:build 后运行 `node scripts/audit-ui.mjs`,报告到忽略目录 `.ui-audit/`;它只提供基础证据,不替代展开状态的交互验收。
|