@icen.ai/ui 0.8.0 → 0.8.1

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 (106) hide show
  1. package/AGENTS.md +15 -9
  2. package/README.md +8 -3
  3. package/dist/base.css +4 -3
  4. package/dist/behaviors/accordion.d.mts +5 -2
  5. package/dist/behaviors/accordion.mjs +36 -11
  6. package/dist/behaviors/ai-chat.d.mts +3 -1
  7. package/dist/behaviors/ai-chat.mjs +66 -43
  8. package/dist/behaviors/ai-composer.d.mts +28 -3
  9. package/dist/behaviors/ai-composer.mjs +291 -209
  10. package/dist/behaviors/ai-core.d.mts +9 -4
  11. package/dist/behaviors/ai-core.mjs +21 -8
  12. package/dist/behaviors/ai-diff.d.mts +2 -2
  13. package/dist/behaviors/ai-diff.mjs +172 -41
  14. package/dist/behaviors/ai-panel.d.mts +11 -8
  15. package/dist/behaviors/ai-panel.mjs +185 -110
  16. package/dist/behaviors/ai-provider.mjs +54 -48
  17. package/dist/behaviors/ai-tool.d.mts +12 -4
  18. package/dist/behaviors/ai-tool.mjs +311 -263
  19. package/dist/behaviors/ai-tools.d.mts +9 -6
  20. package/dist/behaviors/ai-tools.mjs +259 -155
  21. package/dist/behaviors/back-top.mjs +16 -1
  22. package/dist/behaviors/carousel.d.mts +5 -2
  23. package/dist/behaviors/carousel.mjs +53 -26
  24. package/dist/behaviors/charts.d.mts +68 -22
  25. package/dist/behaviors/charts.mjs +221 -150
  26. package/dist/behaviors/command-palette.d.mts +40 -6
  27. package/dist/behaviors/command-palette.mjs +143 -15
  28. package/dist/behaviors/context-menu.d.mts +21 -4
  29. package/dist/behaviors/context-menu.mjs +122 -38
  30. package/dist/behaviors/controls.d.mts +59 -0
  31. package/dist/behaviors/controls.mjs +601 -0
  32. package/dist/behaviors/copy.d.mts +5 -2
  33. package/dist/behaviors/copy.mjs +37 -12
  34. package/dist/behaviors/datatable.d.mts +12 -0
  35. package/dist/behaviors/datatable.mjs +226 -43
  36. package/dist/behaviors/date-picker.d.mts +2 -2
  37. package/dist/behaviors/date-picker.mjs +171 -32
  38. package/dist/behaviors/dropdown.d.mts +6 -2
  39. package/dist/behaviors/dropdown.mjs +164 -25
  40. package/dist/behaviors/events.d.mts +330 -0
  41. package/dist/behaviors/events.mjs +208 -0
  42. package/dist/behaviors/input.mjs +25 -12
  43. package/dist/behaviors/modal.d.mts +24 -5
  44. package/dist/behaviors/modal.mjs +76 -10
  45. package/dist/behaviors/nav.d.mts +1 -1
  46. package/dist/behaviors/nav.mjs +33 -7
  47. package/dist/behaviors/notification.d.mts +20 -4
  48. package/dist/behaviors/notification.mjs +53 -73
  49. package/dist/behaviors/popover.d.mts +39 -3
  50. package/dist/behaviors/popover.mjs +90 -4
  51. package/dist/behaviors/select.d.mts +4 -2
  52. package/dist/behaviors/select.mjs +161 -24
  53. package/dist/behaviors/sidebar.d.mts +5 -2
  54. package/dist/behaviors/sidebar.mjs +43 -13
  55. package/dist/behaviors/slider.d.mts +5 -2
  56. package/dist/behaviors/slider.mjs +54 -43
  57. package/dist/behaviors/split-pane.d.mts +6 -2
  58. package/dist/behaviors/split-pane.mjs +62 -21
  59. package/dist/behaviors/tabs.d.mts +3 -2
  60. package/dist/behaviors/tabs.mjs +65 -14
  61. package/dist/behaviors/tag-input.d.mts +5 -2
  62. package/dist/behaviors/tag-input.mjs +61 -21
  63. package/dist/behaviors/theme.d.mts +13 -2
  64. package/dist/behaviors/theme.mjs +48 -4
  65. package/dist/behaviors/toast.d.mts +30 -8
  66. package/dist/behaviors/toast.mjs +74 -7
  67. package/dist/behaviors/tree.d.mts +5 -2
  68. package/dist/behaviors/tree.mjs +38 -15
  69. package/dist/behaviors/upload.mjs +21 -23
  70. package/dist/cli.mjs +1 -1
  71. package/dist/components/ai-panel.css +1 -1
  72. package/dist/components/ai-tool-call.mjs +1 -1
  73. package/dist/components/badge.css +1 -1
  74. package/dist/components/breadcrumb.css +0 -32
  75. package/dist/components/chart-calendar.mjs +1 -2
  76. package/dist/components/chart-pie.css +0 -6
  77. package/dist/components/charts.css +1 -1
  78. package/dist/components/content.css +3 -16
  79. package/dist/components/datatable.css +1 -1
  80. package/dist/components/date-picker.css +1 -1
  81. package/dist/components/notification.css +2 -3
  82. package/dist/components/pagination.css +3 -1
  83. package/dist/components/pagination.mjs +1 -0
  84. package/dist/components/rating.mjs +1 -0
  85. package/dist/components/segmented.css +9 -1
  86. package/dist/components/segmented.mjs +1 -1
  87. package/dist/components/select.css +67 -4
  88. package/dist/components/steps.css +13 -3
  89. package/dist/components/steps.mjs +1 -0
  90. package/dist/components/switch.css +3 -1
  91. package/dist/components/switch.mjs +1 -0
  92. package/dist/components/table.mjs +1 -0
  93. package/dist/components/tabs.css +23 -0
  94. package/dist/components/tag-input.css +1 -6
  95. package/dist/components/upload.css +0 -15
  96. package/dist/index.d.mts +12 -10
  97. package/dist/index.mjs +2700 -1460
  98. package/dist/registry.json +42 -13
  99. package/dist/retro-effects.css +3 -16
  100. package/dist/tokens/retro-effects.css +3 -16
  101. package/dist/tokens/style-profiles.css +3 -2
  102. package/dist/tokens/typography.css +2 -0
  103. package/dist/tokens.css +5 -2
  104. package/dist/ui.css +138 -98
  105. package/docs/spec/ai-native.md +7 -4
  106. package/package.json +1 -1
@@ -1,4 +1,13 @@
1
1
  // src/behaviors/ai-core.ts
2
+ var USAGE_KEYS = ["input", "output", "cacheRead", "cacheWrite", "reasoning", "total"];
3
+ function addUsage(sum2, u) {
4
+ const out = { ...sum2 };
5
+ for (const k of USAGE_KEYS) {
6
+ const v = u[k];
7
+ if (typeof v === "number" && Number.isFinite(v)) out[k] = (out[k] ?? 0) + v;
8
+ }
9
+ return out;
10
+ }
2
11
  var svg = (body) => `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${body}</svg>`;
3
12
  var ICON_TERMINAL = svg('<path d="m4 17 6-6-6-6"/><path d="M12 19h8"/>');
4
13
  var ICON_FILE = svg(
@@ -258,6 +267,13 @@ function contentToText(content) {
258
267
  return content.filter((p) => p.type === "text").map((p) => p.text).join("");
259
268
  }
260
269
 
270
+ // src/behaviors/events.ts
271
+ function emitIcen(source, type, detail) {
272
+ return source.dispatchEvent(
273
+ new CustomEvent(type, { detail, bubbles: true, composed: true, cancelable: true })
274
+ );
275
+ }
276
+
261
277
  // src/behaviors/ai-provider.ts
262
278
  function isObj2(v) {
263
279
  return typeof v === "object" && v !== null;
@@ -439,15 +455,6 @@ async function readHttpError(res, provider) {
439
455
  const { type, message } = extractHttpError(raw, status);
440
456
  return new AiProviderError({ provider, status, type, message, raw });
441
457
  }
442
- var USAGE_KEYS = ["input", "output", "cacheRead", "cacheWrite", "reasoning", "total"];
443
- function addUsage(sum2, u) {
444
- if (!u) return sum2;
445
- for (const k of USAGE_KEYS) {
446
- const v = u[k];
447
- if (typeof v === "number" && Number.isFinite(v)) sum2[k] = (sum2[k] ?? 0) + v;
448
- }
449
- return sum2;
450
- }
451
458
  function isAuditEntry(v) {
452
459
  return isObj2(v) && typeof v.id === "string" && typeof v.ts === "number" && typeof v.provider === "string" && typeof v.model === "string" && typeof v.baseURL === "string" && typeof v.stream === "boolean" && (v.status === "ok" || v.status === "error") && typeof v.durationMs === "number";
453
460
  }
@@ -492,7 +499,7 @@ function createAiAuditor(opts) {
492
499
  },
493
500
  summary() {
494
501
  const sum2 = {};
495
- for (const e of entries) addUsage(sum2, e.usage);
502
+ for (const e of entries) addUsage(sum2, e.usage ?? {});
496
503
  return sum2;
497
504
  },
498
505
  totals() {
@@ -502,7 +509,7 @@ function createAiAuditor(opts) {
502
509
  let ttftSum = 0;
503
510
  let ttftN = 0;
504
511
  for (const e of entries) {
505
- addUsage(usage, e.usage);
512
+ addUsage(usage, e.usage ?? {});
506
513
  if (typeof e.cost === "number") cost += e.cost;
507
514
  if (e.status === "error") errors++;
508
515
  if (typeof e.ttftMs === "number") {
@@ -523,7 +530,7 @@ function createAiAuditor(opts) {
523
530
  const out = {};
524
531
  for (const e of entries) {
525
532
  const key = `${e.provider}/${e.model}`;
526
- addUsage(out[key] ??= {}, e.usage);
533
+ addUsage(out[key] ??= {}, e.usage ?? {});
527
534
  }
528
535
  return out;
529
536
  }
@@ -778,23 +785,18 @@ function joinSignals(a, b) {
778
785
  return c.signal;
779
786
  }
780
787
  const fwd = () => {
788
+ a.removeEventListener("abort", fwd);
789
+ b.removeEventListener("abort", fwd);
781
790
  if (!c.signal.aborted) c.abort();
782
791
  };
783
792
  a.addEventListener("abort", fwd, { once: true });
784
793
  b.addEventListener("abort", fwd, { once: true });
785
794
  return c.signal;
786
795
  }
787
- function dispatchUsageEvent(usage) {
796
+ function dispatchAiEvent(name, detail) {
788
797
  if (typeof document === "undefined") return;
789
798
  try {
790
- document.dispatchEvent(new CustomEvent("icen:ai-usage", { detail: usage, bubbles: true }));
791
- } catch {
792
- }
793
- }
794
- function dispatchDoneEvent(detail) {
795
- if (typeof document === "undefined") return;
796
- try {
797
- document.dispatchEvent(new CustomEvent("icen:ai-done", { detail, bubbles: true }));
799
+ emitIcen(document, name, detail);
798
800
  } catch {
799
801
  }
800
802
  }
@@ -866,7 +868,31 @@ function createAiClient(options) {
866
868
  return { entry, cost };
867
869
  }
868
870
  const publishUsage = (usage) => {
869
- if (Object.keys(usage).length > 0) dispatchUsageEvent(usage);
871
+ if (Object.keys(usage).length > 0) dispatchAiEvent("icen:ai-usage", usage);
872
+ };
873
+ const finalize = (req, streaming, status, usage, error, t0, ttftMs) => {
874
+ const durationMs = Date.now() - t0;
875
+ const { cost } = audit(
876
+ req,
877
+ streaming,
878
+ status === "ok" ? "ok" : "error",
879
+ usage,
880
+ durationMs,
881
+ status === "cancelled" ? "\u8BF7\u6C42\u5DF2\u53D6\u6D88" : error,
882
+ ttftMs
883
+ );
884
+ dispatchAiEvent("icen:ai-done", {
885
+ status,
886
+ provider: def.id,
887
+ model: req.model ?? defaultModel,
888
+ stream: streaming,
889
+ usage,
890
+ cost,
891
+ error: status === "cancelled" ? void 0 : error,
892
+ durationMs,
893
+ ttftMs
894
+ });
895
+ return cost;
870
896
  };
871
897
  async function chat(req) {
872
898
  const t0 = Date.now();
@@ -908,23 +934,14 @@ function createAiClient(options) {
908
934
  }
909
935
  const usage = normalizeUsage(usageRaw);
910
936
  publishUsage(usage);
911
- const { cost } = audit(req, false, "ok", usage, Date.now() - t0);
912
- dispatchDoneEvent({
913
- status: "ok",
914
- provider: def.id,
915
- model: req.model ?? defaultModel,
916
- stream: false,
917
- usage,
918
- cost,
919
- durationMs: Date.now() - t0
920
- });
937
+ const cost = finalize(req, false, "ok", usage, void 0, t0);
921
938
  const result = { text: outText, usage, cost, finishReason, raw: j };
922
939
  if (outParts && outParts.length > 0) result.parts = outParts;
923
940
  return result;
924
941
  } catch (err) {
925
942
  const e = normalizeThrown(err);
926
943
  audit(req, false, "error", {}, Date.now() - t0, e.message);
927
- dispatchDoneEvent({
944
+ dispatchAiEvent("icen:ai-done", {
928
945
  status: e.type === "cancelled" ? "cancelled" : "error",
929
946
  provider: def.id,
930
947
  model: req.model ?? defaultModel,
@@ -990,26 +1007,15 @@ function createAiClient(options) {
990
1007
  } finally {
991
1008
  const usage = normalizeUsage(usageRaw);
992
1009
  publishUsage(usage);
993
- const { cost } = audit(
1010
+ const cost = finalize(
994
1011
  req,
995
1012
  true,
996
- errorType === "cancelled" ? "error" : status,
1013
+ errorType === "cancelled" ? "cancelled" : status,
997
1014
  usage,
998
- Date.now() - t0,
999
- errorType === "cancelled" ? "\u8BF7\u6C42\u5DF2\u53D6\u6D88" : error,
1015
+ error,
1016
+ t0,
1000
1017
  ttftMs
1001
1018
  );
1002
- dispatchDoneEvent({
1003
- status: errorType === "cancelled" ? "cancelled" : status,
1004
- provider: def.id,
1005
- model: req.model ?? defaultModel,
1006
- stream: true,
1007
- usage,
1008
- cost,
1009
- error: errorType === "cancelled" ? void 0 : error,
1010
- durationMs: Date.now() - t0,
1011
- ttftMs
1012
- });
1013
1019
  finished = true;
1014
1020
  notify();
1015
1021
  ac.abort();
@@ -8,11 +8,19 @@ interface AiSubagentHandle {
8
8
  el: HTMLElement;
9
9
  update(patch: Partial<AiToolCallModel>): void;
10
10
  }
11
+ /** 渲染工具调用卡(整卡挂进传入 el),返回 { el, update }——有生命周期的 render* 返句柄:update(patch) 增量重渲。 */
11
12
  declare function renderAiToolCall(el: HTMLElement, model: AiToolCallModel): AiToolCallHandle;
13
+ /** 渲染子智能体卡(activities 递归复用 renderAiToolCall / 自身),返回 { el, update }——有生命周期的 render* 返句柄。 */
12
14
  declare function renderAiSubagent(el: HTMLElement, model: AiToolCallModel): AiSubagentHandle;
13
- /** 初始化 root 下所有工具调用卡(root 自身是 .ai-tool 也算)。重复调用幂等。 */
14
- declare function initAiTool(root?: ParentNode): void;
15
- /** 初始化 root 下所有子智能体卡(含嵌套;root 自身是 .ai-subagent 也算)。重复调用幂等。 */
16
- declare function initAiSubagent(root?: ParentNode): void;
15
+ /**
16
+ * 初始化 root 下所有工具调用卡(root 自身是 .ai-tool 也算)。重复调用幂等;
17
+ * 返回销毁函数(复刻 initAiChat 约定:解绑全部卡片监听并复位幂等标记)。
18
+ */
19
+ declare function initAiTool(root?: ParentNode): () => void;
20
+ /**
21
+ * 初始化 root 下所有子智能体卡(含嵌套;root 自身是 .ai-subagent 也算)。重复调用幂等;
22
+ * 返回销毁函数(复刻 initAiChat 约定:解绑全部卡片监听并复位幂等标记)。
23
+ */
24
+ declare function initAiSubagent(root?: ParentNode): () => void;
17
25
 
18
26
  export { type AiSubagentHandle, type AiToolCallHandle, initAiSubagent, initAiTool, renderAiSubagent, renderAiToolCall };