@icen.ai/ui 0.4.0 → 0.8.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 (155) hide show
  1. package/AGENTS.md +256 -0
  2. package/README.md +47 -13
  3. package/dist/base.css +31 -4
  4. package/dist/behaviors/accordion.d.mts +4 -0
  5. package/dist/behaviors/accordion.mjs +4 -3
  6. package/dist/behaviors/ai-chat.d.mts +57 -0
  7. package/dist/behaviors/ai-chat.mjs +557 -0
  8. package/dist/behaviors/ai-composer.d.mts +112 -0
  9. package/dist/behaviors/ai-composer.mjs +2032 -0
  10. package/dist/behaviors/ai-core.d.mts +151 -0
  11. package/dist/behaviors/ai-core.mjs +491 -0
  12. package/dist/behaviors/ai-diff.d.mts +53 -0
  13. package/dist/behaviors/ai-diff.mjs +282 -0
  14. package/dist/behaviors/ai-panel.d.mts +98 -0
  15. package/dist/behaviors/ai-panel.mjs +1012 -0
  16. package/dist/behaviors/ai-provider.d.mts +198 -0
  17. package/dist/behaviors/ai-provider.mjs +1055 -0
  18. package/dist/behaviors/ai-tool.d.mts +18 -0
  19. package/dist/behaviors/ai-tool.mjs +2125 -0
  20. package/dist/behaviors/ai-tools.d.mts +81 -0
  21. package/dist/behaviors/ai-tools.mjs +1658 -0
  22. package/dist/behaviors/back-top.d.mts +20 -0
  23. package/dist/behaviors/back-top.mjs +101 -0
  24. package/dist/behaviors/carousel.d.mts +4 -0
  25. package/dist/behaviors/carousel.mjs +34 -16
  26. package/dist/behaviors/charts.d.mts +250 -0
  27. package/dist/behaviors/charts.mjs +1301 -448
  28. package/dist/behaviors/command-palette.d.mts +8 -0
  29. package/dist/behaviors/command-palette.mjs +189 -0
  30. package/dist/behaviors/context-menu.d.mts +36 -0
  31. package/dist/behaviors/context-menu.mjs +6 -2
  32. package/dist/behaviors/copy.d.mts +4 -0
  33. package/dist/behaviors/copy.mjs +7 -6
  34. package/dist/behaviors/datatable.d.mts +78 -0
  35. package/dist/behaviors/datatable.mjs +54 -11
  36. package/dist/behaviors/date-picker.d.mts +4 -0
  37. package/dist/behaviors/date-picker.mjs +296 -0
  38. package/dist/behaviors/dropdown.d.mts +4 -0
  39. package/dist/behaviors/dropdown.mjs +7 -3
  40. package/dist/behaviors/input.d.mts +4 -0
  41. package/dist/behaviors/input.mjs +184 -8
  42. package/dist/behaviors/modal.d.mts +11 -0
  43. package/dist/behaviors/modal.mjs +11 -6
  44. package/dist/behaviors/nav.d.mts +7 -0
  45. package/dist/behaviors/nav.mjs +25 -9
  46. package/dist/behaviors/notification.d.mts +172 -0
  47. package/dist/behaviors/notification.mjs +908 -0
  48. package/dist/behaviors/popover.d.mts +46 -0
  49. package/dist/behaviors/popover.mjs +2 -1
  50. package/dist/behaviors/select.d.mts +4 -0
  51. package/dist/behaviors/select.mjs +268 -34
  52. package/dist/behaviors/sidebar.d.mts +4 -0
  53. package/dist/behaviors/sidebar.mjs +4 -3
  54. package/dist/behaviors/slider.d.mts +4 -0
  55. package/dist/behaviors/slider.mjs +4 -3
  56. package/dist/behaviors/split-pane.d.mts +4 -0
  57. package/dist/behaviors/split-pane.mjs +102 -0
  58. package/dist/behaviors/tabs.d.mts +8 -0
  59. package/dist/behaviors/tabs.mjs +44 -19
  60. package/dist/behaviors/tag-input.d.mts +4 -0
  61. package/dist/behaviors/tag-input.mjs +12 -3
  62. package/dist/behaviors/theme.d.mts +25 -0
  63. package/dist/behaviors/theme.mjs +3 -1
  64. package/dist/behaviors/toast.d.mts +26 -0
  65. package/dist/behaviors/toast.mjs +24 -18
  66. package/dist/behaviors/tree.d.mts +4 -0
  67. package/dist/behaviors/tree.mjs +4 -3
  68. package/dist/behaviors/upload.d.mts +4 -0
  69. package/dist/behaviors/upload.mjs +205 -17
  70. package/dist/components/ai-chat.css +1037 -0
  71. package/dist/components/ai-chat.mjs +3 -0
  72. package/dist/components/ai-composer.mjs +3 -0
  73. package/dist/components/ai-context.mjs +2 -0
  74. package/dist/components/ai-diff.css +311 -0
  75. package/dist/components/ai-diff.mjs +3 -0
  76. package/dist/components/ai-files.mjs +3 -0
  77. package/dist/components/ai-message.mjs +3 -0
  78. package/dist/components/ai-panel.css +682 -0
  79. package/dist/components/ai-reasoning.mjs +3 -0
  80. package/dist/components/ai-subagent.mjs +2 -0
  81. package/dist/components/ai-todo.mjs +2 -0
  82. package/dist/components/ai-tool-call.mjs +2 -0
  83. package/dist/components/ai-tool.css +532 -0
  84. package/dist/components/ai-usage.mjs +3 -0
  85. package/dist/components/back-top.css +88 -0
  86. package/dist/components/back-top.mjs +3 -0
  87. package/dist/components/badge.css +127 -0
  88. package/dist/components/badge.mjs +2 -0
  89. package/dist/components/breadcrumb.css +53 -0
  90. package/dist/components/btn.css +4 -7
  91. package/dist/components/card.css +66 -1
  92. package/dist/components/chart-bar.css +10 -0
  93. package/dist/components/chart-calendar.mjs +5 -0
  94. package/dist/components/chart-gauge.css +1 -1
  95. package/dist/components/chart-heatmap.css +40 -0
  96. package/dist/components/chart-scatter.css +24 -0
  97. package/dist/components/chart-scatter.mjs +4 -0
  98. package/dist/components/charts.css +86 -1
  99. package/dist/components/charts.mjs +1 -0
  100. package/dist/components/command-palette.css +246 -0
  101. package/dist/components/command-palette.mjs +3 -0
  102. package/dist/components/content.css +221 -8
  103. package/dist/components/copy.css +93 -0
  104. package/dist/components/copy.mjs +3 -0
  105. package/dist/components/datatable.css +4 -8
  106. package/dist/components/date-picker.css +240 -0
  107. package/dist/components/date-picker.mjs +3 -0
  108. package/dist/components/empty.css +69 -3
  109. package/dist/components/feedback.css +241 -10
  110. package/dist/components/form.css +129 -11
  111. package/dist/components/form.mjs +2 -0
  112. package/dist/components/input.css +25 -2
  113. package/dist/components/layout.css +36 -36
  114. package/dist/components/media.css +153 -6
  115. package/dist/components/menu.css +2 -2
  116. package/dist/components/modal.css +1 -1
  117. package/dist/components/nav.css +106 -2
  118. package/dist/components/notification.css +387 -0
  119. package/dist/components/notification.mjs +3 -0
  120. package/dist/components/pagination.css +1 -1
  121. package/dist/components/panel.css +104 -9
  122. package/dist/components/pill.css +82 -12
  123. package/dist/components/scroll-area.css +112 -0
  124. package/dist/components/scroll-area.mjs +2 -0
  125. package/dist/components/segmented.css +80 -5
  126. package/dist/components/segmented.mjs +1 -0
  127. package/dist/components/select.css +104 -17
  128. package/dist/components/sidebar.css +119 -1
  129. package/dist/components/slider.css +113 -0
  130. package/dist/components/split-pane.css +111 -0
  131. package/dist/components/split-pane.mjs +3 -0
  132. package/dist/components/stat.css +131 -12
  133. package/dist/components/steps.css +98 -1
  134. package/dist/components/switch.css +145 -7
  135. package/dist/components/table.css +111 -29
  136. package/dist/components/tabs.css +132 -22
  137. package/dist/components/tag-input.css +4 -4
  138. package/dist/components/tag.css +164 -0
  139. package/dist/components/tag.mjs +2 -0
  140. package/dist/components/toast.css +122 -5
  141. package/dist/components/toolbar.css +101 -0
  142. package/dist/components/toolbar.mjs +2 -0
  143. package/dist/components/tooltip.css +2 -2
  144. package/dist/components/upload.css +61 -4
  145. package/dist/index.d.mts +37 -0
  146. package/dist/index.mjs +9409 -929
  147. package/dist/registry.json +176 -4
  148. package/dist/retro-effects.css +21 -17
  149. package/dist/tokens/colors.css +4 -1
  150. package/dist/tokens/retro-effects.css +21 -17
  151. package/dist/tokens/style-profiles.css +21 -0
  152. package/dist/tokens.css +25 -1
  153. package/dist/ui.css +9616 -2839
  154. package/docs/spec/ai-native.md +659 -0
  155. package/package.json +15 -5
@@ -0,0 +1,532 @@
1
+ /*
2
+ * @icen.ai/ui — Component: ai-tool(AI 工具调用卡 + 子智能体卡;含 .ai-item 条目基元完整定义)
3
+ *
4
+ * 完整契约:
5
+ * ── 条目基元 .ai-item(规格 §2 骨架:所有行式 AI 条目的"基类",todo/panel 亦复用)──
6
+ * <div class="ai-item is-running" style="--ai-item-tint: var(--token-accent)">
7
+ * <span class="ai-item-icon"><!-- svg --></span>
8
+ * <div class="ai-item-main">
9
+ * <div class="ai-item-title">一行摘要</div>
10
+ * <div class="ai-item-sub">次要信息(路径/参数)</div>
11
+ * </div>
12
+ * <div class="ai-item-side">
13
+ * <span class="ai-item-status"></span> ← 状态点,纯 CSS 由 .is-* 驱动
14
+ * <span class="ai-item-meta">1.2s</span>
15
+ * </div>
16
+ * <div class="ai-item-detail" hidden>展开详情</div>
17
+ * </div>
18
+ *
19
+ * ── 工具调用卡(.ai-tool-head 复用 .ai-item-* 零件,不带 .ai-item 壳)──
20
+ * <div class="ai-tool ai-tool--shell is-done" data-ai-id="…" data-ai-kind="shell">
21
+ * <button class="ai-tool-head" type="button" aria-expanded="false">
22
+ * <span class="ai-item-icon" aria-hidden="true">…svg…</span>
23
+ * <span class="ai-item-main">
24
+ * <span class="ai-item-title">Read</span>
25
+ * <span class="ai-item-sub">src/foo.ts:1-50</span>
26
+ * </span>
27
+ * <span class="ai-item-status" role="img" aria-label="完成"></span>
28
+ * <span class="ai-item-meta">0.4s</span>
29
+ * </button>
30
+ * <div class="ai-tool-body" hidden>
31
+ * <div class="ai-tool-io"><div class="ai-tool-io-label">输入</div><pre class="ai-tool-io-content">…</pre></div>
32
+ * <div class="ai-tool-io"><div class="ai-tool-io-label">输出</div><pre class="ai-tool-io-content">…</pre></div>
33
+ * <div class="ai-tool-approval"> ← 仅 .is-approval 显示(纯 CSS 驱动)
34
+ * <div class="ai-tool-approval-reason" hidden>审批原因</div> ← 可选(model.approval.reason)
35
+ * <button class="btn btn-sm btn-primary" data-ai-approve type="button">允许</button>
36
+ * <button class="btn btn-sm" data-ai-reject type="button">拒绝</button>
37
+ * </div>
38
+ * </div>
39
+ * </div>
40
+ *
41
+ * ── 子智能体卡 ──
42
+ * <div class="ai-subagent is-running" data-ai-id="…" data-ai-kind="subagent">
43
+ * <button class="ai-subagent-head" type="button" aria-expanded="false">…head 结构同上…</button>
44
+ * <div class="ai-subagent-body" hidden>
45
+ * <div class="ai-subagent-stream"> ← 嵌套 .ai-tool / .ai-subagent;
46
+ * … 行间 style="--ai-activity-index:i" 驱动渐入 stagger
47
+ * </div>
48
+ * <div class="ai-subagent-result">完成回执摘要</div>
49
+ * </div>
50
+ * </div>
51
+ *
52
+ * 状态机 7 态(全条目共享,规格 §1):
53
+ * .is-pending faint 空心点
54
+ * .is-running tint 脉冲点(--ai-item-pulse-duration 变量化时长)
55
+ * .is-streaming ▍流式光标(colors.css blink keyframes,--ai-item-blink-duration 变量化)
56
+ * .is-approval warning 点 + 外环;卡片边框 warning;显示审批按钮
57
+ * .is-done success 纯 CSS 对勾
58
+ * .is-error error 点 + 外环;失败条目由 behavior 首次渲染自动展开
59
+ * .is-cancelled faint 点 + 标题删除线
60
+ *
61
+ * kind 修饰类 ai-tool--<kind> 只覆盖 --ai-item-tint(继承 = 变量级联,不改结构):
62
+ * read/search/grep/glob=info · edit/write=accent · rm=error · shell=muted · mcp/skill=success
63
+ * browser/fetch/todo/plan/subagent/note = 默认 accent(不写规则)
64
+ * 第三方 registerAiKind 的 tint 由 behavior 内联 --ai-item-tint 兜底。
65
+ */
66
+
67
+ /* ══════════════════════════════════════════════════════════════
68
+ 条目基元 .ai-item(行式条目"基类")
69
+ ══════════════════════════════════════════════════════════════ */
70
+
71
+ .ai-item {
72
+ /* 局部变量槽:kind/变体只覆盖这些变量(--btn-* 同款继承模式) */
73
+ --ai-item-tint: var(--token-accent);
74
+ --ai-item-pulse-duration: 1.5s; /* running 脉冲(pill --pill-pulse-duration 同款变量化) */
75
+ --ai-item-blink-duration: 1s; /* streaming 光标闪烁 */
76
+
77
+ display: flex;
78
+ flex-wrap: wrap;
79
+ align-items: center;
80
+ gap: var(--density-space-sm);
81
+ min-width: 0;
82
+ align-self: stretch; /* 宽度自稳定:宿主 flex/grid 居中时不 shrink-wrap(width:100% 会塌成 min-content,禁用) */
83
+ }
84
+
85
+ .ai-item-icon {
86
+ display: inline-flex;
87
+ align-items: center;
88
+ justify-content: center;
89
+ flex-shrink: 0;
90
+ width: 20px;
91
+ height: 20px;
92
+ color: var(--ai-item-tint);
93
+ transition: color var(--icen-tx-fast);
94
+ }
95
+ .ai-item-icon > svg {
96
+ width: 16px;
97
+ height: 16px;
98
+ }
99
+
100
+ .ai-item-main {
101
+ flex: 1 1 auto;
102
+ min-width: 0;
103
+ display: flex;
104
+ flex-direction: column;
105
+ gap: 1px;
106
+ }
107
+ .ai-item-title {
108
+ font-size: var(--density-font-size-md);
109
+ line-height: 1.4;
110
+ color: var(--token-text);
111
+ overflow: hidden;
112
+ text-overflow: ellipsis;
113
+ white-space: nowrap;
114
+ }
115
+ .ai-item-sub {
116
+ font-size: var(--density-font-size-xs);
117
+ line-height: 1.4;
118
+ color: var(--token-text-muted);
119
+ overflow: hidden;
120
+ text-overflow: ellipsis;
121
+ white-space: nowrap;
122
+ }
123
+ .ai-item-side {
124
+ display: inline-flex;
125
+ align-items: center;
126
+ gap: var(--density-space-xs);
127
+ margin-left: auto;
128
+ flex-shrink: 0;
129
+ }
130
+ /* head 直排结构(无 .ai-item-side 包裹)时,状态点顶到右侧 */
131
+ .ai-tool-head > .ai-item-status,
132
+ .ai-subagent-head > .ai-item-status {
133
+ margin-left: auto;
134
+ }
135
+
136
+ .ai-item-meta {
137
+ font-size: var(--density-font-size-xs);
138
+ color: var(--token-text-faint);
139
+ font-variant-numeric: tabular-nums;
140
+ flex-shrink: 0;
141
+ }
142
+
143
+ .ai-item-detail {
144
+ flex-basis: 100%;
145
+ min-width: 100%;
146
+ }
147
+
148
+ /* ── 状态点 .ai-item-status(纯 CSS 圆点,由 .is-* 决定颜色与动效) ── */
149
+ .ai-item-status {
150
+ position: relative;
151
+ flex-shrink: 0;
152
+ width: 8px;
153
+ height: 8px;
154
+ border-radius: 50%;
155
+ }
156
+
157
+ /* 等待:faint 空心点(.ai-subagent 与 .ai-item 共享同一状态语言) */
158
+ :is(.ai-item, .ai-tool, .ai-subagent).is-pending .ai-item-status {
159
+ border: 1.5px solid var(--token-text-faint);
160
+ }
161
+
162
+ /* 执行中:tint 脉冲点 */
163
+ :is(.ai-item, .ai-tool, .ai-subagent).is-running .ai-item-status {
164
+ background: var(--ai-item-tint);
165
+ animation: ai-item-pulse var(--ai-item-pulse-duration) ease-in-out infinite;
166
+ }
167
+ @keyframes ai-item-pulse {
168
+ 0%, 100% { opacity: 1; transform: scale(1); }
169
+ 50% { opacity: 0.4; transform: scale(0.7); }
170
+ }
171
+
172
+ /* 流式中:▍光标闪烁(复用 colors.css 的 blink keyframes,animate-blink 同款) */
173
+ :is(.ai-item, .ai-tool, .ai-subagent).is-streaming .ai-item-status {
174
+ width: 3px;
175
+ height: 12px;
176
+ border-radius: 1px;
177
+ background: var(--ai-item-tint);
178
+ animation: blink var(--ai-item-blink-duration) step-end infinite;
179
+ }
180
+
181
+ /* 待人确认:warning 点 + 外环 */
182
+ :is(.ai-item, .ai-tool, .ai-subagent).is-approval .ai-item-status {
183
+ background: var(--token-warning);
184
+ box-shadow: 0 0 0 3px var(--token-warning-muted);
185
+ }
186
+
187
+ /* 完成:success 对勾(纯 CSS,无 SVG) */
188
+ :is(.ai-item, .ai-tool, .ai-subagent).is-done .ai-item-status::after {
189
+ content: "";
190
+ position: absolute;
191
+ left: 1px;
192
+ top: -1px;
193
+ width: 5px;
194
+ height: 9px;
195
+ border-right: 1.5px solid var(--token-success);
196
+ border-bottom: 1.5px solid var(--token-success);
197
+ transform: rotate(45deg);
198
+ }
199
+
200
+ /* 失败:error 点 + 外环 */
201
+ :is(.ai-item, .ai-tool, .ai-subagent).is-error .ai-item-status {
202
+ background: var(--token-error);
203
+ box-shadow: 0 0 0 3px var(--token-error-muted);
204
+ }
205
+
206
+ /* 已取消:faint 点 + 标题删除线 */
207
+ :is(.ai-item, .ai-tool, .ai-subagent).is-cancelled .ai-item-status {
208
+ background: var(--token-text-faint);
209
+ opacity: 0.6;
210
+ }
211
+ :is(.ai-item, .ai-tool, .ai-subagent).is-cancelled .ai-item-title {
212
+ color: var(--token-text-faint);
213
+ text-decoration: line-through;
214
+ }
215
+
216
+ /* ══════════════════════════════════════════════════════════════
217
+ 工具调用卡 .ai-tool
218
+ ══════════════════════════════════════════════════════════════ */
219
+
220
+ .ai-tool {
221
+ --ai-item-tint: var(--token-accent);
222
+ align-self: stretch; /* 宽度自稳定:宿主 flex/grid 居中时不 shrink-wrap */
223
+ border: 1px solid var(--token-line-soft);
224
+ border-radius: var(--radius-md);
225
+ background: var(--token-surface);
226
+ }
227
+
228
+ /* ── kind 修饰类:只覆盖 --ai-item-tint ──
229
+ browser/fetch/todo/plan/subagent/note 用默认 accent,不写规则 */
230
+ .ai-tool--read,
231
+ .ai-tool--search,
232
+ .ai-tool--grep,
233
+ .ai-tool--glob {
234
+ --ai-item-tint: var(--token-info);
235
+ }
236
+ .ai-tool--edit,
237
+ .ai-tool--write {
238
+ --ai-item-tint: var(--token-accent);
239
+ }
240
+ .ai-tool--rm {
241
+ --ai-item-tint: var(--token-error);
242
+ }
243
+ .ai-tool--shell {
244
+ --ai-item-tint: var(--token-text-muted);
245
+ }
246
+ .ai-tool--mcp,
247
+ .ai-tool--skill {
248
+ --ai-item-tint: var(--token-success);
249
+ }
250
+
251
+ /* ── head ── */
252
+ .ai-tool-head,
253
+ .ai-subagent-head {
254
+ display: flex;
255
+ align-items: center;
256
+ gap: var(--density-space-sm);
257
+ width: 100%;
258
+ padding: var(--density-space-xs) var(--density-space-sm);
259
+ border: none;
260
+ border-radius: inherit; /* hover 底色不戳破卡片圆角 */
261
+ background: transparent;
262
+ color: inherit;
263
+ font: inherit;
264
+ text-align: left;
265
+ cursor: pointer;
266
+ -webkit-tap-highlight-color: transparent;
267
+ transition: background-color var(--icen-tx-fast);
268
+ }
269
+ .ai-tool-head:hover,
270
+ .ai-subagent-head:hover {
271
+ background: var(--token-fill-1);
272
+ }
273
+ .ai-tool-head:focus-visible,
274
+ .ai-subagent-head:focus-visible {
275
+ outline: none;
276
+ box-shadow: var(--icen-ring);
277
+ }
278
+
279
+ /* ── body ── */
280
+ .ai-tool-body {
281
+ display: flex;
282
+ flex-direction: column;
283
+ gap: var(--density-space-sm);
284
+ padding: var(--density-space-sm);
285
+ border-top: 1px solid var(--token-line-soft);
286
+ animation: icen-pop-in var(--icen-tx-fast);
287
+ }
288
+ .ai-tool-body[hidden],
289
+ .ai-subagent-body[hidden],
290
+ .ai-tool-io[hidden],
291
+ .ai-subagent-result[hidden] {
292
+ display: none;
293
+ }
294
+
295
+ /* ── 输入/输出区块(pre 等宽、可滚、max-height 收敛) ── */
296
+ .ai-tool-io {
297
+ display: flex;
298
+ flex-direction: column;
299
+ gap: 4px;
300
+ min-width: 0;
301
+ }
302
+ .ai-tool-io-label {
303
+ font-size: var(--density-font-size-2xs);
304
+ font-weight: 600;
305
+ letter-spacing: 0.08em;
306
+ text-transform: uppercase;
307
+ color: var(--token-text-faint);
308
+ }
309
+ .ai-tool-io-content {
310
+ --ai-tool-io-max: 12rem; /* 收敛上限(组件局部变量) */
311
+ margin: 0;
312
+ padding: var(--density-space-xs) var(--density-space-sm);
313
+ max-height: var(--ai-tool-io-max);
314
+ overflow: auto;
315
+ background: var(--token-bg-soft);
316
+ border: 1px solid var(--token-line-soft);
317
+ border-radius: var(--radius-sm);
318
+ font-family: var(--font-mono);
319
+ font-size: var(--density-font-size-sm);
320
+ line-height: 1.5;
321
+ color: var(--token-text);
322
+ white-space: pre-wrap;
323
+ word-break: break-word;
324
+ }
325
+
326
+ /* 多模态回执(MCP content 数组 → 媒体/链接,spec §10.3):
327
+ 容器纵向排布;媒体本体复用 ai-chat.css 的 .ai-msg-media 全局样式 */
328
+ .ai-tool-io-media {
329
+ display: flex;
330
+ flex-direction: column;
331
+ gap: var(--density-space-xs);
332
+ min-width: 0;
333
+ }
334
+
335
+ /* ── 审批区(仅 .is-approval 显示,纯 CSS 驱动) ── */
336
+ .ai-tool-approval {
337
+ display: none;
338
+ align-items: center;
339
+ gap: var(--density-space-sm);
340
+ padding-top: var(--density-space-xs);
341
+ border-top: 1px dashed var(--token-line-soft);
342
+ }
343
+ .ai-tool.is-approval .ai-tool-approval {
344
+ display: flex;
345
+ }
346
+ .ai-tool-approval-reason {
347
+ flex: 1 1 auto;
348
+ min-width: 0;
349
+ font-size: var(--density-font-size-xs);
350
+ line-height: 1.5;
351
+ color: var(--token-text-muted);
352
+ }
353
+ .ai-tool.is-approval {
354
+ border-color: color-mix(in srgb, var(--token-warning) 40%, transparent);
355
+ }
356
+ .ai-tool.is-error {
357
+ border-color: color-mix(in srgb, var(--token-error) 40%, transparent);
358
+ }
359
+
360
+ /* ══════════════════════════════════════════════════════════════
361
+ 子智能体卡 .ai-subagent(嵌套活动流 = 缩进 + 左侧引导线,可递归)
362
+ ══════════════════════════════════════════════════════════════ */
363
+
364
+ .ai-subagent {
365
+ --ai-item-tint: var(--token-accent);
366
+ align-self: stretch; /* 宽度自稳定:宿主 flex/grid 居中时不 shrink-wrap */
367
+ border: 1px solid var(--token-line-soft);
368
+ border-left: 3px solid var(--ai-item-tint); /* 代理卡身份:tint 左边条 */
369
+ border-radius: var(--radius-md);
370
+ background: var(--token-surface);
371
+ }
372
+ .ai-subagent.is-error {
373
+ border-left-color: var(--token-error);
374
+ }
375
+ .ai-subagent.is-done {
376
+ border-left-color: var(--token-success);
377
+ }
378
+
379
+ .ai-subagent-body {
380
+ display: flex;
381
+ flex-direction: column;
382
+ gap: var(--density-space-sm);
383
+ padding: var(--density-space-sm);
384
+ border-top: 1px solid var(--token-line-soft);
385
+ }
386
+
387
+ /* 嵌套流:缩进 + 引导线;行间渐入 stagger 由 --ai-activity-index(render 写入)驱动 */
388
+ .ai-subagent-stream {
389
+ --ai-stagger-step: 40ms; /* 活动项渐入步长(组件局部变量) */
390
+ position: relative;
391
+ display: flex;
392
+ flex-direction: column;
393
+ gap: var(--density-space-xs);
394
+ padding-left: var(--density-space-md);
395
+ }
396
+ .ai-subagent-stream::before {
397
+ content: "";
398
+ position: absolute;
399
+ left: 5px;
400
+ top: var(--density-space-xs);
401
+ bottom: var(--density-space-xs);
402
+ width: 1px;
403
+ background: var(--token-line-soft);
404
+ }
405
+ /* 展开(body 从 hidden 解除)时,活动项逐条 icen-pop-in 渐入 */
406
+ .ai-subagent-stream > * {
407
+ animation: icen-pop-in var(--icen-tx-fast) backwards;
408
+ animation-delay: calc(var(--ai-activity-index, 0) * var(--ai-stagger-step));
409
+ }
410
+
411
+ /* 完成回执 */
412
+ .ai-subagent-result {
413
+ padding: var(--density-space-xs) var(--density-space-sm);
414
+ background: var(--token-bg-soft);
415
+ border: 1px solid var(--token-line-soft);
416
+ border-radius: var(--radius-sm);
417
+ font-size: var(--density-font-size-sm);
418
+ line-height: 1.5;
419
+ color: var(--token-text-muted);
420
+ }
421
+ .ai-subagent.is-done .ai-subagent-result {
422
+ color: var(--token-text);
423
+ border-color: color-mix(in srgb, var(--token-success) 30%, transparent);
424
+ }
425
+
426
+ /* ══════════════════════════════════════════════════════════════
427
+ 动效守卫
428
+ ══════════════════════════════════════════════════════════════ */
429
+ @media (prefers-reduced-motion: reduce) {
430
+ :is(.ai-item, .ai-tool, .ai-subagent).is-running .ai-item-status,
431
+ :is(.ai-item, .ai-tool, .ai-subagent).is-streaming .ai-item-status {
432
+ animation: none;
433
+ }
434
+ .ai-tool-body,
435
+ .ai-subagent-stream > * {
436
+ animation: none;
437
+ }
438
+ .ai-tool-head,
439
+ .ai-subagent-head {
440
+ transition: none;
441
+ }
442
+ }
443
+
444
+ /* ═══ 工具卡内嵌图表(回执 = ChartSpec 时 setIo 走 renderChart,§13)═══ */
445
+ .ai-tool-io-chart {
446
+ width: 100%;
447
+ min-width: 0;
448
+ }
449
+
450
+ /* ═══ AI 工具挂载区(ai-tools.ts 的 createAiToolArea,§13)═══
451
+ * .ai-tools-mount > .ai-tools-item > head(名/时间/×)+ body(工具自渲染) */
452
+ .ai-tools-mount {
453
+ display: grid;
454
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
455
+ gap: var(--density-space-md);
456
+ align-items: start;
457
+ }
458
+ .ai-tools-item {
459
+ display: flex;
460
+ flex-direction: column;
461
+ min-width: 0;
462
+ border: 1px solid var(--token-line-soft);
463
+ border-radius: var(--radius-md);
464
+ background: var(--token-surface);
465
+ animation: icen-pop-in var(--duration-normal) var(--ease-out);
466
+ }
467
+ .ai-tools-item-head {
468
+ display: flex;
469
+ align-items: center;
470
+ gap: var(--density-space-sm);
471
+ padding: var(--density-space-xs) var(--density-space-sm);
472
+ border-bottom: 1px solid var(--token-line-soft);
473
+ }
474
+ .ai-tools-item-name {
475
+ font-family: var(--font-mono);
476
+ font-size: var(--density-font-size-xs);
477
+ color: var(--token-text);
478
+ }
479
+ .ai-tools-item-meta {
480
+ flex: 1;
481
+ font-family: var(--font-mono);
482
+ font-size: var(--density-font-size-2xs);
483
+ color: var(--token-text-faint);
484
+ font-variant-numeric: tabular-nums;
485
+ }
486
+ .ai-tools-item-remove {
487
+ border: 0;
488
+ background: transparent;
489
+ color: var(--token-text-faint);
490
+ cursor: pointer;
491
+ border-radius: var(--radius-xs);
492
+ font-size: var(--density-font-size-sm);
493
+ line-height: 1;
494
+ padding: 2px 6px;
495
+ transition: color var(--icen-tx-fast), background-color var(--icen-tx-fast);
496
+ }
497
+ .ai-tools-item-remove:hover { color: var(--token-error); background: var(--token-fill-1); }
498
+ .ai-tools-item-remove:focus-visible { outline: none; box-shadow: var(--icen-ring); }
499
+ .ai-tools-item-body {
500
+ padding: var(--density-space-sm);
501
+ min-width: 0;
502
+ }
503
+
504
+ @media (prefers-reduced-motion: reduce) {
505
+ .ai-tools-item { animation: none; }
506
+ }
507
+
508
+ /* 挂载项折叠态:head 为 button(chevron + 名/时间 + ×) */
509
+ .ai-tools-item-head {
510
+ cursor: pointer;
511
+ border: 0;
512
+ background: transparent;
513
+ text-align: left;
514
+ width: 100%;
515
+ font: inherit;
516
+ }
517
+ .ai-tools-item-chevron {
518
+ flex-shrink: 0;
519
+ color: var(--token-text-faint);
520
+ font-size: var(--density-font-size-xs);
521
+ transition: transform var(--icen-tx-fast);
522
+ }
523
+ .ai-tools-item-head[aria-expanded='false'] .ai-tools-item-chevron {
524
+ transform: rotate(-90deg);
525
+ }
526
+ .ai-tools-item.is-collapsed .ai-tools-item-body {
527
+ display: none;
528
+ }
529
+ .ai-tools-item-head:focus-visible {
530
+ outline: none;
531
+ box-shadow: var(--icen-ring);
532
+ }
@@ -0,0 +1,3 @@
1
+ // @icen.ai/ui — kit: ai-usage(CSS + behavior 一行入口;构建产物,勿手改)
2
+ import './ai-panel.css';
3
+ export { renderAiUsage, renderAiUsageRing, renderAiAudit } from '../behaviors/ai-panel.mjs';
@@ -0,0 +1,88 @@
1
+ /*
2
+ * @icen.ai/ui — Component: back-top(回到顶部按钮,与 behaviors/back-top 配套)
3
+ *
4
+ * 契约(两种用法):
5
+ * 1. 手写 + init:behavior 给 .back-top[data-back-top] 加 .is-shown 类
6
+ * <button class="back-top" data-back-top type="button" aria-label="回到顶部">…svg…</button>
7
+ *
8
+ * 2. 全自动:initBackTop() 后任何 [data-back-top-auto] 会被自动 portal 到 body
9
+ * 并接管滚到顶部逻辑,无需手写按钮
10
+ * initBackTop({ autoCreate: true }) // 自动创建一个默认样式的按钮
11
+ *
12
+ * 默认滚动超过 320px 后出现;点击后 window.scrollTo({ top: 0, behavior: 'smooth' })。
13
+ */
14
+
15
+ .back-top {
16
+ position: fixed;
17
+ right: var(--density-space-lg);
18
+ bottom: var(--density-space-lg);
19
+ z-index: var(--z-sticky);
20
+ display: inline-flex;
21
+ align-items: center;
22
+ justify-content: center;
23
+ width: 40px;
24
+ height: 40px;
25
+ padding: 0;
26
+ background: var(--token-card-strong);
27
+ color: var(--token-text-muted);
28
+ border: 1px solid var(--token-outline-soft);
29
+ border-radius: var(--radius-full);
30
+ box-shadow: var(--token-shadow-overlay);
31
+ cursor: pointer;
32
+ -webkit-tap-highlight-color: transparent;
33
+ opacity: 0;
34
+ transform: translateY(12px) scale(0.9);
35
+ pointer-events: none;
36
+ transition:
37
+ opacity var(--icen-tx-normal),
38
+ transform var(--icen-tx-normal),
39
+ color var(--icen-tx-fast),
40
+ border-color var(--icen-tx-fast);
41
+ }
42
+ .back-top.is-shown {
43
+ opacity: 1;
44
+ transform: translateY(0) scale(1);
45
+ pointer-events: auto;
46
+ }
47
+ .back-top:hover {
48
+ color: var(--token-accent);
49
+ border-color: var(--token-accent);
50
+ }
51
+ .back-top:focus-visible {
52
+ outline: none;
53
+ box-shadow: var(--token-shadow-overlay), var(--icen-ring);
54
+ }
55
+ .back-top svg {
56
+ width: 18px;
57
+ height: 18px;
58
+ flex-shrink: 0;
59
+ }
60
+
61
+ /* 尺寸变体 */
62
+ .back-top--sm {
63
+ width: 32px;
64
+ height: 32px;
65
+ }
66
+ .back-top--sm svg { width: 14px; height: 14px; }
67
+ .back-top--lg {
68
+ width: 48px;
69
+ height: 48px;
70
+ }
71
+ .back-top--lg svg { width: 22px; height: 22px; }
72
+
73
+ /* 方向变体:箭头方向(默认上) */
74
+ .back-top[data-dir='left'] svg { transform: rotate(90deg); }
75
+ .back-top[data-dir='right'] svg { transform: rotate(-90deg); }
76
+ .back-top[data-dir='down'] svg { transform: rotate(180deg); }
77
+
78
+ @media (max-width: 480px) {
79
+ .back-top {
80
+ right: var(--density-space-sm);
81
+ bottom: var(--density-space-sm);
82
+ }
83
+ }
84
+
85
+ @media (prefers-reduced-motion: reduce) {
86
+ .back-top { transition: opacity var(--icen-tx-fast); transform: none !important; }
87
+ .back-top.is-shown { transform: none !important; }
88
+ }
@@ -0,0 +1,3 @@
1
+ // @icen.ai/ui — kit: back-top(CSS + behavior 一行入口;构建产物,勿手改)
2
+ import './back-top.css';
3
+ export * from '../behaviors/back-top.mjs';