@icen.ai/ui 0.10.0 → 0.11.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 (355) hide show
  1. package/AGENTS.md +79 -309
  2. package/LICENSE +21 -0
  3. package/README.md +43 -54
  4. package/dist/base.css +57 -16
  5. package/dist/behaviors/accordion.mjs +1 -1
  6. package/dist/behaviors/ai-branch.mjs +1 -0
  7. package/dist/behaviors/ai-chat.d.mts +2 -2
  8. package/dist/behaviors/ai-chat.mjs +53 -10
  9. package/dist/behaviors/ai-composer.d.mts +5 -5
  10. package/dist/behaviors/ai-composer.mjs +21 -10
  11. package/dist/behaviors/ai-core.mjs +1 -0
  12. package/dist/behaviors/ai-diff.mjs +1 -0
  13. package/dist/behaviors/ai-feedback.mjs +1 -0
  14. package/dist/behaviors/ai-panel.d.mts +2 -2
  15. package/dist/behaviors/ai-panel.mjs +1 -0
  16. package/dist/behaviors/ai-provider.d.mts +1 -1
  17. package/dist/behaviors/ai-provider.mjs +1 -0
  18. package/dist/behaviors/ai-threads.mjs +1 -0
  19. package/dist/behaviors/ai-tool.d.mts +1 -1
  20. package/dist/behaviors/ai-tool.mjs +57 -24
  21. package/dist/behaviors/ai-tools.mjs +937 -28
  22. package/dist/behaviors/autocomplete.d.mts +1 -1
  23. package/dist/behaviors/autocomplete.mjs +1 -0
  24. package/dist/behaviors/back-top.mjs +1 -0
  25. package/dist/behaviors/carousel.mjs +8 -1
  26. package/dist/behaviors/cascader.mjs +14 -0
  27. package/dist/behaviors/charts.mjs +56 -20
  28. package/dist/behaviors/code-block.mjs +9 -1
  29. package/dist/behaviors/command-palette.mjs +3 -3
  30. package/dist/behaviors/context-menu.d.mts +2 -2
  31. package/dist/behaviors/context-menu.mjs +1 -0
  32. package/dist/behaviors/controls.d.mts +8 -8
  33. package/dist/behaviors/controls.mjs +37 -6
  34. package/dist/behaviors/copy.mjs +1 -0
  35. package/dist/behaviors/datatable.d.mts +3 -3
  36. package/dist/behaviors/datatable.mjs +76 -11
  37. package/dist/behaviors/date-picker.mjs +1 -0
  38. package/dist/behaviors/events.d.mts +10 -10
  39. package/dist/behaviors/events.mjs +11 -1
  40. package/dist/behaviors/form-validate.d.mts +10 -1
  41. package/dist/behaviors/form-validate.mjs +266 -4611
  42. package/dist/behaviors/i18n.d.mts +1 -0
  43. package/dist/behaviors/i18n.mjs +2 -0
  44. package/dist/behaviors/input.mjs +3 -0
  45. package/dist/behaviors/kb-access.d.mts +2 -2
  46. package/dist/behaviors/kb-access.mjs +8 -2
  47. package/dist/behaviors/kb-acl.d.mts +2 -2
  48. package/dist/behaviors/kb-acl.mjs +1 -0
  49. package/dist/behaviors/kb-answer.d.mts +2 -2
  50. package/dist/behaviors/kb-answer.mjs +56 -23
  51. package/dist/behaviors/kb-audit.d.mts +2 -2
  52. package/dist/behaviors/kb-audit.mjs +1 -0
  53. package/dist/behaviors/kb-canvas.d.mts +3 -3
  54. package/dist/behaviors/kb-canvas.mjs +1 -0
  55. package/dist/behaviors/kb-chain.d.mts +2 -2
  56. package/dist/behaviors/kb-chain.mjs +1 -0
  57. package/dist/behaviors/kb-checkpoint.d.mts +2 -2
  58. package/dist/behaviors/kb-checkpoint.mjs +1 -0
  59. package/dist/behaviors/kb-chunks.d.mts +2 -2
  60. package/dist/behaviors/kb-chunks.mjs +1 -0
  61. package/dist/behaviors/kb-citation.d.mts +2 -2
  62. package/dist/behaviors/kb-citation.mjs +20 -6
  63. package/dist/behaviors/kb-clarify.d.mts +2 -2
  64. package/dist/behaviors/kb-clarify.mjs +1 -0
  65. package/dist/behaviors/kb-conflict.d.mts +2 -2
  66. package/dist/behaviors/kb-conflict.mjs +1 -0
  67. package/dist/behaviors/kb-connector.d.mts +2 -2
  68. package/dist/behaviors/kb-connector.mjs +1 -0
  69. package/dist/behaviors/kb-core.d.mts +1 -1
  70. package/dist/behaviors/kb-core.mjs +1 -0
  71. package/dist/behaviors/kb-eval.d.mts +2 -2
  72. package/dist/behaviors/kb-eval.mjs +8 -2
  73. package/dist/behaviors/kb-explain.d.mts +2 -2
  74. package/dist/behaviors/kb-explain.mjs +13 -2
  75. package/dist/behaviors/kb-filter.d.mts +2 -2
  76. package/dist/behaviors/kb-filter.mjs +8 -2
  77. package/dist/behaviors/kb-gap.d.mts +2 -2
  78. package/dist/behaviors/kb-gap.mjs +1 -0
  79. package/dist/behaviors/kb-hittest.d.mts +2 -2
  80. package/dist/behaviors/kb-hittest.mjs +2 -1
  81. package/dist/behaviors/kb-metadata.mjs +6 -0
  82. package/dist/behaviors/kb-passage.d.mts +2 -2
  83. package/dist/behaviors/kb-passage.mjs +1 -0
  84. package/dist/behaviors/kb-pipeline.d.mts +2 -2
  85. package/dist/behaviors/kb-pipeline.mjs +1 -0
  86. package/dist/behaviors/kb-qa.mjs +1 -0
  87. package/dist/behaviors/kb-rerank.d.mts +2 -2
  88. package/dist/behaviors/kb-rerank.mjs +1 -0
  89. package/dist/behaviors/kb-retrieval.d.mts +2 -2
  90. package/dist/behaviors/kb-retrieval.mjs +18 -4
  91. package/dist/behaviors/kb-review.d.mts +2 -2
  92. package/dist/behaviors/kb-review.mjs +8 -2
  93. package/dist/behaviors/kb-sandbox.d.mts +2 -2
  94. package/dist/behaviors/kb-sandbox.mjs +7 -1
  95. package/dist/behaviors/kb-segment.d.mts +2 -2
  96. package/dist/behaviors/kb-segment.mjs +2 -1
  97. package/dist/behaviors/kb-select.mjs +8 -2
  98. package/dist/behaviors/kb-sources.d.mts +2 -2
  99. package/dist/behaviors/kb-sources.mjs +1 -0
  100. package/dist/behaviors/kb-sql.d.mts +2 -2
  101. package/dist/behaviors/kb-sql.mjs +1 -0
  102. package/dist/behaviors/kb-trace.d.mts +2 -2
  103. package/dist/behaviors/kb-trace.mjs +9 -3
  104. package/dist/behaviors/kb-visibility.d.mts +2 -2
  105. package/dist/behaviors/kb-visibility.mjs +1 -0
  106. package/dist/behaviors/kb-who-can.d.mts +2 -2
  107. package/dist/behaviors/kb-who-can.mjs +8 -2
  108. package/dist/behaviors/mentions.d.mts +1 -1
  109. package/dist/behaviors/mentions.mjs +1 -0
  110. package/dist/behaviors/modal.d.mts +1 -1
  111. package/dist/behaviors/modal.mjs +1 -0
  112. package/dist/behaviors/notification.d.mts +2 -2
  113. package/dist/behaviors/notification.mjs +14 -3
  114. package/dist/behaviors/panel.mjs +1 -0
  115. package/dist/behaviors/scroll-area.d.mts +17 -0
  116. package/dist/behaviors/scroll-area.mjs +59 -0
  117. package/dist/behaviors/select.mjs +8 -2
  118. package/dist/behaviors/slider.mjs +3 -3
  119. package/dist/behaviors/split-pane.mjs +2 -0
  120. package/dist/behaviors/suggestions.mjs +1 -0
  121. package/dist/behaviors/tabs.mjs +10 -0
  122. package/dist/behaviors/tag-input.mjs +1 -0
  123. package/dist/behaviors/theme-switcher.d.mts +2 -2
  124. package/dist/behaviors/theme-switcher.mjs +17 -2
  125. package/dist/behaviors/theme.mjs +16 -2
  126. package/dist/behaviors/toast.d.mts +2 -2
  127. package/dist/behaviors/toast.mjs +1 -0
  128. package/dist/behaviors/tree-select.mjs +14 -0
  129. package/dist/behaviors/tree.mjs +4 -4
  130. package/dist/behaviors/upload.mjs +1 -0
  131. package/dist/behaviors/url-safety.d.mts +8 -0
  132. package/dist/behaviors/url-safety.mjs +11 -0
  133. package/dist/components/accordion.d.mts +2 -0
  134. package/dist/components/ai-branch.d.mts +2 -0
  135. package/dist/components/ai-chat.css +40 -33
  136. package/dist/components/ai-chat.d.mts +2 -0
  137. package/dist/components/ai-composer.d.mts +2 -0
  138. package/dist/components/ai-context.d.mts +2 -0
  139. package/dist/components/ai-context.mjs +1 -0
  140. package/dist/components/ai-diff.css +6 -6
  141. package/dist/components/ai-diff.d.mts +2 -0
  142. package/dist/components/ai-feedback.d.mts +2 -0
  143. package/dist/components/ai-files.d.mts +2 -0
  144. package/dist/components/ai-message.d.mts +2 -0
  145. package/dist/components/ai-panel.css +12 -10
  146. package/dist/components/ai-reasoning.d.mts +2 -0
  147. package/dist/components/ai-subagent.d.mts +2 -0
  148. package/dist/components/ai-subagent.mjs +1 -0
  149. package/dist/components/ai-threads.d.mts +2 -0
  150. package/dist/components/ai-todo.d.mts +2 -0
  151. package/dist/components/ai-todo.mjs +1 -0
  152. package/dist/components/ai-tool-call.d.mts +2 -0
  153. package/dist/components/ai-tool-call.mjs +1 -0
  154. package/dist/components/ai-tool.css +16 -16
  155. package/dist/components/ai-usage.d.mts +2 -0
  156. package/dist/components/alert.d.mts +2 -0
  157. package/dist/components/autocomplete.css +12 -12
  158. package/dist/components/autocomplete.d.mts +2 -0
  159. package/dist/components/avatar.d.mts +2 -0
  160. package/dist/components/back-top.css +47 -16
  161. package/dist/components/back-top.d.mts +2 -0
  162. package/dist/components/badge.css +1 -1
  163. package/dist/components/badge.d.mts +2 -0
  164. package/dist/components/breadcrumb.css +26 -8
  165. package/dist/components/breadcrumb.d.mts +2 -0
  166. package/dist/components/btn.css +67 -62
  167. package/dist/components/btn.d.mts +2 -0
  168. package/dist/components/card.css +22 -22
  169. package/dist/components/card.d.mts +2 -0
  170. package/dist/components/carousel.d.mts +2 -0
  171. package/dist/components/cascader.css +56 -35
  172. package/dist/components/cascader.d.mts +2 -0
  173. package/dist/components/chart-area.css +46 -0
  174. package/dist/components/chart-area.d.mts +2 -0
  175. package/dist/components/chart-bar.css +66 -19
  176. package/dist/components/chart-bar.d.mts +2 -0
  177. package/dist/components/chart-calendar.d.mts +2 -0
  178. package/dist/components/chart-gauge.css +23 -3
  179. package/dist/components/chart-gauge.d.mts +2 -0
  180. package/dist/components/chart-graph.css +15 -3
  181. package/dist/components/chart-graph.d.mts +2 -0
  182. package/dist/components/chart-heatmap.css +117 -95
  183. package/dist/components/chart-heatmap.d.mts +2 -0
  184. package/dist/components/chart-line.css +54 -0
  185. package/dist/components/chart-line.d.mts +2 -0
  186. package/dist/components/chart-map.d.mts +2 -0
  187. package/dist/components/chart-pie.css +29 -0
  188. package/dist/components/chart-pie.d.mts +2 -0
  189. package/dist/components/chart-radar.css +50 -1
  190. package/dist/components/chart-radar.d.mts +2 -0
  191. package/dist/components/chart-scatter.css +39 -2
  192. package/dist/components/chart-scatter.d.mts +2 -0
  193. package/dist/components/chart-sparkline.css +20 -0
  194. package/dist/components/chart-sparkline.d.mts +2 -0
  195. package/dist/components/chart-stack.css +16 -5
  196. package/dist/components/chart-stack.d.mts +2 -0
  197. package/dist/components/charts.css +80 -35
  198. package/dist/components/charts.d.mts +2 -0
  199. package/dist/components/code-block.css +10 -8
  200. package/dist/components/code-block.d.mts +2 -0
  201. package/dist/components/command-palette.css +45 -38
  202. package/dist/components/command-palette.d.mts +2 -0
  203. package/dist/components/content.css +62 -57
  204. package/dist/components/context-menu.d.mts +2 -0
  205. package/dist/components/copy.css +10 -10
  206. package/dist/components/copy.d.mts +2 -0
  207. package/dist/components/datatable.css +72 -59
  208. package/dist/components/datatable.d.mts +2 -0
  209. package/dist/components/date-picker.css +26 -26
  210. package/dist/components/date-picker.d.mts +2 -0
  211. package/dist/components/desc.d.mts +2 -0
  212. package/dist/components/dropdown.d.mts +2 -0
  213. package/dist/components/empty.css +16 -16
  214. package/dist/components/empty.d.mts +2 -0
  215. package/dist/components/feedback.css +31 -29
  216. package/dist/components/form-validate.css +20 -6
  217. package/dist/components/form-validate.d.mts +2 -0
  218. package/dist/components/form.css +17 -14
  219. package/dist/components/form.d.mts +2 -0
  220. package/dist/components/icon.css +21 -10
  221. package/dist/components/icon.d.mts +2 -0
  222. package/dist/components/input.css +22 -22
  223. package/dist/components/input.d.mts +2 -0
  224. package/dist/components/kb-access.d.mts +2 -0
  225. package/dist/components/kb-acl.d.mts +2 -0
  226. package/dist/components/kb-agent.css +134 -55
  227. package/dist/components/kb-answer.d.mts +2 -0
  228. package/dist/components/kb-audit.d.mts +2 -0
  229. package/dist/components/kb-canvas.d.mts +2 -0
  230. package/dist/components/kb-chain.d.mts +2 -0
  231. package/dist/components/kb-checkpoint.d.mts +2 -0
  232. package/dist/components/kb-chunks.d.mts +2 -0
  233. package/dist/components/kb-citation.d.mts +2 -0
  234. package/dist/components/kb-clarify.d.mts +2 -0
  235. package/dist/components/kb-conflict.d.mts +2 -0
  236. package/dist/components/kb-connector.d.mts +2 -0
  237. package/dist/components/kb-data.css +192 -80
  238. package/dist/components/kb-eval.d.mts +2 -0
  239. package/dist/components/kb-explain.d.mts +2 -0
  240. package/dist/components/kb-filter.d.mts +2 -0
  241. package/dist/components/kb-gap.d.mts +2 -0
  242. package/dist/components/kb-ground.css +165 -73
  243. package/dist/components/kb-hittest.d.mts +2 -0
  244. package/dist/components/kb-ingest.css +308 -113
  245. package/dist/components/kb-metadata.d.mts +2 -0
  246. package/dist/components/kb-ops.css +189 -75
  247. package/dist/components/kb-passage.d.mts +2 -0
  248. package/dist/components/kb-perm.css +158 -87
  249. package/dist/components/kb-pipeline.d.mts +2 -0
  250. package/dist/components/kb-qa.d.mts +2 -0
  251. package/dist/components/kb-rerank.d.mts +2 -0
  252. package/dist/components/kb-retrieval.d.mts +2 -0
  253. package/dist/components/kb-review.d.mts +2 -0
  254. package/dist/components/kb-sandbox.d.mts +2 -0
  255. package/dist/components/kb-search.css +353 -116
  256. package/dist/components/kb-segment.d.mts +2 -0
  257. package/dist/components/kb-sources.d.mts +2 -0
  258. package/dist/components/kb-sql.d.mts +2 -0
  259. package/dist/components/kb-trace.d.mts +2 -0
  260. package/dist/components/kb-visibility.d.mts +2 -0
  261. package/dist/components/kb-who-can.d.mts +2 -0
  262. package/dist/components/kb.css +60 -36
  263. package/dist/components/kb.d.mts +2 -0
  264. package/dist/components/kbd.d.mts +2 -0
  265. package/dist/components/layout.css +10 -10
  266. package/dist/components/layout.d.mts +2 -0
  267. package/dist/components/list.d.mts +2 -0
  268. package/dist/components/material-chinese.css +10 -0
  269. package/dist/components/material-soviet.css +10 -0
  270. package/dist/components/material.css +61 -18
  271. package/dist/components/media-card.d.mts +2 -0
  272. package/dist/components/media.css +22 -27
  273. package/dist/components/mentions.css +18 -17
  274. package/dist/components/mentions.d.mts +2 -0
  275. package/dist/components/menu.css +32 -28
  276. package/dist/components/modal.css +30 -27
  277. package/dist/components/modal.d.mts +2 -0
  278. package/dist/components/nav.css +48 -44
  279. package/dist/components/nav.d.mts +2 -0
  280. package/dist/components/notification.css +31 -25
  281. package/dist/components/notification.d.mts +2 -0
  282. package/dist/components/pagination.css +15 -13
  283. package/dist/components/pagination.d.mts +2 -0
  284. package/dist/components/panel.css +19 -20
  285. package/dist/components/panel.d.mts +2 -0
  286. package/dist/components/pill.css +8 -7
  287. package/dist/components/pill.d.mts +2 -0
  288. package/dist/components/popover.css +32 -23
  289. package/dist/components/popover.d.mts +2 -0
  290. package/dist/components/progress.d.mts +2 -0
  291. package/dist/components/rating.d.mts +2 -0
  292. package/dist/components/result.d.mts +2 -0
  293. package/dist/components/scroll-area.css +84 -112
  294. package/dist/components/scroll-area.d.mts +2 -0
  295. package/dist/components/scroll-area.mjs +1 -0
  296. package/dist/components/segmented.css +47 -29
  297. package/dist/components/segmented.d.mts +2 -0
  298. package/dist/components/select.css +80 -41
  299. package/dist/components/select.d.mts +2 -0
  300. package/dist/components/sidebar.css +42 -38
  301. package/dist/components/sidebar.d.mts +2 -0
  302. package/dist/components/skeleton.d.mts +2 -0
  303. package/dist/components/slider.css +26 -22
  304. package/dist/components/slider.d.mts +2 -0
  305. package/dist/components/spinner.d.mts +2 -0
  306. package/dist/components/split-pane.css +16 -7
  307. package/dist/components/split-pane.d.mts +2 -0
  308. package/dist/components/stat.css +17 -16
  309. package/dist/components/stat.d.mts +2 -0
  310. package/dist/components/steps.css +26 -26
  311. package/dist/components/steps.d.mts +2 -0
  312. package/dist/components/switch.css +78 -39
  313. package/dist/components/switch.d.mts +2 -0
  314. package/dist/components/table.css +54 -32
  315. package/dist/components/table.d.mts +2 -0
  316. package/dist/components/tabs.css +53 -32
  317. package/dist/components/tabs.d.mts +2 -0
  318. package/dist/components/tag-input.css +12 -8
  319. package/dist/components/tag-input.d.mts +2 -0
  320. package/dist/components/tag.css +20 -12
  321. package/dist/components/tag.d.mts +2 -0
  322. package/dist/components/theme-switcher.css +7 -7
  323. package/dist/components/theme-switcher.d.mts +2 -0
  324. package/dist/components/timeline.d.mts +2 -0
  325. package/dist/components/toast.css +34 -30
  326. package/dist/components/toast.d.mts +2 -0
  327. package/dist/components/toolbar.css +19 -18
  328. package/dist/components/toolbar.d.mts +2 -0
  329. package/dist/components/tooltip.css +9 -8
  330. package/dist/components/tooltip.d.mts +2 -0
  331. package/dist/components/tree-select.css +63 -40
  332. package/dist/components/tree-select.d.mts +2 -0
  333. package/dist/components/tree.d.mts +2 -0
  334. package/dist/components/upload.css +9 -11
  335. package/dist/components/upload.d.mts +2 -0
  336. package/dist/index.d.mts +85 -84
  337. package/dist/index.mjs +14764 -14311
  338. package/dist/react.d.mts +18 -18
  339. package/dist/react.mjs +135 -36
  340. package/dist/registry.json +795 -64
  341. package/dist/tokens/colors.css +6 -0
  342. package/dist/tokens/design.css +130 -30
  343. package/dist/tokens/dtcg.json +6189 -1461
  344. package/dist/tokens/figma.variables.json +4107 -345
  345. package/dist/tokens/pixel.css +3 -0
  346. package/dist/tokens/scrollbars.css +40 -0
  347. package/dist/tokens/tokens-studio.json +5191 -271
  348. package/dist/tokens.css +304 -81
  349. package/dist/ui.css +4050 -2148
  350. package/dist/vue.d.mts +17 -17
  351. package/dist/vue.mjs +129 -34
  352. package/docs/spec/design-philosophy.md +5 -5
  353. package/docs/spec/design-primitives.md +10 -10
  354. package/docs/spec/scrollbars.md +46 -0
  355. package/package.json +16 -3
@@ -0,0 +1,17 @@
1
+ /** Native scrolling with delegated activity tracking; no replacement tracks or wheel interception. */
2
+ interface ScrollAreaOptions {
3
+ /** Delegation scope. Defaults to document; includes future descendants. */
4
+ root?: Document | HTMLElement;
5
+ /** Idle delay in milliseconds. Local data-icen-scrollbar-delay wins; CSS token is the fallback. */
6
+ idleDelay?: number;
7
+ }
8
+ /**
9
+ * Enables idle hiding for every native scroller in a scope, including portalled
10
+ * panels when mounted on document. Idempotent, SSR-safe, returns cleanup.
11
+ * CSS-only use keeps scrollbars visible; enabled scopes default to scroll mode.
12
+ * Local data-icen-scrollbars selects
13
+ * auto (scroll/hover/focus), scroll (scroll/focus), visible, or hidden.
14
+ */
15
+ declare function initScrollArea(options?: ScrollAreaOptions): () => void;
16
+
17
+ export { type ScrollAreaOptions, initScrollArea };
@@ -0,0 +1,59 @@
1
+ // src/behaviors/scroll-area.ts
2
+ var mounted = /* @__PURE__ */ new WeakSet();
3
+ var noop = () => {
4
+ };
5
+ var isDocument = (node) => node?.nodeType === 9;
6
+ function initScrollArea(options = {}) {
7
+ if (typeof document === "undefined" || typeof window === "undefined") return noop;
8
+ const root = options.root ?? document;
9
+ if (mounted.has(root)) return noop;
10
+ mounted.add(root);
11
+ const host = isDocument(root) ? root.documentElement : root;
12
+ const previous = host.getAttribute("data-icen-scrollbars-ready");
13
+ host.setAttribute("data-icen-scrollbars-ready", "");
14
+ const pending = /* @__PURE__ */ new Map();
15
+ const restore = (el, value) => {
16
+ if (value === null) el.removeAttribute("data-icen-scroll-active");
17
+ else el.setAttribute("data-icen-scroll-active", value);
18
+ };
19
+ const onScroll = (event) => {
20
+ const el = isDocument(event.target) ? event.target.documentElement : event.target;
21
+ if (!(el instanceof HTMLElement)) return;
22
+ for (let node = el; node; node = node.parentElement) {
23
+ if (!mounted.has(node)) continue;
24
+ if (node !== root) return;
25
+ break;
26
+ }
27
+ const old = pending.get(el);
28
+ if (old) clearTimeout(old.timer);
29
+ const before = old ? old.previous : el.getAttribute("data-icen-scroll-active");
30
+ el.setAttribute("data-icen-scroll-active", "");
31
+ const local = el.closest("[data-icen-scrollbar-delay]")?.dataset.icenScrollbarDelay;
32
+ const token = getComputedStyle(el).getPropertyValue("--icen-token-scrollbar-idle-delay").trim();
33
+ const parsed = local !== void 0 ? Number(local) : options.idleDelay ?? (token ? Number.parseFloat(token) * (token.endsWith("ms") ? 1 : token.endsWith("s") ? 1e3 : 1) : 900);
34
+ const delay = Number.isFinite(parsed) ? Math.max(0, Math.min(6e4, parsed)) : 900;
35
+ const timer = setTimeout(() => {
36
+ restore(el, before);
37
+ pending.delete(el);
38
+ }, delay);
39
+ pending.set(el, { timer, previous: before });
40
+ };
41
+ root.addEventListener("scroll", onScroll, { capture: true, passive: true });
42
+ let disposed = false;
43
+ return () => {
44
+ if (disposed) return;
45
+ disposed = true;
46
+ root.removeEventListener("scroll", onScroll, true);
47
+ for (const [el, state] of pending) {
48
+ clearTimeout(state.timer);
49
+ restore(el, state.previous);
50
+ }
51
+ pending.clear();
52
+ if (previous === null) host.removeAttribute("data-icen-scrollbars-ready");
53
+ else host.setAttribute("data-icen-scrollbars-ready", previous);
54
+ mounted.delete(root);
55
+ };
56
+ }
57
+ export {
58
+ initScrollArea
59
+ };
@@ -21,6 +21,7 @@ var ICEN_LOCALE_ZH_CN = {
21
21
  "aiChat.roleTool": "\u5DE5",
22
22
  "aiChat.roleUser": "\u6211",
23
23
  "aiChat.thinking": "\u601D\u8003 {p0}",
24
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
24
25
  /* ── aiComposer ── */
25
26
  "aiComposer.attachAgent": "\u4EE3\u7406",
26
27
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1209,8 +1210,13 @@ function setup(container) {
1209
1210
  el.__icenSelectInit = true;
1210
1211
  const trigger = triggerEl;
1211
1212
  const panel = panelEl;
1212
- const arrow = trigger.querySelector(".icen-select-chevron");
1213
- arrow?.remove();
1213
+ if (!trigger.querySelector(".icen-select-chevron")) {
1214
+ const chevron = createIcon("chevron-down", { size: 12, className: "icen-select-chevron" });
1215
+ if (chevron) {
1216
+ chevron.setAttribute("aria-hidden", "true");
1217
+ trigger.append(chevron);
1218
+ }
1219
+ }
1214
1220
  const isMultiple = container.hasAttribute("data-icen-select-multiple");
1215
1221
  const isSearchable = container.hasAttribute("data-icen-select-search");
1216
1222
  if (isMultiple && !trigger.hasAttribute("aria-label") && !trigger.hasAttribute("aria-labelledby")) trigger.setAttribute("aria-label", container.getAttribute("data-icen-select-label") ?? t("select.fieldLabel"));
@@ -23,7 +23,7 @@ function setupSingle(slider, native, bag) {
23
23
  const sync = () => {
24
24
  const p = pct(native);
25
25
  if (fill) fill.style.width = `${p}%`;
26
- if (thumb) thumb.style.left = `calc(${p}% - 8px)`;
26
+ if (thumb) thumb.style.left = `${p}%`;
27
27
  };
28
28
  bind(native, "input", () => {
29
29
  sync();
@@ -59,8 +59,8 @@ function setupDual(slider, natives, bag) {
59
59
  range.style.left = `${pLo}%`;
60
60
  range.style.right = `${100 - pHi}%`;
61
61
  }
62
- if (thumbLo) thumbLo.style.left = `calc(${pLo}% - 8px)`;
63
- if (thumbHi) thumbHi.style.left = `calc(${pHi}% - 8px)`;
62
+ if (thumbLo) thumbLo.style.left = `${pLo}%`;
63
+ if (thumbHi) thumbHi.style.left = `${pHi}%`;
64
64
  lo.style.clipPath = `inset(0 ${100 - pLo}% 0 0)`;
65
65
  hi.style.clipPath = `inset(0 0 0 ${pHi}%)`;
66
66
  };
@@ -48,6 +48,8 @@ function setup(container) {
48
48
  divider.setAttribute("aria-valuenow", String(Math.round(readCurrent())));
49
49
  let dragging = false;
50
50
  const onDown = (ev) => {
51
+ if (ev.pointerType === "mouse" && ev.button !== 0) return;
52
+ if (!ev.isPrimary) return;
51
53
  dragging = true;
52
54
  divider.classList.add("is-dragging");
53
55
  divider.setPointerCapture(ev.pointerId);
@@ -129,6 +129,7 @@ var ICEN_LOCALE_ZH_CN = {
129
129
  "aiChat.roleTool": "\u5DE5",
130
130
  "aiChat.roleUser": "\u6211",
131
131
  "aiChat.thinking": "\u601D\u8003 {p0}",
132
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
132
133
  /* ── aiComposer ── */
133
134
  "aiComposer.attachAgent": "\u4EE3\u7406",
134
135
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -28,6 +28,13 @@ function syncInk(container, name) {
28
28
  if (!ink) return;
29
29
  ink.style.width = `${btn.offsetWidth}px`;
30
30
  ink.style.transform = `translateX(${btn.offsetLeft}px)`;
31
+ if (btn.offsetTop > 0) {
32
+ ink.style.top = `${btn.offsetTop + btn.offsetHeight}px`;
33
+ ink.style.bottom = "auto";
34
+ } else {
35
+ ink.style.top = "";
36
+ ink.style.bottom = "";
37
+ }
31
38
  }
32
39
  function activate(container, name, writeHash, emit = false) {
33
40
  const buttons = tabButtons(container);
@@ -70,6 +77,9 @@ function focusTab(container, idx) {
70
77
  const buttons = tabButtons(container);
71
78
  const target = buttons[idx];
72
79
  if (!target || isDisabled(target)) return;
80
+ buttons.forEach((b) => {
81
+ b.tabIndex = b === target ? 0 : -1;
82
+ });
73
83
  target.focus();
74
84
  }
75
85
  function nextEnabled(container, from, dir) {
@@ -116,6 +116,7 @@ var ICEN_LOCALE_ZH_CN = {
116
116
  "aiChat.roleTool": "\u5DE5",
117
117
  "aiChat.roleUser": "\u6211",
118
118
  "aiChat.thinking": "\u601D\u8003 {p0}",
119
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
119
120
  /* ── aiComposer ── */
120
121
  "aiComposer.attachAgent": "\u4EE3\u7406",
121
122
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1,5 +1,5 @@
1
- import { ThemeState } from './theme.js';
2
- import { PanelSizing } from './popover.js';
1
+ import { ThemeState } from './theme.mjs';
2
+ import { PanelSizing } from './popover.mjs';
3
3
 
4
4
  interface ThemeSwitcherOptions {
5
5
  /** all = one appearance menu; individual axes can be composed freely. */
@@ -528,8 +528,22 @@ function toggleDark() {
528
528
  var systemListenerAttached = false;
529
529
  var storageListenerAttached = false;
530
530
  function initTheme() {
531
- const t2 = getTheme();
532
- applyTheme(t2);
531
+ let t2 = getTheme();
532
+ if (isBrowser()) {
533
+ const root = document.documentElement;
534
+ if (!hasPersistedPreference() && root.hasAttribute("data-icen-preset") && root.hasAttribute("data-icen-style")) {
535
+ t2 = {
536
+ preset: root.getAttribute("data-icen-preset") ?? t2.preset,
537
+ dark: root.getAttribute("data-icen-theme") === "dark",
538
+ style: root.getAttribute("data-icen-style") ?? t2.style
539
+ };
540
+ lastApplied = { ...t2 };
541
+ } else {
542
+ applyTheme(t2);
543
+ }
544
+ } else {
545
+ applyTheme(t2);
546
+ }
533
547
  if (isBrowser() && !storageListenerAttached) {
534
548
  storageListenerAttached = true;
535
549
  window.addEventListener("storage", (event) => {
@@ -898,6 +912,7 @@ var ICEN_LOCALE_ZH_CN = {
898
912
  "aiChat.roleTool": "\u5DE5",
899
913
  "aiChat.roleUser": "\u6211",
900
914
  "aiChat.thinking": "\u601D\u8003 {p0}",
915
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
901
916
  /* ── aiComposer ── */
902
917
  "aiComposer.attachAgent": "\u4EE3\u7406",
903
918
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -458,8 +458,22 @@ function setPrimitive(primitive) {
458
458
  var systemListenerAttached = false;
459
459
  var storageListenerAttached = false;
460
460
  function initTheme() {
461
- const t = getTheme();
462
- applyTheme(t);
461
+ let t = getTheme();
462
+ if (isBrowser()) {
463
+ const root = document.documentElement;
464
+ if (!hasPersistedPreference() && root.hasAttribute("data-icen-preset") && root.hasAttribute("data-icen-style")) {
465
+ t = {
466
+ preset: root.getAttribute("data-icen-preset") ?? t.preset,
467
+ dark: root.getAttribute("data-icen-theme") === "dark",
468
+ style: root.getAttribute("data-icen-style") ?? t.style
469
+ };
470
+ lastApplied = { ...t };
471
+ } else {
472
+ applyTheme(t);
473
+ }
474
+ } else {
475
+ applyTheme(t);
476
+ }
463
477
  if (isBrowser() && !storageListenerAttached) {
464
478
  storageListenerAttached = true;
465
479
  window.addEventListener("storage", (event) => {
@@ -1,5 +1,5 @@
1
- import { FeedbackAction } from './feedback.js';
2
- import { IconName } from './icons.js';
1
+ import { FeedbackAction } from './feedback.mjs';
2
+ import { IconName } from './icons.mjs';
3
3
 
4
4
  type ToastKind = 'warn' | 'info' | 'success' | 'error';
5
5
  interface ToastOptions {
@@ -302,6 +302,7 @@ var ICEN_LOCALE_ZH_CN = {
302
302
  "aiChat.roleTool": "\u5DE5",
303
303
  "aiChat.roleUser": "\u6211",
304
304
  "aiChat.thinking": "\u601D\u8003 {p0}",
305
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
305
306
  /* ── aiComposer ── */
306
307
  "aiComposer.attachAgent": "\u4EE3\u7406",
307
308
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -21,6 +21,7 @@ var ICEN_LOCALE_ZH_CN = {
21
21
  "aiChat.roleTool": "\u5DE5",
22
22
  "aiChat.roleUser": "\u6211",
23
23
  "aiChat.thinking": "\u601D\u8003 {p0}",
24
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
24
25
  /* ── aiComposer ── */
25
26
  "aiComposer.attachAgent": "\u4EE3\u7406",
26
27
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1237,6 +1238,7 @@ function bindGlobalListeners() {
1237
1238
  document.addEventListener("pointerdown", onGlobalPointerDown);
1238
1239
  document.addEventListener("keydown", onGlobalKeyDown);
1239
1240
  }
1241
+ var activeSetups = /* @__PURE__ */ new Set();
1240
1242
  function bindOpenListeners() {
1241
1243
  window.addEventListener("scroll", onWindowChange, true);
1242
1244
  window.addEventListener("resize", onWindowChange);
@@ -1290,6 +1292,11 @@ function createTreeSelect(el, opts) {
1290
1292
  const valueEl = document.createElement("span");
1291
1293
  valueEl.className = "icen-tree-select-value";
1292
1294
  trigger.appendChild(valueEl);
1295
+ const triggerChevron = createIcon("chevron-down", { size: 12, className: "icen-tree-select-chevron" });
1296
+ if (triggerChevron) {
1297
+ triggerChevron.setAttribute("aria-hidden", "true");
1298
+ trigger.appendChild(triggerChevron);
1299
+ }
1293
1300
  let clearBtn = null;
1294
1301
  if (opts.clearable) {
1295
1302
  clearBtn = document.createElement("button");
@@ -1863,8 +1870,15 @@ function createTreeSelect(el, opts) {
1863
1870
  root.remove();
1864
1871
  el.textContent = "";
1865
1872
  if (instances.get(el) === destroy) instances.delete(el);
1873
+ activeSetups.delete(destroy);
1874
+ if (!activeSetups.size && globalBound) {
1875
+ document.removeEventListener("pointerdown", onGlobalPointerDown);
1876
+ document.removeEventListener("keydown", onGlobalKeyDown);
1877
+ globalBound = false;
1878
+ }
1866
1879
  }
1867
1880
  instances.set(el, destroy);
1881
+ activeSetups.add(destroy);
1868
1882
  return {
1869
1883
  getValue: () => selectedNodesInOrder().map((n) => n.value),
1870
1884
  getLabels: () => selectedNodesInOrder().map((n) => n.label),
@@ -25,8 +25,8 @@ function setup(tree) {
25
25
  if (target.closest(".icen-tree-toggle")) {
26
26
  if (!childUl) return;
27
27
  const toggle = node.querySelector(".icen-tree-toggle");
28
- const collapsed = childUl.hasAttribute("hidden");
29
- if (collapsed) {
28
+ const wasCollapsed = childUl.hasAttribute("hidden");
29
+ if (wasCollapsed) {
30
30
  childUl.removeAttribute("hidden");
31
31
  toggle?.classList.remove("is-collapsed");
32
32
  toggle?.setAttribute("aria-expanded", "true");
@@ -35,7 +35,7 @@ function setup(tree) {
35
35
  toggle?.classList.add("is-collapsed");
36
36
  toggle?.setAttribute("aria-expanded", "false");
37
37
  }
38
- emitIcen(tree, "icen:tree-toggle", { node: li, open: !collapsed });
38
+ emitIcen(tree, "icen:tree-toggle", { node: li, open: wasCollapsed });
39
39
  return;
40
40
  }
41
41
  if (childUl) return;
@@ -54,7 +54,7 @@ function setup(tree) {
54
54
  const node = target.closest(".icen-tree-node");
55
55
  if (!node || node.closest(".icen-tree") !== tree) return;
56
56
  if (node.classList.contains("is-disabled")) return;
57
- const allNodes = Array.from(tree.querySelectorAll(".icen-tree-node:not(.is-disabled)"));
57
+ const allNodes = Array.from(tree.querySelectorAll(".icen-tree-node:not(.is-disabled)")).filter((n) => !n.closest("ul[hidden]"));
58
58
  const idx = allNodes.indexOf(node);
59
59
  if (idx === -1) return;
60
60
  switch (kev.key) {
@@ -116,6 +116,7 @@ var ICEN_LOCALE_ZH_CN = {
116
116
  "aiChat.roleTool": "\u5DE5",
117
117
  "aiChat.roleUser": "\u6211",
118
118
  "aiChat.thinking": "\u601D\u8003 {p0}",
119
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
119
120
  /* ── aiComposer ── */
120
121
  "aiComposer.attachAgent": "\u4EE3\u7406",
121
122
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -0,0 +1,8 @@
1
+ /**
2
+ * 不可信 URL → 可落成 href/src 的串;被判危险则返回 undefined(调用方跳过渲染该槽位)。
3
+ * 归一只用于判定,返回的仍是原始 uri——浏览器解析时会做出同样的归一,不会出现
4
+ * 「守卫看归一后、浏览器看原文」的判定分裂。
5
+ */
6
+ declare function safeUrl(uri: string): string | undefined;
7
+
8
+ export { safeUrl };
@@ -0,0 +1,11 @@
1
+ // src/behaviors/url-safety.ts
2
+ function safeUrl(uri) {
3
+ const s = uri.replace(/[\t\n\r\0-\x1f\x7f]/g, "").trim().toLowerCase();
4
+ if (!s) return void 0;
5
+ if (s.startsWith("javascript:") || s.startsWith("vbscript:")) return void 0;
6
+ if (/^data:\s*text\/html/.test(s)) return void 0;
7
+ return uri;
8
+ }
9
+ export {
10
+ safeUrl
11
+ };
@@ -0,0 +1,2 @@
1
+ // kit: accordion 类型面(构建产物,勿手改)
2
+ export * from '../behaviors/accordion.mjs';
@@ -0,0 +1,2 @@
1
+ // kit: ai-branch 类型面(构建产物,勿手改)
2
+ export * from '../behaviors/ai-branch.mjs';
@@ -53,7 +53,7 @@
53
53
  * 状态机 7 态 .is-* 中的 streaming/done 在本文件消费;running 脉冲点等条目态见 ai-tool.css(.icen-ai-item 基元)。
54
54
  * data-icen-density:summary 档隐藏 meta、默认折叠 reasoning(纯 CSS);
55
55
  * tool/system 类次要消息在 summary 档压淡。verbose 与 normal 目前同视觉(透明度两档生效)。
56
- * 流式光标复用 tokens 的 blink keyframes(.icen-animate-blink 同款);reasoning shimmer 时长走
56
+ * 流式光标复用 base.css 的 icen-blink keyframes;reasoning shimmer 时长走
57
57
  * --ai-shimmer-duration 局部变量(默认值 1.6s)。
58
58
  */
59
59
 
@@ -134,29 +134,29 @@
134
134
  display: grid;
135
135
  grid-template-columns: auto 1fr;
136
136
  gap: var(--icen-density-space-sm);
137
- padding: var(--icen-density-space-sm) var(--icen-density-space-md);
138
- border-radius: var(--icen-radius-md);
137
+ padding: 6px var(--icen-density-space-xs);
138
+ border-radius: var(--icen-control-radius-lg);
139
139
  animation: icen-pop-in var(--ai-msg-enter-duration, var(--icen-duration-normal)) var(--icen-ease-out);
140
140
  }
141
141
 
142
142
  .icen-ai-msg-avatar {
143
- width: 28px;
144
- height: 28px;
143
+ width: 26px;
144
+ height: 26px;
145
145
  flex-shrink: 0;
146
146
  display: inline-flex;
147
147
  align-items: center;
148
148
  justify-content: center;
149
- border-radius: var(--icen-radius-sm);
149
+ border-radius: var(--icen-radius-xs);
150
150
  background: var(--icen-token-fill-2);
151
151
  color: var(--icen-token-text-muted);
152
152
  font-family: var(--icen-font-mono);
153
153
  font-size: var(--icen-density-font-size-2xs);
154
- letter-spacing: 0.04em;
154
+ letter-spacing: 0.03em;
155
155
  user-select: none;
156
156
  }
157
157
  .icen-ai-msg--user .icen-ai-msg-avatar {
158
158
  background: color-mix(in srgb, var(--icen-token-accent) 14%, transparent);
159
- color: var(--icen-token-accent);
159
+ color: var(--icen-token-accent-text);
160
160
  }
161
161
  .icen-ai-msg--assistant .icen-ai-msg-avatar {
162
162
  background: color-mix(in srgb, var(--icen-token-success) 12%, transparent);
@@ -174,19 +174,21 @@
174
174
  .icen-ai-msg-body {
175
175
  min-width: 0;
176
176
  min-height: 1.6em; /* 流式从空开始时占住一行高度,不塌 */
177
- font-size: var(--icen-density-font-size-md);
177
+ font-size: var(--icen-font-size-control);
178
178
  line-height: 1.6;
179
179
  white-space: pre-wrap;
180
180
  word-break: break-word;
181
181
  }
182
182
 
183
- /* 流式光标(▍闪烁,复用 tokens 的 blink keyframes,同 .icen-animate-blink) */
183
+ /* 流式光标(▍闪烁,共享 base.css 的 icen-blink keyframes);
184
+ .icen-ai-msg-text 命中库内自带绑定的 stream() 节点(createAiStream 挂 .is-streaming) */
184
185
  .icen-ai-msg-body.is-streaming::after,
186
+ .icen-ai-msg-text.is-streaming::after,
185
187
  .icen-ai-reasoning-body.is-streaming::after {
186
188
  content: '▍';
187
189
  margin-inline-start: 1px;
188
190
  color: var(--icen-token-accent);
189
- animation: blink 1s step-end infinite;
191
+ animation: icen-blink 1s step-end infinite;
190
192
  }
191
193
 
192
194
  /* 消息操作:hover / focus-within 才出现(键盘可达等价) */
@@ -394,14 +396,10 @@
394
396
  font-variant-numeric: tabular-nums;
395
397
  }
396
398
 
397
- /* 流式中:耗时位换成 shimmer「正在思考…」(时长走局部变量) */
399
+ /* 流式中:耗时位显示 shimmer「正在思考…」——文案由 createAiStream 写入(i18n),
400
+ 此处只做视觉(shimmer 渐变 + 透明填充),不再用 CSS content 冻死中文 */
398
401
  .icen-ai-reasoning.is-streaming .icen-ai-reasoning-time {
399
- display: none;
400
- }
401
- .icen-ai-reasoning.is-streaming .icen-ai-reasoning-head::after {
402
- content: '正在思考…';
403
- margin-inline-start: auto;
404
- font-size: var(--icen-density-font-size-2xs);
402
+ font-variant-numeric: normal;
405
403
  background: linear-gradient(
406
404
  90deg,
407
405
  var(--icen-token-text-faint) 25%,
@@ -436,18 +434,19 @@
436
434
  gap: var(--icen-density-space-xs);
437
435
  min-inline-size: 0;
438
436
  padding: var(--icen-density-space-sm);
439
- border: 1px solid var(--icen-token-line);
440
- border-radius: var(--icen-radius-lg);
437
+ border: 1px solid var(--icen-token-control-border);
438
+ border-radius: var(--icen-control-radius-lg);
441
439
  background: var(--icen-token-surface);
442
- box-shadow: var(--icen-token-shadow-card);
440
+ box-shadow: var(--icen-token-shadow-field);
443
441
  transition: border-color var(--icen-tx-fast), box-shadow var(--icen-tx-fast);
444
442
  }
445
443
  .icen-ai-composer:focus-within {
446
- border-color: var(--icen-hover-border, var(--icen-token-accent));
444
+ border-color: var(--icen-control-focus-border);
445
+ box-shadow: var(--icen-token-shadow-field), 0 0 0 3px color-mix(in srgb, var(--icen-token-accent) 16%, transparent);
447
446
  }
448
447
  .icen-ai-composer:has(.icen-ai-composer-input:focus-visible) {
449
448
  border-color: var(--icen-control-focus-border);
450
- box-shadow: var(--icen-token-shadow-card), 0 0 0 2px color-mix(in srgb, var(--icen-token-accent) 12%, transparent);
449
+ box-shadow: var(--icen-token-shadow-field), 0 0 0 3px color-mix(in srgb, var(--icen-token-accent) 16%, transparent);
451
450
  }
452
451
 
453
452
  /* 排队 / 引用 / 附件 chips 行 */
@@ -469,11 +468,11 @@
469
468
  align-items: center;
470
469
  gap: 4px;
471
470
  max-inline-size: min(100%, 280px);
472
- min-block-size: 30px;
473
- padding: 2px 4px 2px 6px; /* guard:allow-physical symmetric chip padding */
474
- border: 1px solid var(--icen-token-line-soft);
475
- border-radius: var(--icen-radius-sm);
476
- background: var(--icen-token-fill-1);
471
+ min-block-size: 26px;
472
+ padding: 2px 4px 2px 7px; /* guard:allow-physical symmetric chip padding */
473
+ border: 1px solid var(--icen-token-separator-soft);
474
+ border-radius: var(--icen-radius-xs);
475
+ background: var(--icen-token-fill-hover);
477
476
  color: var(--icen-token-text);
478
477
  font-size: var(--icen-density-font-size-xs);
479
478
  line-height: 1.4;
@@ -520,10 +519,10 @@
520
519
  flex-wrap: wrap;
521
520
  align-items: flex-end;
522
521
  gap: var(--icen-density-space-sm);
523
- padding: var(--icen-density-space-xs) var(--icen-density-space-sm);
522
+ padding: 4px var(--icen-field-padding-inline);
524
523
  min-inline-size: 0;
525
524
  border: 0;
526
- border-radius: var(--icen-radius-md);
525
+ border-radius: var(--icen-control-radius);
527
526
  background: transparent;
528
527
  box-shadow: none;
529
528
  }
@@ -531,14 +530,14 @@
531
530
  .icen-ai-composer-input {
532
531
  flex: 1;
533
532
  min-inline-size: 0;
534
- min-block-size: 64px;
533
+ min-block-size: 56px;
535
534
  padding: var(--icen-density-space-xs) 0;
536
535
  border: 0;
537
536
  outline: none;
538
537
  background: transparent;
539
538
  resize: none;
540
539
  font-family: inherit;
541
- font-size: var(--icen-density-font-size-md);
540
+ font-size: var(--icen-font-size-control);
542
541
  line-height: 1.5;
543
542
  max-height: 12em;
544
543
  overflow-y: auto;
@@ -991,13 +990,21 @@
991
990
  }
992
991
  }
993
992
 
994
- /* 触屏无 hover:消息操作常显(否则不可达) */
993
+ /* 触屏无 hover:消息操作常显(否则不可达);动作钮抬到 44px 触达面
994
+ (copy/retry、分支切换、线程操作原为 20-22px,低于 WCAG 2.5.8 下限) */
995
995
  @media (pointer: coarse) {
996
996
  .icen-ai-msg-actions {
997
997
  opacity: 1;
998
998
  visibility: visible;
999
999
  transform: none;
1000
1000
  }
1001
+ .icen-ai-msg-actions [data-icen-ai-msg-action],
1002
+ .icen-ai-branch-prev,
1003
+ .icen-ai-branch-next,
1004
+ .icen-ai-thread-action {
1005
+ min-inline-size: 44px;
1006
+ min-block-size: 44px;
1007
+ }
1001
1008
  }
1002
1009
 
1003
1010
  /* 实时待办 chip(setComposerTodo:业界模式——plan 状态挂输入区,不进对话流) */
@@ -0,0 +1,2 @@
1
+ // kit: ai-chat 类型面(构建产物,勿手改)
2
+ export * from '../behaviors/ai-chat.mjs';
@@ -0,0 +1,2 @@
1
+ // kit: ai-composer 类型面(构建产物,勿手改)
2
+ export * from '../behaviors/ai-composer.mjs';
@@ -0,0 +1,2 @@
1
+ // kit: ai-context 类型面(构建产物,勿手改)
2
+ export * from '../behaviors/ai-panel.mjs';
@@ -1,2 +1,3 @@
1
1
  // @icen.ai/ui — kit: ai-context(CSS + behavior 一行入口;构建产物,勿手改)
2
2
  import './ai-panel.css';
3
+ export * from '../behaviors/ai-panel.mjs';
@@ -62,8 +62,8 @@
62
62
  }
63
63
 
64
64
  .icen-ai-diff-file {
65
- border: 1px solid var(--icen-token-line-soft);
66
- border-radius: var(--icen-radius-md);
65
+ border: 1px solid var(--icen-token-separator-soft);
66
+ border-radius: var(--icen-control-radius-lg);
67
67
  background: var(--icen-token-surface);
68
68
  overflow: hidden;
69
69
  min-width: 0;
@@ -71,10 +71,10 @@
71
71
  }
72
72
 
73
73
  /* 文件头状态色边(inset 色条避免 border 宽差导致布局抖动) */
74
- .icen-ai-diff-file.is-added { box-shadow: inset 3px 0 0 var(--icen-token-success); }
75
- .icen-ai-diff-file.is-modified { box-shadow: inset 3px 0 0 var(--icen-token-accent); }
76
- .icen-ai-diff-file.is-deleted { box-shadow: inset 3px 0 0 var(--icen-token-error); }
77
- .icen-ai-diff-file.is-renamed { box-shadow: inset 3px 0 0 var(--icen-token-info); }
74
+ .icen-ai-diff-file.is-added { box-shadow: inset 2px 0 0 var(--icen-token-success); }
75
+ .icen-ai-diff-file.is-modified { box-shadow: inset 2px 0 0 var(--icen-token-accent); }
76
+ .icen-ai-diff-file.is-deleted { box-shadow: inset 2px 0 0 var(--icen-token-error); }
77
+ .icen-ai-diff-file.is-renamed { box-shadow: inset 2px 0 0 var(--icen-token-info); }
78
78
 
79
79
  /* 决策后淡化(状态章配色见 .icen-ai-diff-verdict) */
80
80
  .icen-ai-diff-file.is-accepted,
@@ -0,0 +1,2 @@
1
+ // kit: ai-diff 类型面(构建产物,勿手改)
2
+ export * from '../behaviors/ai-diff.mjs';
@@ -0,0 +1,2 @@
1
+ // kit: ai-feedback 类型面(构建产物,勿手改)
2
+ export * from '../behaviors/ai-feedback.mjs';
@@ -0,0 +1,2 @@
1
+ // kit: ai-files 类型面(构建产物,勿手改)
2
+ export { renderAiDiff } from '../behaviors/ai-diff.mjs';
@@ -0,0 +1,2 @@
1
+ // kit: ai-message 类型面(构建产物,勿手改)
2
+ export { renderAiMessage, createAiStream, initAiChat } from '../behaviors/ai-chat.mjs';