@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
package/dist/vue.d.mts CHANGED
@@ -1,22 +1,22 @@
1
- import { AiClient, AiAuditor } from './behaviors/ai-provider.js';
1
+ import { AiClient, AiAuditor } from './behaviors/ai-provider.mjs';
2
2
  import * as vue from 'vue';
3
3
  import { PropType, Ref } from 'vue';
4
- import { IcenEventMap } from './behaviors/events.js';
5
- import { ChartSpec } from './behaviors/charts.js';
6
- export { ChartHandle } from './behaviors/charts.js';
7
- import { TableOptions } from './behaviors/datatable.js';
8
- export { TableColumn, TableHandle } from './behaviors/datatable.js';
9
- import { AiMessageModel } from './behaviors/ai-chat.js';
10
- export { AiMessageHandle } from './behaviors/ai-chat.js';
11
- import { AiProviderOption, AiComposerCurrentModel, AiComposerBindOpts } from './behaviors/ai-composer.js';
12
- export { AiContent, AiContentPart, AiStatus, AiToolCallModel, AiUsage } from './behaviors/ai-core.js';
13
- import './behaviors/mentions.js';
14
- import './behaviors/suggestions.js';
15
- import './behaviors/kb-core.js';
16
- import './behaviors/icons.js';
17
- import './behaviors/popover.js';
18
- import './behaviors/ai-panel.js';
19
- import './behaviors/context-menu.js';
4
+ import { IcenEventMap } from './behaviors/events.mjs';
5
+ import { ChartSpec } from './behaviors/charts.mjs';
6
+ export { ChartHandle } from './behaviors/charts.mjs';
7
+ import { TableOptions } from './behaviors/datatable.mjs';
8
+ export { TableColumn, TableHandle } from './behaviors/datatable.mjs';
9
+ import { AiMessageModel } from './behaviors/ai-chat.mjs';
10
+ export { AiMessageHandle } from './behaviors/ai-chat.mjs';
11
+ import { AiProviderOption, AiComposerCurrentModel, AiComposerBindOpts } from './behaviors/ai-composer.mjs';
12
+ export { AiContent, AiContentPart, AiStatus, AiToolCallModel, AiUsage } from './behaviors/ai-core.mjs';
13
+ import './behaviors/mentions.mjs';
14
+ import './behaviors/suggestions.mjs';
15
+ import './behaviors/kb-core.mjs';
16
+ import './behaviors/icons.mjs';
17
+ import './behaviors/popover.mjs';
18
+ import './behaviors/ai-panel.mjs';
19
+ import './behaviors/context-menu.mjs';
20
20
 
21
21
  type MaybeRef<T> = T | Ref<T | null>;
22
22
  type Cleanup = (() => void) | void;
package/dist/vue.mjs CHANGED
@@ -168,6 +168,7 @@ var ICEN_LOCALE_ZH_CN = {
168
168
  "aiChat.roleTool": "\u5DE5",
169
169
  "aiChat.roleUser": "\u6211",
170
170
  "aiChat.thinking": "\u601D\u8003 {p0}",
171
+ "aiChat.thinkingNow": "\u6B63\u5728\u601D\u8003\u2026",
171
172
  /* ── aiComposer ── */
172
173
  "aiComposer.attachAgent": "\u4EE3\u7406",
173
174
  "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
@@ -1215,7 +1216,8 @@ function withChrome(el, opts, hasLegend, paint, state, extras) {
1215
1216
  emitIcen(el, "icen:chart-legend-visibility", { visible: hidden ? false : true });
1216
1217
  });
1217
1218
  syncEye();
1218
- head.append(title, eye);
1219
+ if (hasLegend) head.append(title, eye);
1220
+ else head.append(title);
1219
1221
  el.append(head, body);
1220
1222
  paint(body);
1221
1223
  }
@@ -1316,7 +1318,7 @@ function renderVBar(el, opts) {
1316
1318
  wrap.appendChild(track);
1317
1319
  }
1318
1320
  body.append(wrap, labelsRow(labelsUsed));
1319
- if (seriesList.length > 1) body.appendChild(toggleLegend(seriesList.map((s, si) => ({ key: s.name, label: s.name, tone: s.tone ?? (si === 0 ? opts.tone : void 0), si })), wrap));
1321
+ if (seriesList.length > 1) body.appendChild(toggleLegend(seriesList.map((s, si) => ({ key: `${si}:${s.name}`, label: s.name, tone: s.tone ?? (si === 0 ? opts.tone : void 0), si })), wrap));
1320
1322
  });
1321
1323
  attachChartInteraction(el, "vbar");
1322
1324
  return el;
@@ -1411,8 +1413,10 @@ function renderDonut(el, opts) {
1411
1413
  "stroke-width": "14"
1412
1414
  }));
1413
1415
  let offset = 0;
1416
+ const gap = opts.segments.length > 1 ? 2.5 : 0;
1414
1417
  opts.segments.forEach((seg, segIndex) => {
1415
- const dash = seg.value / total * circumference;
1418
+ const arcLength = Math.max(0, seg.value / total * circumference);
1419
+ const dash = arcLength - Math.min(gap, arcLength * 0.1);
1416
1420
  const arc = svgEl("circle", {
1417
1421
  cx: "60",
1418
1422
  cy: "60",
@@ -1426,7 +1430,7 @@ function renderDonut(el, opts) {
1426
1430
  });
1427
1431
  setMarkData(arc, { index: segIndex, label: seg.label, value: seg.value });
1428
1432
  svg.appendChild(arc);
1429
- offset += dash;
1433
+ offset += arcLength;
1430
1434
  });
1431
1435
  const legend = document.createElement("div");
1432
1436
  legend.className = "icen-chart-legend";
@@ -1461,8 +1465,9 @@ function renderLine(el, opts) {
1461
1465
  const svg = svgEl("svg", { viewBox: `0 0 ${width} ${height}`, role: "img", "aria-label": chartAriaLabel(opts.title, t("charts.type.line")) });
1462
1466
  const defs = svgEl("defs", {});
1463
1467
  for (let i = 0; i < 4; i++) {
1464
- const y = pad + i * (height - pad * 2) / 3;
1468
+ const y = Math.round(pad + i * (height - pad * 2) / 3) + 0.5;
1465
1469
  svg.appendChild(svgEl("line", {
1470
+ class: i === 3 ? "icen-chart-grid icen-chart-baseline" : "icen-chart-grid",
1466
1471
  x1: String(pad),
1467
1472
  x2: String(width - pad),
1468
1473
  y1: String(y),
@@ -1546,7 +1551,7 @@ function renderLine(el, opts) {
1546
1551
  if (defs.firstChild) svg.insertBefore(defs, svg.firstChild);
1547
1552
  wrap.append(svg, pointLabelsRow(labelsUsed, width, pad));
1548
1553
  body.appendChild(wrap);
1549
- if (seriesList.length > 1) body.appendChild(toggleLegend(seriesList.map((s, si) => ({ key: s.name, label: s.name, tone: s.tone ?? (si === 0 ? opts.tone : void 0), si })), wrap));
1554
+ if (seriesList.length > 1) body.appendChild(toggleLegend(seriesList.map((s, si) => ({ key: `${si}:${s.name}`, label: s.name, tone: s.tone ?? (si === 0 ? opts.tone : void 0), si })), wrap));
1550
1555
  });
1551
1556
  if (el.dataset.icenChartBody == null) observeFluidWidth(el, () => renderLine(el, opts));
1552
1557
  attachChartInteraction(el, "line");
@@ -1653,7 +1658,7 @@ function renderRadar(el, opts) {
1653
1658
  setMarkData(dot, { index: i, seriesIndex: si, seriesName: s.name || void 0, label: axes[i] ?? "", value: s.values[i] ?? 0 });
1654
1659
  svg.appendChild(dot);
1655
1660
  }
1656
- legendItems.push({ key: s.name || t("charts.seriesName", { p0: si + 1 }), label: s.name || t("charts.seriesName", { p0: si + 1 }), tone: s.tone, si });
1661
+ legendItems.push({ key: `${si}:${s.name || t("charts.seriesName", { p0: si + 1 })}`, label: s.name || t("charts.seriesName", { p0: si + 1 }), tone: s.tone, si });
1657
1662
  });
1658
1663
  wrap.appendChild(svg);
1659
1664
  body.appendChild(wrap);
@@ -1675,6 +1680,11 @@ function niceCeil(v) {
1675
1680
  else nice = 10;
1676
1681
  return nice * base;
1677
1682
  }
1683
+ function tickPrecision(min, max, steps) {
1684
+ const span = Math.abs(max - min);
1685
+ if (!Number.isFinite(span) || span <= 0) return 0;
1686
+ return Math.max(0, Math.ceil(-Math.log10(span / steps)));
1687
+ }
1678
1688
  function isoDate(d) {
1679
1689
  const m = String(d.getMonth() + 1).padStart(2, "0");
1680
1690
  const day = String(d.getDate()).padStart(2, "0");
@@ -1770,7 +1780,8 @@ function renderSparkline(el, opts) {
1770
1780
  const tone = toneVar(opts.tone);
1771
1781
  const points = values.map((value, i) => ({
1772
1782
  x: values.length <= 1 ? width / 2 : pad + i / (values.length - 1) * (width - pad * 2),
1773
- y: height - pad - value / max * (height - pad * 2),
1783
+ /* 负值钳到基线(与折线图同口径):viewBox 仅 28 高,反向射出更刺眼 */
1784
+ y: height - pad - Math.max(0, value) / max * (height - pad * 2),
1774
1785
  value
1775
1786
  }));
1776
1787
  const line = points.map((p, i) => `${i === 0 ? "M" : "L"}${p.x.toFixed(1)},${p.y.toFixed(1)}`).join(" ");
@@ -1895,6 +1906,7 @@ function renderCalendar(el, opts) {
1895
1906
  weekdayRow.appendChild(s);
1896
1907
  });
1897
1908
  const max = maxOf(entries.map((e) => e.value));
1909
+ entries.sort((a, b) => a.date.localeCompare(b.date));
1898
1910
  const pad = padFirstWeek(grid, entries[0].date, weekStart);
1899
1911
  let lastMonth = -1;
1900
1912
  entries.forEach((entry, i) => {
@@ -1953,8 +1965,9 @@ function renderScatter(el, opts) {
1953
1965
  const xAt = (x) => pad + (x - xMin) / (xMax - xMin) * (width - pad * 2);
1954
1966
  const yAt = (y) => height - pad - (y - yMin) / (yMax - yMin) * (height - pad * 2);
1955
1967
  for (let i = 0; i <= 3; i++) {
1956
- const y = pad + i * (height - pad * 2) / 3;
1968
+ const y = Math.round(pad + i * (height - pad * 2) / 3) + 0.5;
1957
1969
  svg.appendChild(svgEl("line", {
1970
+ class: i === 3 ? "icen-chart-grid icen-chart-baseline" : "icen-chart-grid",
1958
1971
  x1: String(pad),
1959
1972
  x2: String(width - pad),
1960
1973
  y1: String(y),
@@ -1970,12 +1983,13 @@ function renderScatter(el, opts) {
1970
1983
  "font-size": "8",
1971
1984
  fill: "var(--icen-token-text-faint)"
1972
1985
  });
1973
- txt.textContent = fmt(opts, Math.round(tv * 10) / 10);
1986
+ txt.textContent = fmt(opts, +tv.toFixed(tickPrecision(yMin, yMax, 3)));
1974
1987
  svg.appendChild(txt);
1975
1988
  }
1976
1989
  for (let i = 0; i <= 4; i++) {
1977
- const x = pad + i * (width - pad * 2) / 4;
1990
+ const x = Math.round(pad + i * (width - pad * 2) / 4) + 0.5;
1978
1991
  svg.appendChild(svgEl("line", {
1992
+ class: i === 0 ? "icen-chart-grid icen-chart-grid--v icen-chart-axis" : "icen-chart-grid icen-chart-grid--v",
1979
1993
  x1: String(x),
1980
1994
  x2: String(x),
1981
1995
  y1: String(pad),
@@ -1992,7 +2006,7 @@ function renderScatter(el, opts) {
1992
2006
  "font-size": "8",
1993
2007
  fill: "var(--icen-token-text-faint)"
1994
2008
  });
1995
- txt.textContent = fmt(opts, Math.round(tv * 10) / 10);
2009
+ txt.textContent = fmt(opts, +tv.toFixed(tickPrecision(xMin, xMax, 4)));
1996
2010
  svg.appendChild(txt);
1997
2011
  }
1998
2012
  if (opts.yLabel) {
@@ -2356,6 +2370,7 @@ function renderChartSkeleton(body) {
2356
2370
  body.appendChild(box);
2357
2371
  }
2358
2372
  var CHART_MARK_ACCENT = "var(--icen-token-accent)";
2373
+ var CHART_MARK_ACCENT_TEXT = "var(--icen-token-accent-text)";
2359
2374
  function markToneVar(tone) {
2360
2375
  switch (tone) {
2361
2376
  case "success":
@@ -2491,7 +2506,7 @@ function paintSvgChartMarks(root, view, marks, formatValue, warned) {
2491
2506
  y: String(clampNum(y - 10, 8, CHART_LINE_H - 4)),
2492
2507
  "text-anchor": "middle",
2493
2508
  "font-size": "8",
2494
- fill: CHART_MARK_ACCENT
2509
+ fill: CHART_MARK_ACCENT_TEXT
2495
2510
  });
2496
2511
  label.textContent = mark.text ?? mark.label;
2497
2512
  g.appendChild(label);
@@ -3049,6 +3064,12 @@ function renderChart(el, raw) {
3049
3064
  const graphic = root.querySelector('[role="img"]');
3050
3065
  if (graphic && !graphic.getAttribute("aria-label")) {
3051
3066
  graphic.setAttribute("aria-label", spec.title ? `${spec.title}\uFF08${type}\uFF09` : type);
3067
+ } else if (!graphic) {
3068
+ const dom = root.querySelector(".icen-chart-vbar, .icen-chart-hbar");
3069
+ if (dom) {
3070
+ dom.setAttribute("role", "img");
3071
+ dom.setAttribute("aria-label", spec.title ? `${spec.title}\uFF08${type}\uFF09` : type);
3072
+ }
3052
3073
  }
3053
3074
  }
3054
3075
  if (loading) return;
@@ -3761,7 +3782,13 @@ function onKeyDown2(e) {
3761
3782
 
3762
3783
  // src/behaviors/datatable.ts
3763
3784
  function defaultCompare(a, b) {
3764
- if (typeof a === "number" && typeof b === "number") return a - b;
3785
+ if (typeof a === "number" && typeof b === "number") {
3786
+ if (Number.isNaN(a) || Number.isNaN(b)) {
3787
+ if (Number.isNaN(a) && Number.isNaN(b)) return 0;
3788
+ return Number.isNaN(a) ? 1 : -1;
3789
+ }
3790
+ return a - b;
3791
+ }
3765
3792
  return String(a ?? "").localeCompare(String(b ?? ""), "zh-CN", { numeric: true });
3766
3793
  }
3767
3794
  function toNum2(v) {
@@ -4050,11 +4077,13 @@ function createTable(el, opts) {
4050
4077
  const body = document.createElement("div");
4051
4078
  body.className = "icen-dt-body";
4052
4079
  body.setAttribute("role", "rowgroup");
4053
- const summaryEl = document.createElement("div");
4054
- summaryEl.className = "icen-dt-row icen-dt-row--summary";
4055
- summaryEl.setAttribute("role", "row");
4056
- summaryEl.hidden = true;
4057
- canvas.append(head, body, summaryEl);
4080
+ const summaryEl = opts.summaryRow ? document.createElement("div") : null;
4081
+ if (summaryEl) {
4082
+ summaryEl.className = "icen-dt-row icen-dt-row--summary";
4083
+ summaryEl.setAttribute("role", "row");
4084
+ summaryEl.hidden = true;
4085
+ }
4086
+ canvas.append(head, body, ...summaryEl ? [summaryEl] : []);
4058
4087
  scroll.appendChild(canvas);
4059
4088
  root.appendChild(scroll);
4060
4089
  const foot = document.createElement("div");
@@ -4868,6 +4897,7 @@ function createTable(el, opts) {
4868
4897
  return wrap;
4869
4898
  }
4870
4899
  function renderSummary() {
4900
+ if (!summaryEl) return;
4871
4901
  summaryEl.textContent = "";
4872
4902
  summaryEl.hidden = true;
4873
4903
  const cfg = opts.summaryRow;
@@ -5064,9 +5094,9 @@ function createTable(el, opts) {
5064
5094
  }
5065
5095
  }
5066
5096
  let currentTotal = 0;
5067
- function visibleRange(total) {
5097
+ function visibleRange(total, avail) {
5068
5098
  if (!virtual) {
5069
- if (opts.remote || opts.pagination === false) return [0, total];
5099
+ if (opts.remote || opts.pagination === false) return [0, Math.min(total, avail)];
5070
5100
  const start2 = (page - 1) * pageSize;
5071
5101
  return [start2, Math.min(total, start2 + pageSize)];
5072
5102
  }
@@ -5081,6 +5111,10 @@ function createTable(el, opts) {
5081
5111
  const rows = pipeline();
5082
5112
  const entries = groupFn ? flatEntries() : null;
5083
5113
  const total = entries ? entries.length : opts.remote ? opts.totalCount ?? data.length : rows.length;
5114
+ if (!opts.remote && opts.pagination !== false) {
5115
+ const pages = Math.max(1, Math.ceil(total / pageSize));
5116
+ if (page > pages) page = pages;
5117
+ }
5084
5118
  navTotal = entries ? entries.length : rows.length;
5085
5119
  currentTotal = total;
5086
5120
  const keepTop = virtual ? scroll.scrollTop : 0;
@@ -5109,7 +5143,7 @@ function createTable(el, opts) {
5109
5143
  renderSummary();
5110
5144
  return;
5111
5145
  }
5112
- const [start, end] = visibleRange(total);
5146
+ const [start, end] = visibleRange(total, rows.length);
5113
5147
  const frag = document.createDocumentFragment();
5114
5148
  const offsets = frozenOffsets();
5115
5149
  if (virtual && start > 0) {
@@ -5172,11 +5206,21 @@ function createTable(el, opts) {
5172
5206
  const pages = Math.ceil(total / pageSize);
5173
5207
  const pager = document.createElement("nav");
5174
5208
  pager.className = "icen-dt-pager";
5175
- pager.setAttribute("aria-label", t("datatable.paginationAria"));
5209
+ {
5210
+ const base = t("datatable.paginationAria");
5211
+ const used = /* @__PURE__ */ new Set();
5212
+ for (const el2 of document.querySelectorAll(".icen-dt-pager[aria-label]")) {
5213
+ if (!root.contains(el2)) used.add(el2.getAttribute("aria-label") ?? "");
5214
+ }
5215
+ let label = base, n = 2;
5216
+ while (used.has(label)) label = `${base} ${n++}`;
5217
+ pager.setAttribute("aria-label", label);
5218
+ }
5176
5219
  const sizeSel = document.createElement("select");
5177
5220
  sizeSel.className = "icen-dt-page-size";
5178
5221
  sizeSel.setAttribute("aria-label", t("datatable.pageSizeAria"));
5179
- for (const s of pageSizes) {
5222
+ const sizeOptions = pageSizes.includes(pageSize) ? pageSizes : [...pageSizes, pageSize].sort((a, b) => a - b);
5223
+ for (const s of sizeOptions) {
5180
5224
  const o = document.createElement("option");
5181
5225
  o.value = String(s);
5182
5226
  o.textContent = t("pagination.pageSize", { p0: s });
@@ -5268,6 +5312,7 @@ function createTable(el, opts) {
5268
5312
  if (destroyed) return;
5269
5313
  renderHead();
5270
5314
  renderBody();
5315
+ syncFrozenWidths();
5271
5316
  }
5272
5317
  rekey();
5273
5318
  renderAll();
@@ -5288,12 +5333,52 @@ function createTable(el, opts) {
5288
5333
  opts.onPageChange?.(page, pageSize);
5289
5334
  renderAll();
5290
5335
  }
5336
+ function hasFluidFrozen() {
5337
+ return cols().some((c) => frozenSide(c) != null && !/^(\d+(?:\.\d+)?)px/.test(colWidths.get(c.key) ?? c.width ?? ""));
5338
+ }
5339
+ function syncFrozenWidths() {
5340
+ if (!hasFluidFrozen()) return;
5341
+ const visible = cols();
5342
+ const headCells = Array.from(headRow.children);
5343
+ const lead = headCells.length - visible.length;
5344
+ const left = /* @__PURE__ */ new Map();
5345
+ const right = /* @__PURE__ */ new Map();
5346
+ let acc = headCells.slice(0, lead).reduce((s, c) => s + c.offsetWidth, 0);
5347
+ for (let i = 0; i < visible.length; i++) {
5348
+ const c = visible[i];
5349
+ if (frozenSide(c) === "left") left.set(c.key, acc);
5350
+ acc += headCells[lead + i]?.offsetWidth ?? 0;
5351
+ }
5352
+ let accR = 0;
5353
+ for (let i = visible.length - 1; i >= 0; i--) {
5354
+ const c = visible[i];
5355
+ if (frozenSide(c) === "right") right.set(c.key, accR);
5356
+ accR += headCells[lead + i]?.offsetWidth ?? 0;
5357
+ }
5358
+ const rows = [headRow, ...summaryEl ? [summaryEl] : [], ...Array.from(body.querySelectorAll(".icen-dt-row"))];
5359
+ for (const row of rows) {
5360
+ const cells = Array.from(row.children);
5361
+ if (cells.length !== headCells.length) continue;
5362
+ cells.forEach((cell, i) => {
5363
+ const col = i >= lead ? visible[i - lead] : void 0;
5364
+ if (!col) return;
5365
+ const l = left.get(col.key);
5366
+ if (l != null && cell.classList.contains("icen-dt-cell--frozen")) cell.style.left = `${l}px`;
5367
+ const r = right.get(col.key);
5368
+ if (r != null && cell.classList.contains("icen-dt-cell--frozen-right")) cell.style.right = `${r}px`;
5369
+ });
5370
+ }
5371
+ }
5291
5372
  return {
5292
5373
  setPage,
5293
5374
  setPageSize,
5294
5375
  setData(next) {
5295
5376
  if (editing) cancelEdit(true);
5296
5377
  data = next;
5378
+ if (typeof opts.rowKey !== "function" && typeof opts.rowKey !== "string" && selected.size > 0) {
5379
+ selected.clear();
5380
+ emitSelection();
5381
+ }
5297
5382
  rekey();
5298
5383
  invalidate();
5299
5384
  page = 1;
@@ -5536,6 +5621,15 @@ function svgIcon(svg) {
5536
5621
  return parseSvg(svg);
5537
5622
  }
5538
5623
 
5624
+ // src/behaviors/url-safety.ts
5625
+ function safeUrl(uri) {
5626
+ const s = uri.replace(/[\t\n\r\0-\x1f\x7f]/g, "").trim().toLowerCase();
5627
+ if (!s) return void 0;
5628
+ if (s.startsWith("javascript:") || s.startsWith("vbscript:")) return void 0;
5629
+ if (/^data:\s*text\/html/.test(s)) return void 0;
5630
+ return uri;
5631
+ }
5632
+
5539
5633
  // src/behaviors/ai-chat.ts
5540
5634
  var ICON_COPY = iconHTML("copy");
5541
5635
  var ICON_RETRY = iconHTML("refresh");
@@ -5563,6 +5657,8 @@ function createAiStream(el) {
5563
5657
  el.setAttribute("aria-busy", "true");
5564
5658
  if (reasoning) {
5565
5659
  reasoning.classList.add("is-streaming");
5660
+ const timeEl = reasoning.querySelector(".icen-ai-reasoning-time");
5661
+ if (timeEl) timeEl.textContent = t("aiChat.thinkingNow");
5566
5662
  setReasoningOpen(reasoning, true);
5567
5663
  const head = reasoning.querySelector(".icen-ai-reasoning-head");
5568
5664
  if (head && head.dataset.icenReasoningStart == null) head.dataset.icenReasoningStart = String(startedAt);
@@ -5650,10 +5746,9 @@ var ROLE_AVATAR = {
5650
5746
  system: t("aiChat.roleSystem"),
5651
5747
  tool: t("aiChat.roleTool")
5652
5748
  };
5653
- function safeHref(uri) {
5654
- const s = uri.trim().toLowerCase();
5655
- if (s.startsWith("javascript:") || s.startsWith("data:text/html")) return void 0;
5656
- return uri;
5749
+ function safeContentUrl(part) {
5750
+ const src = aiContentUrl(part);
5751
+ return src ? safeUrl(src) : void 0;
5657
5752
  }
5658
5753
  function renderAiContentPart(part) {
5659
5754
  if (part.type === "text") {
@@ -5663,7 +5758,7 @@ function renderAiContentPart(part) {
5663
5758
  return span;
5664
5759
  }
5665
5760
  if (part.type === "image") {
5666
- const src = aiContentUrl(part);
5761
+ const src = safeContentUrl(part);
5667
5762
  if (!src) return void 0;
5668
5763
  const img = document.createElement("img");
5669
5764
  img.className = "icen-ai-msg-media icen-ai-msg-media--image";
@@ -5673,7 +5768,7 @@ function renderAiContentPart(part) {
5673
5768
  return img;
5674
5769
  }
5675
5770
  if (part.type === "audio") {
5676
- const src = aiContentUrl(part);
5771
+ const src = safeContentUrl(part);
5677
5772
  if (!src) return void 0;
5678
5773
  const audio = document.createElement("audio");
5679
5774
  audio.className = "icen-ai-msg-media icen-ai-msg-media--audio";
@@ -5682,7 +5777,7 @@ function renderAiContentPart(part) {
5682
5777
  return audio;
5683
5778
  }
5684
5779
  if (part.type === "video") {
5685
- const src = aiContentUrl(part);
5780
+ const src = safeContentUrl(part);
5686
5781
  if (!src) return void 0;
5687
5782
  const video = document.createElement("video");
5688
5783
  video.className = "icen-ai-msg-media icen-ai-msg-media--video";
@@ -5694,7 +5789,7 @@ function renderAiContentPart(part) {
5694
5789
  if (part.type === "file") {
5695
5790
  const chip = h("span", "icen-ai-msg-file");
5696
5791
  chip.appendChild(h("span", "ai-msg-file-name", part.filename ?? t("aiChat.file")));
5697
- const href2 = part.url ? safeHref(part.url) : void 0;
5792
+ const href2 = part.url ? safeUrl(part.url) : void 0;
5698
5793
  if (href2 && /^(https?:|data:)/i.test(href2)) {
5699
5794
  const a2 = document.createElement("a");
5700
5795
  a2.className = "icen-ai-msg-file-link";
@@ -5707,7 +5802,7 @@ function renderAiContentPart(part) {
5707
5802
  }
5708
5803
  const a = document.createElement("a");
5709
5804
  a.className = "icen-ai-msg-link";
5710
- const href = safeHref(part.uri);
5805
+ const href = safeUrl(part.uri);
5711
5806
  if (href) a.href = href;
5712
5807
  a.textContent = part.name ?? part.uri;
5713
5808
  a.title = part.uri;
@@ -5769,7 +5864,7 @@ function renderAiMessage(scrollEl, model) {
5769
5864
  errEl.textContent = message;
5770
5865
  },
5771
5866
  stream() {
5772
- const span = h("span", "ai-msg-stream-text");
5867
+ const span = h("span", "icen-ai-msg-text ai-msg-stream-text");
5773
5868
  body.appendChild(span);
5774
5869
  return createAiStream(span);
5775
5870
  }
@@ -47,11 +47,11 @@ GitHub Primer 的语义色纪律、Radix Colors 的阶梯尺、Stripe 的"深档
47
47
  ### 2.1 圆角六档职责
48
48
  | 档 | 现代默认值(随 design-radius 联动) | 职责 |
49
49
  |---|---|---|
50
- | `xs` | 4px | 微型件内角:芯片、徽标、小标签 |
51
- | `sm` | 8px | 控件内嵌:按钮、输入框、小卡 |
52
- | `md` | 10px | 默认容器:卡片、面板、浮层 |
53
- | `lg` | 16px | 大容器:modal、工作台卡 |
54
- | `xl` | 24px | 页面级容器/展示面 |
50
+ | `xs` | 5px | 微型件内角:复选框、菜单项、日期格、小标签 |
51
+ | `sm` | 8px | 控件:按钮、输入框、选择器 |
52
+ | `md` | 10px | 内嵌块、大控件 |
53
+ | `lg` | 14px | 卡片、面板、菜单与 popover |
54
+ | `xl` | 20px | 弹窗与页面级展示面 |
55
55
  | `full` | 999px | **胶囊语义专用**(跑道形) |
56
56
 
57
57
  ### 2.2 同心圆法则(Concentric Corners,取法 Apple HIG)
@@ -22,7 +22,7 @@
22
22
 
23
23
  1. **作者种子** `--icen-design-*`:品牌色、表面、文字、几何、节奏、字体、材料参数。
24
24
  2. **语义映射**:推导已有 `--icen-token-* / --icen-radius-* / --icen-density-*`,让现有组件受益。
25
- 3. **材料角色**:content / chrome / floating,共享边缘、模糊和阴影配方。
25
+ 3. **材料角色**:content / chrome / floating,共享边缘、实面和阴影配方。
26
26
  4. **组件适配**:按钮、输入、分段选择、菜单、弹窗等,处理仅靠变量无法表达的细节。
27
27
 
28
28
  现代主题为中性瓷白+冷蓝,独立校准,不继承其它主题的配色。
@@ -40,12 +40,12 @@
40
40
  | 角色 | 背景 | 光与影 | 用途 |
41
41
  | --- | --- | --- | --- |
42
42
  | content | 不透明 | 轻边界,不投影 | 阅读与编辑 |
43
- | chrome | 条件启用透光 | 顶部微光 | 导航与操作 |
44
- | floating | 条件启用透光 | 接触影+环境影+顶部微光 | 临时面板 |
43
+ | chrome | 不透明 | 顶部微光 | 导航与操作 |
44
+ | floating | 不透明 | 接触影+环境影+顶部微光 | 临时面板 |
45
45
 
46
46
  布局、定位和内边距归业务页面。材料不携带固定宽高,不强行让所有内容成为卡片。`data-icen-material` 的通用外轮廓使用 lg 圆角;需要贴边的站栏可由布局覆盖。
47
47
 
48
- 透明度只在支持 backdrop-filter 的浏览器中启用,否则自动使用不透明表面。`prefers-reduced-transparency: reduce` 与 `<html data-icen-transparency="reduced">` 都强制不透明。透明表面的实际对比度依赖背后内容,仍需实屏验证。
48
+ modern 的内容、操作与临时面板始终使用不透明表面,不启用背景模糊。`glass-*` 参数保留供自有材料和既有品牌配方兼容使用;不会让 modern 的标准操作面变成玻璃。`prefers-reduced-transparency: reduce` 与 `<html data-icen-transparency="reduced">` 继续提供跨原语的实面降级。
49
49
 
50
50
  ## 修改与新增品牌
51
51
 
@@ -115,9 +115,9 @@ setDesign(brand.name);
115
115
  | success / warning / error / info | 明暗各有独立值,见源码 | 语义色 |
116
116
  | radius | 10px | 六档轮廓的共同起点 |
117
117
  | space | 4px | 布局节奏单位 |
118
- | control-height | 40px | 标准操作高度 |
119
- | font-size / font | 14px / 系统无衬线 | 界面阅读基准 |
120
- | glass-opacity / glass-blur | 82% / 20px;88% / 20px | 操作层材料 |
118
+ | control-height | 34px | 标准操作高度(density compact 28 / comfortable 38) |
119
+ | font-size / font | 13px / 系统无衬线 | 界面阅读基准;中文下限 12px |
120
+ | glass-opacity / glass-blur | 84% / 24px;90% / 24px | 自有材料的兼容参数,modern 标准组件不消费模糊 |
121
121
  | shadow-color / shadow-strength | 中性灰 11%;黑 28% | 接触影与环境影 |
122
122
  | light / highlight-strength | 白 70%;白 9% | 表面边缘光 |
123
123
  | edge-strength | 12% / 14% | 材料边界 |
@@ -128,8 +128,8 @@ CSS 作者可以直接覆盖全部种子;类型 API 暴露常用旋钮,并
128
128
  ## 现代的具体判断
129
129
 
130
130
  - **文字**:界面系统无衬线;代码单独等宽;数据才使用 tabular-nums。取消全局 Numeric Math 混排。正文阅读可在业务排版中提高到 16px。
131
- - **几何**:xs/sm/md/lg/xl 从共同控件半径推导;贴合内外轮廓同心,独立控件保留自身半径。分段选择内角扣掉外壳 padding 与边框。
132
- - **密度**:normal / compact / comfortable 改变间距和控件高度,不缩小文字;嵌套密度可恢复 normal。触摸环境控件至少 44px。
131
+ - **几何**:xs/sm/md/lg/xl 为 5/8/10/14/20px,从共同基准推导。控件 8px、卡片与面板 14px、弹窗 20px;贴合内外轮廓同心,独立控件保留自身半径。分段选择内角扣掉外壳 padding 与边框。
132
+ - **密度**:normal / compact / comfortable 改变间距和控件高度,不缩小文字;嵌套密度可恢复 normal。触摸环境控件至少 44px。KB 行内操作使用 `--icen-density-item-height`(normal 28 / compact 24 / comfortable 32px),嵌套密度重新计算字号角色。
133
133
  - **反馈**:hover 以中性变化为主,主要动作用品牌色;键盘焦点始终明确。按压轻缩放,减少位置漂移。
134
134
  - **选择**:分段选择使用中性表面和接触影,不把每次选择都变成品牌强调。
135
135
  - **光照**:暗色保留遮挡阴影,降低高光并重新设置边缘,避免照搬亮色投影。
@@ -149,7 +149,7 @@ CSS 作者可以直接覆盖全部种子;类型 API 暴露常用旋钮,并
149
149
 
150
150
  运行时使用 `setPrimitive("pixel")`;自建原语先 `registerPrimitive("brand-shape")`,再用 `[data-icen-style="brand-shape"]` 覆盖几何、字体、光影参数。主题仍单独由 setTheme({preset:...}) 选择。
151
151
 
152
- Apple 研究参考:[Materials](https://developer.apple.com/design/human-interface-guidelines/materials)、[Meet Liquid Glass](https://developer.apple.com/videos/play/wwdc2025/219/)。现代实现以内容/操作分层、同心几何、文字可读性为准则;Web 材料不是系统 Liquid Glass 的光学模拟。
152
+ 现代实现以内容/操作分层、同心几何、文字可读性为准则;使用稳定实面、细边与接触影建立空间。
153
153
 
154
154
  ## 中式与苏式原语
155
155
 
@@ -0,0 +1,46 @@
1
+ # 滚动条
2
+
3
+ 全局使用原生滚动条,不替换滚动容器、不拦截滚轮、不模拟滑块。Chromium/WebKit 使用统一无箭头样式;Firefox 使用标准细滚动条,具体几何由浏览器和系统控制。浏览器、系统或强制颜色模式的可访问性设置可覆盖皮肤。
4
+
5
+ 标准 `scrollbar-color` / `scrollbar-width` 的非 auto 值会覆盖 WebKit 伪元素皮肤,因此支持伪元素的浏览器使用 auto 值以保留无箭头规则;其余浏览器使用标准属性回退。参考 [MDN scrollbar-color](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/scrollbar-color) 与 [WebKit 滚动条说明](https://webkit.org/blog/363/styling-scrollbars/)。
6
+
7
+ 全量引入 `@icen.ai/ui/ui.css` 即包含样式。按需引入时使用 `tokens.css` + `base.css`,再加需要的组件 CSS;`kit/scroll-area` 导出行为和容器样式,仍需上述全局底座。只引 CSS 时保持可见。启用闲置策略:
8
+
9
+ ```ts
10
+ import { initScrollArea } from '@icen.ai/ui/behaviors/scroll-area';
11
+ const dispose = initScrollArea(); // 文档委托,接管之后插入的原生滚动区与 portal
12
+ // 或 initScrollArea({ root: element, idleDelay: 1200 })
13
+ // 卸载时 dispose():移除监听、清理定时器并恢复状态属性
14
+ ```
15
+
16
+ | `data-icen-scrollbars` | 滚动时 | 悬停时 | 聚焦时 | 闲置后 |
17
+ | --- | --- | --- | --- | --- |
18
+ | `auto` | 显示 | 容器悬停时显示 | 显示 | 指针离开且失焦后隐藏 |
19
+ | `scroll`(启用行为后的默认) | 显示 | 不唤醒 | 显示 | 未聚焦时隐藏 |
20
+ | `visible` | 显示 | 显示 | 显示 | 显示 |
21
+ | `hidden` | 隐藏 | 隐藏 | 隐藏 | 隐藏,仍可滚动 |
22
+
23
+ 策略在子树继承,嵌套组件可另设模式。默认 scroll 下,指针停在内容区不阻止闲置隐藏;菜单等需要悬停时保持可见的区域可显式使用 auto。文档根滚动条不因整页悬停一直亮起。无溢出时浏览器不绘制滑块。闲置策略只改变颜色,不反复增减宽度,因此停止滚动时不会造成内容跳动。`hidden` 会取消滚动条占位,适合已有其他导航提示的区域。需要持续位置提示时用 visible。需要直接键盘滚动的普通容器应提供 `tabindex="0"` 和名称。
24
+
25
+ ```html
26
+ <div class="icen-scroll-area" tabindex="0" aria-label="运行日志"
27
+ data-icen-scrollbars="scroll" data-icen-scrollbar-delay="1200"
28
+ data-icen-scrollbar-gutter="stable"
29
+ style="max-height:20rem; --icen-token-scrollbar-size:10px">
30
+ …
31
+ </div>
32
+ ```
33
+
34
+ | 局部控制槽 | 默认 | 用途 |
35
+ | --- | --- | --- |
36
+ | `--icen-token-scrollbar-size` | 8px | 双轴尺寸;`--sm` 6px、`--lg` 12px |
37
+ | `--icen-token-scrollbar-inset` | 2px | 滑块与槽边的透明内距 |
38
+ | `--icen-token-scrollbar-track` | transparent | 轨道颜色 |
39
+ | `--icen-token-scrollbar-thumb` / `-thumb-hover` | 当前主题墨色混合 | 默认/悬停滑块颜色 |
40
+ | `--icen-token-scrollbar-idle-delay` | 900ms | 停止滚动多久后隐藏 |
41
+ | `--icen-token-scrollbar-fade-duration` | normal 动效时长 | 支持原生滑块颜色过渡的浏览器使用;其他环境直接隐藏 |
42
+ | `--icen-token-scrollbar-gutter` | auto | 原生留槽策略 |
43
+
44
+ 延时优先级:最近祖先的 `data-icen-scrollbar-delay`(毫秒)→ `idleDelay` 参数 → CSS token。运行时读取当前值,修改后下一次滚动生效。非法延时回退 900ms,范围限制为 0–60000ms。留槽也可用 `data-icen-scrollbar-gutter="auto|stable|both-edges"`,与是否显示滑块独立。
45
+
46
+ 减少动效时禁用颜色过渡,保留延时显示/隐藏;强制颜色模式恢复系统可见滚动条。原生控件内部、跨源 iframe 与 Shadow DOM 的封闭内部由其宿主控制;如需开放影子树内的滚动活动跟踪,应在内部容器单独初始化。
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@icen.ai/ui",
3
- "version": "0.10.0",
4
- "description": "Icen Design System — 设计 tokens(8 主题 × 4 原语 × 明暗)+ 无框架组件 CSS/行为 JS + AI 原生组件族(7 态状态机/多模态/定价审计)+ 图表通用层(ChartSpec 纯 JSON)+ AI 工具体系",
3
+ "version": "0.11.0",
4
+ "description": "Icen Design System — 设计 tokens(6 主题 × 4 原语 × 明暗)+ 无框架组件 CSS/行为 JS + AI 原生组件族(7 态状态机/多模态/定价审计)+ 图表通用层(ChartSpec 纯 JSON)+ AI 工具体系",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/icen-ai/ui.git"
@@ -28,6 +28,10 @@
28
28
  "sideEffects": [
29
29
  "**/*.css"
30
30
  ],
31
+ "engines": {
32
+ "node": ">=18"
33
+ },
34
+ "packageManager": "bun@1.3.5",
31
35
  "peerDependencies": {
32
36
  "react": ">=18",
33
37
  "react-dom": ">=18",
@@ -58,14 +62,22 @@
58
62
  "dtcg": "bun scripts/dtcg.mjs",
59
63
  "design-tokens": "bun scripts/design-tokens.mjs",
60
64
  "guard": "bun scripts/guard/index.ts",
65
+ "contracts": "bun scripts/contracts.ts --check",
66
+ "contracts:update": "bun scripts/contracts.ts --write",
67
+ "contracts:diff": "bun scripts/contracts.ts --diff",
68
+ "size": "bun scripts/size.ts",
69
+ "check:pkg": "bunx publint && bunx @arethetypeswrong/cli --pack . --ignore-rules no-resolution cjs-resolves-to-esm",
61
70
  "prepublishOnly": "bun run build",
62
71
  "pretest:e2e": "cd site && bun run build",
63
72
  "test": "bun test",
73
+ "test:coverage": "bun scripts/coverage.ts",
64
74
  "test:e2e": "playwright test",
65
- "verify": "bunx tsc --noEmit && bun run guard && bun test && bun run build",
75
+ "test:e2e:update": "playwright test --update-snapshots",
76
+ "verify": "bunx tsc --noEmit && bun run guard && bun test && bun run build && bun run size",
66
77
  "colors": "bun scripts/theme-colors.mjs"
67
78
  },
68
79
  "devDependencies": {
80
+ "@arethetypeswrong/cli": "^0.18.5",
69
81
  "@happy-dom/global-registrator": "^20.14.5",
70
82
  "@playwright/test": "^1.63.0",
71
83
  "@types/node": "^20.14.0",
@@ -73,6 +85,7 @@
73
85
  "@types/react-dom": "^19.3.0",
74
86
  "axe-core": "^4.14.0",
75
87
  "happy-dom": "^20.14.5",
88
+ "publint": "^0.3.25",
76
89
  "react": "^19.3.0",
77
90
  "react-dom": "^19.3.0",
78
91
  "tsup": "^8.3.0",