@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.
Files changed (335) hide show
  1. package/AGENTS.md +176 -75
  2. package/README.md +66 -88
  3. package/dist/base.css +208 -179
  4. package/dist/behaviors/accordion.mjs +8 -8
  5. package/dist/behaviors/ai-branch.d.mts +19 -0
  6. package/dist/behaviors/ai-branch.mjs +1133 -0
  7. package/dist/behaviors/ai-chat.d.mts +12 -10
  8. package/dist/behaviors/ai-chat.mjs +1125 -155
  9. package/dist/behaviors/ai-composer.d.mts +44 -12
  10. package/dist/behaviors/ai-composer.mjs +2084 -523
  11. package/dist/behaviors/ai-core.d.mts +1 -1
  12. package/dist/behaviors/ai-core.mjs +1016 -107
  13. package/dist/behaviors/ai-diff.mjs +1019 -127
  14. package/dist/behaviors/ai-feedback.d.mts +26 -0
  15. package/dist/behaviors/ai-feedback.mjs +1212 -0
  16. package/dist/behaviors/ai-panel.d.mts +21 -7
  17. package/dist/behaviors/ai-panel.mjs +1308 -264
  18. package/dist/behaviors/ai-provider.mjs +1003 -101
  19. package/dist/behaviors/ai-threads.d.mts +38 -0
  20. package/dist/behaviors/ai-threads.mjs +1233 -0
  21. package/dist/behaviors/ai-tool.d.mts +2 -2
  22. package/dist/behaviors/ai-tool.mjs +2042 -396
  23. package/dist/behaviors/ai-tools.d.mts +89 -16
  24. package/dist/behaviors/ai-tools.mjs +4453 -372
  25. package/dist/behaviors/autocomplete.d.mts +53 -0
  26. package/dist/behaviors/autocomplete.mjs +1600 -0
  27. package/dist/behaviors/back-top.d.mts +1 -1
  28. package/dist/behaviors/back-top.mjs +951 -14
  29. package/dist/behaviors/carousel.d.mts +1 -1
  30. package/dist/behaviors/carousel.mjs +906 -11
  31. package/dist/behaviors/cascader.d.mts +48 -0
  32. package/dist/behaviors/cascader.mjs +1853 -0
  33. package/dist/behaviors/charts.d.mts +174 -8
  34. package/dist/behaviors/charts.mjs +2632 -192
  35. package/dist/behaviors/code-block.d.mts +36 -0
  36. package/dist/behaviors/code-block.mjs +1611 -0
  37. package/dist/behaviors/command-palette.d.mts +9 -6
  38. package/dist/behaviors/command-palette.mjs +161 -59
  39. package/dist/behaviors/context-menu.d.mts +9 -8
  40. package/dist/behaviors/context-menu.mjs +1112 -44
  41. package/dist/behaviors/controls.d.mts +13 -13
  42. package/dist/behaviors/controls.mjs +989 -130
  43. package/dist/behaviors/copy.d.mts +21 -2
  44. package/dist/behaviors/copy.mjs +1206 -42
  45. package/dist/behaviors/datatable.d.mts +53 -3
  46. package/dist/behaviors/datatable.mjs +1963 -207
  47. package/dist/behaviors/date-picker.d.mts +0 -1
  48. package/dist/behaviors/date-picker.mjs +1340 -293
  49. package/dist/behaviors/design.d.mts +54 -0
  50. package/dist/behaviors/design.mjs +109 -0
  51. package/dist/behaviors/dropdown.d.mts +5 -6
  52. package/dist/behaviors/dropdown.mjs +262 -110
  53. package/dist/behaviors/events.d.mts +313 -3
  54. package/dist/behaviors/events.mjs +47 -2
  55. package/dist/behaviors/feedback.d.mts +30 -0
  56. package/dist/behaviors/feedback.mjs +296 -0
  57. package/dist/behaviors/focus.d.mts +8 -0
  58. package/dist/behaviors/focus.mjs +24 -0
  59. package/dist/behaviors/form-validate.d.mts +102 -0
  60. package/dist/behaviors/form-validate.mjs +6091 -0
  61. package/dist/behaviors/i18n.d.mts +789 -0
  62. package/dist/behaviors/i18n.mjs +1711 -0
  63. package/dist/behaviors/icons.d.mts +93 -0
  64. package/dist/behaviors/icons.mjs +113 -0
  65. package/dist/behaviors/input.d.mts +9 -1
  66. package/dist/behaviors/input.mjs +1056 -60
  67. package/dist/behaviors/kb-access.d.mts +34 -0
  68. package/dist/behaviors/kb-access.mjs +2459 -0
  69. package/dist/behaviors/kb-acl.d.mts +50 -0
  70. package/dist/behaviors/kb-acl.mjs +1345 -0
  71. package/dist/behaviors/kb-answer.d.mts +38 -0
  72. package/dist/behaviors/kb-answer.mjs +3707 -0
  73. package/dist/behaviors/kb-audit.d.mts +23 -0
  74. package/dist/behaviors/kb-audit.mjs +1297 -0
  75. package/dist/behaviors/kb-canvas.d.mts +44 -0
  76. package/dist/behaviors/kb-canvas.mjs +1512 -0
  77. package/dist/behaviors/kb-chain.d.mts +15 -0
  78. package/dist/behaviors/kb-chain.mjs +1192 -0
  79. package/dist/behaviors/kb-checkpoint.d.mts +16 -0
  80. package/dist/behaviors/kb-checkpoint.mjs +1492 -0
  81. package/dist/behaviors/kb-chunks.d.mts +31 -0
  82. package/dist/behaviors/kb-chunks.mjs +1414 -0
  83. package/dist/behaviors/kb-citation.d.mts +38 -0
  84. package/dist/behaviors/kb-citation.mjs +1699 -0
  85. package/dist/behaviors/kb-clarify.d.mts +20 -0
  86. package/dist/behaviors/kb-clarify.mjs +1176 -0
  87. package/dist/behaviors/kb-conflict.d.mts +22 -0
  88. package/dist/behaviors/kb-conflict.mjs +1206 -0
  89. package/dist/behaviors/kb-connector.d.mts +17 -0
  90. package/dist/behaviors/kb-connector.mjs +1303 -0
  91. package/dist/behaviors/kb-core.d.mts +534 -0
  92. package/dist/behaviors/kb-core.mjs +1805 -0
  93. package/dist/behaviors/kb-eval.d.mts +22 -0
  94. package/dist/behaviors/kb-eval.mjs +2235 -0
  95. package/dist/behaviors/kb-explain.d.mts +11 -0
  96. package/dist/behaviors/kb-explain.mjs +1165 -0
  97. package/dist/behaviors/kb-filter.d.mts +31 -0
  98. package/dist/behaviors/kb-filter.mjs +2417 -0
  99. package/dist/behaviors/kb-gap.d.mts +27 -0
  100. package/dist/behaviors/kb-gap.mjs +1195 -0
  101. package/dist/behaviors/kb-hittest.d.mts +34 -0
  102. package/dist/behaviors/kb-hittest.mjs +1352 -0
  103. package/dist/behaviors/kb-metadata.d.mts +29 -0
  104. package/dist/behaviors/kb-metadata.mjs +1248 -0
  105. package/dist/behaviors/kb-passage.d.mts +41 -0
  106. package/dist/behaviors/kb-passage.mjs +1469 -0
  107. package/dist/behaviors/kb-pipeline.d.mts +18 -0
  108. package/dist/behaviors/kb-pipeline.mjs +1301 -0
  109. package/dist/behaviors/kb-qa.d.mts +26 -0
  110. package/dist/behaviors/kb-qa.mjs +1260 -0
  111. package/dist/behaviors/kb-rerank.d.mts +20 -0
  112. package/dist/behaviors/kb-rerank.mjs +1248 -0
  113. package/dist/behaviors/kb-retrieval.d.mts +49 -0
  114. package/dist/behaviors/kb-retrieval.mjs +2585 -0
  115. package/dist/behaviors/kb-review.d.mts +44 -0
  116. package/dist/behaviors/kb-review.mjs +2282 -0
  117. package/dist/behaviors/kb-sandbox.d.mts +33 -0
  118. package/dist/behaviors/kb-sandbox.mjs +1247 -0
  119. package/dist/behaviors/kb-segment.d.mts +32 -0
  120. package/dist/behaviors/kb-segment.mjs +1431 -0
  121. package/dist/behaviors/kb-select.d.mts +24 -0
  122. package/dist/behaviors/kb-select.mjs +1989 -0
  123. package/dist/behaviors/kb-sources.d.mts +27 -0
  124. package/dist/behaviors/kb-sources.mjs +1287 -0
  125. package/dist/behaviors/kb-sql.d.mts +43 -0
  126. package/dist/behaviors/kb-sql.mjs +1865 -0
  127. package/dist/behaviors/kb-trace.d.mts +16 -0
  128. package/dist/behaviors/kb-trace.mjs +1328 -0
  129. package/dist/behaviors/kb-visibility.d.mts +44 -0
  130. package/dist/behaviors/kb-visibility.mjs +1331 -0
  131. package/dist/behaviors/kb-who-can.d.mts +32 -0
  132. package/dist/behaviors/kb-who-can.mjs +2216 -0
  133. package/dist/behaviors/mentions.d.mts +93 -0
  134. package/dist/behaviors/mentions.mjs +2152 -0
  135. package/dist/behaviors/modal.d.mts +4 -3
  136. package/dist/behaviors/modal.mjs +1055 -33
  137. package/dist/behaviors/nav.d.mts +1 -1
  138. package/dist/behaviors/nav.mjs +6 -6
  139. package/dist/behaviors/notification.d.mts +16 -8
  140. package/dist/behaviors/notification.mjs +1615 -265
  141. package/dist/behaviors/panel.d.mts +4 -0
  142. package/dist/behaviors/panel.mjs +994 -0
  143. package/dist/behaviors/popover.d.mts +28 -5
  144. package/dist/behaviors/popover.mjs +225 -24
  145. package/dist/behaviors/select.d.mts +5 -2
  146. package/dist/behaviors/select.mjs +1410 -117
  147. package/dist/behaviors/sidebar.d.mts +1 -1
  148. package/dist/behaviors/sidebar.mjs +13 -13
  149. package/dist/behaviors/slider.d.mts +1 -1
  150. package/dist/behaviors/slider.mjs +9 -9
  151. package/dist/behaviors/split-pane.d.mts +1 -1
  152. package/dist/behaviors/split-pane.mjs +7 -7
  153. package/dist/behaviors/suggestions.d.mts +27 -0
  154. package/dist/behaviors/suggestions.mjs +1089 -0
  155. package/dist/behaviors/svg-parse.d.mts +14 -0
  156. package/dist/behaviors/svg-parse.mjs +37 -0
  157. package/dist/behaviors/tabs.d.mts +2 -2
  158. package/dist/behaviors/tabs.mjs +25 -25
  159. package/dist/behaviors/tag-input.d.mts +23 -5
  160. package/dist/behaviors/tag-input.mjs +1359 -104
  161. package/dist/behaviors/theme-switcher.d.mts +24 -0
  162. package/dist/behaviors/theme-switcher.mjs +1981 -0
  163. package/dist/behaviors/theme.d.mts +15 -8
  164. package/dist/behaviors/theme.mjs +390 -28
  165. package/dist/behaviors/toast.d.mts +24 -25
  166. package/dist/behaviors/toast.mjs +1266 -88
  167. package/dist/behaviors/tooltip.d.mts +4 -0
  168. package/dist/behaviors/tooltip.mjs +378 -0
  169. package/dist/behaviors/tree-select.d.mts +69 -0
  170. package/dist/behaviors/tree-select.mjs +1907 -0
  171. package/dist/behaviors/tree.d.mts +1 -1
  172. package/dist/behaviors/tree.mjs +15 -15
  173. package/dist/behaviors/upload.d.mts +3 -2
  174. package/dist/behaviors/upload.mjs +1076 -66
  175. package/dist/cli.mjs +5 -6
  176. package/dist/components/ai-branch.mjs +3 -0
  177. package/dist/components/ai-chat.css +846 -458
  178. package/dist/components/ai-diff.css +153 -132
  179. package/dist/components/ai-feedback.mjs +3 -0
  180. package/dist/components/ai-panel.css +495 -270
  181. package/dist/components/ai-threads.mjs +3 -0
  182. package/dist/components/ai-tool.css +393 -238
  183. package/dist/components/autocomplete.css +61 -0
  184. package/dist/components/autocomplete.mjs +3 -0
  185. package/dist/components/back-top.css +34 -31
  186. package/dist/components/badge.css +44 -41
  187. package/dist/components/breadcrumb.css +67 -46
  188. package/dist/components/btn.css +80 -74
  189. package/dist/components/card.css +117 -106
  190. package/dist/components/cascader.css +311 -0
  191. package/dist/components/cascader.mjs +3 -0
  192. package/dist/components/chart-area.css +8 -2
  193. package/dist/components/chart-bar.css +95 -33
  194. package/dist/components/chart-gauge.css +14 -11
  195. package/dist/components/chart-graph.css +60 -0
  196. package/dist/components/chart-graph.mjs +4 -0
  197. package/dist/components/chart-heatmap.css +96 -90
  198. package/dist/components/chart-line.css +8 -3
  199. package/dist/components/chart-map.mjs +3 -0
  200. package/dist/components/chart-pie.css +9 -6
  201. package/dist/components/chart-radar.css +8 -5
  202. package/dist/components/chart-scatter.css +9 -6
  203. package/dist/components/chart-scatter.mjs +1 -1
  204. package/dist/components/chart-sparkline.css +5 -2
  205. package/dist/components/chart-stack.css +14 -11
  206. package/dist/components/charts.css +190 -67
  207. package/dist/components/charts.mjs +1 -0
  208. package/dist/components/code-block.css +418 -0
  209. package/dist/components/code-block.mjs +4 -0
  210. package/dist/components/command-palette.css +138 -117
  211. package/dist/components/content.css +257 -251
  212. package/dist/components/copy.css +72 -44
  213. package/dist/components/datatable.css +423 -181
  214. package/dist/components/date-picker.css +135 -104
  215. package/dist/components/empty.css +68 -65
  216. package/dist/components/feedback.css +201 -183
  217. package/dist/components/form-validate.css +120 -0
  218. package/dist/components/form-validate.mjs +3 -0
  219. package/dist/components/form.css +150 -127
  220. package/dist/components/icon.css +102 -0
  221. package/dist/components/icon.mjs +3 -0
  222. package/dist/components/input.css +159 -104
  223. package/dist/components/kb-access.mjs +4 -0
  224. package/dist/components/kb-acl.mjs +4 -0
  225. package/dist/components/kb-agent.css +496 -0
  226. package/dist/components/kb-answer.mjs +4 -0
  227. package/dist/components/kb-audit.mjs +4 -0
  228. package/dist/components/kb-canvas.mjs +4 -0
  229. package/dist/components/kb-chain.mjs +4 -0
  230. package/dist/components/kb-checkpoint.mjs +4 -0
  231. package/dist/components/kb-chunks.mjs +4 -0
  232. package/dist/components/kb-citation.mjs +4 -0
  233. package/dist/components/kb-clarify.mjs +4 -0
  234. package/dist/components/kb-conflict.mjs +4 -0
  235. package/dist/components/kb-connector.mjs +4 -0
  236. package/dist/components/kb-data.css +653 -0
  237. package/dist/components/kb-eval.mjs +4 -0
  238. package/dist/components/kb-explain.mjs +4 -0
  239. package/dist/components/kb-filter.mjs +4 -0
  240. package/dist/components/kb-gap.mjs +4 -0
  241. package/dist/components/kb-ground.css +578 -0
  242. package/dist/components/kb-hittest.mjs +4 -0
  243. package/dist/components/kb-ingest.css +882 -0
  244. package/dist/components/kb-metadata.mjs +4 -0
  245. package/dist/components/kb-ops.css +554 -0
  246. package/dist/components/kb-passage.mjs +4 -0
  247. package/dist/components/kb-perm.css +433 -0
  248. package/dist/components/kb-pipeline.mjs +4 -0
  249. package/dist/components/kb-qa.mjs +4 -0
  250. package/dist/components/kb-rerank.mjs +4 -0
  251. package/dist/components/kb-retrieval.mjs +4 -0
  252. package/dist/components/kb-review.mjs +4 -0
  253. package/dist/components/kb-sandbox.mjs +4 -0
  254. package/dist/components/kb-search.css +897 -0
  255. package/dist/components/kb-segment.mjs +4 -0
  256. package/dist/components/kb-sources.mjs +4 -0
  257. package/dist/components/kb-sql.mjs +4 -0
  258. package/dist/components/kb-trace.mjs +4 -0
  259. package/dist/components/kb-visibility.mjs +4 -0
  260. package/dist/components/kb-who-can.mjs +4 -0
  261. package/dist/components/kb.css +263 -0
  262. package/dist/components/kb.mjs +9 -0
  263. package/dist/components/layout.css +85 -82
  264. package/dist/components/material-chinese.css +73 -0
  265. package/dist/components/material-soviet.css +76 -0
  266. package/dist/components/material.css +275 -0
  267. package/dist/components/media.css +220 -166
  268. package/dist/components/mentions.css +189 -0
  269. package/dist/components/mentions.mjs +3 -0
  270. package/dist/components/menu.css +113 -105
  271. package/dist/components/modal.css +107 -112
  272. package/dist/components/nav.css +118 -115
  273. package/dist/components/notification.css +238 -174
  274. package/dist/components/pagination.css +56 -53
  275. package/dist/components/panel.css +66 -63
  276. package/dist/components/panel.mjs +1 -0
  277. package/dist/components/pill.css +81 -71
  278. package/dist/components/popover.css +67 -53
  279. package/dist/components/scroll-area.css +113 -110
  280. package/dist/components/segmented.css +146 -143
  281. package/dist/components/select.css +206 -186
  282. package/dist/components/sidebar.css +137 -127
  283. package/dist/components/slider.css +117 -114
  284. package/dist/components/split-pane.css +112 -109
  285. package/dist/components/stat.css +112 -106
  286. package/dist/components/steps.css +109 -103
  287. package/dist/components/switch.css +138 -134
  288. package/dist/components/table.css +131 -107
  289. package/dist/components/tabs.css +114 -108
  290. package/dist/components/tag-input.css +48 -133
  291. package/dist/components/tag.css +81 -71
  292. package/dist/components/theme-switcher.css +105 -0
  293. package/dist/components/theme-switcher.mjs +3 -0
  294. package/dist/components/toast.css +100 -86
  295. package/dist/components/toolbar.css +45 -42
  296. package/dist/components/tooltip.css +102 -43
  297. package/dist/components/tooltip.mjs +1 -0
  298. package/dist/components/tree-select.css +416 -0
  299. package/dist/components/tree-select.mjs +3 -0
  300. package/dist/components/upload.css +135 -92
  301. package/dist/fonts/LICENSES/ark-pixel/OFL.txt +96 -0
  302. package/dist/fonts/LICENSES/cubic-11/OFL.txt +108 -0
  303. package/dist/fonts/LICENSES/galmuri/LICENSE.txt +93 -0
  304. package/dist/fonts/OFL.txt +96 -0
  305. package/dist/fonts/README.md +14 -0
  306. package/dist/fonts/fusion-pixel-12px-zh-hans.woff2 +0 -0
  307. package/dist/index.d.mts +64 -15
  308. package/dist/index.mjs +28049 -8595
  309. package/dist/react.d.mts +91 -0
  310. package/dist/react.mjs +8208 -0
  311. package/dist/registry.json +454 -15
  312. package/dist/tokens/chinese.css +44 -0
  313. package/dist/tokens/colors.css +365 -1222
  314. package/dist/tokens/design.css +109 -0
  315. package/dist/tokens/dtcg.json +11198 -0
  316. package/dist/tokens/figma.variables.json +7017 -0
  317. package/dist/tokens/icon-masks.css +78 -0
  318. package/dist/tokens/pixel.css +50 -0
  319. package/dist/tokens/soviet.css +44 -0
  320. package/dist/tokens/style-profiles.css +36 -547
  321. package/dist/tokens/themes.json +308 -0
  322. package/dist/tokens/tokens-studio.json +6728 -0
  323. package/dist/tokens/typography.css +21 -18
  324. package/dist/tokens.css +1555 -1801
  325. package/dist/ui.css +16147 -8597
  326. package/dist/vue.d.mts +344 -0
  327. package/dist/vue.mjs +7781 -0
  328. package/docs/spec/ai-input-experience.md +75 -0
  329. package/docs/spec/ai-native.md +238 -147
  330. package/docs/spec/design-philosophy.md +189 -0
  331. package/docs/spec/design-primitives.md +196 -0
  332. package/docs/spec/kb-family.md +475 -0
  333. package/package.json +42 -7
  334. package/dist/retro-effects.css +0 -255
  335. package/dist/tokens/retro-effects.css +0 -255
@@ -1,256 +1,242 @@
1
+ @layer icen.components {
1
2
  /*
2
3
  * @icen.ai/ui — Component: select(弹层选择器)
3
4
  * 规格源自 opengal primitives/input.tsx 的 Select;与 behaviors/select.ts 配套。
4
5
  *
5
6
  * 完整契约:
6
- * <div class="select [data-disabled] [.is-open]" data-select
7
- * [data-select-search] [data-select-multiple] [data-select-max="3"]
8
- * [data-panel-width="220"] [data-panel-min="200"]
9
- * [data-panel-max="360"] [data-panel-max-height="320"]>
10
- * <!-- 选项 .select-option 内支持任意 HTML(色卡 / 图标 / 多行);
7
+ * <div class="icen-select [data-icen-disabled] [.is-open]" data-icen-select
8
+ * [data-icen-select-search] [data-icen-select-multiple] [data-icen-select-max="3"]
9
+ * [data-icen-panel-width="220"] [data-icen-panel-min="200"]
10
+ * [data-icen-panel-max="360"] [data-icen-panel-max-height="320"]>
11
+ * <!-- 选项 .icen-select-option 内支持任意 HTML(色卡 / 图标 / 多行);
11
12
  * 面板尺寸为全库统一 PanelSizing 契约(behaviors/popover.ts) -->
12
- * <button class="select-trigger pressable focus-ring [--sm|--lg]" aria-haspopup="listbox"
13
+ * <button class="icen-select-trigger icen-pressable icen-focus-ring [--sm|--lg]" aria-haspopup="listbox"
13
14
  * aria-expanded="false" [disabled]>
14
- * <span class="select-leading">…</span> 可选前缀
15
- * <span class="select-value is-empty">占位</span> 多选有选中时 behavior 隐藏它
16
- * <span class="select-chips"> ← 多选选中态由 behavior 渲染(勿手写)
17
- * <span class="select-chip">标签<span class="select-chip-x" role="button" tabindex="-1">×</span></span>
18
- * <span class="select-chip select-chip--more">+2</span>
15
+ * <span class="icen-select-leading">…</span> 可选前缀
16
+ * <span class="icen-select-value is-empty">占位</span> 多选有选中时 behavior 隐藏它
17
+ * <span class="icen-select-chips"> ← 多选选中态由 behavior 渲染(勿手写)
18
+ * <span class="icen-select-chip">标签<span class="icen-select-chip-x" role="button" tabindex="-1">×</span></span>
19
+ * <span class="icen-select-chip icen-select-chip--more">+2</span>
19
20
  * </span>
20
- * <svg class="select-chevron">…</svg>
21
+ * <svg class="icen-select-chevron">…</svg>
21
22
  * </button>
22
- * <button class="select-clear" aria-label="清除全部" hidden>×</button> ← 多选可选:
23
- * 与 trigger 同级(不能嵌套在 button 内),绝对定位叠进 trigger 右侧;
23
+ * <button class="icen-select-clear" aria-label="清除全部" hidden>×</button> ← 多选可选:
24
+ * 与 trigger 同级(不能嵌套在 button 内),绝对定位叠进 trigger 行内末端侧(RTL 镜像左侧);
24
25
  * behavior 在有选中时自动显示
25
- * <div class="select-panel" hidden role="listbox">
26
- * <div class="select-search"> ← data-select-search 时 behavior 自动注入
27
- * <input class="select-search-input" placeholder="搜索…" />
26
+ * <div class="icen-select-panel" hidden role="listbox">
27
+ * <div class="icen-select-search"> ← data-icen-select-search 时 behavior 自动注入
28
+ * <icen-input class="icen-select-search-input" placeholder="搜索…" />
28
29
  * </div>
29
- * <div class="select-group"> ← 可选分组
30
- * <p class="select-group-label">组标题</p>
31
- * <button class="select-option [.is-focused|.is-selected|.is-disabled]" data-value="x">…</button>
30
+ * <div class="icen-select-group"> ← 可选分组
31
+ * <p class="icen-select-group-label">组标题</p>
32
+ * <button class="icen-select-option [.is-focused|.is-selected|.is-disabled]" data-icen-value="x">…</button>
32
33
  * </div>
33
- * <div class="select-empty">无匹配项</div> ← 搜索无结果时 behavior 显示
34
+ * <div class="icen-select-empty">无匹配项</div> ← 搜索无结果时 behavior 显示
34
35
  * </div>
35
- * <input type="hidden" data-select-value /> 可选,behavior 同步 value
36
+ * <input type="hidden" data-icen-select-value /> 可选,behavior 同步 value
36
37
  * </div>
37
38
  *
38
39
  * behavior 维护:
39
- * - .select.is-open ↔ aria-expanded;panel portal 到 body(inline left/top/width/max-height,
40
- * 带 data-side="top|bottom";多选时带 data-select-multiple);ESC/外部点击关闭
41
- * - 选项 .is-focused 跟随键盘箭头;Enter 选中 → 写回 .select-value / .is-selected
42
- * - data-select-search:面板顶部自动插入搜索框,实时过滤(含 data-keywords),空分组自动隐藏
43
- * - data-select-multiple:点击切选不关面板,trigger 显示计数,hidden input 同步逗号分隔值
40
+ * - .icen-select.is-open ↔ aria-expanded;panel portal 到 body(inline left/top/width/max-height,
41
+ * 带 data-icen-side="top|bottom";多选时带 data-icen-select-multiple);ESC/外部点击关闭
42
+ * - 选项 .is-focused 跟随键盘箭头;Enter 选中 → 写回 .icen-select-value / .is-selected
43
+ * - data-icen-select-search:面板顶部自动插入搜索框,实时过滤(含 data-icen-keywords),空分组自动隐藏
44
+ * - data-icen-select-multiple:点击切选不关面板,trigger 显示计数,hidden input 同步逗号分隔值
44
45
  */
45
46
 
46
- .select {
47
+ .icen-select {
48
+ --select-height: var(--icen-density-input-height-md);
47
49
  position: relative;
48
- width: 100%;
50
+ inline-size: 100%;
49
51
  }
50
52
 
51
- .select-trigger {
53
+ .icen-select-trigger {
54
+ position: relative;
52
55
  display: flex;
53
56
  align-items: center;
54
- gap: var(--density-space-xs);
55
- width: 100%;
56
- height: var(--density-input-height-md);
57
- padding: 0 var(--density-space-sm);
58
- font-size: var(--density-font-size-md);
59
- text-align: left;
60
- background: var(--token-control);
61
- color: var(--token-text);
62
- border: 1px solid var(--token-outline-soft);
63
- border-radius: var(--radius-md);
64
- box-shadow: var(--token-shadow-inset);
57
+ gap: var(--icen-density-space-xs);
58
+ inline-size: 100%;
59
+ height: var(--select-height);
60
+ padding: 0 var(--icen-density-space-sm);
61
+ font-size: var(--icen-density-font-size-md);
62
+ text-align: start;
63
+ background: var(--icen-token-control);
64
+ color: var(--icen-token-text);
65
+ border: 1px solid var(--icen-token-outline-soft);
66
+ border-radius: var(--icen-radius-md);
67
+ box-shadow: var(--icen-token-shadow-inset);
65
68
  cursor: pointer;
66
69
  transition:
67
70
  border-color var(--icen-tx-fast),
68
71
  box-shadow var(--icen-tx-fast);
72
+ padding-inline-end: var(--icen-density-space-sm);
69
73
  }
70
- .select-trigger:hover:not(:disabled) {
74
+ .icen-select-trigger:hover:not(:disabled) {
71
75
  border-color: var(--icen-hover-border);
72
76
  }
73
- .select-trigger:focus-visible {
77
+ .icen-select-trigger:focus-visible {
74
78
  outline: none;
75
79
  border-color: var(--icen-control-focus-border);
76
80
  box-shadow: var(--icen-control-focus-shadow);
77
81
  }
78
- .select-trigger:disabled,
79
- .select[data-disabled] .select-trigger,
80
- .select[aria-disabled='true'] .select-trigger {
82
+ .icen-select-trigger:disabled,
83
+ .icen-select[data-icen-disabled] .icen-select-trigger,
84
+ .icen-select[aria-disabled='true'] .icen-select-trigger {
81
85
  opacity: var(--icen-disabled-opacity);
82
86
  cursor: not-allowed;
83
87
  pointer-events: none;
84
88
  }
85
89
 
86
90
  /* 尺寸变体(与 input-wrap 对齐) */
87
- .select-trigger--sm { height: var(--density-input-height-sm); padding: 0 10px; font-size: var(--density-font-size-sm); }
88
- .select-trigger--lg { height: var(--density-input-height-lg); padding: 0 var(--density-space-md); font-size: var(--density-font-size-lg); }
91
+ .icen-select-trigger--sm { height: var(--icen-density-input-height-sm); padding: 0 10px; font-size: var(--icen-density-font-size-sm); }
92
+ .icen-select-trigger--lg { height: var(--icen-density-input-height-lg); padding: 0 var(--icen-density-space-md); font-size: var(--icen-density-font-size-lg); }
89
93
 
90
- .select-leading {
94
+ .icen-select-leading {
91
95
  display: inline-flex;
92
96
  align-items: center;
93
97
  flex-shrink: 0;
94
- color: var(--token-text-faint);
98
+ color: var(--icen-token-text-faint);
95
99
  }
96
- .select-leading svg { width: 14px; height: 14px; }
100
+ .icen-select-leading svg { width: 14px; height: 14px; }
97
101
 
98
- .select-value {
102
+ .icen-select-value {
99
103
  flex: 1;
100
104
  min-width: 0;
101
105
  overflow: hidden;
102
106
  text-overflow: ellipsis;
103
107
  white-space: nowrap;
104
108
  }
105
- .select-value.is-empty {
106
- color: color-mix(in srgb, var(--token-text-faint) 60%, transparent);
109
+ .icen-select-value.is-empty {
110
+ color: color-mix(in srgb, var(--icen-token-text-faint) 60%, transparent);
107
111
  }
108
112
 
109
- .select-chevron {
110
- width: 14px;
111
- height: 14px;
112
- flex-shrink: 0;
113
- color: var(--token-text-faint);
113
+ .icen-select-chevron {
114
+ position: absolute;
115
+ inset-inline-end: var(--icen-density-space-sm);
116
+ inset-block-start: 50%;
117
+ translate: 0 -50%;
118
+ inline-size: 16px;
119
+ block-size: 16px;
120
+ flex: none;
121
+ color: var(--icen-token-text-muted);
122
+ pointer-events: none;
114
123
  transition: transform var(--icen-tx-fast);
115
124
  }
116
- .select.is-open .select-chevron { transform: rotate(180deg); }
125
+ .icen-select.is-open .icen-select-chevron { transform: rotate(180deg); }
117
126
 
118
127
  /* 面板由 behavior portal 到 body:left/top/width/max-height 由 JS 按 trigger rect inline 写入;
119
- data-side="top|bottom" 标记翻侧方向;多选时 panel 带 data-select-multiple 属性。 */
120
- .select-panel {
128
+ data-icen-side="top|bottom" 标记翻侧方向;多选时 panel 带 data-icen-select-multiple 属性。 */
129
+ .icen-select-panel {
121
130
  position: absolute;
122
- z-index: var(--z-popover);
131
+ z-index: var(--icen-z-popover);
123
132
  overflow-y: auto;
124
133
  overscroll-behavior: contain;
125
- padding: 4px;
126
- background: var(--token-card-strong);
127
- border: 1px solid var(--token-outline);
128
- border-radius: var(--radius-md);
129
- box-shadow: var(--token-shadow-overlay);
134
+ padding: var(--icen-density-space-sm);
135
+ background: var(--icen-token-card-strong);
136
+ border: 1px solid var(--icen-token-outline);
137
+ border-radius: var(--icen-radius-lg);
138
+ box-shadow: var(--icen-token-shadow-overlay);
130
139
  transform-origin: top center;
131
140
  animation: icen-pop-in var(--icen-tx-fast);
132
141
  }
133
- .select-panel[data-side='top'] { transform-origin: bottom center; }
142
+ .icen-select-panel[data-icen-side='top'] { transform-origin: bottom center; }
143
+ .icen-select-options { min-inline-size: 0; }
134
144
 
135
145
  /* 选项 */
136
- .select-option {
146
+ .icen-select-option {
137
147
  display: flex;
138
148
  align-items: center;
139
- gap: var(--density-space-xs);
149
+ gap: var(--icen-density-space-xs);
140
150
  width: 100%;
141
- padding: 6px var(--density-space-sm);
142
- font-size: var(--density-font-size-sm);
143
- text-align: left;
151
+ padding: 6px var(--icen-density-space-sm);
152
+ font-size: var(--icen-density-font-size-sm);
153
+ text-align: start;
144
154
  border: none;
145
155
  background: transparent;
146
- color: var(--token-text);
147
- border-radius: var(--radius-sm);
156
+ color: var(--icen-token-text);
157
+ border-radius: var(--icen-radius-sm);
148
158
  cursor: pointer;
149
159
  transition:
150
160
  background-color var(--icen-tx-fast),
151
161
  color var(--icen-tx-fast);
152
162
  }
153
- .select-option:hover:not(.is-disabled) { background: var(--token-fill-1); }
154
- .select-option.is-focused {
155
- background: var(--token-fill-2);
156
- color: var(--token-text);
163
+ .icen-select-option:hover:not(.is-disabled) { background: var(--icen-token-fill-1); }
164
+ .icen-select-option.is-focused {
165
+ background: var(--icen-token-fill-2);
166
+ color: var(--icen-token-text);
157
167
  }
158
- .select-option.is-selected {
159
- color: var(--token-accent);
168
+ .icen-select-option.is-selected {
169
+ color: var(--icen-token-accent-text);
160
170
  font-weight: 500;
161
- background: var(--token-accent-subtle);
162
- }
163
- .select-option.is-selected::after {
164
- content: '✓';
165
- margin-left: auto;
166
- flex-shrink: 0;
167
- color: var(--token-accent);
171
+ background: var(--icen-token-accent-subtle);
168
172
  }
169
- .select-option.is-disabled {
173
+ .icen-select-option.is-disabled {
170
174
  opacity: 0.4;
171
175
  cursor: not-allowed;
172
176
  }
173
177
 
174
178
  /* 分组(行为可选渲染 optgroup) */
175
- .select-group {
179
+ .icen-select-group {
176
180
  padding: 0 4px;
177
181
  margin-top: 4px;
178
182
  }
179
- .select-group-label {
180
- padding: 6px var(--density-space-sm) 2px;
181
- font-size: var(--density-font-size-xs);
182
- color: var(--token-text-faint);
183
+ .icen-select-group-label {
184
+ padding: 6px var(--icen-density-space-sm) 2px;
185
+ font-size: var(--icen-density-font-size-xs);
186
+ color: var(--icen-token-text-faint);
183
187
  text-transform: uppercase;
184
188
  letter-spacing: 0.05em;
185
189
  }
186
190
 
187
191
  /* 空状态(behavior 渲染 no-match) */
188
- .select-empty {
189
- padding: var(--density-space-md);
190
- font-size: var(--density-font-size-sm);
191
- color: var(--token-text-faint);
192
+ .icen-select-empty {
193
+ padding: var(--icen-density-space-md);
194
+ font-size: var(--icen-density-font-size-sm);
195
+ color: var(--icen-token-text-faint);
192
196
  text-align: center;
193
197
  }
194
198
 
195
- /* ── 搜索框(data-select-search 时 behavior 自动注入) ── */
196
- .select-search {
197
- padding: 4px 4px 6px;
198
- border-bottom: 1px solid var(--token-outline-soft);
199
+ /* ── 搜索框(data-icen-select-search 时 behavior 自动注入) ── */
200
+ .icen-select-search {
201
+ padding: var(--icen-density-space-xs);
202
+ border-bottom: 1px solid var(--icen-token-outline-soft);
199
203
  margin-bottom: 4px;
200
204
  position: sticky;
201
205
  top: 0;
202
- background: var(--token-card-strong);
206
+ background: var(--icen-token-card-strong);
203
207
  z-index: 1;
204
208
  }
205
- .select-search-input {
206
- width: 100%;
207
- height: 30px;
208
- padding: 0 var(--density-space-sm);
209
- font-size: var(--density-font-size-sm);
210
- color: var(--token-text);
211
- background: var(--token-control);
212
- border: 1px solid var(--token-outline-soft);
213
- border-radius: var(--radius-sm);
214
- transition: border-color var(--icen-tx-fast), box-shadow var(--icen-tx-fast);
215
- }
216
- .select-search-input:focus {
217
- outline: none;
218
- border-color: var(--icen-control-focus-border);
219
- box-shadow: var(--icen-control-focus-shadow);
220
- }
209
+ .icen-select-search-input { min-inline-size: 0; }
221
210
 
222
- /* ── 多选清除按钮(与 trigger 同级,绝对定位叠进 trigger 右侧、chevron 左侧) ── */
223
- .select-clear {
211
+
212
+ /* ── 多选清除按钮(与 trigger 同级,绝对定位叠进 trigger 行内末端侧、chevron 内侧) ── */
213
+ .icen-select-clear {
224
214
  position: absolute;
225
- top: 50%;
226
- right: calc(var(--density-space-sm) + 20px);
227
- transform: translateY(-50%);
228
- z-index: 1;
215
+ inset-block-start: 50%;
216
+ inset-inline-end: var(--icen-density-space-sm);
217
+ translate: 0 -50%;
229
218
  display: inline-flex;
230
219
  align-items: center;
231
220
  justify-content: center;
232
- flex-shrink: 0;
233
- width: 18px;
234
- height: 18px;
221
+ inline-size: 24px;
222
+ block-size: 24px;
235
223
  padding: 0;
236
224
  border: 0;
237
- border-radius: var(--radius-xs);
225
+ border-radius: var(--icen-radius-sm);
238
226
  background: transparent;
239
- color: var(--token-text-faint);
240
- font-size: var(--density-font-size-lg);
241
- line-height: 1;
227
+ color: var(--icen-token-text-muted);
242
228
  cursor: pointer;
243
- transition: color var(--icen-tx-fast), background-color var(--icen-tx-fast);
229
+ transition: opacity var(--icen-tx-fast), background-color var(--icen-tx-fast), color var(--icen-tx-fast);
244
230
  }
245
- .select-clear:hover {
246
- color: var(--token-text);
247
- background: var(--token-fill-1);
231
+ .icen-select-clear:hover {
232
+ color: var(--icen-token-text);
233
+ background: var(--icen-token-fill-1);
248
234
  }
249
- /* 有清除钮时 trigger 右侧让位(clear 18px + chevron 14px + 间距) */
250
- .select:has(.select-clear) .select-trigger { padding-right: 52px; }
235
+ /* 有清除钮时 trigger 行内末端侧让位(clear 18px + chevron 14px + 间距) */
236
+ .icen-select:has(.icen-select-clear:not([hidden])) .icen-select-trigger { padding-inline-end: calc(var(--icen-density-space-sm) + var(--icen-density-input-height-sm) + var(--icen-density-space-xs)); }
251
237
 
252
238
  /* ── 多选 chips(tag 式展示;× 仅 hover 对应 chip 时出现) ── */
253
- .select-chips {
239
+ .icen-select-chips {
254
240
  display: inline-flex;
255
241
  flex-wrap: wrap;
256
242
  align-items: center;
@@ -258,73 +244,107 @@
258
244
  flex: 1;
259
245
  min-width: 0;
260
246
  }
261
- .select-chip {
247
+ .icen-select-chip {
262
248
  display: inline-flex;
263
249
  align-items: center;
264
- max-width: 100%;
265
- font-size: var(--density-font-size-xs);
250
+ max-inline-size: 100%;
251
+ font-size: var(--icen-density-font-size-xs);
266
252
  line-height: 1.6;
267
- color: var(--token-text);
268
- background: var(--token-fill-2);
269
- border-radius: var(--radius-sm);
253
+ color: var(--icen-token-text);
254
+ background: var(--icen-token-fill-2);
255
+ border-radius: var(--icen-radius-sm);
270
256
  padding: 0 7px;
271
257
  white-space: nowrap;
272
258
  }
273
- .select-chip-x {
259
+ .icen-select-chip-x {
274
260
  display: inline-flex;
275
261
  align-items: center;
276
262
  justify-content: center;
277
- width: 0;
278
- opacity: 0;
279
- overflow: hidden;
280
- margin-left: 0;
281
- color: var(--token-text-faint);
282
- border-radius: var(--radius-full);
283
- font-size: var(--density-font-size-md);
284
- line-height: 1;
263
+ flex: none;
264
+ inline-size: 16px;
265
+ block-size: 20px;
266
+ margin-inline-start: var(--icen-density-space-xs);
267
+ padding: 0;
268
+ border: 0;
269
+ border-radius: var(--icen-radius-xs);
270
+ background: transparent;
271
+ color: var(--icen-token-text-muted);
285
272
  cursor: pointer;
286
- transition:
287
- width var(--icen-tx-fast),
288
- opacity var(--icen-tx-fast),
289
- margin-left var(--icen-tx-fast),
290
- color var(--icen-tx-fast);
273
+ transition: opacity var(--icen-tx-fast), background-color var(--icen-tx-fast), color var(--icen-tx-fast);
291
274
  }
292
- .select-chip:hover .select-chip-x,
293
- .select-chip-x:focus-visible { width: 12px; opacity: 1; margin-left: 4px; }
294
- .select-chip-x:hover { color: var(--token-error); }
295
- .select-chip--more { color: var(--token-text-muted); background: var(--token-fill-1); }
275
+ .icen-select-chip-x:focus-visible { outline: 2px solid var(--icen-token-accent); outline-offset: 1px; }
276
+ .icen-select-chip-x:hover { color: var(--icen-token-error); }
277
+ .icen-select-chip--more { color: var(--icen-token-text-muted); background: var(--icen-token-fill-1); }
296
278
 
297
279
  /* ── 多选 trigger 高度自适应(chips 可能换行) ── */
298
- .select[data-select-multiple] .select-trigger {
299
- min-height: var(--density-input-height-md);
280
+ .icen-select[data-icen-select-multiple] .icen-select-trigger {
281
+ min-height: var(--select-height);
300
282
  height: auto;
301
283
  padding-top: 4px;
302
284
  padding-bottom: 4px;
303
285
  flex-wrap: wrap;
304
286
  }
305
287
 
306
- /* 多选项 checkbox 指示器(选项左侧;panel portal 到 body,属性在 panel 上) */
307
- .select-panel[data-select-multiple] .select-option::before {
308
- content: '';
309
- width: 14px;
310
- height: 14px;
311
- flex-shrink: 0;
312
- border: 1.5px solid var(--token-outline);
313
- border-radius: var(--radius-xs);
314
- transition: background-color var(--icen-tx-fast), border-color var(--icen-tx-fast);
288
+ @media (prefers-reduced-motion: reduce) {
289
+ .icen-select-panel { animation: none; }
290
+ .icen-select-search-input,
291
+ .icen-select-chip-x,
292
+ .icen-select-clear { transition: none; }
315
293
  }
316
- .select-panel[data-select-multiple] .select-option.is-selected::before {
317
- background: var(--token-accent);
318
- border-color: var(--token-accent);
294
+
295
+ @media (hover: hover) and (pointer: fine) {
296
+ .icen-select-clear:not([hidden]) { opacity: 0; pointer-events: none; }
297
+ .icen-select:is(:hover,:focus-within) .icen-select-clear:not([hidden]) { opacity: 1; pointer-events: auto; }
319
298
  }
320
- .select-panel[data-select-multiple] .select-option.is-selected::after {
321
- content: '✓';
322
- margin-left: auto;
299
+ @media (pointer: coarse) {
300
+ .icen-select-clear { min-inline-size: 44px; min-block-size: 44px; inset-inline-end: var(--icen-density-space-sm); }
301
+ .icen-select:has(.icen-select-clear:not([hidden])) .icen-select-trigger { padding-inline-end: calc(var(--icen-density-input-height-sm) + var(--icen-density-space-sm) + var(--icen-density-space-xs)); }
323
302
  }
324
303
 
325
- @media (prefers-reduced-motion: reduce) {
326
- .select-panel { animation: none; }
327
- .select-search-input,
328
- .select-chip-x,
329
- .select-clear { transition: none; }
304
+ .icen-select-trigger--sm, .icen-select-trigger--lg { padding-inline-end: var(--icen-density-space-sm); }
305
+
306
+ /* The chips and trigger occupy one grid cell without nesting interactive elements. */
307
+ .icen-select:has(> .icen-select-chips:not([hidden])) { display: grid; }
308
+ .icen-select:has(> .icen-select-chips:not([hidden])) > .icen-select-trigger {
309
+ grid-area: 1 / 1;
310
+ block-size: auto;
311
+ min-block-size: var(--select-height);
312
+ align-self: stretch;
313
+ }
314
+ .icen-select > .icen-select-chips {
315
+ position: relative;
316
+ grid-area: 1 / 1;
317
+ align-self: center;
318
+ min-block-size: var(--select-height);
319
+ padding-block: var(--icen-density-space-xs);
320
+ padding-inline-start: var(--icen-density-space-sm);
321
+ padding-inline-end: var(--icen-density-space-sm);
322
+ pointer-events: none;
323
+ }
324
+ .icen-select:has(.icen-select-clear:not([hidden])) > .icen-select-chips { padding-inline-end: calc(var(--icen-density-space-sm) + var(--icen-density-input-height-sm) + var(--icen-density-space-xs)); }
325
+ .icen-select-chip { pointer-events: auto; }
326
+ .icen-select-chip > span { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; }
327
+ @media (hover: hover) and (pointer: fine) {
328
+ .icen-select-chip-x { opacity: 0; }
329
+ .icen-select-chip:is(:hover,:focus-within) .icen-select-chip-x { opacity: 1; }
330
+ }
331
+ @media (pointer: coarse) {
332
+ .icen-select-chip-x { min-inline-size: 44px; min-block-size: 44px; }
333
+ .icen-select:has(.icen-select-clear:not([hidden])) > .icen-select-chips { padding-inline-end: calc(var(--icen-density-input-height-sm) + var(--icen-density-space-sm) + var(--icen-density-space-xs)); }
334
+ }
335
+
336
+ .icen-select-chips[hidden], .icen-select-clear[hidden] { display: none; }
337
+
338
+ /* Optional rich-option color sample: copied markup works with select.css alone. */
339
+ .icen-select-swatch { display: inline-flex; flex: none; inline-size: 36px; block-size: 18px; border: 1px solid var(--icen-token-line-soft); border-radius: var(--icen-radius-xs); overflow: hidden; }
340
+ .icen-select-swatch > i { flex: 1; }
341
+
342
+ .icen-select:has(> .icen-select-trigger--sm) { --select-height: var(--icen-density-input-height-sm); }
343
+ .icen-select:has(> .icen-select-trigger--lg) { --select-height: var(--icen-density-input-height-lg); }
344
+
345
+ .icen-select-panel:has(> .icen-select-search) { scroll-padding-block-start: calc(var(--icen-density-input-height-sm) + 3 * var(--icen-density-space-xs) + var(--icen-density-space-sm) + 1px); }
346
+
347
+ /* Popup affordance is carried by the control surface, not a direction glyph. */
348
+ .icen-select-chevron { display: none; }
349
+
330
350
  }