@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,12 +1,1172 @@
1
- // src/behaviors/notification.ts
2
- var KIND_ICON = {
3
- success: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><path d="m9 11 3 3L22 4"/></svg>',
4
- warning: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>',
5
- error: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/></svg>',
6
- info: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>'
1
+ // src/behaviors/icons.ts
2
+ var ICON_PATHS = {
3
+ file: "M6 2.5h5.5L16 7v9.5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-12a2 2 0 0 1 2-2ZM11.5 2.5V7H16",
4
+ folder: "M3 5a1.5 1.5 0 0 1 1.5-1.5H8l2 2h5.5A1.5 1.5 0 0 1 17 7v8a1.5 1.5 0 0 1-1.5 1.5h-11A1.5 1.5 0 0 1 3 15Z",
5
+ globe: "M17.5 10a7.5 7.5 0 1 1-15 0 7.5 7.5 0 0 1 15 0ZM2.5 10h15M10 2.5c-4 4-4 11 0 15 4-4 4-11 0-15Z",
6
+ document: "M6 2.5h5.5L16 7v9.5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-12a2 2 0 0 1 2-2ZM11.5 2.5V7H16M7 10.5h6M7 13.5h6",
7
+ agent: "M10 6V3M8 3h2M5 6h10a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2ZM1.5 10h1.5M17 10h1.5M7 10v2M13 10v2M8 14h4",
8
+ paperclip: "M14 7 8.3 12.7a1.6 1.6 0 0 1-2.3-2.3l6.3-6.3a3.2 3.2 0 0 1 4.5 4.5l-7 7a4.7 4.7 0 0 1-6.7-6.7l7-7",
9
+ stop: "M6.5 5h7A1.5 1.5 0 0 1 15 6.5v7a1.5 1.5 0 0 1-1.5 1.5h-7A1.5 1.5 0 0 1 5 13.5v-7A1.5 1.5 0 0 1 6.5 5Z",
10
+ terminal: "M5 3.5h10a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-9a2 2 0 0 1 2-2ZM6 7l3 3-3 3M11 13h3",
11
+ branch: "M6 6v8M14 6v2a4 4 0 0 1-4 4H6M8 4a2 2 0 1 1-4 0 2 2 0 0 1 4 0ZM8 16a2 2 0 1 1-4 0 2 2 0 0 1 4 0ZM16 4a2 2 0 1 1-4 0 2 2 0 0 1 4 0Z",
12
+ "line-numbers": "M3 5h2M3 10h2M3 15h2M8 5h9M8 10h9M8 15h9",
13
+ wrap: "M3 5h14M3 10h10a3 3 0 0 1 0 6h-3M12.5 13.5 10 16l2.5 2.5",
14
+ calendar: "M5.5 4h9A2.5 2.5 0 0 1 17 6.5v8a2.5 2.5 0 0 1-2.5 2.5h-9A2.5 2.5 0 0 1 3 14.5v-8A2.5 2.5 0 0 1 5.5 4ZM6.5 2.5v3M13.5 2.5v3M3 8h14M6.5 11h.1M10 11h.1M13.5 11h.1M6.5 14h.1M10 14h.1",
15
+ close: "M6 6l8 8M14 6l-8 8",
16
+ check: "M4.5 10.2l3.6 3.6 7.4-7.6",
17
+ "chevron-down": "M5.5 7.75 10 12.25l4.5-4.5",
18
+ "chevron-up": "M5.5 12.25 10 7.75l4.5 4.5",
19
+ "chevron-right": "M7.75 5.5 12.25 10l-4.5 4.5",
20
+ "chevron-left": "M12.25 5.5 7.75 10l4.5 4.5",
21
+ "arrow-right": "M3.5 10h13M11 4.5l5.5 5.5-5.5 5.5",
22
+ "arrow-left": "M16.5 10h-13M9 4.5 3.5 10 9 15.5",
23
+ "arrow-up": "M10 16.5v-13M4.5 9 10 3.5 15.5 9",
24
+ "arrow-down": "M10 3.5v13M4.5 11l5.5 5.5 5.5-5.5",
25
+ plus: "M10 4v12M4 10h12",
26
+ minus: "M4 10h12",
27
+ sort: "M6 15V4M3 7l3-3 3 3M14 5v11M11 13l3 3 3-3",
28
+ search: "M13.3 13.3 17 17M14.5 8.5a6 6 0 1 1-12 0 6 6 0 0 1 12 0",
29
+ sun: "M13.5 10a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0M10 1.75v1.5M10 16.75v1.5M1.75 10h1.5M16.75 10h1.5M4.17 4.17l1.06 1.06M14.77 14.77l1.06 1.06M4.17 15.83l1.06-1.06M14.77 5.23l1.06-1.06",
30
+ moon: "M17.25 11.15A7.5 7.5 0 0 1 8.85 2.75a7.5 7.5 0 1 0 8.4 8.4Z",
31
+ modern: "M6.5 3h7A3.5 3.5 0 0 1 17 6.5v7a3.5 3.5 0 0 1-3.5 3.5h-7A3.5 3.5 0 0 1 3 13.5v-7A3.5 3.5 0 0 1 6.5 3ZM7 10l3-3 3 3-3 3Z",
32
+ pixel: "M3 3h5v5H3ZM12 3h5v5h-5ZM3 12h5v5H3ZM12 12h5v5h-5Z",
33
+ chinese: "M3 8c3 0 5-2 7-5 2 3 4 5 7 5M4 8h12M6 8v8m8-8v8M3 16h14M8 16v-5h4v5",
34
+ soviet: "M3 17h14M5 17V8h4v9m0-12h6v12M7 8V5h2m2 3h2m-2 3h2m-2 3h2M10 5V3h4v2",
35
+ more: "M4 9.9v.2M10 9.9v.2M16 9.9v.2",
36
+ copy: "M7 7h8a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H9a2 2 0 0 1-2-2V7ZM13 7V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2",
37
+ edit: "M11.5 4.5l4 4M4 12l9-9a1.4 1.4 0 0 1 2 0l2 2a1.4 1.4 0 0 1 0 2l-9 9-5 1Z",
38
+ link: "M8 6l2-2a4.2 4.2 0 0 1 6 6l-2 2M12 14l-2 2a4.2 4.2 0 0 1-6-6l2-2M7 13l6-6",
39
+ trash: "M3.5 5.5h13M7 5.5V3h6v2.5M5 5.5l.7 11.5h8.6L15 5.5M8 9v5M12 9v5",
40
+ spinner: "M10 3a7 7 0 1 1-7 7",
41
+ "circle-check": "M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0ZM6 10l2.7 2.7 5.3-5.4",
42
+ "circle-error": "M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0ZM7.2 7.2l5.6 5.6M12.8 7.2l-5.6 5.6",
43
+ "circle-info": "M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0ZM10 9v5M10 6.1v.15",
44
+ "triangle-alert": "M8.7 3.5a1.5 1.5 0 0 1 2.6 0l6.4 11.3a1.5 1.5 0 0 1-1.3 2.2H3.6a1.5 1.5 0 0 1-1.3-2.2ZM10 7.2v4.4M10 14v.15",
45
+ refresh: "M16.5 7.2A7 7 0 0 0 4.3 5.9L2.5 8M2.5 3.5V8H7M3.5 12.8a7 7 0 0 0 12.2 1.3l1.8-2.1M13 12h4.5v4.5",
46
+ external: "M11.5 3H17v5.5M17 3l-8 8M8 3H5a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-3",
47
+ home: "M3.5 10.25 10 4l6.5 6.25M5.75 8.75v7a.75.75 0 0 0 .75.75h7.5a.75.75 0 0 0 .75-.75v-7",
48
+ settings: "M3.5 5.5h13M3.5 10h13M3.5 14.5h13M7 4v3M12.5 8.5v3M8 13v3",
49
+ star: "M10 2.5l2.4 5.1 5.6.4-4.2 3.7 1.3 5.5-5.1-3-5.1 3 1.3-5.5L1.8 8l5.6-.4Z",
50
+ eye: "M2.2 10s3-5.4 7.8-5.4S17.8 10 17.8 10s-3 5.4-7.8 5.4S2.2 10 2.2 10ZM10 12.4a2.4 2.4 0 1 0 0-4.8 2.4 2.4 0 0 0 0 4.8Z",
51
+ "eye-off": "M2.2 10s3-5.4 7.8-5.4S17.8 10 17.8 10s-3 5.4-7.8 5.4S2.2 10 2.2 10ZM10 12.4a2.4 2.4 0 1 0 0-4.8 2.4 2.4 0 0 0 0 4.8ZM3.5 3.5l13 13",
52
+ inbox: "M3.5 12.25h3.7l1.5 2.5h2.6l1.5-2.5h3.7M4.7 5.5l-1.2 6.75v3.25a1.5 1.5 0 0 0 1.5 1.5h10a1.5 1.5 0 0 0 1.5-1.5v-3.25L15.3 5.5a1.3 1.3 0 0 0-1.25-1H5.95a1.3 1.3 0 0 0-1.25 1Z",
53
+ bell: "M10 3.5a4.5 4.5 0 0 1 4.5 4.5c0 4.5 1.8 5.7 2.5 6.5H3c.7-.8 2.5-2 2.5-6.5A4.5 4.5 0 0 1 10 3.5ZM8.5 16.5a1.6 1.6 0 0 0 3 0",
54
+ users: "M13.8 16.5v-1.5a3.5 3.5 0 0 0-3.5-3.5H6.3a3.5 3.5 0 0 0-3.5 3.5v1.5M8.3 8.9a2.7 2.7 0 1 0 0-5.4 2.7 2.7 0 0 0 0 5.4ZM16.5 16.5v-1.3a3.3 3.3 0 0 0-2.3-3.1M12.3 3.7a2.7 2.7 0 0 1 0 5.2",
55
+ activity: "M17 10h-2.6l-2 5.8L8 4.2 6 10H3",
56
+ "trend-up": "M3.5 14.5l4.2-4.2 2.8 2.8 5.9-5.9M12.4 7.2h4.2v4.2",
57
+ "trend-down": "M3.5 5.5l4.2 4.2 2.8-2.8 5.9 5.9M12.4 12.8h4.2V8.6",
58
+ rocket: "M10 2.5c2 1.5 3.2 4 3.2 6.8 0 1.5-.3 2.9-.8 4.2H7.6c-.5-1.3-.8-2.7-.8-4.2 0-2.8 1.2-5.3 3.2-6.8ZM10 8.6a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM7.6 12.5 5.6 15.4c-.9.3-1.6 1-2 2M12.4 12.5l2 2.9c.9.3 1.6 1 2 2M8.7 13.8c0 1.8.5 3.1 1.3 4.2.8-1.1 1.3-2.4 1.3-4.2",
59
+ bold: "M6.5 4h4.2a3 3 0 0 1 0 6H6.5M6.5 10h5a3 3 0 0 1 0 6H6.5M6.5 4v12",
60
+ italic: "M8.5 4.5h7M4.5 15.5h7M12.5 4.5l-5 11",
61
+ underline: "M6 4v5.5a4 4 0 0 0 8 0V4M4.5 16h11",
62
+ "align-left": "M3.5 4.5h13M3.5 10h8.5M3.5 15.5h11",
63
+ "align-center": "M3.5 4.5h13M5.75 10h8.5M4.5 15.5h11",
64
+ "align-right": "M3.5 4.5h13M8 10h8.5M5.5 15.5h11",
65
+ list: "M6.5 5h10M6.5 10h10M6.5 15h10M3.5 5h.01M3.5 10h.01M3.5 15h.01",
66
+ server: "M3 3h14a1.5 1.5 0 0 1 1.5 1.5v2A1.5 1.5 0 0 1 17 8H3a1.5 1.5 0 0 1-1.5-1.5v-2A1.5 1.5 0 0 1 3 3ZM3 12h14a1.5 1.5 0 0 1 1.5 1.5v2A1.5 1.5 0 0 1 17 17H3a1.5 1.5 0 0 1-1.5-1.5v-2A1.5 1.5 0 0 1 3 12ZM5 5.5h.01M5 14.5h.01",
67
+ sparkle: "M10 2.5l1.6 4.3 4.3 1.6-4.3 1.6L10 14.3l-1.6-4.3-4.3-1.6 4.3-1.6ZM15.5 12.5l.8 2.1 2.1.8-2.1.8-.8 2.1-.8-2.1-2.1-.8 2.1-.8Z",
68
+ play: "M6.5 4.8v10.4c0 .9 1 1.5 1.8 1l8.3-5.2a1.2 1.2 0 0 0 0-2L8.3 3.8a1.2 1.2 0 0 0-1.8 1Z",
69
+ "chart-line": "M3.5 3.5v13h13M6.5 12l2.8-2.8 2.2 2.2 4-4.4",
70
+ layers: "M10 3.2 3.6 6.5 10 9.8l6.4-3.3ZM4.5 10.4 10 13.2l5.5-2.8M4.5 13.6 10 16.4l5.5-2.8",
71
+ box: "M17 6 10 3.2 3 6v8l7 2.8 7-2.8ZM3 6l7 2.8L17 6M10 9v7.8",
72
+ filter: "M4 4.5h12l-4.4 5.1v5l-3.2-1.6V9.6Z",
73
+ columns: "M3.5 4h13v12h-13ZM8.2 4v12M12.8 4v12",
74
+ download: "M10 3.5v8M6.8 8.3 10 11.5l3.2-3.2M4 15v2.5a1.5 1.5 0 0 0 1.5 1.5h9a1.5 1.5 0 0 0 1.5-1.5V15"
75
+ };
76
+ var custom = /* @__PURE__ */ new Map();
77
+ function iconPath(name) {
78
+ return Object.hasOwn(ICON_PATHS, name) ? ICON_PATHS[name] : custom.get(name) ?? null;
79
+ }
80
+ function iconAttributes(o = {}) {
81
+ const size = Number.isFinite(o.size) && o.size > 0 ? o.size : 16;
82
+ return { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", width: String(size), height: String(size), fill: "none", stroke: "currentColor", "stroke-width": "1.6", "stroke-linecap": "round", "stroke-linejoin": "round", focusable: "false", class: ["icen-symbol", o.className].filter(Boolean).join(" "), ...o.label ? { role: "img", "aria-label": o.label } : { "aria-hidden": "true" } };
83
+ }
84
+ function createIcon(name, o = {}) {
85
+ if (typeof document === "undefined") return null;
86
+ const path = iconPath(name);
87
+ if (!path) return null;
88
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
89
+ for (const [key, value] of Object.entries(iconAttributes(o))) svg.setAttribute(key, value);
90
+ const line = document.createElementNS(svg.namespaceURI, "path");
91
+ line.setAttribute("d", path);
92
+ svg.append(line);
93
+ return svg;
94
+ }
95
+
96
+ // src/behaviors/feedback.ts
97
+ function createFeedbackClock(el, state, expire, progress, pauseOnHover = () => true) {
98
+ if (typeof document === "undefined") return { pause() {
99
+ }, resume() {
100
+ }, reset() {
101
+ }, destroy() {
102
+ } };
103
+ const reasons = /* @__PURE__ */ new Set();
104
+ const ac = new AbortController();
105
+ let destroyed = false;
106
+ function sync(reset = false) {
107
+ state.paused = state.duration > 0 && reasons.size > 0;
108
+ el.classList.toggle("is-paused", state.paused);
109
+ const fill = el.querySelector(progress);
110
+ if (fill) {
111
+ if (reset) {
112
+ fill.style.animationName = "none";
113
+ void fill.offsetWidth;
114
+ fill.style.animationName = "";
115
+ fill.style.animationDuration = `${state.duration}ms`;
116
+ }
117
+ fill.style.animationPlayState = state.paused ? "paused" : "running";
118
+ }
119
+ }
120
+ function stop() {
121
+ if (!state.timer) return;
122
+ window.clearTimeout(state.timer);
123
+ state.timer = 0;
124
+ state.remaining = Math.max(0, state.remaining - (Date.now() - state.startedAt));
125
+ }
126
+ function start() {
127
+ if (destroyed || state.duration <= 0 || reasons.size || state.timer) return;
128
+ if (state.remaining <= 0) {
129
+ expire();
130
+ return;
131
+ }
132
+ state.startedAt = Date.now();
133
+ state.timer = window.setTimeout(() => {
134
+ state.timer = 0;
135
+ state.remaining = 0;
136
+ if (!destroyed) expire();
137
+ }, state.remaining);
138
+ }
139
+ const clock = {
140
+ pause(reason = "manual") {
141
+ if (destroyed) return;
142
+ reasons.add(reason);
143
+ stop();
144
+ sync();
145
+ },
146
+ resume(reason = "manual") {
147
+ if (destroyed) return;
148
+ reasons.delete(reason);
149
+ sync();
150
+ start();
151
+ },
152
+ reset(ms) {
153
+ if (destroyed) return;
154
+ stop();
155
+ state.duration = Number.isFinite(ms) ? Math.max(0, ms) : 0;
156
+ state.remaining = state.duration;
157
+ sync(true);
158
+ start();
159
+ },
160
+ destroy() {
161
+ if (destroyed) return;
162
+ destroyed = true;
163
+ stop();
164
+ reasons.clear();
165
+ ac.abort();
166
+ }
167
+ };
168
+ el.addEventListener("mouseenter", () => {
169
+ if (pauseOnHover()) clock.pause("hover");
170
+ }, { signal: ac.signal });
171
+ el.addEventListener("mouseleave", () => clock.resume("hover"), { signal: ac.signal });
172
+ el.addEventListener("focusin", () => clock.pause("focus"), { signal: ac.signal });
173
+ el.addEventListener("focusout", (event) => {
174
+ if (!(event.relatedTarget instanceof Node) || !el.contains(event.relatedTarget)) clock.resume("focus");
175
+ }, { signal: ac.signal });
176
+ const visibility = () => document.hidden ? clock.pause("visibility") : clock.resume("visibility");
177
+ document.addEventListener("visibilitychange", visibility, { signal: ac.signal });
178
+ if (document.hidden) reasons.add("visibility");
179
+ if (el.contains(document.activeElement)) reasons.add("focus");
180
+ clock.reset(state.duration);
181
+ return clock;
182
+ }
183
+ var pending = /* @__PURE__ */ new WeakMap();
184
+ function cancelFeedbackAction(card) {
185
+ pending.get(card)?.abort();
186
+ }
187
+ function runFeedbackAction(card, button, action, hooks) {
188
+ if (typeof document === "undefined") return;
189
+ if (pending.has(card) || card.classList.contains("is-leaving") || !card.isConnected) return;
190
+ const ac = new AbortController();
191
+ const controls = Array.from(card.querySelectorAll(".icen-toast-action,.icen-notification-action"));
192
+ const original = controls.map((item) => item.getAttribute("aria-disabled"));
193
+ let spinner = null;
194
+ let busy = false;
195
+ let signalled = false;
196
+ const restore = () => {
197
+ if (busy) {
198
+ busy = false;
199
+ controls.forEach((item, index) => original[index] == null ? item.removeAttribute("aria-disabled") : item.setAttribute("aria-disabled", original[index]));
200
+ button.removeAttribute("aria-busy");
201
+ spinner?.remove();
202
+ }
203
+ if (signalled) {
204
+ signalled = false;
205
+ hooks.busy(false);
206
+ }
207
+ };
208
+ const operation = { abort() {
209
+ ac.abort();
210
+ if (pending.get(card) === operation) {
211
+ pending.delete(card);
212
+ restore();
213
+ }
214
+ } };
215
+ pending.set(card, operation);
216
+ const finish = (result, error) => {
217
+ if (ac.signal.aborted || pending.get(card) !== operation) return;
218
+ pending.delete(card);
219
+ try {
220
+ if (card.isConnected && !card.classList.contains("is-leaving")) {
221
+ if (error !== void 0) hooks.error(error);
222
+ else hooks.complete(result !== false);
223
+ }
224
+ } finally {
225
+ restore();
226
+ }
227
+ };
228
+ try {
229
+ signalled = true;
230
+ hooks.busy(true);
231
+ const result = action(ac.signal);
232
+ if (result && typeof result.then === "function") {
233
+ busy = true;
234
+ controls.forEach((item) => item.setAttribute("aria-disabled", "true"));
235
+ button.setAttribute("aria-busy", "true");
236
+ let label = button.querySelector(".icen-feedback-action-label");
237
+ if (!label) {
238
+ label = document.createElement("span");
239
+ label.className = "icen-feedback-action-label";
240
+ while (button.firstChild) label.append(button.firstChild);
241
+ button.append(label);
242
+ }
243
+ spinner = document.createElement("span");
244
+ spinner.className = "icen-feedback-action-spinner";
245
+ spinner.setAttribute("aria-hidden", "true");
246
+ spinner.append(createIcon("spinner"));
247
+ button.append(spinner);
248
+ void Promise.resolve(result).then((value) => finish(value), (error) => finish(false, error ?? new Error("Action rejected")));
249
+ } else finish(result);
250
+ } catch (error) {
251
+ finish(false, error ?? new Error("Action failed"));
252
+ }
253
+ }
254
+ function setFeedbackError(host, message) {
255
+ if (typeof document === "undefined") return;
256
+ let error = host.querySelector(":scope > .icen-feedback-error");
257
+ if (!message) {
258
+ error?.remove();
259
+ return;
260
+ }
261
+ if (!error) {
262
+ error = document.createElement("span");
263
+ error.className = "icen-feedback-error";
264
+ error.setAttribute("role", "alert");
265
+ host.append(error);
266
+ }
267
+ setFeedbackText(error, message);
268
+ }
269
+ function setFeedbackText(host, value) {
270
+ if (typeof document === "undefined") return;
271
+ const text = document.createElement("bdi");
272
+ text.textContent = value;
273
+ host.replaceChildren(text);
274
+ }
275
+ var origins = /* @__PURE__ */ new WeakMap();
276
+ function rememberFeedbackOrigin(card) {
277
+ if (typeof document === "undefined") return;
278
+ const focused = document.activeElement instanceof HTMLElement ? document.activeElement : null;
279
+ const previous = focused?.closest(".icen-toast,.icen-notification");
280
+ const chain = [...focused ? [focused] : [], ...previous ? origins.get(previous) ?? [] : []];
281
+ origins.set(card, [...new Set(chain)].filter((item) => item.isConnected));
282
+ }
283
+ function restoreFeedbackFocus(card) {
284
+ if (typeof document === "undefined") return;
285
+ const origin = origins.get(card)?.find((item) => item.isConnected && !item.closest("[hidden],[inert],.is-leaving") && !item.matches(':disabled,[aria-disabled="true"]'));
286
+ if (card.contains(document.activeElement)) origin?.focus({ preventScroll: true });
287
+ }
288
+
289
+ // src/behaviors/i18n.ts
290
+ var ICEN_LOCALE_ZH_CN = {
291
+ /* ── aiBranch ── */
292
+ "aiBranch.nextVersion": "\u4E0B\u4E00\u7248\u672C",
293
+ "aiBranch.prevVersion": "\u4E0A\u4E00\u7248\u672C",
294
+ "aiBranch.version": "\u5206\u652F\u7248\u672C",
295
+ /* ── aiChat ── */
296
+ "aiChat.backToBottom": "\u56DE\u5230\u5E95\u90E8",
297
+ "aiChat.backToBottomCount": "\u56DE\u5230\u5E95\u90E8 \xB7 {p0} \u6761\u65B0\u6D88\u606F",
298
+ "aiChat.continue": "\u7EE7\u7EED\u751F\u6210",
299
+ "aiChat.download": "\u4E0B\u8F7D",
300
+ "aiChat.file": "\u6587\u4EF6",
301
+ "aiChat.roleSystem": "\u7CFB",
302
+ "aiChat.roleTool": "\u5DE5",
303
+ "aiChat.roleUser": "\u6211",
304
+ "aiChat.thinking": "\u601D\u8003 {p0}",
305
+ /* ── aiComposer ── */
306
+ "aiComposer.attachAgent": "\u4EE3\u7406",
307
+ "aiComposer.library": "\u6DFB\u52A0\u4E0A\u4E0B\u6587\u4E0E\u547D\u4EE4",
308
+ "aiComposer.searchLibrary": "\u641C\u7D22\u6280\u80FD\u3001\u5DE5\u5177\u3001\u6587\u4EF6\u4E0E\u547D\u4EE4",
309
+ "aiComposer.all": "\u5168\u90E8",
310
+ "aiComposer.skills": "\u6280\u80FD",
311
+ "aiComposer.tools": "\u5DE5\u5177",
312
+ "aiComposer.libraryHint": "\u4E0A\u4E0B\u6587\u968F\u6D88\u606F\u53D1\u9001 \xB7 \u547D\u4EE4\u5148\u586B\u5165\u8F93\u5165\u6846",
313
+ "aiComposer.commandHint": "\u2191 \u2193 \u6D4F\u89C8 \xB7 Enter \u6267\u884C \xB7 Esc \u8FD4\u56DE",
314
+ "aiComposer.refHint": "\u2191 \u2193 \u6D4F\u89C8 \xB7 Enter \u5F15\u7528 \xB7 Esc \u8FD4\u56DE",
315
+ "aiComposer.noLibraryMatch": "\u6CA1\u6709\u5339\u914D\u7684\u9879\u76EE\uFF0C\u8BD5\u8BD5\u5176\u4ED6\u5173\u952E\u8BCD",
316
+ "aiComposer.filesNeedAdapter": "\u9644\u4EF6\u5C1A\u672A\u63A5\u901A\u4E0A\u4F20\u3002\u8BF7\u914D\u7F6E prepareMessage \u540E\u91CD\u8BD5\uFF0C\u6587\u4EF6\u4ECD\u4FDD\u7559\u5728\u6B64\u8BF7\u6C42\u4E2D\u3002",
317
+ "aiComposer.attachDoc": "\u6587\u6863",
318
+ "aiComposer.attachFile": "\u6587\u4EF6",
319
+ "aiComposer.attachFolder": "\u6587\u4EF6\u5939",
320
+ "aiComposer.cacheInvalidHint": "\u5207\u6362\u6A21\u578B\u4F1A\u4F7F prompt \u7F13\u5B58\u5931\u6548",
321
+ "aiComposer.commands": "\u547D\u4EE4",
322
+ "aiComposer.currentTodos": "\u5F53\u524D\u5F85\u529E",
323
+ "aiComposer.done": "\u5B8C\u6210",
324
+ "aiComposer.justNow": "\u521A\u521A \xB7 {p0}",
325
+ "aiComposer.modelAria": "\u6A21\u578B {p0}\uFF08{p1}\uFF09",
326
+ "aiComposer.noCommandMatch": "\u65E0\u5339\u914D\u547D\u4EE4",
327
+ "aiComposer.noModelMatch": "\u65E0\u5339\u914D\u6A21\u578B",
328
+ "aiComposer.noRefMatch": "\u65E0\u5339\u914D\u5F15\u7528",
329
+ "aiComposer.placeholder": "\u8F93\u5165\u6D88\u606F\uFF0C/ \u547D\u4EE4 \xB7 @ \u5F15\u7528 \xB7 Enter \u53D1\u9001",
330
+ "aiComposer.refs": "\u5F15\u7528",
331
+ "aiComposer.removeAttachment": "\u79FB\u9664\u9644\u4EF6 {p0}",
332
+ "aiComposer.removeQueued": "\u79FB\u9664\u6392\u961F\u6D88\u606F {p0}",
333
+ "aiComposer.removeRef": "\u79FB\u9664\u5F15\u7528 {p0}",
334
+ "aiComposer.searchModels": "\u641C\u7D22\u6A21\u578B",
335
+ "aiComposer.selectModel": "\u9009\u62E9\u6A21\u578B",
336
+ "aiComposer.send": "\u53D1\u9001",
337
+ "aiComposer.stop": "\u505C\u6B62\u751F\u6210",
338
+ "aiComposer.stopped": "\u5DF2\u505C\u6B62",
339
+ "aiComposer.todoChip": "\u5F53\u524D\u5F85\u529E {p0}/{p1}{p2}",
340
+ "aiComposer.todoHasError": "\uFF08\u6709\u5931\u8D25\u9879\uFF09",
341
+ /* ── aiCore ── */
342
+ "aiCore.kindBrowser": "\u6D4F\u89C8",
343
+ "aiCore.kindChart": "\u56FE\u8868",
344
+ "aiCore.kindDelete": "\u5220\u9664",
345
+ "aiCore.kindEdit": "\u7F16\u8F91",
346
+ "aiCore.kindFetch": "\u8BF7\u6C42",
347
+ "aiCore.kindGlob": "\u5339\u914D",
348
+ "aiCore.kindGrep": "\u641C\u7D22",
349
+ "aiCore.kindNote": "\u7B14\u8BB0",
350
+ "aiCore.kindPlan": "\u8BA1\u5212",
351
+ "aiCore.kindRead": "\u8BFB\u53D6",
352
+ "aiCore.kindSearch": "\u68C0\u7D22",
353
+ "aiCore.kindShell": "\u547D\u4EE4",
354
+ "aiCore.kindSkill": "\u6280\u80FD",
355
+ "aiCore.kindSubagent": "\u5B50\u4EE3\u7406",
356
+ "aiCore.kindTodo": "\u5F85\u529E",
357
+ "aiCore.kindWrite": "\u5199\u5165",
358
+ "aiCore.statusApproval": "\u5F85\u786E\u8BA4",
359
+ "aiCore.statusCancelled": "\u5DF2\u53D6\u6D88",
360
+ "aiCore.statusDone": "\u5B8C\u6210",
361
+ "aiCore.statusError": "\u5931\u8D25",
362
+ "aiCore.statusPending": "\u7B49\u5F85",
363
+ "aiCore.statusRunning": "\u6267\u884C\u4E2D",
364
+ "aiCore.statusStreaming": "\u6D41\u5F0F\u4E2D",
365
+ "aiCore.todoProgress": "{p0}/{p1} \u5B8C\u6210",
366
+ /* ── aiDiff ── */
367
+ "aiDiff.accepted": "\u5DF2\u63A5\u53D7",
368
+ "aiDiff.binary": "\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u65E0\u6CD5\u663E\u793A\u6587\u672C\u5DEE\u5F02",
369
+ "aiDiff.empty": "\u65E0\u5DEE\u5F02\u5185\u5BB9",
370
+ "aiDiff.rejected": "\u5DF2\u62D2\u7EDD",
371
+ /* ── aiFeedback ── */
372
+ "aiFeedback.helpful": "\u6709\u5E2E\u52A9",
373
+ "aiFeedback.notHelpful": "\u65E0\u5E2E\u52A9",
374
+ "aiFeedback.reasonCitationMismatch": "\u5F15\u7528\u4E0D\u7B26",
375
+ "aiFeedback.reasonOutdated": "\u5185\u5BB9\u8FC7\u65F6",
376
+ "aiFeedback.reasonUnauthorized": "\u8D8A\u6743\u4FE1\u606F",
377
+ "aiFeedback.reasonUnsourced": "\u65E0\u5F15\u7528\u4F9D\u636E",
378
+ "aiFeedback.reasonWrong": "\u7B54\u6848\u6709\u8BEF",
379
+ "aiFeedback.thanks": "\u611F\u8C22\u53CD\u9988\uFF0C\u5DF2\u5173\u8054\u5230\u8BE5\u6761\u56DE\u7B54\u7684\u8FFD\u8E2A\u8BB0\u5F55",
380
+ /* ── aiPanel ── */
381
+ "aiPanel.audit": "\u5BA1\u8BA1",
382
+ "aiPanel.cacheRead": "\u7F13\u5B58\u8BFB",
383
+ "aiPanel.cacheWrite": "\u7F13\u5B58\u5199",
384
+ "aiPanel.callsTokens": "{p0} \u6B21 \xB7 {p1} tok{p2}",
385
+ "aiPanel.clearAudit": "\u6E05\u9664\u5BA1\u8BA1",
386
+ "aiPanel.context": "\u4E0A\u4E0B\u6587",
387
+ "aiPanel.contextWindow": "\u4E0A\u4E0B\u6587\u7A97\u53E3",
388
+ "aiPanel.errorsCount": "{p0} \u5931\u8D25",
389
+ "aiPanel.files": "\u6587\u4EF6 ({p0})",
390
+ "aiPanel.itemStatus": "{p0}\uFF0C\u72B6\u6001\uFF1A{p1}",
391
+ "aiPanel.noAudit": "\u6682\u65E0\u5BA1\u8BA1\u8BB0\u5F55",
392
+ "aiPanel.noUsage": "\u6682\u65E0\u7528\u91CF",
393
+ "aiPanel.reasoning": "\u63A8\u7406",
394
+ "aiPanel.requestsCount": "{p0} \u6B21\u8BF7\u6C42",
395
+ "aiPanel.ringPercent": "\u4E0A\u4E0B\u6587\u7A97\u53E3\u5360\u7528 {p0}%\uFF0C\u70B9\u51FB\u67E5\u770B\u8BE6\u60C5",
396
+ "aiPanel.ringUsed": "\u5DF2\u7528 {p0}\uFF0C\u70B9\u51FB\u67E5\u770B\u8BE6\u60C5",
397
+ "aiPanel.taskProgress": "\u4EFB\u52A1\u8FDB\u5EA6",
398
+ "aiPanel.toolsCount": "{p0} \u5DE5\u5177",
399
+ "aiPanel.usage": "\u7528\u91CF",
400
+ "aiPanel.usageAria": "\u7528\u91CF\uFF1A{p0}",
401
+ /* ── aiProvider ── */
402
+ "aiProvider.audioUrlOnly": "\u4EC5 URL \u7684\u97F3\u9891\uFF08input_audio \u9700 base64\uFF0C\u8BF7\u5148\u53D6\u56DE\u5185\u8054\uFF09",
403
+ "aiProvider.audioUrlOnlyAnthropic": "\u4EC5 URL \u7684\u97F3\u9891\uFF08audio \u5757\u9700 base64 source\uFF09",
404
+ "aiProvider.base64File": "base64 \u6587\u4EF6\uFF08file \u90E8\u4EF6\u9700 Files API file_id\uFF0C\u8BF7\u7F6E\u4E8E url \u69FD\uFF09",
405
+ "aiProvider.corsHint": "\uFF1B\u6D4F\u89C8\u5668\u76F4\u8FDE {p0}\uFF08{p1}\uFF09\u5F88\u53EF\u80FD\u88AB CORS \u62E6\u622A\uFF0C\u5EFA\u8BAE\u7ECF\u4EE3\u7406/\u81EA\u5EFA\u7F51\u5173\u8F6C\u53D1",
406
+ "aiProvider.emptyResponse": "\u54CD\u5E94\u4E3A\u7A7A",
407
+ "aiProvider.glmLabel": "GLM\uFF08\u667A\u8C31\uFF09",
408
+ "aiProvider.invalidJson": "\u54CD\u5E94\u4E0D\u662F\u5408\u6CD5 JSON",
409
+ "aiProvider.kimiLabel": "Kimi\uFF08\u6708\u4E4B\u6697\u9762\uFF09",
410
+ "aiProvider.networkFailed": "\u7F51\u7EDC\u8BF7\u6C42\u5931\u8D25\uFF1A{p0}{p1}",
411
+ "aiProvider.nonPdfDocument": "\u975E PDF \u6587\u4EF6\u5757\uFF08document \u5757\u4E3A application/pdf\uFF0C\u6536\u5230 {p0}\uFF09",
412
+ "aiProvider.requestCancelled": "\u8BF7\u6C42\u5DF2\u53D6\u6D88",
413
+ "aiProvider.resourceRef": "[\u8D44\u6E90] {p0} ({p1})",
414
+ "aiProvider.streamError": "\u6D41\u5F0F\u54CD\u5E94\u9519\u8BEF",
415
+ "aiProvider.toolRoleNoCallId": "role 'tool' \u4E14\u7F3A toolCallId\uFF08openai \u65CF\u9700 tool_call_id\uFF09",
416
+ "aiProvider.toolRoleNoUseId": "role 'tool' \u4E14\u7F3A toolCallId\uFF08anthropic \u65CF\u6620\u5C04 tool_result \u9700 tool_use_id\uFF09",
417
+ "aiProvider.unsupported": "{p0} \u7EBF\u534F\u8BAE\u4E0D\u652F\u6301 {p1}",
418
+ "aiProvider.videoUnsupported": "video \u8F93\u5165\uFF08\u65E0\u4E3B\u6D41 chat API \u652F\u6301\uFF09",
419
+ "aiProvider.videoUnsupportedAnthropic": "video \u8F93\u5165",
420
+ /* ── aiThreads ── */
421
+ "aiThreads.actionsAria": "\u4F1A\u8BDD\u64CD\u4F5C",
422
+ "aiThreads.archived": "\u5DF2\u5F52\u6863",
423
+ /* ── aiTool ── */
424
+ "aiTool.allow": "\u5141\u8BB8",
425
+ "aiTool.reject": "\u62D2\u7EDD",
426
+ /* ── aiTools ── */
427
+ "aiTools.chart.area": "line \u591A\u7CFB\u5217\u586B\u5145\u9762\u79EF",
428
+ "aiTools.chart.data": "\u4EFB\u610F\u7EF4\u5EA6\u539F\u59CB\u8BB0\u5F55 + dims \u5B57\u6BB5\u6620\u5C04\uFF08\u81EA\u52A8\u900F\u89C6\u6210 \u7C7B\u76EE \xD7 \u7CFB\u5217\uFF09",
429
+ "aiTools.chart.dates": "\u8D21\u732E\u65E5\u5386 ISO \u65E5\u671F\uFF08\u4E0E values \u914D\u5BF9\uFF09",
430
+ "aiTools.chart.description": "\u5728\u7528\u6237\u754C\u9762\u6E32\u67D3\u4E00\u5F20\u56FE\u8868\u53EF\u89C6\u5316\u3002\u8F93\u5165\u4E00\u4EFD\u56FE\u8868\u89C4\u683C\uFF08\u7EAF JSON\uFF09\uFF1Alabels+values\uFF08\u7C7B\u76EE\u6570\u503C\uFF09\u3001series\uFF08\u591A\u7CFB\u5217\uFF09\u3001segments\uFF08\u5360\u6BD4\uFF09\u3001points\uFF08\u6563\u70B9\u6C14\u6CE1\uFF09\u3001dates\uFF08\u8D21\u732E\u65E5\u5386\uFF09\u4EFB\u7ED9\u5176\u4E00\uFF1Btype \u7F3A\u7701\u65F6\u6309\u6570\u636E\u5F62\u6001\u81EA\u52A8\u9009\u578B\uFF08\u65F6\u95F4\u5E8F\u5217\u2192\u6298\u7EBF\u3001\u5360\u6BD4\u2192\u73AF\u5F62\u3001\u65E5\u671F\u2192\u8D21\u732E\u65E5\u5386\u3001\u5750\u6807\u70B9\u2192\u6563\u70B9\uFF09\u3002\u56FE\u8868\u5E26\u4EA4\u4E92\uFF08\u60AC\u505C\u63D0\u793A/\u70B9\u51FB/\u53F3\u952E\uFF09\u4E0E\u53EF\u9690\u85CF\u56FE\u4F8B\u3002",
431
+ "aiTools.chart.dims": "data[] \u7684\u5B57\u6BB5\u6620\u5C04\uFF1A{label?, series?, value?, x?, y?}",
432
+ "aiTools.chart.format": "\u6570\u503C\u683C\u5F0F\u5316\uFF1A{notation?: compact|percent|ms, unit?}",
433
+ "aiTools.chart.labels": "\u7C7B\u76EE\u8F74\uFF08line/vbar/hbar\uFF09",
434
+ "aiTools.chart.legend": "false = \u521D\u59CB\u9690\u85CF\u56FE\u4F8B",
435
+ "aiTools.chart.lttb": "\u5927\u6570\u636E\u91CF\u964D\u91C7\u6837\uFF1Atrue=\u81EA\u52A8\u4E0A\u9650\uFF0C\u6570\u5B57=\u6700\u5927\u4FDD\u7559\u70B9\u6570\uFF08\u6E32\u67D3\u5C42\u5951\u7EA6\uFF0C\u968F\u56FE\u8868\u91CD\u5EA6\u573A\u666F\u843D\u5730\uFF09",
436
+ "aiTools.chart.marks": "\u6807\u8BB0\u5C42\uFF08\u9608\u503C\u7EBF/\u53C2\u8003\u533A\u95F4/\u5F3A\u8C03\u70B9\uFF09\uFF0C\u5143\u7D20\u4E3A\u7EAF JSON \u63CF\u8FF0\u5B50\uFF08\u6E32\u67D3\u5C42\u5951\u7EA6\uFF0C\u968F\u56FE\u8868\u91CD\u5EA6\u573A\u666F\u843D\u5730\uFF09",
437
+ "aiTools.chart.points": "\u6563\u70B9/\u6C14\u6CE1\uFF1A[{x,y,size?,label?}]",
438
+ "aiTools.chart.radarAxes": "\u96F7\u8FBE\u8F74\u540D",
439
+ "aiTools.chart.segments": "\u5360\u6BD4\u578B\uFF08donut/stack\uFF09\uFF1A[{label,value}]",
440
+ "aiTools.chart.series": "\u591A\u7CFB\u5217\uFF08line/vbar/radar\uFF09",
441
+ "aiTools.chart.stacked": "vbar \u591A\u7CFB\u5217\u5806\u53E0\uFF08\u9ED8\u8BA4\u5206\u7EC4\uFF09",
442
+ "aiTools.chart.title": "\u56FE\u8868\u6807\u9898\uFF08\u6E32\u67D3\u5728\u5934\u90E8\u884C\u5DE6\u4FA7\uFF09",
443
+ "aiTools.chart.tooltip": "false = \u5173\u95ED\u5185\u7F6E\u63D0\u793A",
444
+ "aiTools.chart.type": "\u56FE\u8868\u7C7B\u578B\uFF0C\u7F3A\u7701\u81EA\u52A8\u63A8\u65AD",
445
+ "aiTools.chart.values": "\u5355\u7CFB\u5217\u6570\u503C\uFF08\u4E0E labels \u914D\u5BF9\uFF09",
446
+ "aiTools.chart.zoom": "\u7F29\u653E\u4EA4\u4E92\uFF1A'x'=\u7C7B\u76EE\u8F74\u533A\u95F4\u7F29\u653E\uFF0C'brush'=\u5237\u9009\u7F29\u653E",
447
+ "aiTools.datatable.columns": "\u5217\u5B9A\u4E49\u6570\u7EC4\uFF1A\u6BCF\u9879 { key, title, sortable?, filterable? }\uFF08key \u5BF9\u5E94 rows \u5143\u7D20\u5B57\u6BB5\u540D\uFF09",
448
+ "aiTools.datatable.description": "\u5728\u7528\u6237\u754C\u9762\u6E32\u67D3\u4E00\u4E2A\u53EF\u641C\u7D22\u3001\u5206\u9875\u3001\u53EF\u5BFC\u51FA CSV \u7684\u6570\u636E\u8868\u683C\u3002\u8F93\u5165\u7EAF JSON\uFF1Acolumns \u4E3A\u5217\u5B9A\u4E49\uFF08key/title \u5FC5\u586B\uFF09\uFF0Crows \u4E3A\u884C\u5BF9\u8C61\u6570\u7EC4\uFF08\u5B57\u6BB5\u540D\u5BF9\u9F50\u5217 key\uFF09\u3002\u8FD4\u56DE { title, rows: \u884C\u6570 } \u6458\u8981\u3002",
449
+ "aiTools.datatable.rows": "\u884C\u6570\u636E\u6570\u7EC4\uFF1A\u6BCF\u9879\u4E3A\u4E00\u4E2A\u5BF9\u8C61\uFF0C\u5B57\u6BB5\u540D\u5BF9\u9F50 columns[].key",
450
+ "aiTools.datatable.title": "\u8868\u683C\u6807\u9898\uFF08\u6E32\u67D3\u5728\u5DE5\u5177\u680F\u5DE6\u4FA7\uFF09",
451
+ "aiTools.execFailed": "\u5DE5\u5177\u6267\u884C\u5931\u8D25\uFF1A{p0}",
452
+ "aiTools.execTimeout": "\u6267\u884C\u8D85\u65F6\uFF08{p0}ms\uFF09",
453
+ "aiTools.manifestHeader": "\u53EF\u7528 UI \u5DE5\u5177\uFF08\u8C03\u7528\u540E\u5728\u7528\u6237\u754C\u9762\u6302\u8F7D\u53EF\u89C6\u5316\u7ED3\u679C\uFF09\uFF1A",
454
+ "aiTools.missingRequired": "\u7F3A\u5C11\u5FC5\u586B\u5B57\u6BB5",
455
+ "aiTools.none": "\uFF08\u65E0\u5DF2\u6CE8\u518C\u7684 UI \u5DE5\u5177\uFF09",
456
+ "aiTools.notInEnum": "\u4E0D\u5728\u5141\u8BB8\u53D6\u503C\u5185\uFF08{p0}\uFF09",
457
+ "aiTools.numMax": "\u6570\u503C {p0} \u5927\u4E8E\u6700\u5927\u503C {p1}",
458
+ "aiTools.numMin": "\u6570\u503C {p0} \u5C0F\u4E8E\u6700\u5C0F\u503C {p1}",
459
+ "aiTools.removeMount": "\u79FB\u9664 {p0} \u6302\u8F7D",
460
+ "aiTools.strMax": "\u957F\u5EA6 {p0} \u8D85\u8FC7\u4E0A\u9650 {p1}",
461
+ "aiTools.strMin": "\u957F\u5EA6 {p0} \u5C0F\u4E8E\u4E0B\u9650 {p1}",
462
+ "aiTools.typeMismatch": "\u671F\u671B {p0}\uFF0C\u5B9E\u5F97 {p1}",
463
+ "aiTools.validationFailed": "\u53C2\u6570\u6821\u9A8C\u5931\u8D25\uFF08{p0} \u9879\uFF09",
464
+ /* ── autocomplete ── */
465
+ "suggestions.loading": "\u6B63\u5728\u67E5\u627E\u5EFA\u8BAE\u2026",
466
+ "suggestions.error": "\u6682\u65F6\u65E0\u6CD5\u52A0\u8F7D\u5EFA\u8BAE\uFF0C\u8BF7\u91CD\u8BD5\u3002",
467
+ "suggestions.options": "\u5EFA\u8BAE",
468
+ "suggestions.empty": "\u6CA1\u6709\u5339\u914D\u7684\u5EFA\u8BAE",
469
+ "autocomplete.empty": "\u65E0\u5339\u914D\u7ED3\u679C",
470
+ /* ── backTop ── */
471
+ "backTop.label": "\u56DE\u5230\u9876\u90E8",
472
+ /* ── carousel ── */
473
+ "carousel.item": "\u7B2C {p0} \u5F20",
474
+ "carousel.region": "\u8F6E\u64AD",
475
+ "carousel.slide": "\u5E7B\u706F\u7247",
476
+ "carousel.status": "\u7B2C {p0} / {p1} \u5F20",
477
+ /* ── charts ── */
478
+ "charts.calendarWeekdays": ["\u4E00", "", "\u4E09", "", "\u4E94", "", "\u65E5"],
479
+ "charts.few": "\u5C11",
480
+ "charts.hideLegend": "\u9690\u85CF\u56FE\u4F8B",
481
+ "charts.loading": "\u52A0\u8F7D\u4E2D",
482
+ "charts.many": "\u591A",
483
+ "charts.monthLabel": "{p0}\u6708",
484
+ "charts.noData": "\u6682\u65E0\u6570\u636E",
485
+ "charts.resetZoom": "\u91CD\u7F6E\u7F29\u653E",
486
+ "charts.sampled": "\u5DF2\u62BD\u6837 {p0}\u2192{p1} \u70B9",
487
+ "charts.type.area": "\u9762\u79EF\u56FE",
488
+ "charts.type.donut": "\u73AF\u5F62\u56FE",
489
+ "charts.type.gauge": "\u4EEA\u8868\u76D8",
490
+ "charts.type.graph": "\u77E5\u8BC6\u56FE\u8C31",
491
+ "charts.type.heatmap": "\u70ED\u529B\u56FE",
492
+ "charts.type.line": "\u6298\u7EBF\u56FE",
493
+ "charts.type.map": "\u5730\u56FE",
494
+ "charts.type.radar": "\u96F7\u8FBE\u56FE",
495
+ "charts.type.scatter": "\u6563\u70B9\u56FE",
496
+ "charts.type.sparkline": "\u8FF7\u4F60\u8D8B\u52BF",
497
+ "charts.seriesName": "\u7CFB\u5217{p0}",
498
+ "charts.showLegend": "\u663E\u793A\u56FE\u4F8B",
499
+ "charts.value": "\u6570\u503C",
500
+ /* ── themeSwitcher ── */
501
+ "themeSwitcher.appearance": "\u5916\u89C2",
502
+ "themeSwitcher.theme": "\u4E3B\u9898",
503
+ "themeSwitcher.primitive": "\u539F\u8BED",
504
+ "themeSwitcher.mode": "\u660E\u6697",
505
+ "themeSwitcher.light": "\u6D45\u8272",
506
+ "themeSwitcher.dark": "\u6DF1\u8272",
507
+ "themeSwitcher.modern": "\u73B0\u4EE3",
508
+ "themeSwitcher.dongyun": "\u4E1C\u97F5",
509
+ "themeSwitcher.jugou": "\u5DE8\u6784",
510
+ "themeSwitcher.piano": "\u94A2\u7434",
511
+ "themeSwitcher.monet": "\u83AB\u5948",
512
+ "themeSwitcher.vangogh": "\u68B5\u9AD8",
513
+ "themeSwitcher.chinese": "\u4E2D\u5F0F",
514
+ "themeSwitcher.soviet": "\u82CF\u5F0F",
515
+ "themeSwitcher.pixel": "\u50CF\u7D20",
516
+ /* ── codeBlock ── */
517
+ "codeBlock.collapse": "\u6536\u8D77",
518
+ "codeBlock.region": "\u4EE3\u7801\u5185\u5BB9",
519
+ "codeBlock.copyFailed": "\u672A\u80FD\u590D\u5236\uFF0C\u8BF7\u91CD\u8BD5\u3002",
520
+ "codeBlock.copyRetry": "\u91CD\u8BD5\u590D\u5236",
521
+ "codeBlock.copy": "\u590D\u5236",
522
+ "codeBlock.foldCollapse": "\u6298\u53E0\u4EE3\u7801",
523
+ "codeBlock.foldExpand": "\u5C55\u5F00\u4EE3\u7801",
524
+ "codeBlock.linesTotal": "\u5171 {p0} \u884C",
525
+ "codeBlock.numHide": "\u9690\u85CF\u884C\u53F7",
526
+ "codeBlock.numShow": "\u663E\u793A\u884C\u53F7",
527
+ "codeBlock.tailAria": "\u5C55\u5F00\u6216\u6536\u8D77\u4EE3\u7801",
528
+ "codeBlock.wrapOff": "\u5173\u95ED\u6362\u884C",
529
+ "codeBlock.wrapOn": "\u81EA\u52A8\u6362\u884C",
530
+ /* ── common ── */
531
+ "common.accept": "\u63A5\u53D7",
532
+ "common.add": "\u65B0\u589E",
533
+ "common.all": "\u5168\u90E8",
534
+ "common.approve": "\u6279\u51C6",
535
+ "common.cancel": "\u53D6\u6D88",
536
+ "common.actionFailed": "\u64CD\u4F5C\u672A\u5B8C\u6210\uFF0C\u8BF7\u91CD\u8BD5\u3002",
537
+ "common.close": "\u5173\u95ED",
538
+ "common.confirm": "\u786E\u8BA4",
539
+ "common.copied": "\u5DF2\u590D\u5236",
540
+ "common.copy": "\u590D\u5236",
541
+ "common.delete": "\u5220\u9664",
542
+ "common.enable": "\u542F\u7528",
543
+ "common.exportCsv": "\u5BFC\u51FA CSV",
544
+ "common.healthy": "\u6B63\u5E38",
545
+ "common.input": "\u8F93\u5165",
546
+ "common.loadingEllipsis": "\u52A0\u8F7D\u4E2D\u2026",
547
+ "common.official": "\u5B98\u65B9",
548
+ "common.output": "\u8F93\u51FA",
549
+ "common.page": "\u7B2C {p0} \u9875",
550
+ "common.reject": "\u62D2\u7EDD",
551
+ "common.remove": "\u79FB\u9664",
552
+ "common.requestAccess": "\u7533\u8BF7\u8BBF\u95EE",
553
+ "common.requestAccessFor": "\u7533\u8BF7\u8BBF\u95EE {p0}",
554
+ "common.restricted": "\u53D7\u9650",
555
+ "common.retry": "\u91CD\u8BD5",
556
+ "common.rows": "{p0} \u884C",
557
+ "common.run": "\u8FD0\u884C",
558
+ "common.steps": "{p0} \u6B65",
559
+ "common.submit": "\u63D0\u4EA4",
560
+ "common.unknown": "\u672A\u77E5",
561
+ /* ── contextMenu ── */
562
+ "contextMenu.back": "\u540E\u9000",
563
+ "contextMenu.copyPageLink": "\u590D\u5236\u9875\u9762\u94FE\u63A5",
564
+ "contextMenu.forward": "\u524D\u8FDB",
565
+ "contextMenu.refresh": "\u5237\u65B0",
566
+ /* ── copy ── */
567
+ "copy.copied": "\u5DF2\u590D\u5236",
568
+ "copy.failed": "\u672A\u80FD\u590D\u5236\uFF0C\u8BF7\u91CD\u8BD5\u3002",
569
+ "copy.denied": "clipboard API \u88AB\u62D2\uFF08{p0}\uFF09\u4E14\u56DE\u9000 execCommand \u5931\u8D25",
570
+ "copy.unavailable": "\u526A\u8D34\u677F\u4E0D\u53EF\u7528\uFF08\u65E0 clipboard API \u4E14 execCommand \u56DE\u9000\u5931\u8D25\uFF09",
571
+ "copy.unknown": "\u672A\u77E5\u9519\u8BEF",
572
+ /* ── datatable ── */
573
+ "datatable.clear": "\u6E05\u7A7A",
574
+ "datatable.collapseGroup": "\u6298\u53E0\u5206\u7EC4 {p0}",
575
+ "datatable.columnSettingsAria": "\u5217\u8BBE\u7F6E",
576
+ "datatable.countUnit": "{p0} \u6761",
577
+ "datatable.editHint": "\u7F16\u8F91\u300C{p0}\u300D\uFF1A\u53CC\u51FB\u6216\u6309 Enter",
578
+ "datatable.editHintWithValue": "{p0}\uFF08\u53CC\u51FB\u6216\u6309 Enter \u7F16\u8F91\u300C{p1}\u300D\uFF09",
579
+ "datatable.empty": "\u6682\u65E0\u6570\u636E",
580
+ "datatable.emptyValue": "\uFF08\u7A7A\uFF09",
581
+ "datatable.expandGroup": "\u5C55\u5F00\u5206\u7EC4 {p0}",
582
+ "datatable.expandRow": "\u5C55\u5F00\u884C",
583
+ "datatable.filterChipAria": "\u7B5B\u9009\u300C{p0}\u300D",
584
+ "datatable.pageSizeAria": "\u6BCF\u9875\u6761\u6570",
585
+ "datatable.paginationAria": "\u5206\u9875",
586
+ "datatable.reset": "\u91CD\u7F6E",
587
+ "datatable.resizeAria": "\u8C03\u6574\u300C{p0}\u300D\u5217\u5BBD",
588
+ "datatable.searchAria": "\u641C\u7D22\u8868\u683C",
589
+ "datatable.searchPlaceholder": "\u641C\u7D22\u2026",
590
+ "datatable.selectAll": "\u5168\u9009",
591
+ "datatable.selectRow": "\u9009\u62E9\u8BE5\u884C",
592
+ "datatable.selectedCount": "\u5DF2\u9009 {p0} \u9879",
593
+ "datatable.totalCount": "\u5171 {p0} \u6761",
594
+ "datatable.totalLabel": "\u5408\u8BA1",
595
+ /* ── datePicker ── */
596
+ "datePicker.noDates": "\u6CA1\u6709\u53EF\u9009\u65E5\u671F",
597
+ "datePicker.clear": "\u6E05\u9664",
598
+ "datePicker.nextMonth": "\u4E0B\u4E00\u6708",
599
+ "datePicker.prevMonth": "\u4E0A\u4E00\u6708",
600
+ "datePicker.selectDate": "\u9009\u62E9\u65E5\u671F",
601
+ "datePicker.today": "\u4ECA\u5929",
602
+ "datePicker.weekdays": ["\u4E00", "\u4E8C", "\u4E09", "\u56DB", "\u4E94", "\u516D", "\u65E5"],
603
+ "datePicker.weekdaysSunFirst": ["\u65E5", "\u4E00", "\u4E8C", "\u4E09", "\u56DB", "\u4E94", "\u516D"],
604
+ "datePicker.yearMonth": "{p0} \u5E74 {p1} \u6708",
605
+ /* ── formValidate ── */
606
+ "formValidate.email": "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u90AE\u7BB1\u5730\u5740",
607
+ "formValidate.invalid": "\u8F93\u5165\u4E0D\u5408\u6CD5",
608
+ "formValidate.matches": "\u4E24\u6B21\u8F93\u5165\u4E0D\u4E00\u81F4",
609
+ "formValidate.max": "\u4E0D\u80FD\u5927\u4E8E {max}",
610
+ "formValidate.maxlength": "\u6700\u591A\u8F93\u5165 {max} \u4E2A\u5B57\u7B26",
611
+ "formValidate.min": "\u4E0D\u80FD\u5C0F\u4E8E {min}",
612
+ "formValidate.minlength": "\u81F3\u5C11\u8F93\u5165 {min} \u4E2A\u5B57\u7B26",
613
+ "formValidate.number": "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u6570\u5B57",
614
+ "formValidate.pattern": "\u8F93\u5165\u683C\u5F0F\u4E0D\u6B63\u786E",
615
+ "formValidate.required": "\u6B64\u9879\u4E3A\u5FC5\u586B\u9879",
616
+ "formValidate.selectPlaceholder": "\u8BF7\u9009\u62E9",
617
+ "formValidate.step": "\u6570\u503C\u5FC5\u987B\u662F {step} \u7684\u500D\u6570",
618
+ "formValidate.summary": "\u8868\u5355\u6709 {p0} \u9879\u5185\u5BB9\u9700\u8981\u4FEE\u6B63\uFF0C\u8BF7\u4FEE\u6539\u540E\u91CD\u65B0\u63D0\u4EA4",
619
+ "formValidate.tool.description": "\u5411\u7528\u6237\u6E32\u67D3\u4E00\u4E2A\u7ED3\u6784\u5316\u8868\u5355\u6536\u96C6\u8F93\u5165",
620
+ "formValidate.tool.fields": "\u5B57\u6BB5\u5217\u8868",
621
+ "formValidate.tool.help": "\u5B57\u6BB5\u4E0B\u65B9\u7684\u5E2E\u52A9\u6587\u6848",
622
+ "formValidate.tool.label": "\u5B57\u6BB5\u6807\u7B7E",
623
+ "formValidate.tool.max": "\u6700\u5927\u503C\uFF08number \u7528\uFF09",
624
+ "formValidate.tool.min": "\u6700\u5C0F\u503C\uFF08number \u7528\uFF09",
625
+ "formValidate.tool.name": "\u5B57\u6BB5\u540D\uFF08\u63D0\u4EA4\u503C\u7684 key\uFF09",
626
+ "formValidate.tool.options": "select \u9009\u9879\uFF08\u5B57\u7B26\u4E32\u6216 {label,value}\uFF09",
627
+ "formValidate.tool.pattern": "\u6B63\u5219\u7EA6\u675F\uFF08HTML pattern \u8BED\u6CD5\uFF0C\u6574\u4E32\u5339\u914D\uFF09",
628
+ "formValidate.tool.required": "\u662F\u5426\u5FC5\u586B",
629
+ "formValidate.tool.submitText": "\u63D0\u4EA4\u6309\u94AE\u6587\u6848\uFF0C\u9ED8\u8BA4\u300C\u63D0\u4EA4\u300D",
630
+ "formValidate.tool.title": "\u8868\u5355\u6807\u9898\uFF08\u53EF\u9009\uFF09",
631
+ "formValidate.tool.type": "\u63A7\u4EF6\u7C7B\u578B\uFF0C\u9ED8\u8BA4 text",
632
+ "formValidate.url": "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u94FE\u63A5\u5730\u5740",
633
+ /* ── input ── */
634
+ "input.clearSearch": "\u6E05\u7A7A\u641C\u7D22",
635
+ "input.hidePassword": "\u9690\u85CF\u5BC6\u7801",
636
+ "input.otpPosition": "\u7B2C {p0} \u4F4D\uFF0C\u5171 {p1} \u4F4D",
637
+ "panel.expand": "\u5C55\u5F00",
638
+ "panel.collapse": "\u6298\u53E0",
639
+ "input.showPassword": "\u663E\u793A\u5BC6\u7801",
640
+ /* ── kbAccess ── */
641
+ "kbAccess.approveTip": "\u6279\u51C6\u8BE5\u8BBF\u95EE\u7533\u8BF7",
642
+ "kbAccess.approvedBadge": "\u5DF2\u6279\u51C6 \xB7 {p0}",
643
+ "kbAccess.approverNotePlaceholder": "\u7ED9\u8BF7\u6C42\u4EBA\u7684\u7559\u8A00\uFF08\u53EF\u9009\uFF09",
644
+ "kbAccess.daysLeft": "{p0} \u5929\u540E",
645
+ "kbAccess.defaultSubject": "\u8BE5\u5185\u5BB9",
646
+ "kbAccess.deniedHint": "\u672A\u901A\u8FC7\u2014\u2014\u53EF\u8C03\u6574\u7406\u7531\u540E\u91CD\u65B0\u7533\u8BF7",
647
+ "kbAccess.denyNoteLabel": "\u62D2\u7EDD\u7559\u8A00\uFF08\u53EF\u9009\uFF09",
648
+ "kbAccess.duration30d": "30 \u5929",
649
+ "kbAccess.duration7d": "7 \u5929",
650
+ "kbAccess.durationForever": "\u6C38\u4E45",
651
+ "kbAccess.durationLabel": "\u8BBF\u95EE\u65F6\u957F",
652
+ "kbAccess.expired": "\u5DF2\u5230\u671F",
653
+ "kbAccess.expiresAt": "{p0}\u5230\u671F",
654
+ "kbAccess.grantAsPrefix": "\u6279\u51C6\u4E3A{p0}",
655
+ "kbAccess.grantRoleLabel": "\u6279\u51C6\u89D2\u8272",
656
+ "kbAccess.hoursLeft": "{p0} \u5C0F\u65F6\u540E",
657
+ "kbAccess.minutesLeft": "{p0} \u5206\u949F\u540E",
658
+ "kbAccess.ownerLabel": "\u5185\u5BB9\u8D1F\u8D23\u4EBA",
659
+ "kbAccess.ownerPrefix": "\u8D1F\u8D23\u4EBA\uFF1A{p0}",
660
+ "kbAccess.reapply": "\u91CD\u65B0\u7533\u8BF7",
661
+ "kbAccess.reasonLabel": "\u7533\u8BF7\u7406\u7531",
662
+ "kbAccess.reasonPlaceholder": "\u8BF4\u660E\u4E1A\u52A1\u539F\u56E0\uFF08\u5BA1\u6279\u4EBA\u53EF\u89C1\uFF09",
663
+ "kbAccess.rejectTip": "\u62D2\u7EDD\u8BE5\u8BBF\u95EE\u7533\u8BF7",
664
+ "kbAccess.requestRenewal": "\u7533\u8BF7\u7EED\u671F",
665
+ "kbAccess.requestToPrefix": "\u8BF7\u6C42\u5C06\u53D1\u9001\u7ED9\uFF1A{p0}",
666
+ "kbAccess.restrictedContent": "\u53D7\u9650\u5185\u5BB9",
667
+ "kbAccess.restrictedHint": "\u6B64\u5185\u5BB9\u4EC5\u5BF9\u6388\u6743\u8005\u5F00\u653E",
668
+ "kbAccess.revokedHint": "\u8BBF\u95EE\u5DF2\u88AB\u6536\u56DE",
669
+ "kbAccess.roleLabel": "\u7533\u8BF7\u89D2\u8272",
670
+ "kbAccess.submitRequest": "\u63D0\u4EA4\u7533\u8BF7",
671
+ "kbAccess.switchIdentity": "\u5207\u6362\u8EAB\u4EFD",
672
+ "kbAccess.switchIdentityTip": "\u5207\u6362\u8EAB\u4EFD\u540E\u91CD\u65B0\u68C0\u67E5\u6743\u9650",
673
+ "kbAccess.unknownRequester": "\u672A\u77E5\u8BF7\u6C42\u4EBA",
674
+ "kbAccess.waitingApproval": "\u7B49\u5F85 {p0} \u5BA1\u6279",
675
+ /* ── kbAcl ── */
676
+ "kbAcl.breakHint": "\u505C\u6B62\u4ECE\u7236\u7EA7\u7EE7\u627F\uFF0C\u6539\u4E3A\u72EC\u7ACB\u7BA1\u7406\u672C\u9879\u6743\u9650",
677
+ "kbAcl.breakInheritance": "\u505C\u6B62\u7EE7\u627F",
678
+ "kbAcl.brokenNotice": "\u5DF2\u505C\u6B62\u7EE7\u627F\u2014\u2014\u672C\u9879\u6743\u9650\u72EC\u7ACB\u4E8E\u7236\u7EA7",
679
+ "kbAcl.detachedChildren": "{p0}\uFF1A{p1} \u4E2A\u5B50\u9879\u5DF2\u8131\u79BB",
680
+ "kbAcl.directAccess": "\u76F4\u63A5\u8BBF\u95EE",
681
+ "kbAcl.exception": "\u4F8B\u5916",
682
+ "kbAcl.expiredOn": "\u5DF2\u8FC7\u671F\uFF08{p0}\uFF09",
683
+ "kbAcl.expiresIn": "{p0} \u5230\u671F",
684
+ "kbAcl.grantAccess": "\u6388\u4E88\u8BBF\u95EE",
685
+ "kbAcl.inheritedFrom": "\u7EE7\u627F\u81EA {p0}",
686
+ "kbAcl.inheritedFromLabel": "\u7EE7\u627F\u81EA",
687
+ "kbAcl.linkAccess": "\u94FE\u63A5\u8BBF\u95EE",
688
+ "kbAcl.noDirect": "\u6682\u65E0\u76F4\u63A5\u6388\u6743",
689
+ "kbAcl.noLinks": "\u65E0\u94FE\u63A5",
690
+ "kbAcl.removeEntry": "\u79FB\u9664 {p0}",
691
+ "kbAcl.restoreHint": "\u6062\u590D\u7EE7\u627F\u5C06\u4E22\u5F03\u672C\u9879\u81EA\u5B9A\u4E49\u7684\u6743\u9650",
692
+ "kbAcl.restoreInheritance": "\u6062\u590D\u7EE7\u627F",
693
+ "kbAcl.rootNotice": "\u6839\u7EA7\u8D44\u6E90\u2014\u2014\u65E0\u7236\u7EA7\u7EE7\u627F",
694
+ "kbAcl.systemBadge": "\u7CFB\u7EDF\u7BA1\u7406",
695
+ "kbAcl.systemNote": "\u7CFB\u7EDF\u81EA\u52A8\uFF0C\u4E0D\u53EF\u624B\u5DE5\u79FB\u9664",
696
+ "kbAcl.unnamedResource": "\u672A\u547D\u540D\u8D44\u6E90",
697
+ "kbAcl.visibleToCount": "\u5BF9 {p0} \u4EBA\u53EF\u89C1",
698
+ /* ── kbAnswer ── */
699
+ "kbAnswer.chartBar": "\u67F1\u72B6",
700
+ "kbAnswer.chartLine": "\u6298\u7EBF",
701
+ "kbAnswer.chartPie": "\u997C\u56FE",
702
+ "kbAnswer.exportNoun": "\u5BFC\u51FA {p0}",
703
+ "kbAnswer.filtered": "\u5DF2\u6309\u4F60\u7684\u6570\u636E\u6743\u9650\u8FC7\u6EE4",
704
+ "kbAnswer.filteredDetail": "\u5DF2\u6309\u4F60\u7684\u6570\u636E\u6743\u9650\u8FC7\u6EE4\uFF1A{p0}",
705
+ "kbAnswer.followups": "\u8FFD\u95EE\u5EFA\u8BAE",
706
+ "kbAnswer.hitAssets": "\u547D\u4E2D\u8D44\u4EA7\uFF1A{p0}",
707
+ "kbAnswer.kindCurated": "\u4EBA\u5DE5\u7B56\u5C55",
708
+ "kbAnswer.kindFunction": "\u51FD\u6570",
709
+ "kbAnswer.kindParameterized": "\u53C2\u6570\u5316\u67E5\u8BE2",
710
+ "kbAnswer.maskedPrefix": "\u5DF2\u8131\u654F\u5217\uFF1A",
711
+ "kbAnswer.rerunTip": "\u53C2\u6570\u53EF\u6539\u91CD\u8DD1",
712
+ "kbAnswer.truncated": "\u5DF2\u622A\u65AD\uFF1A\u663E\u793A {p0}/{p1} \u884C{p2}",
713
+ "kbAnswer.verifiedBadge": "\u8BA4\u8BC1\u7B54\u6848",
714
+ /* ── kbAudit ── */
715
+ "kbAudit.actionDetail": "\u5904\u7F6E\uFF1A{p0} \xB7 {p1}",
716
+ "kbAudit.actionLabel": "\u5904\u7F6E",
717
+ "kbAudit.alertedNote": "\u5DF2\u5B9E\u65F6\u544A\u8B66\u5B89\u5168\u56E2\u961F",
718
+ "kbAudit.channelFilterAria": "\u5BA1\u8BA1\u901A\u9053\u8FC7\u6EE4",
719
+ "kbAudit.channelPermission": "\u6743\u9650\u53D8\u66F4",
720
+ "kbAudit.channelRead": "\u8BFB\u53D6",
721
+ "kbAudit.channelRequest": "\u7533\u8BF7",
722
+ "kbAudit.channelSystem": "\u7CFB\u7EDF",
723
+ "kbAudit.empty": "\u6682\u65E0\u5BA1\u8BA1\u4E8B\u4EF6",
724
+ "kbAudit.exportTip": "\u5BFC\u51FA\u5F53\u524D\u8FC7\u6EE4\u89C6\u56FE\u4E3A CSV",
725
+ "kbAudit.hygieneLabel": "\u6743\u9650\u5F02\u5473",
726
+ "kbAudit.noHygiene": "\u672A\u53D1\u73B0\u6743\u9650\u5F02\u5473",
727
+ /* ── kbCanvas ── */
728
+ "kbCanvas.splitterAria": "\u8C03\u6574\u753B\u5E03\u53CC\u680F\u6BD4\u4F8B",
729
+ "kbCanvas.splitterTip": "\u62D6\u62FD\u8C03\u6574\u6BD4\u4F8B\uFF08\u2190/\u2192 \u5FAE\u8C03\uFF0C\u53CC\u51FB\u590D\u4F4D\uFF09",
730
+ /* ── kbCheckpoint ── */
731
+ "kbCheckpoint.chatAuditNote": "\u8BA8\u8BBA\u5386\u53F2\u6709\u5BA1\u8BA1\u4EF7\u503C",
732
+ "kbCheckpoint.label": "\u68C0\u67E5\u70B9",
733
+ "kbCheckpoint.restore": "\u6062\u590D\u68C0\u67E5\u70B9",
734
+ "kbCheckpoint.scopeBoth": "\u5185\u5BB9\u4E0E\u5BF9\u8BDD",
735
+ "kbCheckpoint.scopeChat": "\u4EC5\u5BF9\u8BDD",
736
+ "kbCheckpoint.scopeContent": "\u4EC5\u5185\u5BB9\uFF08\u4FDD\u7559\u5BF9\u8BDD\uFF09",
737
+ "kbCheckpoint.scopeMissing": "\u8BE5\u68C0\u67E5\u70B9\u672A\u5305\u542B\u6B64\u6062\u590D\u8303\u56F4",
738
+ /* ── kbChunks ── */
739
+ "kbChunks.addKeyword": "+ \u5173\u952E\u8BCD",
740
+ "kbChunks.chunkAddKeywordAria": "chunk {p0} \u65B0\u589E\u5173\u952E\u8BCD",
741
+ "kbChunks.chunkContentAria": "chunk {p0} \u5185\u5BB9",
742
+ "kbChunks.chunkEnableAria": "chunk {p0} \u542F\u7528",
743
+ "kbChunks.deleteChunkAria": "\u5220\u9664 chunk {p0}",
744
+ "kbChunks.disableNote": "\u5173\u95ED\u540E\u4E0D\u5220\u9664\uFF0C\u4EC5\u6392\u9664\u51FA\u68C0\u7D22",
745
+ "kbChunks.edited": "\u5DF2\u7F16\u8F91",
746
+ "kbChunks.empty": "\u6682\u65E0 chunk",
747
+ "kbChunks.modeFull": "\u5168\u6587",
748
+ "kbChunks.modeLabel": "\u641C\u7D22\u6A21\u5F0F",
749
+ "kbChunks.modeVector": "\u8BED\u4E49",
750
+ "kbChunks.removeKeyword": "\u79FB\u9664\u5173\u952E\u8BCD {p0}",
751
+ "kbChunks.searchAria": "\u641C\u7D22 chunk",
752
+ "kbChunks.searchFullPlaceholder": "\u5168\u6587\u641C\u7D22 chunk\u2026",
753
+ "kbChunks.searchVectorPlaceholder": "\u8BED\u4E49\u641C\u7D22 chunk\u2026",
754
+ /* ── kbCitation ── */
755
+ "kbCitation.sourceN": "\u6765\u6E90 {p0}",
756
+ "kbCitation.unavailable": "\u6765\u6E90\u5DF2\u4E0D\u53EF\u7528",
757
+ /* ── kbClarify ── */
758
+ "kbClarify.parsedPrefix": "\u5DF2\u89E3\u6790\uFF1A",
759
+ /* ── kbConflict ── */
760
+ "kbConflict.owner": "\u8D23\u4EFB\u4EBA {p0}",
761
+ /* ── kbConnector ── */
762
+ "kbConnector.changeRate": "\u53D8\u66F4\u7387",
763
+ "kbConnector.crawlRate": "\u6293\u53D6\u7387",
764
+ "kbConnector.credentials": "\u51ED\u8BC1",
765
+ "kbConnector.credentialsExpired": "\u51ED\u8BC1\u8FC7\u671F",
766
+ "kbConnector.editSchedule": "\u7F16\u8F91\u8BA1\u5212",
767
+ "kbConnector.empty": "\u6682\u65E0\u8FDE\u63A5\u5668",
768
+ "kbConnector.failing": "\u5F02\u5E38",
769
+ "kbConnector.lastSync": "\u6700\u8FD1\u540C\u6B65 {p0}",
770
+ "kbConnector.neverSynced": "\u4ECE\u672A\u540C\u6B65",
771
+ "kbConnector.notConfigured": "\u672A\u914D\u7F6E",
772
+ "kbConnector.off": "\u5DF2\u505C\u7528",
773
+ "kbConnector.perDay": "{p0}/\u5929",
774
+ "kbConnector.reauth": "\u91CD\u65B0\u6388\u6743",
775
+ "kbConnector.stale": "\u505C\u6EDE",
776
+ "kbConnector.syncNow": "\u7ACB\u5373\u540C\u6B65",
777
+ "kbConnector.synced": "\u5DF2\u540C\u6B65",
778
+ /* ── kbCore ── */
779
+ "kbCore.accessDenied": "\u672A\u901A\u8FC7",
780
+ "kbCore.accessExpired": "\u5DF2\u8FC7\u671F",
781
+ "kbCore.accessExpiring": "\u5373\u5C06\u5230\u671F",
782
+ "kbCore.accessGranted": "\u5DF2\u5F00\u901A",
783
+ "kbCore.accessNotRequested": "\u672A\u7533\u8BF7",
784
+ "kbCore.accessPending": "\u5F85\u5BA1\u6279",
785
+ "kbCore.accessRequested": "\u5DF2\u63D0\u4EA4",
786
+ "kbCore.accessRevoked": "\u5DF2\u6536\u56DE",
787
+ "kbCore.auditApprove": "\u6279\u51C6",
788
+ "kbCore.auditBreakGlass": "\u5E94\u6025\u8BBF\u95EE",
789
+ "kbCore.auditDelegation": "\u59D4\u6D3E",
790
+ "kbCore.auditDeny": "\u62D2\u7EDD",
791
+ "kbCore.auditGrant": "\u6388\u4E88",
792
+ "kbCore.auditPermissionChange": "\u6743\u9650\u53D8\u66F4",
793
+ "kbCore.auditPreview": "\u9884\u89C8",
794
+ "kbCore.auditRead": "\u8BFB\u53D6",
795
+ "kbCore.auditRequest": "\u7533\u8BF7",
796
+ "kbCore.auditRevoke": "\u6536\u56DE",
797
+ "kbCore.auditSync": "\u6743\u9650\u540C\u6B65",
798
+ "kbCore.daysAgo": "{p0} \u5929\u524D",
799
+ "kbCore.hoursAgo": "{p0} \u5C0F\u65F6\u524D",
800
+ "kbCore.hygieneBroadGroup": "\u8FC7\u5BBD\u7EC4\u6388\u6743",
801
+ "kbCore.hygieneBrokenInheritance": "\u65AD\u7EE7\u627F",
802
+ "kbCore.hygieneOrgWideLink": "\u7EC4\u7EC7\u7EA7\u94FE\u63A5",
803
+ "kbCore.hygieneOrphanedOwner": "\u8D1F\u8D23\u4EBA\u7F3A\u4F4D",
804
+ "kbCore.hygieneOverexposed": "\u8FC7\u5EA6\u66B4\u9732",
805
+ "kbCore.hygieneSensitiveMismatch": "\u654F\u611F\u5EA6\u9519\u914D",
806
+ "kbCore.justNow": "\u521A\u521A",
807
+ "kbCore.levelComment": "\u53EF\u8BC4\u8BBA",
808
+ "kbCore.levelEdit": "\u53EF\u7F16\u8F91",
809
+ "kbCore.levelNone": "\u65E0\u6743\u9650",
810
+ "kbCore.levelOwner": "\u8D1F\u8D23\u4EBA",
811
+ "kbCore.levelView": "\u53EF\u67E5\u770B",
812
+ "kbCore.minutesAgo": "{p0} \u5206\u949F\u524D",
813
+ "kbCore.runCancelled": "\u5DF2\u53D6\u6D88",
814
+ "kbCore.runDone": "\u5DF2\u5B8C\u6210",
815
+ "kbCore.runFailed": "\u5931\u8D25",
816
+ "kbCore.runQueued": "\u6392\u961F\u4E2D",
817
+ "kbCore.runRunning": "\u8FDB\u884C\u4E2D",
818
+ "kbCore.runUnstarted": "\u672A\u5F00\u59CB",
819
+ "kbCore.stageAgent": "\u4EE3\u7406",
820
+ "kbCore.stageChunk": "\u5207\u7247",
821
+ "kbCore.stageEmbed": "\u5411\u91CF\u5316",
822
+ "kbCore.stageGeneration": "\u751F\u6210",
823
+ "kbCore.stageGuard": "\u62A4\u680F",
824
+ "kbCore.stageQuery": "\u67E5\u8BE2",
825
+ "kbCore.stageRerank": "\u91CD\u6392",
826
+ "kbCore.stageRetrieval": "\u68C0\u7D22",
827
+ "kbCore.stageTool": "\u5DE5\u5177",
828
+ "kbCore.typeApi": "\u63A5\u53E3",
829
+ "kbCore.typeCode": "\u4EE3\u7801",
830
+ "kbCore.typeDatabase": "\u6570\u636E\u5E93",
831
+ "kbCore.typeDocument": "\u6587\u6863",
832
+ "kbCore.typeEmail": "\u90AE\u4EF6",
833
+ "kbCore.typeImage": "\u56FE\u7247",
834
+ "kbCore.typeKb": "\u77E5\u8BC6\u5E93",
835
+ "kbCore.typeTable": "\u8868\u683C",
836
+ "kbCore.typeTicket": "\u5DE5\u5355",
837
+ "kbCore.typeWebpage": "\u7F51\u9875",
838
+ "kbCore.unnamedSource": "\u672A\u547D\u540D\u6765\u6E90",
839
+ "kbCore.unnamedSubject": "\u672A\u547D\u540D\u4E3B\u4F53",
840
+ "kbCore.visHidden": "\u4E0D\u53EF\u89C1",
841
+ "kbCore.visMetadataOnly": "\u4EC5\u5143\u6570\u636E",
842
+ "kbCore.visSummaryOnly": "\u4EC5\u6458\u8981",
843
+ "kbCore.visVisible": "\u53EF\u89C1",
844
+ /* ── kbEval ── */
845
+ "kbEval.avgA": "A \u5747\u5206 {p0}",
846
+ "kbEval.avgB": "B \u5747\u5206 {p0}",
847
+ "kbEval.compare": "\u5BF9\u6BD4",
848
+ "kbEval.runSelectAria": "\u9009\u62E9\u5BF9\u6BD4\u8FD0\u884C",
849
+ "kbEval.expected": "\u671F\u671B",
850
+ "kbEval.gradeImprovement": "\u63D0\u5347",
851
+ "kbEval.gradeRegression": "\u56DE\u5F52",
852
+ "kbEval.gradeTie": "\u6301\u5E73",
853
+ "kbEval.gradeTradeoff": "\u6743\u8861",
854
+ "kbEval.noData": "\u6CA1\u6709\u5BF9\u6BD4\u6570\u636E",
855
+ "kbEval.onlyRegression": "\u4EC5\u770B\u56DE\u5F52",
856
+ "kbEval.outputA": "\u8F93\u51FA A",
857
+ "kbEval.outputB": "\u8F93\u51FA B",
858
+ "kbEval.outputN": "\u8F93\u51FA {p0}",
859
+ /* ── kbExplain ── */
860
+ "kbExplain.empty": "\u6682\u65E0\u53E3\u5F84\u4FE1\u606F",
861
+ "kbExplain.groupAgg": "\u805A\u5408",
862
+ "kbExplain.groupColumn": "\u5217",
863
+ "kbExplain.groupFilter": "\u7B5B\u9009",
864
+ "kbExplain.groupTable": "\u8868",
865
+ "kbExplain.trigger": "\u8FD9\u4E2A\u6570\u5B57\u662F\u600E\u4E48\u7B97\u51FA\u6765\u7684",
866
+ "kbExplain.viewDefinition": "\u67E5\u770B\u53E3\u5F84",
867
+ /* ── kbFilter ── */
868
+ "kbFilter.addGroup": "+ \u7EC4",
869
+ "kbFilter.addRule": "+ \u89C4\u5219",
870
+ "kbFilter.and": "\u4E14",
871
+ "kbFilter.combineMode": "\u7EC4\u5408\u65B9\u5F0F {p0}",
872
+ "kbFilter.copyDsl": "\u590D\u5236 DSL",
873
+ "kbFilter.deleteGroup": "\u5220\u9664\u7EC4",
874
+ "kbFilter.deleteRule": "\u5220\u9664\u89C4\u5219",
875
+ "kbFilter.fieldLabel": "\u5B57\u6BB5",
876
+ "kbFilter.fieldPlaceholder": "\u8FC7\u6EE4\u5B57\u6BB5",
877
+ "kbFilter.noValueNeeded": "\uFF08\u65E0\u9700\u503C\uFF09",
878
+ "kbFilter.none": "\uFF08\u65E0\u8FC7\u6EE4\uFF09",
879
+ "kbFilter.opContains": "\u5305\u542B",
880
+ "kbFilter.opEq": "\u7B49\u4E8E",
881
+ "kbFilter.opExists": "\u5B58\u5728",
882
+ "kbFilter.opGt": "\u5927\u4E8E",
883
+ "kbFilter.opGte": "\u5927\u4E8E\u7B49\u4E8E",
884
+ "kbFilter.opIn": "\u5C5E\u4E8E",
885
+ "kbFilter.opLt": "\u5C0F\u4E8E",
886
+ "kbFilter.opLte": "\u5C0F\u4E8E\u7B49\u4E8E",
887
+ "kbFilter.opNe": "\u4E0D\u7B49\u4E8E",
888
+ "kbFilter.operatorLabel": "\u64CD\u4F5C\u7B26",
889
+ "kbFilter.or": "\u6216",
890
+ "kbFilter.toggleAndOr": "\u5207\u6362 AND / OR",
891
+ "kbFilter.valueAria": "\u8FC7\u6EE4\u503C",
892
+ "kbFilter.valueLabel": "\u503C",
893
+ "kbFilter.valuePlaceholder": "\u503C 1, \u503C 2\uFF08\u9017\u53F7\u5206\u9694\uFF09",
894
+ /* ── kbGap ── */
895
+ "kbGap.addSynonym": "\u52A0\u540C\u4E49\u8BCD",
896
+ "kbGap.colCount": "\u6B21\u6570",
897
+ "kbGap.colLastSeen": "\u6700\u8FD1\u51FA\u73B0",
898
+ "kbGap.colQuery": "\u67E5\u8BE2",
899
+ "kbGap.colShare": "\u5360\u6BD4",
900
+ "kbGap.createDoc": "\u5EFA\u6587\u6863",
901
+ "kbGap.empty": "\u6CA1\u6709\u672A\u547D\u4E2D\u67E5\u8BE2\u2014\u2014\u8986\u76D6\u826F\u597D",
902
+ "kbGap.title": "\u672A\u547D\u4E2D\u67E5\u8BE2\u8D8B\u52BF",
903
+ "kbGap.zeroClickHint": "\u7528\u6237\u53EF\u80FD\u5DF2\u4ECE\u5F15\u7528\u7247\u6BB5\u5F97\u5230\u7B54\u6848\uFF1B\u96F6\u70B9\u51FB\u9700\u4EBA\u5DE5\u5224\u8BFB\uFF0C\u4E0D\u76F4\u63A5\u89C6\u4E3A\u5931\u8D25",
904
+ "kbGap.zeroClickRate": "\u96F6\u70B9\u51FB\u7387",
905
+ "kbGap.zeroClickTitle": "\u96F6\u70B9\u51FB \u2260 \u5931\u8D25",
906
+ /* ── kbHittest ── */
907
+ "kbHittest.addAria": "\u65B0\u589E\u6D4B\u8BD5\u95EE\u9898",
908
+ "kbHittest.addPlaceholder": "\u65B0\u589E\u95EE\u9898\uFF0CEnter \u6DFB\u52A0",
909
+ "kbHittest.avgScore": "\u5747\u5206",
910
+ "kbHittest.deleteQuestion": "\u5220\u9664\u95EE\u9898",
911
+ "kbHittest.empty": "\u6682\u65E0\u6D4B\u8BD5\u95EE\u9898\u2014\u2014\u6DFB\u52A0\u7B2C\u4E00\u6761\uFF0C\u5F00\u59CB\u53EC\u56DE\u56DE\u5F52",
912
+ "kbHittest.expectHit": "\u671F\u671B\u547D\u4E2D\u5728\u524D\u6392\u547D\u4E2D\u4E2D",
913
+ "kbHittest.expectMiss": "\u671F\u671B\u672A\u547D\u4E2D",
914
+ "kbHittest.hitRate": "\u547D\u4E2D\u7387",
915
+ "kbHittest.noExpectation": "\u672A\u8BBE\u671F\u671B",
916
+ "kbHittest.notRun": "\u672A\u8FD0\u884C",
917
+ "kbHittest.pass": "\u901A\u8FC7",
918
+ "kbHittest.pin": "\u7F6E\u9876\u56FA\u5B9A",
919
+ "kbHittest.runAll": "\u8FD0\u884C\u5168\u90E8",
920
+ "kbHittest.sessionOnly": "\u53C2\u6570\u4EC5\u672C\u6B21\u4F1A\u8BDD\u751F\u6548",
921
+ "kbHittest.sessionOnlyHint": "\u6D4B\u8BD5\u8FD0\u884C\u7684\u68C0\u7D22\u53C2\u6570\uFF08topK/\u9608\u503C/\u91CD\u6392\uFF09\u4E0D\u843D\u5E93\uFF0C\u4EC5\u672C\u6B21\u4F1A\u8BDD\u751F\u6548",
922
+ "kbHittest.unpin": "\u53D6\u6D88\u7F6E\u9876",
923
+ /* ── kbMetadata ── */
924
+ "kbMetadata.addField": "\u65B0\u589E\u5B57\u6BB5",
925
+ "kbMetadata.builtIn": "\u5185\u7F6E",
926
+ "kbMetadata.colField": "\u5B57\u6BB5",
927
+ "kbMetadata.colType": "\u7C7B\u578B",
928
+ "kbMetadata.colValue": "\u503C",
929
+ "kbMetadata.empty": "\u6682\u65E0\u5143\u6570\u636E\u5B57\u6BB5",
930
+ "kbMetadata.nameLabel": "\u65B0\u5B57\u6BB5\u540D",
931
+ "kbMetadata.namePlaceholder": "\u5B57\u6BB5\u540D\uFF0C\u5982 department",
932
+ "kbMetadata.removeField": "\u79FB\u9664\u5B57\u6BB5 {p0}",
933
+ "kbMetadata.typeLabel": "\u65B0\u5B57\u6BB5\u7C7B\u578B",
934
+ "kbMetadata.valueOf": "{p0} \u7684\u503C",
935
+ /* ── kbPassage ── */
936
+ "kbPassage.blockRange": "\u5757 {p0}\u2013{p1}",
937
+ "kbPassage.close": "\u5173\u95ED\u539F\u6587",
938
+ "kbPassage.expandContext": "\u5C55\u5F00\u4E0A\u4E0B\u6587",
939
+ "kbPassage.locate": "\u539F\u6587\u5B9A\u4F4D",
940
+ "kbPassage.none": "\uFF08\u65E0\u539F\u6587\uFF09",
941
+ "kbPassage.pageRange": "\u7B2C {p0}\u2013{p1} \u9875",
942
+ "kbPassage.restricted": "\u5185\u5BB9\u53D7\u9650",
943
+ "kbPassage.unitByte": "\u5B57\u8282",
944
+ "kbPassage.unitChar": "\u5B57\u7B26",
945
+ /* ── kbPipeline ── */
946
+ "kbPipeline.empty": "\u6682\u65E0\u89E3\u6790\u4EFB\u52A1",
947
+ "kbPipeline.progress": "\u89E3\u6790\u8FDB\u5EA6",
948
+ "kbPipeline.rerun": "\u91CD\u8DD1",
949
+ "kbPipeline.unknownStage": "\u672A\u77E5\u9636\u6BB5",
950
+ /* ── kbQa ── */
951
+ "kbQa.colAnswer": "\u7B54\u6848",
952
+ "kbQa.colQuestion": "\u95EE\u9898",
953
+ "kbQa.csvHint": "CSV \u6A21\u677F\uFF1Aquestion,answer\uFF08\u6BCF\u884C\u4E00\u5BF9\uFF0CUTF-8\uFF09",
954
+ "kbQa.deleteRow": "\u5220\u9664\u7B2C {p0} \u884C",
955
+ "kbQa.empty": "\u6682\u65E0\u8BA4\u8BC1\u95EE\u7B54\u5BF9",
956
+ "kbQa.importCsv": "\u5BFC\u5165 CSV",
957
+ /* ── kbRerank ── */
958
+ "kbRerank.after": "\u91CD\u6392\u540E",
959
+ "kbRerank.before": "\u91CD\u6392\u524D",
960
+ "kbRerank.compareTitle": "\u91CD\u6392\u5BF9\u6BD4",
961
+ "kbRerank.down": "\u4E0B\u964D {p0} \u4F4D",
962
+ "kbRerank.dropped": "\u843D\u9009",
963
+ "kbRerank.empty": "\u4E24\u4FA7\u5747\u4E3A\u7A7A\u2014\u2014\u8FD0\u884C\u68C0\u7D22\u540E\u518D\u5BF9\u6BD4",
964
+ "kbRerank.enableCompare": "\u542F\u7528\u91CD\u6392\u5BF9\u6BD4",
965
+ "kbRerank.newIn": "\u65B0\u8FDB",
966
+ "kbRerank.unmarked": "\u672A\u6807",
967
+ "kbRerank.up": "\u4E0A\u5347 {p0} \u4F4D",
968
+ /* ── kbRetrieval ── */
969
+ "kbRetrieval.breakdown": "\u62C6\u89E3",
970
+ "kbRetrieval.copyParams": "\u590D\u5236\u53C2\u6570 JSON",
971
+ "kbRetrieval.decreaseTopK": "\u51CF\u5C11 topK",
972
+ "kbRetrieval.empty": "\u8F93\u5165\u95EE\u9898\u5E76\u8FD0\u884C\uFF0C\u547D\u4E2D\u7ED3\u679C\u5C06\u51FA\u73B0\u5728\u8FD9\u91CC",
973
+ "kbRetrieval.failOpenNotice": "fail-open\uFF1A\u5F53\u524D\u67E5\u8BE2\u672A\u643A\u5E26\u8EAB\u4EFD\u8FC7\u6EE4\uFF0C\u5C06\u8FD4\u56DE\u5168\u90E8\u5019\u9009\uFF08\u4EC5\u9650\u8C03\u8BD5\uFF09",
974
+ "kbRetrieval.hybridWeight": "\u6DF7\u5408\u6743\u91CD\uFF08\u5DE6\u8BED\u4E49\u53F3\u5173\u952E\u8BCD\uFF09",
975
+ "kbRetrieval.identityLabel": "\u68C0\u7D22\u8EAB\u4EFD",
976
+ "kbRetrieval.identityShort": "\u8EAB\u4EFD",
977
+ "kbRetrieval.increaseTopK": "\u589E\u52A0 topK",
978
+ "kbRetrieval.keywordHint": "\u5173\u952E\u8BCD\uFF1A\u5927\u5E93\u5FEB\u901F\u7CBE\u786E",
979
+ "kbRetrieval.layerLabel": "\u8FC7\u6EE4\u5C42",
980
+ "kbRetrieval.layerNone": "none\uFF1Afail-open\uFF0C\u65E0\u8EAB\u4EFD\u8FC7\u6EE4\u8FD4\u56DE\u5168\u90E8\u2014\u2014\u5371\u9669\uFF0C\u4EC5\u6F14\u793A",
981
+ "kbRetrieval.layerPost": "post-filter\uFF1A\u5206\u6570\u5DF2\u53EF\u89C2\u5BDF\u2014\u2014\u7F3A\u9677\u5C42\uFF0C\u4EC5\u6F14\u793A",
982
+ "kbRetrieval.layerPre": "pre-filter\uFF1AACL \u5728\u68C0\u7D22\u6267\u884C\u4F53\u5185\u751F\u6548\u2014\u2014\u5B89\u5168\u57FA\u7EBF",
983
+ "kbRetrieval.leakNote": "\u5206\u6BCD\u672A\u8FC7\u6EE4\u524D\u8BA1\u6570\u5C5E\u6CC4\u9732\uFF0C\u4E0D\u663E\u793A",
984
+ "kbRetrieval.modeHybrid": "\u6DF7\u5408",
985
+ "kbRetrieval.modeKeyword": "\u5173\u952E\u8BCD",
986
+ "kbRetrieval.modeLabel": "\u68C0\u7D22\u6A21\u5F0F",
987
+ "kbRetrieval.modeVector": "\u5411\u91CF",
988
+ "kbRetrieval.postFilterNotice": "post-filter\uFF1A\u5206\u6570\u5DF2\u5728\u8FC7\u6EE4\u524D\u4EA7\u751F\uFF08\u7F3A\u9677\u5C42\u6F14\u793A\uFF09",
989
+ "kbRetrieval.queryLabel": "\u68C0\u7D22\u95EE\u9898",
990
+ "kbRetrieval.queryPlaceholder": "\u68C0\u7D22\u95EE\u9898\uFF0CEnter \u8FD0\u884C",
991
+ "kbRetrieval.rerankLabel": "\u91CD\u6392",
992
+ "kbRetrieval.rerankThresholdOff": "\u9608\u503C \u5173 \xB7 \u5B58\u6D3B {p0}",
993
+ "kbRetrieval.rerankThresholdOn": "\u9608\u503C {p0} \xB7 \u5B58\u6D3B {p1}",
994
+ "kbRetrieval.running": "\u8FD0\u884C\u4E2D\u2026",
995
+ "kbRetrieval.thresholdLabel": "\u5206\u6570\u9608\u503C",
996
+ "kbRetrieval.thresholdValue": "\u9608\u503C N/A",
997
+ "kbRetrieval.vectorHint": "\u8BED\u4E49\uFF1A\u8DE8\u8BED\u8A00/\u65E0\u7CBE\u786E\u8BCD",
998
+ "kbRetrieval.vectorPercent": "\u8BED\u4E49 {p0}",
999
+ "kbRetrieval.weightValue": "\u5411\u91CF {p0}% / \u5173\u952E\u8BCD {p1}%",
1000
+ /* ── kbReview ── */
1001
+ "kbReview.assignee": "\u5206\u914D\u4EBA",
1002
+ "kbReview.doneNext": "\u5B8C\u6210\u5E76\u4E0B\u4E00\u6761",
1003
+ "kbReview.empty": "\u6CA1\u6709\u5F85\u5BA1\u67E5\u6761\u76EE",
1004
+ "kbReview.emptyAssignee": "\u8BE5\u5206\u914D\u4EBA\u4E0B\u6CA1\u6709\u6761\u76EE",
1005
+ "kbReview.emptyQueue": "\u961F\u5217\u4E3A\u7A7A",
1006
+ "kbReview.kbCloseHint": "\u5173\u95ED\u63D0\u793A",
1007
+ "kbReview.kbSelectOption": "\u9009\u62E9\u9009\u9879",
1008
+ "kbReview.kbSwitchItem": "\u5207\u6362\u6761\u76EE",
1009
+ "kbReview.kbToggleHint": "\u663E\u793A/\u9690\u85CF\u672C\u63D0\u793A",
1010
+ "kbReview.shortcuts": "? \u5FEB\u6377\u952E",
1011
+ "kbReview.typeAnswer": "\u56DE\u7B54",
1012
+ "kbReview.typeMessage": "\u6D88\u606F",
1013
+ "kbReview.typeTrace": "\u8F68\u8FF9",
1014
+ "kbReview.unassigned": "\u672A\u5206\u914D",
1015
+ /* ── kbSandbox ── */
1016
+ "kbSandbox.noResolver": "\u5BBF\u4E3B\u672A\u63D0\u4F9B ui:// \u89E3\u6790\u5668",
1017
+ "kbSandbox.notReady": "kb-sandbox: \u5E94\u7528\u672A\u5C31\u7EEA",
1018
+ "kbSandbox.resolveFailed": "ui:// \u89E3\u6790\u5931\u8D25\uFF1A{p0}",
1019
+ "kbSandbox.timeout": "kb-sandbox: \u8C03\u7528\u8D85\u65F6\uFF08{p0}ms\uFF09",
1020
+ "kbSandbox.title": "MCP App \u6C99\u7BB1",
1021
+ /* ── kbSegment ── */
1022
+ "kbSegment.avgLength": "\u5747\u957F {p0}",
1023
+ "kbSegment.childNote": "\u5B50\u5206\u6BB5\u6309\u957F\u5EA6\u81EA\u52A8\u751F\u6210",
1024
+ "kbSegment.cleanBlankLines": "\u5408\u5E76\u8FDE\u7EED\u7A7A\u884C",
1025
+ "kbSegment.cleanEmails": "\u53BB\u9664\u90AE\u7BB1",
1026
+ "kbSegment.cleanLinks": "\u53BB\u9664\u94FE\u63A5",
1027
+ "kbSegment.empty": "\u6837\u672C\u4E3A\u7A7A\uFF0C\u6682\u65E0\u53EF\u9884\u89C8\u5206\u6BB5",
1028
+ "kbSegment.maxLengthLabel": "\u6700\u5927\u957F\u5EA6",
1029
+ "kbSegment.maxLengthPlaceholder": "\u5206\u6BB5\u6700\u5927\u957F\u5EA6",
1030
+ "kbSegment.modeAuto": "\u81EA\u52A8",
1031
+ "kbSegment.modeCustom": "\u81EA\u5B9A\u4E49",
1032
+ "kbSegment.modeLabel": "\u5206\u6BB5\u6A21\u5F0F",
1033
+ "kbSegment.modeNote": "\u5206\u6BB5\u6A21\u5F0F\u521B\u5EFA\u540E\u4E0D\u53EF\u66F4\u6539\uFF0C\u53C2\u6570\u53EF\u968F\u65F6\u8C03\u6574",
1034
+ "kbSegment.modeParentChild": "\u7236\u5B50",
1035
+ "kbSegment.overlapInvalid": "\u91CD\u53E0\u9700\u5C0F\u4E8E\u6700\u5927\u957F\u5EA6",
1036
+ "kbSegment.overlapLabel": "\u91CD\u53E0",
1037
+ "kbSegment.overlapPlaceholder": "\u5206\u6BB5\u91CD\u53E0",
1038
+ "kbSegment.previewNote": "\u5171 {p0} \u6BB5\uFF0C\u4EC5\u9884\u89C8\u524D {p1} \u6BB5",
1039
+ "kbSegment.segmentsCount": "{p0} \u6BB5",
1040
+ "kbSegment.separatorLabel": "\u5206\u9694\u7B26",
1041
+ "kbSegment.separatorPlaceholder": "\u5206\u6BB5\u5206\u9694\u7B26",
1042
+ "kbSegment.toggleTip": "\u70B9\u51FB\u5C55\u5F00/\u6536\u8D77",
1043
+ /* ── kbSources ── */
1044
+ "kbSources.cited": "\u88AB\u5F15 \xD7{p0}",
1045
+ "kbSources.empty": "\u4E0B\u4E00\u6761\u7B54\u6848\u5F15\u7528\u7684\u6BB5\u843D\u5C06\u51FA\u73B0\u5728\u8FD9\u91CC",
1046
+ /* ── kbSql ── */
1047
+ "kbSql.adminOnly": "\u4EC5\u7BA1\u7406\u5458\u53EF\u89C1",
1048
+ "kbSql.applyFix": "\u5E94\u7528\u4FEE\u590D\u5E76\u91CD\u8DD1",
1049
+ "kbSql.confirmRerun": "\u786E\u8BA4\u5E76\u91CD\u8DD1",
1050
+ "kbSql.editRerun": "\u7F16\u8F91\u91CD\u8DD1",
1051
+ "kbSql.fixReady": "\u68C0\u6D4B\u5230\u4E0A\u7248\u62A5\u9519\uFF0C\u4FEE\u590D\u5EFA\u8BAE\u5DF2\u5C31\u7EEA",
1052
+ "kbSql.generated": "\u751F\u6210\u7684 SQL",
1053
+ /* ── kbTrace ── */
1054
+ "kbTrace.empty": "\u6682\u65E0\u8C03\u7528\u94FE\u6570\u636E",
1055
+ "kbTrace.hits": "\u547D\u4E2D {p0}",
1056
+ /* ── kbVisibility ── */
1057
+ "kbVisibility.adminOnlyNote": "\u4EE5\u4E0A\u5BF9\u7167\u4EC5\u9650 admin \u5BA1\u8BA1",
1058
+ "kbVisibility.adminWarn": "admin \u5BA1\u8BA1\u89C6\u56FE\u2014\u2014\u547D\u4E2D\u5DEE\u5F02\u5BF9\u7167\u5BF9\u666E\u901A\u7528\u6237\u6784\u6210\u6CC4\u9732\uFF0C\u52FF\u5D4C\u5165\u7EC8\u7AEF\u7528\u6237\u754C\u9762",
1059
+ "kbVisibility.failOpenNote": "fail-open\uFF1AKendra \u65E0\u8EAB\u4EFD\u4E0A\u4E0B\u6587\u8FD4\u56DE\u5168\u90E8\u6587\u6863\u2014\u2014\u68C0\u7D22\u5FC5\u987B\u643A\u5E26\u670D\u52A1\u7AEF\u8EAB\u4EFD",
1060
+ "kbVisibility.focusColumn": "\u805A\u7126\u8EAB\u4EFD {p0} \u7684\u5217",
1061
+ "kbVisibility.layerValue": "\u8FC7\u6EE4\u5C42\uFF1A{p0}",
1062
+ "kbVisibility.leakageNote": "\u8BA1\u6570\u5DEE\u5F02\u5373 volume leakage\uFF1A\u5BF9\u666E\u901A\u7528\u6237\u53EA\u53EF\u7ED9\u300C\u5DF2\u6309\u6743\u9650\u8FC7\u6EE4\u300D\u6052\u5B9A\u6587\u6848\uFF0C\u7F13\u89E3\u53EA\u6709 padding \u53D6\u6574",
1063
+ "kbVisibility.postFilterNote": "post-filter\uFF1AtopK \u88AB\u65E0\u6743\u7ED3\u679C\u5360\u7528\u4E14\u76F8\u4F3C\u5EA6\u5206\u6570\u53EF\u88AB\u89C2\u5BDF",
1064
+ "kbVisibility.queryLabel": "\u67E5\u8BE2\uFF1A{p0}",
1065
+ "kbVisibility.safeCount": "\u5B89\u5168\u8BA1\u6570 {p0}",
1066
+ "kbVisibility.sourceUnavailable": "\u539F\u6587\u4E0D\u53EF\u7528",
1067
+ "kbVisibility.unnamedHit": "\u672A\u547D\u540D\u547D\u4E2D",
1068
+ /* ── kbWhoCan ── */
1069
+ "kbWhoCan.check": "\u68C0\u67E5",
1070
+ "kbWhoCan.checkIdentity": "\u68C0\u67E5\u8EAB\u4EFD",
1071
+ "kbWhoCan.daysUntil": "{p0} \u5929\u540E",
1072
+ "kbWhoCan.deniedBy": "\u88AB\u7B56\u7565\u62D2\u7EDD\uFF1A{p0}",
1073
+ "kbWhoCan.denyVeto": "\u88AB Deny \u4E00\u7968\u5426\u51B3",
1074
+ "kbWhoCan.direct": "\u76F4\u63A5",
1075
+ "kbWhoCan.expiresSoon": "\u6700\u8FD1\u5230\u671F {p0}",
1076
+ "kbWhoCan.hoursUntil": "{p0} \u5C0F\u65F6\u540E",
1077
+ "kbWhoCan.inherit": "\u7EE7\u627F",
1078
+ "kbWhoCan.link": "\u94FE\u63A5",
1079
+ "kbWhoCan.noDeny": "\u65E0 Deny \u751F\u6548",
1080
+ "kbWhoCan.noIdentity": "\u672A\u63D0\u4F9B\u53EF\u68C0\u67E5\u7684\u8EAB\u4EFD",
1081
+ "kbWhoCan.none": "\u672A\u547D\u4E2D\u4EFB\u4F55\u6388\u6743\u2014\u2014\u9ED8\u8BA4\u62D2\u7EDD",
1082
+ "kbWhoCan.recheckTip": "\u91CD\u65B0\u68C0\u67E5\u5F53\u524D\u8EAB\u4EFD\u7684\u6709\u6548\u6743\u9650",
1083
+ "kbWhoCan.stackRule": "\u53E0\u52A0\u89C4\u5219\uFF1A\u591A\u6765\u6E90\u5E76\u96C6 \u2192 {p0}\uFF1B{p1}",
1084
+ /* ── mentions ── */
1085
+ "mentions.create": "\u521B\u5EFA\u201C{p0}\u201D",
1086
+ "mentions.customBadge": "\u81EA\u5B9A\u4E49",
1087
+ "mentions.loading": "\u52A0\u8F7D\u4E2D\u2026",
1088
+ /* ── notification ── */
1089
+ "notification.groupBusy": "\u64CD\u4F5C\u7ED3\u675F\u540E\u53EF\u4EE5\u6536\u8D77\u8FD9\u7EC4\u901A\u77E5\u3002",
1090
+ "notification.groupUnread": "{count} \u6761\u540C\u7EC4\u901A\u77E5\uFF0C{unread} \u6761\u672A\u8BFB",
1091
+ "notification.groupCount": "{count} \u6761\u540C\u7EC4\u901A\u77E5",
1092
+ "notification.groupExpanded": "\u6536\u8D77\u8FD9\u7EC4\u901A\u77E5",
1093
+ "notification.ariaLabel": "\u901A\u77E5",
1094
+ "notification.viewDetails": "\u67E5\u770B\u8BE6\u60C5",
1095
+ /* ── pagination ── */
1096
+ "pagination.next": "\u4E0B\u4E00\u9875",
1097
+ "pagination.pageSize": "{p0} \u6761/\u9875",
1098
+ "pagination.prev": "\u4E0A\u4E00\u9875",
1099
+ /* ── select ── */
1100
+ "select.fieldLabel": "\u9009\u62E9\u9009\u9879",
1101
+ "select.noMatch": "\u65E0\u5339\u914D\u9879",
1102
+ "select.remove": "\u79FB\u9664 {p0}",
1103
+ "select.searchPlaceholder": "\u641C\u7D22\u2026",
1104
+ /* ── cascader / tree-select ── */
1105
+ "cascader.placeholder": "\u8BF7\u9009\u62E9",
1106
+ "cascader.noMatch": "\u65E0\u5339\u914D",
1107
+ "cascader.search": "\u641C\u7D22",
1108
+ "treeSelect.placeholder": "\u8BF7\u9009\u62E9",
1109
+ "treeSelect.noMatch": "\u65E0\u5339\u914D",
1110
+ "treeSelect.search": "\u641C\u7D22",
1111
+ /* ── tagInput ── */
1112
+ "tagInput.ariaLabel": "\u6807\u7B7E\u8F93\u5165\uFF0C\u5171 {p0} \u4E2A",
1113
+ "tagInput.remove": "\u79FB\u9664 {p0}",
1114
+ "tagInput.field": "\u6DFB\u52A0\u6807\u7B7E",
1115
+ "tagInput.added": "\u5DF2\u6DFB\u52A0 {p0} \u4E2A\u6807\u7B7E\u3002",
1116
+ "tagInput.removed": "\u5DF2\u79FB\u9664 {p0}\u3002",
1117
+ "tagInput.duplicate": "\u5DF2\u6709\u300C{p0}\u300D\uFF0C\u53EF\u4EE5\u7F16\u8F91\u540E\u91CD\u8BD5\u3002",
1118
+ "tagInput.limit": "\u6700\u591A {p0} \u4E2A\u6807\u7B7E\uFF0C\u8BF7\u5148\u79FB\u9664\u4E00\u4E2A\u3002",
1119
+ /* ── upload ── */
1120
+ "upload.remove": "\u79FB\u9664 {p0}",
1121
+ "upload.tooBig": "\u6587\u4EF6\u8D85\u8FC7 {p0}",
1122
+ "upload.tooMany": "\u6700\u591A {p0} \u4E2A\u6587\u4EF6",
1123
+ "upload.typeNotAllowed": "\u6587\u4EF6\u7C7B\u578B\u4E0D\u652F\u6301"
7
1124
  };
8
- var CLOSE_SVG = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>';
9
- var PROGRESS_ICON = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" x2="12" y1="15" y2="3"/></svg>';
1125
+ var current = { ...ICEN_LOCALE_ZH_CN };
1126
+ function t(key, vars) {
1127
+ const raw = current[key] ?? ICEN_LOCALE_ZH_CN[key];
1128
+ if (vars == null || Array.isArray(raw)) return raw;
1129
+ return raw.replace(/\{(\w+)\}/g, (m, name) => name in vars ? String(vars[name]) : m);
1130
+ }
1131
+
1132
+ // src/behaviors/svg-parse.ts
1133
+ function parseSvg(source) {
1134
+ if (typeof document === "undefined" || typeof DOMParser === "undefined") return null;
1135
+ const trimmed = source.trimStart();
1136
+ if (!trimmed.startsWith("<svg")) return null;
1137
+ const src = /^<svg(?![^>]*\bxmlns[=:])/i.test(trimmed) ? trimmed.replace(/^<svg/i, '<svg xmlns="http://www.w3.org/2000/svg"') : trimmed;
1138
+ let parsed;
1139
+ try {
1140
+ parsed = new DOMParser().parseFromString(src, "image/svg+xml");
1141
+ } catch {
1142
+ return null;
1143
+ }
1144
+ const root = parsed.documentElement;
1145
+ if (!root || root.tagName.toLowerCase() !== "svg" || parsed.querySelector("parsererror")) return null;
1146
+ const sanitize = (el) => {
1147
+ for (const attr of Array.from(el.attributes)) {
1148
+ const name = attr.name.toLowerCase();
1149
+ if (name.startsWith("on")) el.removeAttribute(attr.name);
1150
+ if ((name === "href" || name === "xlink:href") && attr.value.trim().toLowerCase().startsWith("javascript:")) {
1151
+ el.removeAttribute(attr.name);
1152
+ }
1153
+ }
1154
+ for (const child of Array.from(el.children)) {
1155
+ const tag = child.tagName.toLowerCase();
1156
+ if (tag === "script" || tag === "foreignobject") {
1157
+ child.remove();
1158
+ continue;
1159
+ }
1160
+ sanitize(child);
1161
+ }
1162
+ };
1163
+ sanitize(root);
1164
+ return document.importNode(root, true);
1165
+ }
1166
+
1167
+ // src/behaviors/notification.ts
1168
+ var clocks = /* @__PURE__ */ new WeakMap();
1169
+ var KIND_SYMBOL = { success: "circle-check", warning: "triangle-alert", error: "circle-error", info: "circle-info" };
10
1170
  var cfg = {
11
1171
  position: "top-right",
12
1172
  maxStack: 5,
@@ -23,26 +1183,25 @@ function genId() {
23
1183
  return "notif-" + Math.random().toString(36).slice(2, 10);
24
1184
  }
25
1185
  function ensureContainer() {
26
- const sel = `.notification-container[data-notif-default]`;
1186
+ const sel = `.icen-notification-container[data-icen-notif-default]`;
27
1187
  const existing = document.body.querySelector(sel);
28
1188
  if (existing) {
29
1189
  syncContainerPosition(existing);
30
1190
  return existing;
31
1191
  }
32
1192
  const el = document.createElement("div");
33
- el.className = "notification-container";
1193
+ el.className = "icen-notification-container";
34
1194
  el.setAttribute("role", "region");
35
- el.setAttribute("aria-label", "\u901A\u77E5");
36
- el.dataset.notifDefault = "";
1195
+ el.setAttribute("aria-label", t("notification.ariaLabel"));
1196
+ el.dataset.icenNotifDefault = "";
37
1197
  syncContainerPosition(el);
38
1198
  document.body.appendChild(el);
39
1199
  return el;
40
1200
  }
41
1201
  function syncContainerPosition(el) {
42
- el.dataset.position = cfg.position;
1202
+ el.dataset.icenPosition = cfg.position;
43
1203
  }
44
1204
  var DEFAULT_PERSIST_KEY = "icen.ui.notifications";
45
- var knownPersistKeys = /* @__PURE__ */ new Set();
46
1205
  function persistKeyFor(p) {
47
1206
  if (p === true) return DEFAULT_PERSIST_KEY;
48
1207
  if (typeof p === "string" && p.length > 0) return p;
@@ -51,40 +1210,50 @@ function persistKeyFor(p) {
51
1210
  function recordPersist(record) {
52
1211
  return record.cfgRef ? record.cfgRef.persist : cfg.persist;
53
1212
  }
54
- function persistSave() {
55
- try {
56
- const groups = /* @__PURE__ */ new Map();
57
- for (const key of knownPersistKeys) groups.set(key, []);
58
- for (const r of store.values()) {
59
- const key = persistKeyFor(recordPersist(r));
60
- if (!key) continue;
61
- knownPersistKeys.add(key);
62
- let bucket = groups.get(key);
63
- if (!bucket) {
64
- bucket = [];
65
- groups.set(key, bucket);
66
- }
67
- if (r.opts.duration) continue;
68
- bucket.push({
69
- id: r.id,
70
- title: r.title,
71
- kind: r.kind,
72
- description: r.opts.description ?? "",
73
- tag: r.opts.tag,
74
- unread: r.opts.unread,
75
- priority: r.opts.priority,
76
- progress: r.opts.progress,
77
- progressLabel: r.opts.progressLabel,
78
- link: r.opts.link,
79
- linkLabel: r.opts.linkLabel,
80
- data: r.opts.data,
81
- createdAt: r.createdAt
82
- });
1213
+ function persistSave(removed = []) {
1214
+ if (!isBrowser()) return;
1215
+ const groups = /* @__PURE__ */ new Map();
1216
+ const bucket = (key) => {
1217
+ let items = groups.get(key);
1218
+ if (!items) {
1219
+ items = new Map(persistLoad(key).map((item) => [item.id, item]));
1220
+ groups.set(key, items);
83
1221
  }
84
- for (const [key, items] of groups) {
85
- localStorage.setItem(key, JSON.stringify(items));
1222
+ return items;
1223
+ };
1224
+ for (const r of removed) {
1225
+ const key = persistKeyFor(recordPersist(r));
1226
+ if (key) bucket(key).delete(r.id);
1227
+ }
1228
+ for (const r of store.values()) {
1229
+ const key = persistKeyFor(recordPersist(r));
1230
+ if (!key) continue;
1231
+ const items = bucket(key);
1232
+ if (r.duration > 0) {
1233
+ items.delete(r.id);
1234
+ continue;
1235
+ }
1236
+ items.set(r.id, {
1237
+ id: r.id,
1238
+ title: r.title,
1239
+ kind: r.kind,
1240
+ description: r.opts.description ?? "",
1241
+ tag: r.opts.tag,
1242
+ unread: r.opts.unread,
1243
+ priority: r.opts.priority,
1244
+ progress: r.opts.progress,
1245
+ progressLabel: r.opts.progressLabel,
1246
+ link: r.opts.link,
1247
+ linkLabel: r.opts.linkLabel,
1248
+ data: r.opts.data,
1249
+ createdAt: r.createdAt
1250
+ });
1251
+ }
1252
+ for (const [key, items] of groups) {
1253
+ try {
1254
+ localStorage.setItem(key, JSON.stringify([...items.values()]));
1255
+ } catch {
86
1256
  }
87
- } catch {
88
1257
  }
89
1258
  }
90
1259
  function persistLoad(key) {
@@ -92,14 +1261,50 @@ function persistLoad(key) {
92
1261
  const raw = localStorage.getItem(key);
93
1262
  if (!raw) return [];
94
1263
  const arr = JSON.parse(raw);
95
- return Array.isArray(arr) ? arr : [];
1264
+ if (!Array.isArray(arr)) return [];
1265
+ const unique = /* @__PURE__ */ new Map();
1266
+ for (const item of arr) {
1267
+ if (!item || typeof item !== "object" || typeof item.id !== "string" || !item.id || typeof item.title !== "string") continue;
1268
+ if (!["success", "warning", "error", "info"].includes(item.kind)) continue;
1269
+ const text = (value) => typeof value === "string" ? value : void 0;
1270
+ unique.set(item.id, {
1271
+ id: item.id,
1272
+ title: item.title,
1273
+ kind: item.kind,
1274
+ description: text(item.description),
1275
+ tag: text(item.tag),
1276
+ unread: item.unread === true,
1277
+ priority: item.priority === "high" ? "high" : "normal",
1278
+ progress: typeof item.progress === "number" && Number.isFinite(item.progress) ? Math.min(1, Math.max(0, item.progress)) : void 0,
1279
+ progressLabel: text(item.progressLabel),
1280
+ link: text(item.link),
1281
+ linkLabel: text(item.linkLabel),
1282
+ data: item.data,
1283
+ createdAt: typeof item.createdAt === "number" && Number.isFinite(item.createdAt) ? item.createdAt : void 0
1284
+ });
1285
+ }
1286
+ return [...unique.values()];
96
1287
  } catch {
97
1288
  return [];
98
1289
  }
99
1290
  }
1291
+ function configurePersistence(config, next, records) {
1292
+ const oldKey = persistKeyFor(config.persist), newKey = persistKeyFor(next);
1293
+ if (oldKey && newKey && oldKey !== newKey) {
1294
+ try {
1295
+ const items = persistLoad(oldKey).filter((item) => !records.some((r) => r.id === item.id));
1296
+ localStorage.setItem(oldKey, JSON.stringify(items));
1297
+ } catch {
1298
+ }
1299
+ }
1300
+ config.persist = next;
1301
+ persistSave();
1302
+ }
100
1303
  function restorePersisted(container, key, cfgRef) {
101
1304
  const records = [];
102
1305
  for (const item of persistLoad(key)) {
1306
+ if (store.has(item.id)) continue;
1307
+ removeRetiredCopies(item.id);
103
1308
  const record = {
104
1309
  id: item.id,
105
1310
  title: item.title,
@@ -129,6 +1334,7 @@ function restorePersisted(container, key, cfgRef) {
129
1334
  const el = renderNotification(record, container, () => handle);
130
1335
  record.el = el;
131
1336
  handle.el = el;
1337
+ attachTimer(record, handle);
132
1338
  pushToContainer(container, el, record.opts.priority ?? "normal");
133
1339
  records.push(record);
134
1340
  }
@@ -157,46 +1363,24 @@ function playSound(sound) {
157
1363
  gain.connect(audioCtx.destination);
158
1364
  osc.frequency.value = freq;
159
1365
  osc.type = "sine";
160
- const t = now + i * 0.08;
161
- gain.gain.setValueAtTime(0, t);
162
- gain.gain.linearRampToValueAtTime(0.08, t + 0.01);
163
- gain.gain.exponentialRampToValueAtTime(1e-3, t + 0.12);
164
- osc.start(t);
165
- osc.stop(t + 0.13);
1366
+ const t2 = now + i * 0.08;
1367
+ gain.gain.setValueAtTime(0, t2);
1368
+ gain.gain.linearRampToValueAtTime(0.08, t2 + 0.01);
1369
+ gain.gain.exponentialRampToValueAtTime(1e-3, t2 + 0.12);
1370
+ osc.start(t2);
1371
+ osc.stop(t2 + 0.13);
166
1372
  });
167
1373
  } catch {
168
1374
  }
169
1375
  }
170
- function stripUnsafeSvg(el) {
171
- for (const attr of Array.from(el.attributes)) {
172
- if (attr.name.toLowerCase().startsWith("on")) el.removeAttribute(attr.name);
173
- }
174
- for (const child of Array.from(el.children)) {
175
- const tag = child.tagName.toLowerCase();
176
- if (tag === "script" || tag === "foreignobject") child.remove();
177
- else stripUnsafeSvg(child);
178
- }
179
- }
180
- function sanitizeSvgIcon(source) {
181
- if (!source.trimStart().startsWith("<svg")) return null;
182
- try {
183
- const doc = new DOMParser().parseFromString(source, "image/svg+xml");
184
- const svg = doc.documentElement;
185
- if (!svg || svg.tagName.toLowerCase() !== "svg") return null;
186
- stripUnsafeSvg(svg);
187
- return document.importNode(svg, true);
188
- } catch {
189
- return null;
190
- }
191
- }
192
1376
  function buildIcon(record) {
193
1377
  const wrap = document.createElement("span");
194
- wrap.className = "notification-icon";
1378
+ wrap.className = "icen-notification-icon";
195
1379
  wrap.setAttribute("aria-hidden", "true");
196
1380
  const { icon, avatar } = record.opts;
197
1381
  if (avatar) {
198
1382
  const img = document.createElement("img");
199
- img.className = "notification-avatar";
1383
+ img.className = "icen-notification-avatar";
200
1384
  img.src = avatar;
201
1385
  img.alt = "";
202
1386
  img.loading = "lazy";
@@ -207,58 +1391,89 @@ function buildIcon(record) {
207
1391
  wrap.style.display = "none";
208
1392
  return wrap;
209
1393
  }
1394
+ if (record.opts.iconName) {
1395
+ const symbol = createIcon(record.opts.iconName);
1396
+ if (symbol) {
1397
+ wrap.append(symbol);
1398
+ return wrap;
1399
+ }
1400
+ }
210
1401
  if (typeof icon === "string" && icon.length > 0) {
211
1402
  if (/^https?:\/\/|^data:image\//.test(icon) || icon.endsWith(".png") || icon.endsWith(".jpg") || icon.endsWith(".svg") || icon.endsWith(".webp")) {
212
1403
  const img = document.createElement("img");
213
- img.className = "notification-avatar";
1404
+ img.className = "icen-notification-avatar";
214
1405
  img.src = icon;
215
1406
  img.alt = "";
216
1407
  wrap.appendChild(img);
217
1408
  } else {
218
- const svg = sanitizeSvgIcon(icon);
1409
+ const svg = parseSvg(icon);
219
1410
  if (svg) wrap.appendChild(svg);
220
- else wrap.textContent = icon;
1411
+ if (!svg) wrap.append(createIcon(KIND_SYMBOL[record.kind]));
221
1412
  }
222
1413
  return wrap;
223
1414
  }
224
- const fallback = sanitizeSvgIcon(
225
- record.opts.progress !== void 0 && record.opts.progress >= 0 ? PROGRESS_ICON : KIND_ICON[record.kind]
226
- );
227
- if (fallback) wrap.appendChild(fallback);
1415
+ const progressing = record.kind === "info" && record.opts.progress !== void 0;
1416
+ const name = progressing ? record.opts.progress >= 1 ? "circle-check" : "spinner" : KIND_SYMBOL[record.kind];
1417
+ const fallback = createIcon(name);
1418
+ if (fallback) {
1419
+ if (name === "spinner") fallback.classList.add("icen-notification-busy-symbol");
1420
+ wrap.append(fallback);
1421
+ }
228
1422
  return wrap;
229
1423
  }
230
1424
  function buildTitle(title) {
231
1425
  const el = document.createElement("p");
232
- el.className = "notification-title";
233
- el.textContent = title;
1426
+ el.className = "icen-notification-title";
1427
+ setFeedbackText(el, title);
234
1428
  return el;
235
1429
  }
236
1430
  function buildDescription(text) {
237
1431
  const el = document.createElement("p");
238
- el.className = "notification-message";
1432
+ el.className = "icen-notification-message";
239
1433
  el.style.whiteSpace = "pre-wrap";
240
- el.textContent = text;
1434
+ setFeedbackText(el, text);
241
1435
  return el;
242
1436
  }
243
1437
  function buildActions(record) {
244
- const actions = record.opts.actions?.length ? record.opts.actions : record.opts.actionLabel ? [{ label: record.opts.actionLabel, onClick: record.opts.onAction }] : null;
1438
+ const actions = record.opts.actions !== void 0 ? record.opts.actions : record.opts.actionLabel ? [{ label: record.opts.actionLabel, onClick: record.opts.onAction }] : null;
245
1439
  if (!actions || actions.length === 0) return null;
246
1440
  const wrap = document.createElement("div");
247
- wrap.className = "notification-actions";
1441
+ wrap.className = "icen-notification-actions";
248
1442
  for (const a of actions) {
249
1443
  const btn = document.createElement("button");
250
1444
  btn.type = "button";
251
- btn.className = "notification-action";
252
- if (a.type === "primary") btn.classList.add("notification-action--primary");
253
- else if (a.type === "danger") btn.classList.add("notification-action--danger");
254
- btn.textContent = a.label;
1445
+ btn.className = "icen-notification-action";
1446
+ if (a.type === "primary") btn.classList.add("icen-notification-action--primary");
1447
+ else if (a.type === "danger") btn.classList.add("icen-notification-action--danger");
1448
+ setFeedbackText(btn, a.label);
255
1449
  btn.addEventListener("click", (ev) => {
256
1450
  ev.stopPropagation();
257
- if (a.onClick) {
258
- const ret = a.onClick();
259
- if (ret === false) return;
260
- }
261
- if (!a.keepOpen) dismissRecord(record.id);
1451
+ const card = record.el;
1452
+ if (!card || store.get(record.id) !== record) return;
1453
+ const content = card.querySelector(".icen-notification-content");
1454
+ setFeedbackError(content);
1455
+ runFeedbackAction(card, btn, a.onClick ?? (() => void 0), {
1456
+ busy(value) {
1457
+ const clock = clocks.get(record);
1458
+ if (value) {
1459
+ busyRecords.add(record);
1460
+ clock?.pause("action");
1461
+ clock?.resume("failure");
1462
+ } else {
1463
+ busyRecords.delete(record);
1464
+ clock?.resume("action");
1465
+ }
1466
+ if (card.parentElement) syncNotificationGroups(card.parentElement);
1467
+ },
1468
+ complete(accepted) {
1469
+ if (!accepted) clocks.get(record)?.pause("failure");
1470
+ else if (!a.keepOpen && store.get(record.id) === record) dismissRecord(record.id);
1471
+ },
1472
+ error() {
1473
+ clocks.get(record)?.pause("failure");
1474
+ setFeedbackError(content, record.opts.actionError ?? t("common.actionFailed"));
1475
+ }
1476
+ });
262
1477
  });
263
1478
  wrap.appendChild(btn);
264
1479
  }
@@ -268,11 +1483,11 @@ function buildLink(record) {
268
1483
  const { link, linkLabel } = record.opts;
269
1484
  if (!link) return null;
270
1485
  const wrap = document.createElement("div");
271
- wrap.className = "notification-link-wrap";
1486
+ wrap.className = "icen-notification-link-wrap";
272
1487
  const a = document.createElement("a");
273
- a.className = "notification-link";
1488
+ a.className = "icen-notification-link";
274
1489
  a.href = link;
275
- a.textContent = linkLabel ?? "\u67E5\u770B\u8BE6\u60C5";
1490
+ a.textContent = linkLabel ?? t("notification.viewDetails");
276
1491
  a.addEventListener("click", (ev) => ev.stopPropagation());
277
1492
  wrap.appendChild(a);
278
1493
  return wrap;
@@ -281,23 +1496,23 @@ function buildProgressBar(record) {
281
1496
  const { progress, progressLabel } = record.opts;
282
1497
  if (progress === void 0 || progress < 0) return null;
283
1498
  const wrap = document.createElement("div");
284
- wrap.className = "notification-progress";
1499
+ wrap.className = "icen-notification-progress";
285
1500
  const track = document.createElement("div");
286
- track.className = "notification-progress-track";
1501
+ track.className = "icen-notification-progress-track";
287
1502
  const fill = document.createElement("div");
288
- fill.className = "notification-progress-bar";
1503
+ fill.className = "icen-notification-progress-bar";
289
1504
  const pct = Math.min(100, Math.max(0, progress * 100));
290
1505
  fill.style.width = pct + "%";
291
1506
  track.appendChild(fill);
292
1507
  wrap.appendChild(track);
293
1508
  if (progressLabel) {
294
1509
  const lbl = document.createElement("span");
295
- lbl.className = "notification-progress-label";
1510
+ lbl.className = "icen-notification-progress-label";
296
1511
  lbl.textContent = progressLabel;
297
1512
  wrap.appendChild(lbl);
298
1513
  } else if (progress > 0) {
299
1514
  const lbl = document.createElement("span");
300
- lbl.className = "notification-progress-label";
1515
+ lbl.className = "icen-notification-progress-label";
301
1516
  lbl.textContent = Math.round(pct) + "%";
302
1517
  wrap.appendChild(lbl);
303
1518
  }
@@ -307,10 +1522,10 @@ function buildCountdownBar(record) {
307
1522
  if (!record.duration || record.duration <= 0) return null;
308
1523
  if (record.opts.showCountdown === false) return null;
309
1524
  const bar = document.createElement("div");
310
- bar.className = "notification-countdown";
1525
+ bar.className = "icen-notification-countdown";
311
1526
  bar.setAttribute("aria-hidden", "true");
312
1527
  const fill = document.createElement("div");
313
- fill.className = "notification-countdown-fill";
1528
+ fill.className = "icen-notification-countdown-fill";
314
1529
  fill.style.animationDuration = record.duration + "ms";
315
1530
  fill.style.animationPlayState = "running";
316
1531
  bar.appendChild(fill);
@@ -319,19 +1534,19 @@ function buildCountdownBar(record) {
319
1534
  function syncCountdownBar(record) {
320
1535
  const el = record.el;
321
1536
  if (!el) return;
322
- const existing = el.querySelector(".notification-countdown");
1537
+ const existing = el.querySelector(".icen-notification-countdown");
323
1538
  if (record.duration <= 0 || record.opts.showCountdown === false) {
324
1539
  existing?.remove();
325
1540
  return;
326
1541
  }
327
1542
  let fill;
328
1543
  if (existing) {
329
- fill = existing.querySelector(".notification-countdown-fill");
1544
+ fill = existing.querySelector(".icen-notification-countdown-fill");
330
1545
  } else {
331
1546
  const bar = buildCountdownBar(record);
332
1547
  if (!bar) return;
333
1548
  el.appendChild(bar);
334
- fill = bar.querySelector(".notification-countdown-fill");
1549
+ fill = bar.querySelector(".icen-notification-countdown-fill");
335
1550
  }
336
1551
  if (fill) {
337
1552
  fill.style.animation = "none";
@@ -345,9 +1560,10 @@ function buildClose(record) {
345
1560
  if (record.opts.closable === false) return null;
346
1561
  const btn = document.createElement("button");
347
1562
  btn.type = "button";
348
- btn.className = "notification-close";
349
- btn.setAttribute("aria-label", "\u5173\u95ED");
350
- const svg = sanitizeSvgIcon(CLOSE_SVG);
1563
+ btn.className = "icen-notification-close icen-icon-action";
1564
+ btn.setAttribute("data-icen-reveal", "");
1565
+ btn.setAttribute("aria-label", t("common.close"));
1566
+ const svg = createIcon("close");
351
1567
  if (svg) btn.appendChild(svg);
352
1568
  btn.addEventListener("click", (ev) => {
353
1569
  ev.stopPropagation();
@@ -357,25 +1573,32 @@ function buildClose(record) {
357
1573
  }
358
1574
  function renderNotification(record, container, getHandle) {
359
1575
  const el = document.createElement("div");
360
- let cls = record.kind === "info" ? "notification" : `notification notification--${record.kind}`;
1576
+ let cls = record.kind === "info" ? "icen-notification" : `icen-notification icen-notification--${record.kind}`;
1577
+ rememberFeedbackOrigin(el);
361
1578
  if (record.opts.priority === "high") cls += " is-priority";
362
1579
  if (record.opts.unread) cls += " is-unread";
363
1580
  if (record.opts.progress !== void 0 && record.opts.progress >= 0) cls += " is-progress";
364
- if (record.opts.avatar) cls += " has-avatar";
1581
+ if (record.opts.avatar) cls += " icen-has-avatar";
1582
+ if ((record.opts.progress ?? 0) >= 1) cls += " is-complete";
365
1583
  if (record.opts.onClick) {
366
1584
  cls += " is-clickable";
367
- el.setAttribute("role", "button");
368
- el.tabIndex = 0;
369
- } else {
370
- el.setAttribute("role", "alert");
371
1585
  }
1586
+ el.setAttribute("role", record.kind === "error" || record.kind === "warning" ? "alert" : "status");
372
1587
  el.className = cls;
373
1588
  el.id = record.id;
374
1589
  const icon = buildIcon(record);
375
1590
  el.appendChild(icon);
376
1591
  const content = document.createElement("div");
377
- content.className = "notification-content";
378
- content.appendChild(buildTitle(record.title));
1592
+ content.className = "icen-notification-content";
1593
+ const title = buildTitle(record.title);
1594
+ if (record.opts.onClick) {
1595
+ const open = document.createElement("button");
1596
+ open.type = "button";
1597
+ open.className = "icen-notification-open";
1598
+ setFeedbackText(open, record.title);
1599
+ title.replaceChildren(open);
1600
+ }
1601
+ content.appendChild(title);
379
1602
  if (record.opts.description) content.appendChild(buildDescription(record.opts.description));
380
1603
  const actions = buildActions(record);
381
1604
  if (actions) content.appendChild(actions);
@@ -390,18 +1613,117 @@ function renderNotification(record, container, getHandle) {
390
1613
  if (countdown) el.appendChild(countdown);
391
1614
  if (record.opts.onClick) {
392
1615
  const onClick = record.opts.onClick;
393
- const handleClick = () => onClick(getHandle());
394
- el.addEventListener("click", handleClick);
395
- el.addEventListener("keydown", (ev) => {
396
- if (ev.key === "Enter" || ev.key === " ") {
397
- ev.preventDefault();
398
- handleClick();
399
- }
1616
+ el.addEventListener("click", (ev) => {
1617
+ const control = ev.target instanceof Element ? ev.target.closest('button,a,input,select,textarea,[role="button"]') : null;
1618
+ if (control && !control.classList.contains("icen-notification-open")) return;
1619
+ onClick(getHandle());
400
1620
  });
401
1621
  }
402
1622
  record.el = el;
403
1623
  return el;
404
1624
  }
1625
+ var groupStates = /* @__PURE__ */ new WeakMap();
1626
+ var busyRecords = /* @__PURE__ */ new WeakSet();
1627
+ function syncNotificationGroups(container) {
1628
+ const records = Array.from(container.querySelectorAll(":scope > .icen-notification:not(.is-leaving)")).map((el) => store.get(el.id)).filter((r) => Boolean(r?.el && r.el.parentElement === container));
1629
+ const groups = /* @__PURE__ */ new Map();
1630
+ let states = groupStates.get(container);
1631
+ if (!states) {
1632
+ states = /* @__PURE__ */ new Map();
1633
+ groupStates.set(container, states);
1634
+ }
1635
+ for (const record of records) {
1636
+ const tag = record.opts.tag;
1637
+ if (tag) {
1638
+ const members = groups.get(tag) ?? [];
1639
+ members.push(record);
1640
+ groups.set(tag, members);
1641
+ }
1642
+ }
1643
+ for (const tag of states.keys()) if (!groups.has(tag)) states.delete(tag);
1644
+ const representatives = /* @__PURE__ */ new Set();
1645
+ const active = document.activeElement;
1646
+ let restore = null;
1647
+ for (const [tag, members] of groups) {
1648
+ if (members.length < 2) {
1649
+ states.delete(tag);
1650
+ continue;
1651
+ }
1652
+ let state = states.get(tag);
1653
+ if (!state) {
1654
+ state = { expanded: false };
1655
+ states.set(tag, state);
1656
+ }
1657
+ const high = members.filter((r) => r.opts.priority === "high");
1658
+ const eligible = high.length ? high : members;
1659
+ const representative = Array.from(store.values()).filter((r) => eligible.includes(r)).at(-1);
1660
+ const card = representative.el;
1661
+ representatives.add(card);
1662
+ const pending2 = members.some((r) => busyRecords.has(r));
1663
+ const focused = members.some((r) => r !== representative && r.el.contains(active) && !(active instanceof Element && active.closest(".icen-notification-group-toggle")));
1664
+ if (pending2 || focused) state.expanded = true;
1665
+ let button = card.querySelector(".icen-notification-group-toggle");
1666
+ if (!button) {
1667
+ button = document.createElement("button");
1668
+ button.type = "button";
1669
+ button.className = "icen-notification-group-toggle";
1670
+ button.addEventListener("click", (event) => {
1671
+ event.stopPropagation();
1672
+ const current2 = groupStates.get(container)?.get(button.dataset.icenNotifGroup);
1673
+ if (!current2) return;
1674
+ if (button.getAttribute("aria-disabled") === "true") return;
1675
+ current2.expanded = !current2.expanded;
1676
+ syncNotificationGroups(container);
1677
+ });
1678
+ card.querySelector(".icen-notification-content").append(button);
1679
+ }
1680
+ button.dataset.icenNotifGroup = tag;
1681
+ button.setAttribute("aria-expanded", String(state.expanded));
1682
+ button.setAttribute("aria-controls", members.filter((r) => r !== representative).map((r) => r.id).join(" "));
1683
+ if (pending2 && state.expanded) {
1684
+ button.setAttribute("aria-disabled", "true");
1685
+ button.setAttribute("aria-description", t("notification.groupBusy"));
1686
+ } else {
1687
+ button.removeAttribute("aria-disabled");
1688
+ button.removeAttribute("aria-description");
1689
+ }
1690
+ const unread = members.filter((r) => r.opts.unread).length;
1691
+ const text = document.createElement("bdi");
1692
+ text.textContent = t(state.expanded ? "notification.groupExpanded" : unread ? "notification.groupUnread" : "notification.groupCount", { count: members.length, unread });
1693
+ const icon = createIcon("chevron-down");
1694
+ button.replaceChildren(text, icon);
1695
+ for (const member of members) {
1696
+ const el = member.el, hide = !state.expanded && member !== representative;
1697
+ const revealing = el.hidden && !hide;
1698
+ el.hidden = hide;
1699
+ el.inert = hide;
1700
+ el.classList.toggle("is-group-hidden", hide);
1701
+ if (hide) el.classList.remove("is-group-revealing");
1702
+ else if (revealing) el.classList.add("is-group-revealing");
1703
+ if (hide) clocks.get(member)?.pause("group");
1704
+ else clocks.get(member)?.resume("group");
1705
+ if (el !== card && el.querySelector(".icen-notification-group-toggle")?.contains(active)) restore = button;
1706
+ }
1707
+ }
1708
+ for (const record of records) {
1709
+ const el = record.el;
1710
+ if (!representatives.has(el)) {
1711
+ const previous = el.querySelector(".icen-notification-group-toggle");
1712
+ if (previous?.contains(active) && !restore) {
1713
+ restore = el.querySelector(".icen-notification-close,.icen-notification-open,.icen-notification-action");
1714
+ if (!restore) restoreFeedbackFocus(el);
1715
+ }
1716
+ previous?.remove();
1717
+ }
1718
+ if (!record.opts.tag || (groups.get(record.opts.tag)?.length ?? 0) < 2) {
1719
+ el.hidden = false;
1720
+ el.inert = false;
1721
+ el.classList.remove("is-group-hidden");
1722
+ clocks.get(record)?.resume("group");
1723
+ }
1724
+ }
1725
+ restore?.focus({ preventScroll: true });
1726
+ }
405
1727
  function pushToContainer(container, el, priority) {
406
1728
  if (priority === "high") {
407
1729
  const firstNormal = Array.from(container.children).find(
@@ -416,107 +1738,98 @@ function pushToContainer(container, el, priority) {
416
1738
  var LEAVE_FALLBACK_MS = 360;
417
1739
  function removeOne(el, onClose) {
418
1740
  if (el.classList.contains("is-leaving")) return;
1741
+ restoreFeedbackFocus(el);
1742
+ el.inert = true;
1743
+ el.setAttribute("aria-hidden", "true");
419
1744
  el.classList.add("is-leaving");
420
1745
  let done = false;
421
1746
  const finish = () => {
422
1747
  if (done) return;
423
1748
  done = true;
1749
+ el.removeEventListener("transitionend", onTransition);
1750
+ window.clearTimeout(fallback);
424
1751
  el.remove();
425
1752
  onClose?.();
426
1753
  };
427
- el.addEventListener("transitionend", finish, { once: true });
428
- window.setTimeout(finish, LEAVE_FALLBACK_MS);
1754
+ const onTransition = (event) => {
1755
+ if (event.target === el) finish();
1756
+ };
1757
+ el.addEventListener("transitionend", onTransition);
1758
+ const fallback = window.setTimeout(finish, LEAVE_FALLBACK_MS);
429
1759
  }
430
1760
  function trimStack(container, maxStack, remove) {
431
- for (; ; ) {
432
- const items = Array.from(container.querySelectorAll(":scope > .notification"));
433
- if (items.length <= maxStack) return;
434
- const target = items.find((it) => !it.classList.contains("is-priority")) ?? items[0];
435
- if (!target) return;
436
- const rec = target.id ? store.get(target.id) : void 0;
437
- if (rec?.timer) window.clearTimeout(rec.timer);
438
- if (target.classList.contains("is-leaving")) {
439
- target.remove();
440
- if (target.id) remove(target.id);
441
- continue;
442
- }
443
- removeOne(target);
444
- if (target.id) remove(target.id);
445
- return;
1761
+ const rows = Array.from(container.querySelectorAll(":scope > .icen-notification:not(.is-leaving)"));
1762
+ while (rows.length > maxStack) {
1763
+ const read = rows.findIndex((item) => !item.classList.contains("is-priority") && !item.classList.contains("is-unread"));
1764
+ const index = read >= 0 ? read : rows.findIndex((item) => !item.classList.contains("is-priority"));
1765
+ const target = rows.splice(index < 0 ? 0 : index, 1)[0];
1766
+ const record = store.get(target.id);
1767
+ if (record) stopRuntime(record);
1768
+ remove(target.id);
1769
+ if (record) persistSave([record]);
1770
+ removeOne(target, record ? () => record.opts.onClose?.(makeHandle(record)) : void 0);
1771
+ syncNotificationGroups(container);
446
1772
  }
447
1773
  }
448
1774
  function attachTimer(record, handle) {
449
- const el = record.el;
450
- if (!el) return;
451
- const start = () => {
452
- if (record.timer) window.clearTimeout(record.timer);
453
- record.timer = 0;
454
- if (record.remaining <= 0) return;
455
- record.startedAt = Date.now();
456
- record.timer = window.setTimeout(() => dismissRecord(record.id), record.remaining);
457
- record.paused = false;
1775
+ if (!record.el) return;
1776
+ let clock = clocks.get(record);
1777
+ if (!clock) {
1778
+ clock = createFeedbackClock(record.el, record, () => dismissRecord(record.id), ".icen-notification-countdown-fill", () => record.opts.pauseOnHover ?? record.cfgRef?.pauseOnHover ?? cfg.pauseOnHover);
1779
+ clocks.set(record, clock);
1780
+ }
1781
+ record.restartTimer = () => clock.reset(record.duration);
1782
+ handle.pause = () => clock.pause();
1783
+ handle.resume = () => {
1784
+ clock.resume("failure");
1785
+ clock.resume();
458
1786
  };
459
- const pause = () => {
460
- if (record.paused) return;
461
- if (!record.timer) return;
1787
+ }
1788
+ function stopRuntime(record) {
1789
+ clocks.get(record)?.destroy();
1790
+ clocks.delete(record);
1791
+ if (record.timer) {
462
1792
  window.clearTimeout(record.timer);
463
1793
  record.timer = 0;
464
- record.remaining = Math.max(0, record.remaining - (Date.now() - record.startedAt));
465
- record.paused = true;
466
- el.classList.add("is-paused");
467
- const fill = el.querySelector(".notification-countdown-fill");
468
- if (fill) fill.style.animationPlayState = "paused";
469
- };
470
- const resume = () => {
471
- if (!record.paused) return;
472
- record.paused = false;
473
- el.classList.remove("is-paused");
474
- const fill = el.querySelector(".notification-countdown-fill");
475
- if (fill) fill.style.animationPlayState = "running";
476
- if (record.remaining <= 0) {
477
- dismissRecord(record.id);
478
- return;
479
- }
480
- start();
481
- };
482
- record.restartTimer = () => {
483
- record.paused = false;
484
- el.classList.remove("is-paused");
485
- start();
486
- };
487
- const pauseOnHover = record.opts.pauseOnHover ?? record.cfgRef?.pauseOnHover ?? cfg.pauseOnHover;
488
- if (pauseOnHover && !record.hoverBound) {
489
- record.hoverBound = true;
490
- el.addEventListener("mouseenter", () => handle.pause());
491
- el.addEventListener("mouseleave", () => handle.resume());
492
- }
493
- handle.pause = pause;
494
- handle.resume = resume;
495
- if (record.duration > 0) {
496
- record.remaining = record.duration;
497
- start();
498
1794
  }
1795
+ if (record.el) cancelFeedbackAction(record.el);
499
1796
  }
500
1797
  function makeHandle(record) {
501
1798
  const handle = {
502
1799
  id: record.id,
503
1800
  el: record.el ?? document.createElement("div"),
504
- dismiss: () => dismissRecord(record.id),
505
- update: (patch) => updateRecord(record.id, patch),
506
- setProgress: (value, label) => updateRecord(record.id, {
507
- progress: Math.min(1, Math.max(0, value)),
508
- progressLabel: label
509
- }),
510
- markRead: () => updateRecord(record.id, { unread: false }),
511
- pause: () => {
1801
+ dismiss: () => {
1802
+ if (store.get(record.id) === record) dismissRecord(record.id);
1803
+ },
1804
+ update: (patch) => {
1805
+ if (store.get(record.id) === record) updateRecord(record.id, patch);
1806
+ },
1807
+ setProgress: (value, label) => {
1808
+ if (store.get(record.id) === record) updateRecord(record.id, {
1809
+ progress: Math.min(1, Math.max(0, value)),
1810
+ progressLabel: label
1811
+ });
512
1812
  },
1813
+ markRead: () => {
1814
+ if (store.get(record.id) === record) updateRecord(record.id, { unread: false });
1815
+ },
1816
+ pause: () => clocks.get(record)?.pause(),
513
1817
  resume: () => {
1818
+ clocks.get(record)?.resume("failure");
1819
+ clocks.get(record)?.resume();
514
1820
  }
515
1821
  };
516
1822
  return handle;
517
1823
  }
1824
+ function removeRetiredCopies(id) {
1825
+ document.querySelectorAll(".icen-notification.is-leaving").forEach((el) => {
1826
+ if (el.id === id) el.remove();
1827
+ });
1828
+ }
518
1829
  function pushRecord(title, kind, opts, container, maxStack, cfgRef, ownerStore) {
519
1830
  const id = opts.id ?? genId();
1831
+ if (store.has(id)) dismissRecord(id, true);
1832
+ removeRetiredCopies(id);
520
1833
  const duration = opts.duration ?? 0;
521
1834
  const record = {
522
1835
  id,
@@ -546,6 +1859,7 @@ function pushRecord(title, kind, opts, container, maxStack, cfgRef, ownerStore)
546
1859
  ownerStore?.delete(removedId);
547
1860
  store.delete(removedId);
548
1861
  });
1862
+ syncNotificationGroups(container);
549
1863
  persistSave();
550
1864
  playSound(cfgRef?.sound ?? cfg.sound);
551
1865
  opts.onShow?.(handle);
@@ -554,29 +1868,34 @@ function pushRecord(title, kind, opts, container, maxStack, cfgRef, ownerStore)
554
1868
  function showRecord(title, kind, opts) {
555
1869
  if (!isBrowser()) return null;
556
1870
  const container = ensureContainer();
557
- const id = opts.id ?? genId();
558
- if (store.has(id)) dismissRecord(id);
559
1871
  return pushRecord(title, kind, opts, container, cfg.maxStack);
560
1872
  }
561
- function dismissRecord(id) {
1873
+ function dismissRecord(id, immediate = false) {
562
1874
  const record = store.get(id);
563
1875
  if (!record) {
564
1876
  const el = document.getElementById(id);
565
- if (el && el.classList.contains("notification")) removeOne(el);
1877
+ if (el && el.classList.contains("icen-notification")) removeOne(el);
566
1878
  return;
567
1879
  }
568
- if (record.timer) window.clearTimeout(record.timer);
1880
+ stopRuntime(record);
569
1881
  const handle = makeHandle(record);
570
1882
  const onClose = record.opts.onClose;
571
1883
  store.delete(id);
572
1884
  record.ownerStore?.delete(id);
573
- if (record.el) removeOne(record.el, () => onClose?.(handle));
1885
+ if (record.el && immediate) {
1886
+ restoreFeedbackFocus(record.el);
1887
+ record.el.remove();
1888
+ onClose?.(handle);
1889
+ } else if (record.el) removeOne(record.el, () => onClose?.(handle));
574
1890
  else onClose?.(handle);
575
- persistSave();
1891
+ if (record.el?.parentElement) syncNotificationGroups(record.el.parentElement);
1892
+ persistSave([record]);
576
1893
  }
577
1894
  function updateRecord(id, patch) {
578
1895
  const record = store.get(id);
579
1896
  if (!record) return;
1897
+ const wasComplete = (record.opts.progress ?? 0) >= 1;
1898
+ const wasProgress = record.opts.progress !== void 0;
580
1899
  if (patch.title !== void 0) record.title = patch.title;
581
1900
  if (patch.description !== void 0) record.opts.description = patch.description;
582
1901
  if (patch.duration !== void 0) {
@@ -590,33 +1909,54 @@ function updateRecord(id, patch) {
590
1909
  if (patch.tag !== void 0) record.opts.tag = patch.tag;
591
1910
  if (patch.priority !== void 0) record.opts.priority = patch.priority;
592
1911
  if (patch.icon !== void 0) record.opts.icon = patch.icon;
1912
+ if (patch.iconName !== void 0) record.opts.iconName = patch.iconName;
593
1913
  if (patch.avatar !== void 0) record.opts.avatar = patch.avatar;
594
1914
  if (patch.link !== void 0) record.opts.link = patch.link;
595
1915
  if (patch.linkLabel !== void 0) record.opts.linkLabel = patch.linkLabel;
596
1916
  const el = record.el;
597
1917
  if (!el) return;
1918
+ if (patch.actions !== void 0) {
1919
+ cancelFeedbackAction(el);
1920
+ if (store.get(id) !== record) return;
1921
+ const old = el.querySelector(".icen-notification-actions"), owned = old?.contains(document.activeElement);
1922
+ const next = buildActions(record), target = next?.querySelector("button") ?? el.querySelector(".icen-notification-close");
1923
+ if (owned && !target) restoreFeedbackFocus(el);
1924
+ old?.remove();
1925
+ if (next) el.querySelector(".icen-notification-content")?.append(next);
1926
+ if (owned) target?.focus({ preventScroll: true });
1927
+ if (!el.contains(document.activeElement)) clocks.get(record)?.resume("focus");
1928
+ }
1929
+ if (patch.icon !== void 0 || patch.iconName !== void 0 || patch.avatar !== void 0 || patch.progress !== void 0 && (!wasProgress || wasComplete !== patch.progress >= 1)) {
1930
+ el.querySelector(".icen-notification-icon")?.replaceWith(buildIcon(record));
1931
+ el.classList.toggle("icen-has-avatar", Boolean(record.opts.avatar));
1932
+ }
1933
+ if (patch.link !== void 0 || patch.linkLabel !== void 0) {
1934
+ el.querySelector(".icen-notification-link-wrap")?.remove();
1935
+ const link = buildLink(record);
1936
+ if (link) el.querySelector(".icen-notification-content")?.append(link);
1937
+ }
598
1938
  if (patch.duration !== void 0 && el.isConnected) {
599
1939
  syncCountdownBar(record);
600
1940
  if (record.restartTimer) record.restartTimer();
601
1941
  else if (patch.duration > 0) attachTimer(record, makeHandle(record));
602
1942
  }
603
1943
  if (patch.title !== void 0) {
604
- const t = el.querySelector(".notification-title");
605
- if (t) t.textContent = patch.title;
1944
+ const t2 = el.querySelector(".icen-notification-title");
1945
+ if (t2) setFeedbackText(t2.querySelector(".icen-notification-open") ?? t2, patch.title);
606
1946
  }
607
1947
  if (patch.description !== void 0) {
608
- let m = el.querySelector(".notification-message");
1948
+ let m = el.querySelector(".icen-notification-message");
609
1949
  if (patch.description) {
610
1950
  if (!m) {
611
1951
  m = document.createElement("p");
612
- m.className = "notification-message";
1952
+ m.className = "icen-notification-message";
613
1953
  m.style.whiteSpace = "pre-wrap";
614
- const content = el.querySelector(".notification-content");
615
- const titleEl = content?.querySelector(".notification-title");
1954
+ const content = el.querySelector(".icen-notification-content");
1955
+ const titleEl = content?.querySelector(".icen-notification-title");
616
1956
  if (titleEl && titleEl.nextSibling) content?.insertBefore(m, titleEl.nextSibling);
617
1957
  else content?.appendChild(m);
618
1958
  }
619
- m.textContent = patch.description;
1959
+ setFeedbackText(m, patch.description);
620
1960
  } else if (m) {
621
1961
  m.remove();
622
1962
  }
@@ -626,33 +1966,36 @@ function updateRecord(id, patch) {
626
1966
  }
627
1967
  if (patch.priority !== void 0) {
628
1968
  el.classList.toggle("is-priority", patch.priority === "high");
1969
+ if (el.parentElement) pushToContainer(el.parentElement, el, patch.priority);
629
1970
  }
630
1971
  if (patch.progress !== void 0 || patch.progressLabel !== void 0) {
631
1972
  el.classList.add("is-progress");
632
- let progWrap = el.querySelector(".notification-progress");
1973
+ el.classList.toggle("is-complete", (record.opts.progress ?? 0) >= 1);
1974
+ let progWrap = el.querySelector(".icen-notification-progress");
633
1975
  const pct = Math.min(100, Math.max(0, (record.opts.progress ?? 0) * 100));
634
1976
  if (!progWrap) {
635
1977
  progWrap = document.createElement("div");
636
- progWrap.className = "notification-progress";
1978
+ progWrap.className = "icen-notification-progress";
637
1979
  const track = document.createElement("div");
638
- track.className = "notification-progress-track";
1980
+ track.className = "icen-notification-progress-track";
639
1981
  const fill2 = document.createElement("div");
640
- fill2.className = "notification-progress-bar";
1982
+ fill2.className = "icen-notification-progress-bar";
641
1983
  track.appendChild(fill2);
642
1984
  progWrap.appendChild(track);
643
- el.querySelector(".notification-content")?.appendChild(progWrap);
1985
+ el.querySelector(".icen-notification-content")?.appendChild(progWrap);
644
1986
  }
645
- const fill = progWrap.querySelector(".notification-progress-bar");
1987
+ const fill = progWrap.querySelector(".icen-notification-progress-bar");
646
1988
  if (fill) fill.style.width = pct + "%";
647
- let lbl = progWrap.querySelector(".notification-progress-label");
1989
+ let lbl = progWrap.querySelector(".icen-notification-progress-label");
648
1990
  const labelText = record.opts.progressLabel ?? Math.round(pct) + "%";
649
1991
  if (!lbl) {
650
1992
  lbl = document.createElement("span");
651
- lbl.className = "notification-progress-label";
1993
+ lbl.className = "icen-notification-progress-label";
652
1994
  progWrap.appendChild(lbl);
653
1995
  }
654
1996
  lbl.textContent = labelText;
655
1997
  }
1998
+ if (el.parentElement) syncNotificationGroups(el.parentElement);
656
1999
  persistSave();
657
2000
  }
658
2001
  function confirmDialog(title, opts = {}) {
@@ -667,8 +2010,8 @@ function confirmDialog(title, opts = {}) {
667
2010
  resolved = true;
668
2011
  resolve(val);
669
2012
  };
670
- const confirmLabel = opts.confirmLabel ?? "\u786E\u8BA4";
671
- const cancelLabel = opts.cancelLabel ?? "\u53D6\u6D88";
2013
+ const confirmLabel = opts.confirmLabel ?? t("common.confirm");
2014
+ const cancelLabel = opts.cancelLabel ?? t("common.cancel");
672
2015
  const actions = [
673
2016
  {
674
2017
  label: cancelLabel,
@@ -713,28 +2056,32 @@ function createNotificationCenter(parent, opts = {}) {
713
2056
  const mount = parent ?? document.body;
714
2057
  const local = {
715
2058
  position: opts.position ?? "top-right",
716
- maxStack: opts.maxStack ?? 5,
2059
+ maxStack: typeof opts.maxStack === "number" && Number.isFinite(opts.maxStack) && opts.maxStack >= 1 ? Math.floor(opts.maxStack) : 5,
717
2060
  pauseOnHover: opts.pauseOnHover ?? true,
718
2061
  persist: opts.persist ?? false,
719
2062
  sound: opts.sound ?? false
720
2063
  };
721
2064
  const container = document.createElement("div");
722
- container.className = "notification-container";
2065
+ container.className = "icen-notification-container";
723
2066
  container.setAttribute("role", "region");
724
- container.setAttribute("aria-label", "\u901A\u77E5");
725
- container.dataset.position = local.position;
2067
+ container.setAttribute("aria-label", t("notification.ariaLabel"));
2068
+ container.dataset.icenPosition = local.position;
726
2069
  mount.appendChild(container);
727
2070
  const localStore = /* @__PURE__ */ new Map();
728
2071
  let destroyed = false;
729
2072
  const pKey = persistKeyFor(local.persist);
730
2073
  if (pKey) {
731
- knownPersistKeys.add(pKey);
732
2074
  for (const r of restorePersisted(container, pKey, local)) {
733
2075
  r.ownerStore = localStore;
734
2076
  localStore.set(r.id, r);
735
2077
  store.set(r.id, r);
736
2078
  }
737
2079
  }
2080
+ trimStack(container, local.maxStack, (id) => {
2081
+ localStore.delete(id);
2082
+ store.delete(id);
2083
+ });
2084
+ syncNotificationGroups(container);
738
2085
  function push(input) {
739
2086
  if (destroyed) return null;
740
2087
  return pushRecord(
@@ -749,36 +2096,30 @@ function createNotificationCenter(parent, opts = {}) {
749
2096
  }
750
2097
  function dismiss(id) {
751
2098
  if (id) {
752
- const rec = localStore.get(id);
753
- if (!rec) return;
754
- if (rec.timer) window.clearTimeout(rec.timer);
755
- const handle = makeHandle(rec);
756
- localStore.delete(id);
757
- store.delete(id);
758
- if (rec.el) removeOne(rec.el, () => rec.opts.onClose?.(handle));
759
- persistSave();
2099
+ if (localStore.has(id)) dismissRecord(id);
760
2100
  return;
761
2101
  }
762
- Array.from(localStore.keys()).forEach((k) => dismiss(k));
2102
+ Array.from(localStore.keys()).forEach((key) => dismissRecord(key));
763
2103
  }
764
2104
  function clear() {
765
2105
  dismiss();
766
2106
  }
767
2107
  function markAllRead() {
768
- localStore.forEach((rec) => {
769
- rec.opts.unread = false;
770
- rec.el?.classList.remove("is-unread");
771
- });
2108
+ Array.from(localStore.keys()).forEach((id) => updateRecord(id, { unread: false }));
772
2109
  }
773
2110
  function destroy() {
774
2111
  if (destroyed) return;
2112
+ persistSave();
775
2113
  destroyed = true;
2114
+ const closing = Array.from(localStore.values());
776
2115
  localStore.forEach((rec) => {
777
- if (rec.timer) window.clearTimeout(rec.timer);
2116
+ stopRuntime(rec);
2117
+ if (rec.el) restoreFeedbackFocus(rec.el);
778
2118
  store.delete(rec.id);
779
2119
  });
780
2120
  localStore.clear();
781
2121
  container.remove();
2122
+ closing.forEach((rec) => rec.opts.onClose?.(makeHandle(rec)));
782
2123
  }
783
2124
  return {
784
2125
  push,
@@ -789,17 +2130,20 @@ function createNotificationCenter(parent, opts = {}) {
789
2130
  get: (id) => localStore.get(id) ?? null,
790
2131
  getAll: () => Array.from(localStore.values()),
791
2132
  config: (next) => {
2133
+ if (destroyed) return;
792
2134
  if (next.position) {
793
2135
  local.position = next.position;
794
- container.dataset.position = next.position;
2136
+ container.dataset.icenPosition = next.position;
795
2137
  }
796
- if (typeof next.maxStack === "number" && next.maxStack > 0) local.maxStack = next.maxStack;
797
- if (typeof next.pauseOnHover === "boolean") local.pauseOnHover = next.pauseOnHover;
798
- if (next.persist !== void 0) {
799
- local.persist = next.persist;
800
- const k = persistKeyFor(next.persist);
801
- if (k) knownPersistKeys.add(k);
2138
+ if (typeof next.maxStack === "number" && Number.isFinite(next.maxStack) && next.maxStack >= 1) {
2139
+ local.maxStack = Math.floor(next.maxStack);
2140
+ trimStack(container, local.maxStack, (id) => {
2141
+ localStore.delete(id);
2142
+ store.delete(id);
2143
+ });
802
2144
  }
2145
+ if (typeof next.pauseOnHover === "boolean") local.pauseOnHover = next.pauseOnHover;
2146
+ if (next.persist !== void 0) configurePersistence(local, next.persist, Array.from(localStore.values()));
803
2147
  if (next.sound !== void 0) local.sound = next.sound;
804
2148
  },
805
2149
  el: container
@@ -838,18 +2182,19 @@ var notify = Object.assign(
838
2182
  get: (id) => store.get(id) ?? null,
839
2183
  getAll: () => Array.from(store.values()),
840
2184
  config: (opts) => {
2185
+ if (!isBrowser()) return;
841
2186
  if (opts.position) {
842
2187
  cfg.position = opts.position;
843
- const c = document.body.querySelector(".notification-container[data-notif-default]");
844
- if (c) c.dataset.position = opts.position;
2188
+ const c = document.body.querySelector(".icen-notification-container[data-icen-notif-default]");
2189
+ if (c) c.dataset.icenPosition = opts.position;
845
2190
  }
846
- if (typeof opts.maxStack === "number" && opts.maxStack > 0) cfg.maxStack = opts.maxStack;
847
- if (typeof opts.pauseOnHover === "boolean") cfg.pauseOnHover = opts.pauseOnHover;
848
- if (opts.persist !== void 0) {
849
- cfg.persist = opts.persist;
850
- const k = persistKeyFor(opts.persist);
851
- if (k) knownPersistKeys.add(k);
2191
+ if (typeof opts.maxStack === "number" && Number.isFinite(opts.maxStack) && opts.maxStack >= 1) {
2192
+ cfg.maxStack = Math.floor(opts.maxStack);
2193
+ const c = document.querySelector("[data-icen-notif-default]");
2194
+ if (c) trimStack(c, cfg.maxStack, (id) => store.delete(id));
852
2195
  }
2196
+ if (typeof opts.pauseOnHover === "boolean") cfg.pauseOnHover = opts.pauseOnHover;
2197
+ if (opts.persist !== void 0) configurePersistence(cfg, opts.persist, Array.from(store.values()).filter((r) => !r.cfgRef));
853
2198
  if (opts.sound !== void 0) cfg.sound = opts.sound;
854
2199
  }
855
2200
  }
@@ -857,29 +2202,34 @@ var notify = Object.assign(
857
2202
  function initNotification() {
858
2203
  if (!isBrowser()) return () => {
859
2204
  };
860
- if (globalInit.done) return () => {
861
- };
2205
+ if (globalInit.done) return globalInit.dispose;
862
2206
  globalInit.done = true;
863
2207
  const container = ensureContainer();
864
2208
  const key = persistKeyFor(cfg.persist);
865
2209
  const restored = [];
866
2210
  if (key) {
867
- knownPersistKeys.add(key);
868
2211
  for (const r of restorePersisted(container, key)) {
869
2212
  store.set(r.id, r);
870
2213
  restored.push(r);
871
2214
  }
872
2215
  }
873
- return () => {
2216
+ trimStack(container, cfg.maxStack, (id) => store.delete(id));
2217
+ syncNotificationGroups(container);
2218
+ const dispose = () => {
2219
+ if (globalInit.dispose !== dispose) return;
2220
+ persistSave();
874
2221
  for (const r of restored) {
875
- if (r.timer) window.clearTimeout(r.timer);
876
- store.delete(r.id);
2222
+ stopRuntime(r);
2223
+ if (store.get(r.id) === r) store.delete(r.id);
877
2224
  r.el?.remove();
878
2225
  }
879
2226
  restored.length = 0;
880
2227
  if (container.childElementCount === 0) container.remove();
881
2228
  globalInit.done = false;
2229
+ globalInit.dispose = void 0;
882
2230
  };
2231
+ globalInit.dispose = dispose;
2232
+ return dispose;
883
2233
  }
884
2234
  export {
885
2235
  createNotificationCenter,