@icen.ai/ui 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/AGENTS.md +138 -80
  2. package/README.md +66 -91
  3. package/dist/base.css +208 -179
  4. package/dist/behaviors/accordion.mjs +8 -8
  5. package/dist/behaviors/ai-branch.d.mts +1 -1
  6. package/dist/behaviors/ai-branch.mjs +1010 -94
  7. package/dist/behaviors/ai-chat.d.mts +7 -7
  8. package/dist/behaviors/ai-chat.mjs +1071 -161
  9. package/dist/behaviors/ai-composer.d.mts +44 -12
  10. package/dist/behaviors/ai-composer.mjs +1997 -524
  11. package/dist/behaviors/ai-core.d.mts +1 -1
  12. package/dist/behaviors/ai-core.mjs +1016 -107
  13. package/dist/behaviors/ai-diff.mjs +1019 -127
  14. package/dist/behaviors/ai-feedback.d.mts +1 -1
  15. package/dist/behaviors/ai-feedback.mjs +1035 -126
  16. package/dist/behaviors/ai-panel.d.mts +8 -8
  17. package/dist/behaviors/ai-panel.mjs +1284 -266
  18. package/dist/behaviors/ai-provider.mjs +1003 -101
  19. package/dist/behaviors/ai-threads.d.mts +1 -1
  20. package/dist/behaviors/ai-threads.mjs +1068 -154
  21. package/dist/behaviors/ai-tool.d.mts +2 -2
  22. package/dist/behaviors/ai-tool.mjs +2037 -396
  23. package/dist/behaviors/ai-tools.d.mts +89 -16
  24. package/dist/behaviors/ai-tools.mjs +4448 -372
  25. package/dist/behaviors/autocomplete.d.mts +53 -0
  26. package/dist/behaviors/autocomplete.mjs +1600 -0
  27. package/dist/behaviors/back-top.d.mts +1 -1
  28. package/dist/behaviors/back-top.mjs +951 -14
  29. package/dist/behaviors/carousel.d.mts +1 -1
  30. package/dist/behaviors/carousel.mjs +906 -11
  31. package/dist/behaviors/cascader.d.mts +48 -0
  32. package/dist/behaviors/cascader.mjs +1853 -0
  33. package/dist/behaviors/charts.d.mts +72 -8
  34. package/dist/behaviors/charts.mjs +1901 -256
  35. package/dist/behaviors/code-block.d.mts +36 -0
  36. package/dist/behaviors/code-block.mjs +1611 -0
  37. package/dist/behaviors/command-palette.d.mts +9 -6
  38. package/dist/behaviors/command-palette.mjs +161 -59
  39. package/dist/behaviors/context-menu.d.mts +9 -8
  40. package/dist/behaviors/context-menu.mjs +1112 -44
  41. package/dist/behaviors/controls.d.mts +13 -13
  42. package/dist/behaviors/controls.mjs +989 -130
  43. package/dist/behaviors/copy.d.mts +21 -2
  44. package/dist/behaviors/copy.mjs +1206 -42
  45. package/dist/behaviors/datatable.d.mts +53 -3
  46. package/dist/behaviors/datatable.mjs +1963 -207
  47. package/dist/behaviors/date-picker.d.mts +0 -1
  48. package/dist/behaviors/date-picker.mjs +1340 -293
  49. package/dist/behaviors/design.d.mts +54 -0
  50. package/dist/behaviors/design.mjs +109 -0
  51. package/dist/behaviors/dropdown.d.mts +5 -6
  52. package/dist/behaviors/dropdown.mjs +262 -110
  53. package/dist/behaviors/events.d.mts +120 -3
  54. package/dist/behaviors/events.mjs +47 -2
  55. package/dist/behaviors/feedback.d.mts +30 -0
  56. package/dist/behaviors/feedback.mjs +296 -0
  57. package/dist/behaviors/focus.d.mts +8 -0
  58. package/dist/behaviors/focus.mjs +24 -0
  59. package/dist/behaviors/form-validate.d.mts +102 -0
  60. package/dist/behaviors/form-validate.mjs +6091 -0
  61. package/dist/behaviors/i18n.d.mts +789 -0
  62. package/dist/behaviors/i18n.mjs +1711 -0
  63. package/dist/behaviors/icons.d.mts +93 -0
  64. package/dist/behaviors/icons.mjs +113 -0
  65. package/dist/behaviors/input.d.mts +9 -1
  66. package/dist/behaviors/input.mjs +1056 -60
  67. package/dist/behaviors/kb-access.d.mts +1 -1
  68. package/dist/behaviors/kb-access.mjs +2129 -239
  69. package/dist/behaviors/kb-acl.d.mts +6 -6
  70. package/dist/behaviors/kb-acl.mjs +1119 -179
  71. package/dist/behaviors/kb-answer.mjs +2070 -418
  72. package/dist/behaviors/kb-audit.d.mts +1 -1
  73. package/dist/behaviors/kb-audit.mjs +1076 -154
  74. package/dist/behaviors/kb-canvas.mjs +1100 -177
  75. package/dist/behaviors/kb-chain.mjs +1022 -100
  76. package/dist/behaviors/kb-checkpoint.d.mts +1 -1
  77. package/dist/behaviors/kb-checkpoint.mjs +1319 -169
  78. package/dist/behaviors/kb-chunks.mjs +1152 -213
  79. package/dist/behaviors/kb-citation.d.mts +1 -1
  80. package/dist/behaviors/kb-citation.mjs +1201 -179
  81. package/dist/behaviors/kb-clarify.mjs +1058 -130
  82. package/dist/behaviors/kb-conflict.mjs +1041 -119
  83. package/dist/behaviors/kb-connector.mjs +1104 -176
  84. package/dist/behaviors/kb-core.d.mts +6 -1
  85. package/dist/behaviors/kb-core.mjs +1077 -162
  86. package/dist/behaviors/kb-eval.mjs +1971 -144
  87. package/dist/behaviors/kb-explain.d.mts +1 -1
  88. package/dist/behaviors/kb-explain.mjs +1024 -102
  89. package/dist/behaviors/kb-filter.mjs +2008 -178
  90. package/dist/behaviors/kb-gap.d.mts +1 -1
  91. package/dist/behaviors/kb-gap.mjs +1043 -121
  92. package/dist/behaviors/kb-hittest.d.mts +1 -1
  93. package/dist/behaviors/kb-hittest.mjs +1093 -150
  94. package/dist/behaviors/kb-metadata.mjs +1052 -130
  95. package/dist/behaviors/kb-passage.d.mts +2 -2
  96. package/dist/behaviors/kb-passage.mjs +1101 -161
  97. package/dist/behaviors/kb-pipeline.d.mts +2 -2
  98. package/dist/behaviors/kb-pipeline.mjs +1082 -162
  99. package/dist/behaviors/kb-qa.mjs +1088 -160
  100. package/dist/behaviors/kb-rerank.mjs +1047 -114
  101. package/dist/behaviors/kb-retrieval.mjs +2063 -224
  102. package/dist/behaviors/kb-review.mjs +1990 -159
  103. package/dist/behaviors/kb-sandbox.d.mts +1 -1
  104. package/dist/behaviors/kb-sandbox.mjs +1026 -104
  105. package/dist/behaviors/kb-segment.mjs +1111 -179
  106. package/dist/behaviors/kb-select.d.mts +24 -0
  107. package/dist/behaviors/kb-select.mjs +1989 -0
  108. package/dist/behaviors/kb-sources.d.mts +1 -1
  109. package/dist/behaviors/kb-sources.mjs +1084 -170
  110. package/dist/behaviors/kb-sql.d.mts +1 -1
  111. package/dist/behaviors/kb-sql.mjs +1143 -226
  112. package/dist/behaviors/kb-trace.d.mts +1 -1
  113. package/dist/behaviors/kb-trace.mjs +1042 -128
  114. package/dist/behaviors/kb-visibility.mjs +1086 -158
  115. package/dist/behaviors/kb-who-can.mjs +1974 -137
  116. package/dist/behaviors/mentions.d.mts +93 -0
  117. package/dist/behaviors/mentions.mjs +2152 -0
  118. package/dist/behaviors/modal.d.mts +4 -3
  119. package/dist/behaviors/modal.mjs +1055 -33
  120. package/dist/behaviors/nav.d.mts +1 -1
  121. package/dist/behaviors/nav.mjs +6 -6
  122. package/dist/behaviors/notification.d.mts +16 -8
  123. package/dist/behaviors/notification.mjs +1615 -265
  124. package/dist/behaviors/panel.d.mts +4 -0
  125. package/dist/behaviors/panel.mjs +994 -0
  126. package/dist/behaviors/popover.d.mts +28 -5
  127. package/dist/behaviors/popover.mjs +225 -24
  128. package/dist/behaviors/select.d.mts +5 -2
  129. package/dist/behaviors/select.mjs +1410 -117
  130. package/dist/behaviors/sidebar.d.mts +1 -1
  131. package/dist/behaviors/sidebar.mjs +13 -13
  132. package/dist/behaviors/slider.d.mts +1 -1
  133. package/dist/behaviors/slider.mjs +9 -9
  134. package/dist/behaviors/split-pane.d.mts +1 -1
  135. package/dist/behaviors/split-pane.mjs +7 -7
  136. package/dist/behaviors/suggestions.d.mts +27 -0
  137. package/dist/behaviors/suggestions.mjs +1089 -0
  138. package/dist/behaviors/svg-parse.d.mts +14 -0
  139. package/dist/behaviors/svg-parse.mjs +37 -0
  140. package/dist/behaviors/tabs.d.mts +2 -2
  141. package/dist/behaviors/tabs.mjs +25 -25
  142. package/dist/behaviors/tag-input.d.mts +23 -5
  143. package/dist/behaviors/tag-input.mjs +1359 -104
  144. package/dist/behaviors/theme-switcher.d.mts +24 -0
  145. package/dist/behaviors/theme-switcher.mjs +1981 -0
  146. package/dist/behaviors/theme.d.mts +15 -8
  147. package/dist/behaviors/theme.mjs +390 -28
  148. package/dist/behaviors/toast.d.mts +24 -25
  149. package/dist/behaviors/toast.mjs +1266 -88
  150. package/dist/behaviors/tooltip.d.mts +4 -0
  151. package/dist/behaviors/tooltip.mjs +378 -0
  152. package/dist/behaviors/tree-select.d.mts +69 -0
  153. package/dist/behaviors/tree-select.mjs +1907 -0
  154. package/dist/behaviors/tree.d.mts +1 -1
  155. package/dist/behaviors/tree.mjs +15 -15
  156. package/dist/behaviors/upload.d.mts +3 -2
  157. package/dist/behaviors/upload.mjs +1076 -66
  158. package/dist/cli.mjs +5 -6
  159. package/dist/components/ai-chat.css +666 -573
  160. package/dist/components/ai-diff.css +153 -132
  161. package/dist/components/ai-panel.css +351 -343
  162. package/dist/components/ai-tool.css +393 -238
  163. package/dist/components/autocomplete.css +61 -0
  164. package/dist/components/autocomplete.mjs +3 -0
  165. package/dist/components/back-top.css +34 -31
  166. package/dist/components/badge.css +44 -41
  167. package/dist/components/breadcrumb.css +67 -46
  168. package/dist/components/btn.css +80 -74
  169. package/dist/components/card.css +117 -106
  170. package/dist/components/cascader.css +311 -0
  171. package/dist/components/cascader.mjs +3 -0
  172. package/dist/components/chart-area.css +8 -2
  173. package/dist/components/chart-bar.css +95 -33
  174. package/dist/components/chart-gauge.css +14 -11
  175. package/dist/components/chart-graph.css +20 -17
  176. package/dist/components/chart-heatmap.css +96 -90
  177. package/dist/components/chart-line.css +8 -3
  178. package/dist/components/chart-pie.css +9 -6
  179. package/dist/components/chart-radar.css +8 -5
  180. package/dist/components/chart-scatter.css +9 -6
  181. package/dist/components/chart-sparkline.css +5 -2
  182. package/dist/components/chart-stack.css +14 -11
  183. package/dist/components/charts.css +164 -73
  184. package/dist/components/code-block.css +418 -0
  185. package/dist/components/code-block.mjs +4 -0
  186. package/dist/components/command-palette.css +138 -117
  187. package/dist/components/content.css +257 -251
  188. package/dist/components/copy.css +72 -44
  189. package/dist/components/datatable.css +423 -181
  190. package/dist/components/date-picker.css +135 -104
  191. package/dist/components/empty.css +68 -65
  192. package/dist/components/feedback.css +201 -183
  193. package/dist/components/form-validate.css +120 -0
  194. package/dist/components/form-validate.mjs +3 -0
  195. package/dist/components/form.css +150 -127
  196. package/dist/components/icon.css +102 -0
  197. package/dist/components/icon.mjs +3 -0
  198. package/dist/components/input.css +159 -104
  199. package/dist/components/kb-agent.css +188 -173
  200. package/dist/components/kb-data.css +257 -253
  201. package/dist/components/kb-ground.css +197 -185
  202. package/dist/components/kb-ingest.css +334 -350
  203. package/dist/components/kb-ops.css +265 -259
  204. package/dist/components/kb-perm.css +260 -271
  205. package/dist/components/kb-search.css +317 -360
  206. package/dist/components/kb.css +120 -109
  207. package/dist/components/layout.css +85 -82
  208. package/dist/components/material-chinese.css +73 -0
  209. package/dist/components/material-soviet.css +76 -0
  210. package/dist/components/material.css +275 -0
  211. package/dist/components/media.css +220 -166
  212. package/dist/components/mentions.css +189 -0
  213. package/dist/components/mentions.mjs +3 -0
  214. package/dist/components/menu.css +113 -105
  215. package/dist/components/modal.css +107 -112
  216. package/dist/components/nav.css +118 -115
  217. package/dist/components/notification.css +238 -174
  218. package/dist/components/pagination.css +56 -53
  219. package/dist/components/panel.css +66 -63
  220. package/dist/components/panel.mjs +1 -0
  221. package/dist/components/pill.css +81 -71
  222. package/dist/components/popover.css +67 -53
  223. package/dist/components/scroll-area.css +113 -110
  224. package/dist/components/segmented.css +146 -143
  225. package/dist/components/select.css +206 -186
  226. package/dist/components/sidebar.css +137 -127
  227. package/dist/components/slider.css +117 -114
  228. package/dist/components/split-pane.css +112 -109
  229. package/dist/components/stat.css +112 -106
  230. package/dist/components/steps.css +109 -103
  231. package/dist/components/switch.css +138 -134
  232. package/dist/components/table.css +131 -107
  233. package/dist/components/tabs.css +114 -108
  234. package/dist/components/tag-input.css +48 -133
  235. package/dist/components/tag.css +81 -71
  236. package/dist/components/theme-switcher.css +105 -0
  237. package/dist/components/theme-switcher.mjs +3 -0
  238. package/dist/components/toast.css +100 -86
  239. package/dist/components/toolbar.css +45 -42
  240. package/dist/components/tooltip.css +102 -43
  241. package/dist/components/tooltip.mjs +1 -0
  242. package/dist/components/tree-select.css +416 -0
  243. package/dist/components/tree-select.mjs +3 -0
  244. package/dist/components/upload.css +135 -92
  245. package/dist/fonts/LICENSES/ark-pixel/OFL.txt +96 -0
  246. package/dist/fonts/LICENSES/cubic-11/OFL.txt +108 -0
  247. package/dist/fonts/LICENSES/galmuri/LICENSE.txt +93 -0
  248. package/dist/fonts/OFL.txt +96 -0
  249. package/dist/fonts/README.md +14 -0
  250. package/dist/fonts/fusion-pixel-12px-zh-hans.woff2 +0 -0
  251. package/dist/index.d.mts +28 -14
  252. package/dist/index.mjs +20705 -9601
  253. package/dist/react.d.mts +91 -0
  254. package/dist/react.mjs +8208 -0
  255. package/dist/registry.json +130 -13
  256. package/dist/tokens/chinese.css +44 -0
  257. package/dist/tokens/colors.css +365 -1222
  258. package/dist/tokens/design.css +109 -0
  259. package/dist/tokens/dtcg.json +11198 -0
  260. package/dist/tokens/figma.variables.json +7017 -0
  261. package/dist/tokens/icon-masks.css +78 -0
  262. package/dist/tokens/pixel.css +50 -0
  263. package/dist/tokens/soviet.css +44 -0
  264. package/dist/tokens/style-profiles.css +36 -547
  265. package/dist/tokens/themes.json +308 -0
  266. package/dist/tokens/tokens-studio.json +6728 -0
  267. package/dist/tokens/typography.css +21 -18
  268. package/dist/tokens.css +1555 -1801
  269. package/dist/ui.css +11975 -9831
  270. package/dist/vue.d.mts +344 -0
  271. package/dist/vue.mjs +7781 -0
  272. package/docs/spec/ai-input-experience.md +75 -0
  273. package/docs/spec/ai-native.md +238 -147
  274. package/docs/spec/design-philosophy.md +189 -0
  275. package/docs/spec/design-primitives.md +196 -0
  276. package/docs/spec/kb-family.md +147 -115
  277. package/package.json +43 -8
  278. package/dist/retro-effects.css +0 -255
  279. package/dist/tokens/retro-effects.css +0 -255
  280. package/docs/research/2026-10-03-ai-kb-components.md +0 -392
  281. package/docs/research/2026-10-03-kb-permissions.md +0 -992
@@ -1,21 +1,26 @@
1
+ /** Theme = palette + dark mode + primitive. 现代、像素、中式、苏式 are independent primitives.
2
+ * data-icen-preset selects color; data-icen-style selects the primitive.
3
+ * Geometry/materials never replace the selected color theme. */
1
4
  interface ThemeState {
2
5
  preset: string;
3
6
  dark: boolean;
4
7
  style: string;
5
8
  }
6
- declare const PRESETS: readonly ["clay", "piano", "art", "vangogh", "ink", "retro"];
7
- declare const STYLES: readonly ["modern", "retro", "terminal"];
9
+ declare const PRESETS: string[];
10
+ declare const PRIMITIVES: readonly ["modern", "chinese", "soviet", "pixel"];
11
+ declare function registerPrimitive(name: string): boolean;
12
+ declare function listPrimitives(): string[];
8
13
  declare const STORAGE_KEY = "icen.ui.theme";
9
14
  /**
10
- * 注册宿主自建预设(宿主先在自家 CSS 写好 `.<name>` 与 `.<name>.dark` 完整 token 面,
11
- * 仿照 colors.css 现有 6 套)。名字须命中 /^[a-z][a-z0-9-]{1,20}$/ 且不与
15
+ * 注册宿主自建预设(宿主先在自家 CSS 写好 `.<name>` 与 `.<name>[data-icen-theme="dark"]` 完整 token 面,
16
+ * 仿照 colors.css 的既有主题)。名字须命中 /^[a-z][a-z0-9-]{1,20}$/ 且不与
12
17
  * dark / style-* 保留字冲突;注册只影响 listThemePresets() 枚举(UI 切换器用),
13
18
  * 不注册的自建预设同样可以 setTheme(校验同样放行)。返回是否接受注册。
14
19
  */
15
20
  declare function registerThemePreset(name: string): boolean;
16
21
  /** 全部可用预设名:内置 6 套 + 已注册的自建预设(UI 切换器枚举用,顺序稳定)。 */
17
22
  declare function listThemePresets(): string[];
18
- /** 默认主题:clay + 跟随系统明暗 + modern。SSR 下返回离线兜底值。 */
23
+ /** 默认主题:现代主题 + 跟随系统明暗 + 现代原语。SSR 下返回离线兜底值。 */
19
24
  declare function getDefaultTheme(): ThemeState;
20
25
  /** 读 localStorage 中的持久化主题;缺失或坏数据回退默认。 */
21
26
  declare function getTheme(): ThemeState;
@@ -23,14 +28,16 @@ declare function getTheme(): ThemeState;
23
28
  declare function applyTheme(t: ThemeState): void;
24
29
  /** 合并当前主题与 patch,应用并持久化,返回新态。patch 中的非法枚举值回退默认。 */
25
30
  declare function setTheme(patch: Partial<ThemeState>): ThemeState;
31
+ /** 当前实际生效的外观;applyTheme 或存储不可写时仍准确。getTheme 专门读取持久化偏好。 */
32
+ declare function getCurrentTheme(): ThemeState;
26
33
  /** 切换明暗,返回新态。 */
27
34
  declare function toggleDark(): ThemeState;
28
- /** 只切风格 profile(modern / retro / terminal;非法值回退 modern),返回新态。 */
29
- declare function setStyle(style: string): ThemeState;
35
+ /** 只切原语(现代 / 中式 / 苏式 / 像素;非法值回退现代),返回新态。 */
36
+ declare function setPrimitive(primitive: string): ThemeState;
30
37
  /** 页面加载早期调用:读持久化主题并应用,防闪烁。
31
38
  * 无持久化偏好时,自动跟随系统的 prefers-color-scheme 变化(实时);
32
39
  * 一旦用户显式 setTheme / toggleDark,跟随停止(持久化优先)。
33
40
  * 重复调用幂等(系统监听不会重复挂)。 */
34
41
  declare function initTheme(): ThemeState;
35
42
 
36
- export { PRESETS, STORAGE_KEY, STYLES, type ThemeState, applyTheme, getDefaultTheme, getTheme, initTheme, listThemePresets, registerThemePreset, setStyle, setTheme, toggleDark };
43
+ export { PRESETS, PRIMITIVES, STORAGE_KEY, type ThemeState, applyTheme, getCurrentTheme, getDefaultTheme, getTheme, initTheme, listPrimitives, listThemePresets, registerPrimitive, registerThemePreset, setPrimitive, setTheme, toggleDark };
@@ -1,3 +1,313 @@
1
+ // src/tokens/themes.json
2
+ var themes_default = [
3
+ {
4
+ id: "modern",
5
+ name: "\u73B0\u4EE3",
6
+ label: "\u73B0\u4EE3",
7
+ summary: "\u74F7\u767D\u4E0E\u51B7\u84DD\uFF0C\u8BA9\u5185\u5BB9\u6E05\u695A\uFF0C\u8BA9\u64CD\u4F5C\u8F7B\u76C8\u3002",
8
+ material: "\u6E05\u900F\u74F7\u9762 \xB7 \u51B7\u8C03\u67D4\u5149",
9
+ light: {
10
+ bg: "#f5f6f8",
11
+ surface: "#ffffff",
12
+ raised: "#edf0f5",
13
+ ink: "#202124",
14
+ muted: "#606773",
15
+ faint: "#626c79",
16
+ accent: "#087bf5",
17
+ accentStrong: "#0062cc",
18
+ accentText: "#0059b8",
19
+ onAccent: "#ffffff",
20
+ cold: "#58758f",
21
+ success: "#247347",
22
+ warning: "#846000",
23
+ error: "#b02d36",
24
+ info: "#336c91",
25
+ shadowColor: "#182337",
26
+ glassOpacity: 84,
27
+ shadowStrength: 10,
28
+ edgeStrength: 11,
29
+ highlightStrength: 76
30
+ },
31
+ dark: {
32
+ bg: "#15171b",
33
+ surface: "#22272f",
34
+ raised: "#2c333e",
35
+ ink: "#f1f4f9",
36
+ muted: "#b1bbca",
37
+ faint: "#9faabd",
38
+ accent: "#8cbdff",
39
+ accentStrong: "#91bfff",
40
+ accentText: "#9dc6ff",
41
+ onAccent: "#10223c",
42
+ cold: "#9bb4cb",
43
+ success: "#8bd3a6",
44
+ warning: "#e4c373",
45
+ error: "#f2a1a5",
46
+ info: "#97c8e8",
47
+ shadowColor: "#000000",
48
+ glassOpacity: 90,
49
+ shadowStrength: 27,
50
+ edgeStrength: 13,
51
+ highlightStrength: 8
52
+ }
53
+ },
54
+ {
55
+ id: "dongyun",
56
+ name: "\u4E1C\u97F5",
57
+ label: "dongyun \u4E1C\u97F5",
58
+ summary: "\u7EE2\u767D\u7559\u51FA\u547C\u5438\uFF0C\u9752\u74F7\u4E0E\u6C89\u58A8\u76F8\u6620\uFF0C\u6E29\u6DA6\u800C\u6709\u5206\u5BF8\u3002",
59
+ material: "\u7EE2\u672C\u4E0E\u9752\u74F7 \xB7 \u6E29\u6DA6\u7EC6\u5149",
60
+ light: {
61
+ bg: "#f4f1e9",
62
+ surface: "#fffdf7",
63
+ raised: "#e9e6db",
64
+ ink: "#293a34",
65
+ muted: "#60695c",
66
+ faint: "#626957",
67
+ accent: "#477668",
68
+ accentStrong: "#305c4e",
69
+ accentText: "#315748",
70
+ onAccent: "#fffdf7",
71
+ cold: "#85724d",
72
+ success: "#3b6544",
73
+ warning: "#795517",
74
+ error: "#a33e37",
75
+ info: "#426477",
76
+ shadowColor: "#343c2e",
77
+ glassOpacity: 97,
78
+ shadowStrength: 7,
79
+ edgeStrength: 14,
80
+ highlightStrength: 40
81
+ },
82
+ dark: {
83
+ bg: "#181e1b",
84
+ surface: "#242e28",
85
+ raised: "#334037",
86
+ ink: "#f0eee0",
87
+ muted: "#bfc8b6",
88
+ faint: "#b2bea9",
89
+ accent: "#a0c5ac",
90
+ accentStrong: "#b0d0b6",
91
+ accentText: "#bdd9c1",
92
+ onAccent: "#24382b",
93
+ cold: "#d0bd8d",
94
+ success: "#accd9e",
95
+ warning: "#e1c68d",
96
+ error: "#edada2",
97
+ info: "#accbda",
98
+ shadowColor: "#080e0a",
99
+ glassOpacity: 98,
100
+ shadowStrength: 25,
101
+ edgeStrength: 17,
102
+ highlightStrength: 5
103
+ }
104
+ },
105
+ {
106
+ id: "jugou",
107
+ name: "\u5DE8\u6784",
108
+ label: "jugou \u5DE8\u6784",
109
+ summary: "\u77F3\u7070\u767D\u3001\u94C1\u7070\u4E0E\u6DF1\u6731\u7EA2\uFF0C\u4EE5\u6E05\u695A\u7684\u7ED3\u6784\u6258\u4F4F\u6709\u5206\u91CF\u7684\u5185\u5BB9\u3002",
110
+ material: "\u6DF7\u51DD\u571F\u4E0E\u642A\u74F7 \xB7 \u5B9E\u4F53\u627F\u91CD",
111
+ light: {
112
+ bg: "#edece6",
113
+ surface: "#faf9f3",
114
+ raised: "#e1e0d8",
115
+ ink: "#252723",
116
+ muted: "#5e625b",
117
+ faint: "#62645b",
118
+ accent: "#b53c2d",
119
+ accentStrong: "#9e3025",
120
+ accentText: "#912e24",
121
+ onAccent: "#fffaf0",
122
+ cold: "#596d75",
123
+ success: "#3d6141",
124
+ warning: "#765413",
125
+ error: "#9a3138",
126
+ info: "#3c6078",
127
+ shadowColor: "#242821",
128
+ glassOpacity: 100,
129
+ shadowStrength: 16,
130
+ edgeStrength: 24,
131
+ highlightStrength: 20
132
+ },
133
+ dark: {
134
+ bg: "#1b1d1c",
135
+ surface: "#2a2e2c",
136
+ raised: "#393e3b",
137
+ ink: "#f4f0e3",
138
+ muted: "#c3c6ba",
139
+ faint: "#b8bdae",
140
+ accent: "#ed9d86",
141
+ accentStrong: "#f1ac92",
142
+ accentText: "#f6bba3",
143
+ onAccent: "#3c211b",
144
+ cold: "#b1c5ce",
145
+ success: "#aecb9f",
146
+ warning: "#e6c88b",
147
+ error: "#f0b1ad",
148
+ info: "#accbdc",
149
+ shadowColor: "#090d0b",
150
+ glassOpacity: 100,
151
+ shadowStrength: 38,
152
+ edgeStrength: 25,
153
+ highlightStrength: 4
154
+ }
155
+ },
156
+ {
157
+ id: "piano",
158
+ name: "\u94A2\u7434",
159
+ label: "piano \u94A2\u7434",
160
+ summary: "\u8C61\u7259\u767D\u4E0E\u4E4C\u6728\u9ED1\u4FDD\u6301\u4E3B\u6B21\uFF0C\u91D1\u68D5\u53EA\u843D\u5728\u5173\u952E\u52A8\u4F5C\u3002",
161
+ material: "\u8C61\u7259\u7434\u952E \xB7 \u4E4C\u6728\u4E0E\u6F06\u9762\u5FAE\u5149",
162
+ light: {
163
+ bg: "#f5f3ed",
164
+ surface: "#fffefb",
165
+ raised: "#ece8df",
166
+ ink: "#252522",
167
+ muted: "#69685f",
168
+ faint: "#6a675c",
169
+ accent: "#94713f",
170
+ accentStrong: "#765424",
171
+ accentText: "#72501f",
172
+ onAccent: "#fffefb",
173
+ cold: "#657386",
174
+ success: "#3d6e4b",
175
+ warning: "#805d17",
176
+ error: "#a53d39",
177
+ info: "#456984",
178
+ shadowColor: "#24231e",
179
+ glassOpacity: 89,
180
+ shadowStrength: 12,
181
+ edgeStrength: 14,
182
+ highlightStrength: 90
183
+ },
184
+ dark: {
185
+ bg: "#131416",
186
+ surface: "#222427",
187
+ raised: "#303338",
188
+ ink: "#f4f1e8",
189
+ muted: "#b8b5aa",
190
+ faint: "#aaa89e",
191
+ accent: "#d2b278",
192
+ accentStrong: "#d8ba85",
193
+ accentText: "#e3c48c",
194
+ onAccent: "#292215",
195
+ cold: "#a5b3c6",
196
+ success: "#a4cfb0",
197
+ warning: "#e2c57f",
198
+ error: "#e9aaa7",
199
+ info: "#a5c5e3",
200
+ shadowColor: "#000000",
201
+ glassOpacity: 93,
202
+ shadowStrength: 33,
203
+ edgeStrength: 17,
204
+ highlightStrength: 11
205
+ }
206
+ },
207
+ {
208
+ id: "monet",
209
+ name: "\u83AB\u5948",
210
+ label: "monet \u83AB\u5948",
211
+ summary: "\u6C34\u9762\u84DD\u7EFF\u53E0\u51FA\u67D4\u5149\uFF0C\u7D2B\u8C03\u542B\u84C4\uFF0C\u5B89\u9759\u800C\u4E0D\u5BE1\u6DE1\u3002",
212
+ material: "\u7761\u83B2\u6C34\u9762 \xB7 \u84DD\u7EFF\u67D4\u5149\u4E0E\u542B\u84C4\u7D2B\u8C03",
213
+ light: {
214
+ bg: "#f4f7f4",
215
+ surface: "#fcfdfb",
216
+ raised: "#e8eeea",
217
+ ink: "#20332e",
218
+ muted: "#5b6f65",
219
+ faint: "#5b6e64",
220
+ accent: "#2b675c",
221
+ accentStrong: "#245c50",
222
+ accentText: "#24574c",
223
+ onAccent: "#ffffff",
224
+ cold: "#667c8a",
225
+ success: "#307449",
226
+ warning: "#805f1b",
227
+ error: "#a43d42",
228
+ info: "#3d6a82",
229
+ shadowColor: "#23372f",
230
+ glassOpacity: 93,
231
+ shadowStrength: 8,
232
+ edgeStrength: 12,
233
+ highlightStrength: 52
234
+ },
235
+ dark: {
236
+ bg: "#121d1a",
237
+ surface: "#1d2d27",
238
+ raised: "#2c3d34",
239
+ ink: "#e6f0e7",
240
+ muted: "#a7c0b1",
241
+ faint: "#9cb1a4",
242
+ accent: "#93c9ad",
243
+ accentStrong: "#a0d2b7",
244
+ accentText: "#a5d8bd",
245
+ onAccent: "#173328",
246
+ cold: "#a1baca",
247
+ success: "#91d2a2",
248
+ warning: "#dac487",
249
+ error: "#e8a7ad",
250
+ info: "#9bc4da",
251
+ shadowColor: "#06100b",
252
+ glassOpacity: 95,
253
+ shadowStrength: 27,
254
+ edgeStrength: 14,
255
+ highlightStrength: 6
256
+ }
257
+ },
258
+ {
259
+ id: "vangogh",
260
+ name: "\u68B5\u9AD8",
261
+ label: "vangogh \u68B5\u9AD8",
262
+ summary: "\u65E5\u95F4\u662F\u9EA6\u7530\u91CC\u7684\u94B4\u84DD\uFF0C\u5165\u591C\u662F\u6DF1\u84DD\u4E0A\u7684\u661F\u5149\u91D1\u3002",
263
+ material: "\u4E9A\u9EBB\u753B\u5E03 \xB7 \u94B4\u84DD\u4E0E\u9EA6\u7A57\u91D1",
264
+ light: {
265
+ bg: "#f8f3e4",
266
+ surface: "#fffdf3",
267
+ raised: "#efe5c9",
268
+ ink: "#253650",
269
+ muted: "#5c6580",
270
+ faint: "#5e667b",
271
+ accent: "#275ea0",
272
+ accentStrong: "#224e83",
273
+ accentText: "#234c7b",
274
+ onAccent: "#fffdf3",
275
+ cold: "#a0711e",
276
+ success: "#416b3a",
277
+ warning: "#855a15",
278
+ error: "#a83c31",
279
+ info: "#356b85",
280
+ shadowColor: "#463d27",
281
+ glassOpacity: 92,
282
+ shadowStrength: 11,
283
+ edgeStrength: 13,
284
+ highlightStrength: 62
285
+ },
286
+ dark: {
287
+ bg: "#111e32",
288
+ surface: "#1c2d46",
289
+ raised: "#2a3f5b",
290
+ ink: "#f8efcf",
291
+ muted: "#c2c4b5",
292
+ faint: "#afb7bd",
293
+ accent: "#e5be54",
294
+ accentStrong: "#ebc568",
295
+ accentText: "#efd181",
296
+ onAccent: "#2b2617",
297
+ cold: "#88a5d6",
298
+ success: "#b3d29b",
299
+ warning: "#f0cd7b",
300
+ error: "#efaaa0",
301
+ info: "#a1c9e8",
302
+ shadowColor: "#050b15",
303
+ glassOpacity: 93,
304
+ shadowStrength: 30,
305
+ edgeStrength: 16,
306
+ highlightStrength: 7
307
+ }
308
+ }
309
+ ];
310
+
1
311
  // src/behaviors/events.ts
2
312
  function emitIcen(source, type, detail) {
3
313
  return source.dispatchEvent(
@@ -5,14 +315,44 @@ function emitIcen(source, type, detail) {
5
315
  );
6
316
  }
7
317
 
318
+ // src/behaviors/design.ts
319
+ var appearanceFrame;
320
+ function prepareDesignChange() {
321
+ if (typeof document === "undefined" || typeof window.requestAnimationFrame !== "function") return;
322
+ const root = document.documentElement;
323
+ root.setAttribute("data-icen-design-changing", "");
324
+ void root.offsetWidth;
325
+ if (appearanceFrame !== void 0) window.cancelAnimationFrame(appearanceFrame);
326
+ appearanceFrame = window.requestAnimationFrame(() => {
327
+ appearanceFrame = window.requestAnimationFrame(() => {
328
+ void root.offsetWidth;
329
+ root.removeAttribute("data-icen-design-changing");
330
+ appearanceFrame = void 0;
331
+ });
332
+ });
333
+ }
334
+
8
335
  // src/behaviors/theme.ts
9
- var PRESETS = ["clay", "piano", "art", "vangogh", "ink", "retro"];
10
- var STYLES = ["modern", "retro", "terminal"];
336
+ var PRESETS = themes_default.map((theme) => theme.id);
337
+ var PRIMITIVES = ["modern", "chinese", "soviet", "pixel"];
338
+ var customPrimitives = /* @__PURE__ */ new Set();
339
+ function registerPrimitive(name) {
340
+ if (!/^[a-z][a-z0-9-]{1,20}$/.test(name)) return false;
341
+ if (PRIMITIVES.includes(name)) return true;
342
+ customPrimitives.add(name);
343
+ return true;
344
+ }
345
+ function listPrimitives() {
346
+ return [...PRIMITIVES, ...customPrimitives];
347
+ }
348
+ function normalizePrimitive(name) {
349
+ return typeof name === "string" && listPrimitives().includes(name) ? name : "modern";
350
+ }
11
351
  var STORAGE_KEY = "icen.ui.theme";
12
352
  var PRESET_NAME_RE = /^[a-z][a-z0-9-]{1,20}$/;
13
- var RESERVED_PRESET_NAMES = /* @__PURE__ */ new Set(["dark", ...STYLES.map((s) => `style-${s}`)]);
353
+ var RESERVED_PRESET_NAMES = /* @__PURE__ */ new Set(["dark"]);
14
354
  var customPresets = /* @__PURE__ */ new Set();
15
- var FALLBACK = { preset: "clay", dark: false, style: "modern" };
355
+ var FALLBACK = { preset: "modern", dark: false, style: "modern" };
16
356
  function isBrowser() {
17
357
  return typeof document !== "undefined";
18
358
  }
@@ -25,14 +365,14 @@ function registerThemePreset(name) {
25
365
  return true;
26
366
  }
27
367
  function listThemePresets() {
28
- return [...PRESETS, ...customPresets];
368
+ return [.../* @__PURE__ */ new Set([...PRESETS, ...customPresets])];
29
369
  }
30
370
  function getDefaultTheme() {
31
371
  if (!isBrowser() || typeof window.matchMedia !== "function") {
32
372
  return { ...FALLBACK };
33
373
  }
34
374
  return {
35
- preset: "clay",
375
+ preset: "modern",
36
376
  dark: window.matchMedia("(prefers-color-scheme: dark)").matches,
37
377
  style: "modern"
38
378
  };
@@ -41,7 +381,7 @@ function isThemeState(v) {
41
381
  if (typeof v !== "object" || v === null) return false;
42
382
  const t = v;
43
383
  return typeof t.preset === "string" && /* 持久化路径与 setTheme 同一开放白名单:自建预设跨刷新存活 */
44
- isValidPreset(t.preset) && typeof t.dark === "boolean" && typeof t.style === "string" && STYLES.includes(t.style);
384
+ isValidPreset(t.preset) && typeof t.dark === "boolean" && typeof t.style === "string";
45
385
  }
46
386
  function getTheme() {
47
387
  if (!isBrowser()) return getDefaultTheme();
@@ -50,7 +390,14 @@ function getTheme() {
50
390
  if (!raw) return getDefaultTheme();
51
391
  const parsed = JSON.parse(raw);
52
392
  if (!isThemeState(parsed)) return getDefaultTheme();
53
- return { preset: parsed.preset, dark: parsed.dark, style: parsed.style };
393
+ const normalized = { preset: parsed.preset, dark: parsed.dark, style: normalizePrimitive(parsed.style) };
394
+ if (normalized.style !== parsed.style || normalized.preset !== parsed.preset) {
395
+ try {
396
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify(normalized));
397
+ } catch {
398
+ }
399
+ }
400
+ return normalized;
54
401
  } catch {
55
402
  return getDefaultTheme();
56
403
  }
@@ -58,17 +405,14 @@ function getTheme() {
58
405
  var lastApplied = null;
59
406
  function apply(t) {
60
407
  if (!isBrowser()) return;
61
- const cls = document.documentElement.classList;
62
- if (lastApplied && !PRESETS.includes(lastApplied.preset)) {
63
- cls.remove(lastApplied.preset);
64
- }
65
- for (const p of PRESETS) cls.remove(p);
66
- for (const s of STYLES) cls.remove(`style-${s}`);
67
- cls.remove("dark");
68
- cls.add(t.preset);
69
- if (t.dark) cls.add("dark");
70
- cls.add(`style-${t.style}`);
71
- const changed = lastApplied !== null && (lastApplied.preset !== t.preset || lastApplied.dark !== t.dark || lastApplied.style !== t.style);
408
+ prepareDesignChange();
409
+ const root = document.documentElement;
410
+ const hadAppearance = root.hasAttribute("data-icen-style");
411
+ root.setAttribute("data-icen-preset", t.preset);
412
+ if (t.dark) root.setAttribute("data-icen-theme", "dark");
413
+ else root.removeAttribute("data-icen-theme");
414
+ root.setAttribute("data-icen-style", t.style);
415
+ const changed = hadAppearance && lastApplied !== null && (lastApplied.preset !== t.preset || lastApplied.dark !== t.dark || lastApplied.style !== t.style);
72
416
  lastApplied = { ...t };
73
417
  if (changed) {
74
418
  emitIcen(document.documentElement, "icen:theme-change", {
@@ -79,34 +423,49 @@ function apply(t) {
79
423
  }
80
424
  }
81
425
  function applyTheme(t) {
82
- apply(t);
426
+ apply({ ...t, style: normalizePrimitive(t.style) });
83
427
  }
84
428
  function setTheme(patch) {
85
- const merged = { ...getTheme(), ...patch };
429
+ const merged = { ...getCurrentTheme(), ...patch };
86
430
  const next = {
87
431
  preset: isValidPreset(merged.preset) ? merged.preset : FALLBACK.preset,
88
432
  dark: merged.dark === true,
89
- style: STYLES.includes(merged.style) ? merged.style : FALLBACK.style
433
+ style: normalizePrimitive(merged.style)
90
434
  };
91
- apply(next);
92
435
  if (isBrowser()) {
93
436
  try {
94
437
  window.localStorage.setItem(STORAGE_KEY, JSON.stringify(next));
95
438
  } catch {
96
439
  }
97
440
  }
441
+ apply(next);
98
442
  return next;
99
443
  }
444
+ function getCurrentTheme() {
445
+ if (!isBrowser()) return getDefaultTheme();
446
+ const root = document.documentElement;
447
+ const preset = root.getAttribute("data-icen-preset");
448
+ const style = root.getAttribute("data-icen-style");
449
+ if (!preset || !style) return getTheme();
450
+ return { preset, style: normalizePrimitive(style), dark: root.getAttribute("data-icen-theme") === "dark" };
451
+ }
100
452
  function toggleDark() {
101
- return setTheme({ dark: !getTheme().dark });
453
+ return setTheme({ dark: !getCurrentTheme().dark });
102
454
  }
103
- function setStyle(style) {
104
- return setTheme({ style });
455
+ function setPrimitive(primitive) {
456
+ return setTheme({ style: primitive });
105
457
  }
106
458
  var systemListenerAttached = false;
459
+ var storageListenerAttached = false;
107
460
  function initTheme() {
108
461
  const t = getTheme();
109
462
  applyTheme(t);
463
+ if (isBrowser() && !storageListenerAttached) {
464
+ storageListenerAttached = true;
465
+ window.addEventListener("storage", (event) => {
466
+ if (event.key === STORAGE_KEY || event.key === null) applyTheme(getTheme());
467
+ });
468
+ }
110
469
  if (isBrowser() && typeof window.matchMedia === "function" && !systemListenerAttached && !hasPersistedPreference()) {
111
470
  systemListenerAttached = true;
112
471
  let lastDark = t.dark;
@@ -138,15 +497,18 @@ function hasPersistedPreference() {
138
497
  }
139
498
  export {
140
499
  PRESETS,
500
+ PRIMITIVES,
141
501
  STORAGE_KEY,
142
- STYLES,
143
502
  applyTheme,
503
+ getCurrentTheme,
144
504
  getDefaultTheme,
145
505
  getTheme,
146
506
  initTheme,
507
+ listPrimitives,
147
508
  listThemePresets,
509
+ registerPrimitive,
148
510
  registerThemePreset,
149
- setStyle,
511
+ setPrimitive,
150
512
  setTheme,
151
513
  toggleDark
152
514
  };
@@ -1,45 +1,44 @@
1
- type ToastKind = 'ok' | 'err' | 'warn' | 'info' | 'success' | 'error';
1
+ import { FeedbackAction } from './feedback.js';
2
+ import { IconName } from './icons.js';
3
+
4
+ type ToastKind = 'warn' | 'info' | 'success' | 'error';
2
5
  interface ToastOptions {
3
- /** 保留时长(毫秒),默认 2600;带 action 时默认 6000 */
6
+ /** 保留时长(毫秒),默认 2600;action 默认 6000;0 常驻。焦点/hover/后台/忙碌时暂停。 */
4
7
  ms?: number;
5
8
  /** 配合 action:可撤销 / 重试 / 查看等 */
6
9
  actionLabel?: string;
7
- /** action 触发回调;返回 false 阻止 toast 关闭 */
8
- onAction?: () => void | Promise<void> | boolean;
9
- /** 内联 SVG 字符串图标(消毒后渲染为 .toast-icon);非 <svg> 开头或解析失败静默忽略 */
10
+ /** 等待同步/异步操作;false 保持打开,reject 保留重试反馈。关闭会 abort 传入的 signal。 */
11
+ onAction?: FeedbackAction;
12
+ /** Inline retry feedback on thrown/rejected actions; defaults to localized text. */
13
+ actionError?: string;
14
+ /** 内联 SVG 字符串图标(消毒后渲染为 .icen-toast-icon);非 <svg> 开头或解析失败静默忽略 */
10
15
  icon?: string;
11
- /** 显示右上角关闭按钮(.toast-close,点击即关闭本条),默认 false */
16
+ iconName?: IconName;
17
+ /** 显示右上角关闭按钮(.icen-toast-close,点击即关闭本条),默认 false */
12
18
  closable?: boolean;
13
- /** 显示底部超时进度条(.toast-progress,动画时长 = 本条保留时长),默认 false */
19
+ /** 显示底部超时进度条(.icen-toast-progress,动画时长 = 本条保留时长),默认 false */
14
20
  progress?: boolean;
15
21
  }
16
22
  /** 单条 toast 句柄:dismiss() 立即关闭本条(幂等,可重复调用)。 */
17
23
  interface ToastHandle {
18
24
  dismiss(): void;
25
+ pause(): void;
26
+ resume(): void;
19
27
  }
20
28
  interface ToastConfig {
21
29
  /** 同屏最大堆叠,默认 5;超出从最早的开始移除 */
22
30
  maxStack?: number;
23
31
  }
32
+ type ToastTiming = number | ToastOptions;
24
33
  interface ToastFn {
25
- (message: string, kind?: ToastKind, ms?: number): ToastHandle;
26
- /** success 语义(.toast--success),规范词表入口 */
27
- success(message: string, ms?: number): ToastHandle;
28
- /**
29
- * success 语义(.toast--success)。
30
- * @deprecated 词表统一:改用 toast.success(),本别名下个大版本删除。
31
- */
32
- ok(message: string, ms?: number): ToastHandle;
33
- /** error 语义(.toast--error),规范词表入口 */
34
- error(message: string, ms?: number): ToastHandle;
35
- /**
36
- * error 语义(.toast--error)。
37
- * @deprecated 词表统一:改用 toast.error(),本别名下个大版本删除。
38
- */
39
- err(message: string, ms?: number): ToastHandle;
40
- warn(message: string, ms?: number): ToastHandle;
41
- info(message: string, ms?: number): ToastHandle;
42
- action(message: string, actionLabel: string, onAction: () => void, ms?: number): ToastHandle;
34
+ (message: string, kind?: ToastKind, ms?: ToastTiming): ToastHandle;
35
+ /** success 语义(.icen-toast--success) */
36
+ success(message: string, ms?: ToastTiming): ToastHandle;
37
+ /** error 语义(.icen-toast--error) */
38
+ error(message: string, ms?: ToastTiming): ToastHandle;
39
+ warn(message: string, ms?: ToastTiming): ToastHandle;
40
+ info(message: string, ms?: ToastTiming): ToastHandle;
41
+ action(message: string, actionLabel: string, onAction: FeedbackAction, ms?: ToastTiming): ToastHandle;
43
42
  dismiss(): void;
44
43
  config(opts: ToastConfig): void;
45
44
  }