@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,3 +1,10 @@
1
+ // src/behaviors/events.ts
2
+ function emitIcen(source, type, detail) {
3
+ return source.dispatchEvent(
4
+ new CustomEvent(type, { detail, bubbles: true, composed: true, cancelable: true })
5
+ );
6
+ }
7
+
1
8
  // src/behaviors/back-top.ts
2
9
  function numOr(value, fallback) {
3
10
  if (value === void 0 || value === "") return fallback;
@@ -51,7 +58,10 @@ function setup(btn, opts = {}) {
51
58
  const scrollHost = !isWindow && targetEl ? targetEl : window;
52
59
  scrollHost.addEventListener("scroll", onScroll, { passive: true });
53
60
  window.addEventListener("resize", onScroll, { passive: true });
54
- const onClick = () => scrollToTop(target, offset);
61
+ const onClick = () => {
62
+ scrollToTop(target, offset);
63
+ emitIcen(btn, "icen:back-top", {});
64
+ };
55
65
  btn.addEventListener("click", onClick);
56
66
  apply();
57
67
  return () => {
@@ -67,6 +77,7 @@ function initBackTop(opts = {}) {
67
77
  const root = opts.root ?? document;
68
78
  if (opts.autoCreate) {
69
79
  let btn = document.body.querySelector(".back-top[data-back-top-auto]");
80
+ let created = false;
70
81
  if (!btn) {
71
82
  btn = document.createElement("button");
72
83
  btn.type = "button";
@@ -77,9 +88,13 @@ function initBackTop(opts = {}) {
77
88
  const svg = new DOMParser().parseFromString(AUTO_BTN_SVG, "image/svg+xml").documentElement;
78
89
  btn.appendChild(document.importNode(svg, true));
79
90
  document.body.appendChild(btn);
91
+ created = true;
80
92
  }
81
93
  const cleanup = setup(btn, opts);
82
94
  if (cleanup) cleanups.push(cleanup);
95
+ if (created) cleanups.push(() => {
96
+ btn?.remove();
97
+ });
83
98
  }
84
99
  const candidates = [];
85
100
  if (root instanceof Element && root.matches(".back-top[data-back-top]")) candidates.push(root);
@@ -1,4 +1,7 @@
1
- /** 为 root 下每个 .carousel 初始化(root 自身是 .carousel 也算)。 */
2
- declare function initCarousel(root?: ParentNode): void;
1
+ /**
2
+ * 为 root 下每个 .carousel 初始化(root 自身是 .carousel 也算)。
3
+ * 返回销毁函数:移除本次挂上的全部监听并复位幂等标记(销毁后可重新 init)。SSR 下返回 no-op。
4
+ */
5
+ declare function initCarousel(root?: ParentNode): () => void;
3
6
 
4
7
  export { initCarousel };
@@ -1,23 +1,30 @@
1
+ // src/behaviors/events.ts
2
+ function emitIcen(source, type, detail) {
3
+ return source.dispatchEvent(
4
+ new CustomEvent(type, { detail, bubbles: true, composed: true, cancelable: true })
5
+ );
6
+ }
7
+
1
8
  // src/behaviors/carousel.ts
2
9
  function setup(carousel) {
3
10
  const el = carousel;
4
- if (el.__icenCarouselInit) return;
5
- el.__icenCarouselInit = true;
6
- const trackQ = carousel.querySelector(":scope > .carousel-track");
7
- if (!trackQ) return;
8
- const track = trackQ;
11
+ if (el.__icenCarouselInit) return void 0;
12
+ const track = carousel.querySelector(":scope > .carousel-track");
13
+ if (!track) return void 0;
9
14
  const prev = carousel.querySelector(".carousel-arrow--prev");
10
15
  const next = carousel.querySelector(".carousel-arrow--next");
11
16
  const dotsBox = carousel.querySelector(".carousel-dots");
17
+ const querySlides = () => Array.from(track.querySelectorAll(":scope > .carousel-slide"));
12
18
  let index = 0;
13
19
  let slides = querySlides();
14
20
  let count = slides.length;
15
- if (count === 0) return;
21
+ if (count === 0) return void 0;
22
+ el.__icenCarouselInit = true;
16
23
  let dots = [];
17
- function querySlides() {
18
- return Array.from(track.querySelectorAll(":scope > .carousel-slide"));
19
- }
24
+ let dotOffs = [];
20
25
  function buildDots() {
26
+ for (const off of dotOffs) off();
27
+ dotOffs = [];
21
28
  if (!dotsBox) return;
22
29
  while (dotsBox.firstChild) dotsBox.removeChild(dotsBox.firstChild);
23
30
  dots = [];
@@ -27,7 +34,9 @@ function setup(carousel) {
27
34
  dot.type = "button";
28
35
  dot.className = "carousel-dot";
29
36
  dot.setAttribute("aria-label", `\u7B2C ${i + 1} \u5F20`);
30
- dot.addEventListener("click", () => go(i));
37
+ const onDotClick = () => go(i);
38
+ dot.addEventListener("click", onDotClick);
39
+ dotOffs.push(() => dot.removeEventListener("click", onDotClick));
31
40
  dotsBox.appendChild(dot);
32
41
  dots.push(dot);
33
42
  }
@@ -39,7 +48,7 @@ function setup(carousel) {
39
48
  if (index >= count) index = Math.max(0, count - 1);
40
49
  buildDots();
41
50
  }
42
- function render() {
51
+ const render = () => {
43
52
  track.style.transform = `translateX(${-index * 100}%)`;
44
53
  slides.forEach((s, i) => s.setAttribute("aria-hidden", String(i !== index)));
45
54
  dots.forEach((d, i) => {
@@ -47,20 +56,19 @@ function setup(carousel) {
47
56
  if (i === index) d.setAttribute("aria-current", "true");
48
57
  else d.removeAttribute("aria-current");
49
58
  });
50
- }
59
+ };
51
60
  function go(i) {
52
61
  syncSlides();
53
62
  if (count === 0) return;
54
63
  index = (i % count + count) % count;
55
64
  render();
56
- carousel.dispatchEvent(new CustomEvent("icen:carousel-change", {
57
- bubbles: true,
58
- detail: { index, count }
59
- }));
65
+ emitIcen(carousel, "icen:carousel-change", { index, count });
60
66
  }
61
- prev?.addEventListener("click", () => go(index - 1));
62
- next?.addEventListener("click", () => go(index + 1));
63
- carousel.addEventListener("keydown", (ev) => {
67
+ const onPrev = () => go(index - 1);
68
+ const onNext = () => go(index + 1);
69
+ prev?.addEventListener("click", onPrev);
70
+ next?.addEventListener("click", onNext);
71
+ const onKeyDown = (ev) => {
64
72
  const kev = ev;
65
73
  switch (kev.key) {
66
74
  case "ArrowLeft":
@@ -80,17 +88,36 @@ function setup(carousel) {
80
88
  go(count - 1);
81
89
  break;
82
90
  }
83
- });
91
+ };
92
+ carousel.addEventListener("keydown", onKeyDown);
84
93
  buildDots();
85
94
  render();
95
+ return () => {
96
+ prev?.removeEventListener("click", onPrev);
97
+ next?.removeEventListener("click", onNext);
98
+ carousel.removeEventListener("keydown", onKeyDown);
99
+ for (const off of dotOffs) off();
100
+ dotOffs = [];
101
+ dotsBox?.replaceChildren();
102
+ el.__icenCarouselInit = false;
103
+ };
86
104
  }
87
105
  function initCarousel(root) {
88
- if (typeof document === "undefined") return;
89
- const scope = root ?? document;
90
- const containers = [];
91
- if (scope instanceof Element && scope.matches(".carousel")) containers.push(scope);
92
- containers.push(...Array.from(scope.querySelectorAll(".carousel")));
93
- for (const c of containers) setup(c);
106
+ const cleanups = [];
107
+ if (typeof document !== "undefined") {
108
+ const scope = root ?? document;
109
+ const containers = [];
110
+ if (scope instanceof Element && scope.matches(".carousel")) containers.push(scope);
111
+ containers.push(...Array.from(scope.querySelectorAll(".carousel")));
112
+ for (const c of containers) {
113
+ const cleanup = setup(c);
114
+ if (cleanup) cleanups.push(cleanup);
115
+ }
116
+ }
117
+ return () => {
118
+ for (const fn of cleanups) fn();
119
+ cleanups.length = 0;
120
+ };
94
121
  }
95
122
  export {
96
123
  initCarousel
@@ -1,4 +1,5 @@
1
- type ChartTone = 'accent' | 'success' | 'warning' | 'error' | 'muted';
1
+ /** 色调名:内置 5 语义名(经 --token-* 取色);`string & {}` 保自动补全同时放行 registerChartTone 注册的命名档 */
2
+ type ChartTone = 'accent' | 'success' | 'warning' | 'error' | 'muted' | (string & {});
2
3
  interface ChartSeriesOptions extends ChartChromeOptions {
3
4
  labels: string[];
4
5
  values: number[];
@@ -16,6 +17,20 @@ interface ChartSegmentsOptions extends ChartChromeOptions {
16
17
  emptyLabel?: string;
17
18
  formatValue?: (value: number) => string;
18
19
  }
20
+ /**
21
+ * 注册自定义调色盘档位(CSS 变量名,宿主须在样式里提供该变量);tone 取值在
22
+ * 内置 5 语义名(accent/success/warning/error/muted)与调色盘序号之外的自定义
23
+ * 命名档。注册后任意 tone 槽位(spec.series[i].tone / segments[].tone / 各渲染器
24
+ * opts.tone)用该名字取色;查不到该变量时浏览器回退到初始色。
25
+ *
26
+ * @example
27
+ * ```css
28
+ * :root { --my-brand: #e2543e; }
29
+ * ```
30
+ * registerChartTone('brand', '--my-brand');
31
+ * spec.series[0].tone = 'brand';
32
+ */
33
+ declare function registerChartTone(name: string, cssVar: string): void;
19
34
  /** 多系列系列项(ChartSpec 的 series 与各图型共用形态);tone 可为语义名或调色盘序号 1..6 */
20
35
  interface ChartSeriesSpec {
21
36
  name: string;
@@ -35,10 +50,6 @@ interface ChartChromeOptions {
35
50
  title?: string;
36
51
  legend?: boolean;
37
52
  }
38
- /** 跨渲染存活的图例隐藏状态(renderChart 的 update 复渲染沿用;直调不传=每次新状态) */
39
- interface ChartLegendState {
40
- hidden: boolean | null;
41
- }
42
53
  /** 垂直柱状图(单系列,或 series 多系列分组/堆叠——通用层与 renderChart 消费) */
43
54
  interface ChartVBarOptions extends ChartSeriesOptions {
44
55
  /** 多系列(labels 共用,values 长度对齐);缺省回落单系列 values */
@@ -46,13 +57,13 @@ interface ChartVBarOptions extends ChartSeriesOptions {
46
57
  /** 多系列时堆叠(默认分组并排) */
47
58
  stacked?: boolean;
48
59
  }
49
- declare function renderVBar(el: HTMLElement, opts: ChartVBarOptions): void;
60
+ declare function renderVBar(el: HTMLElement, opts: ChartVBarOptions): HTMLElement;
50
61
  /** 水平条形图 */
51
- declare function renderHBar(el: HTMLElement, opts: ChartSeriesOptions): void;
62
+ declare function renderHBar(el: HTMLElement, opts: ChartSeriesOptions): HTMLElement;
52
63
  /** 堆叠条形图(单条 100% + 图例) */
53
- declare function renderStack(el: HTMLElement, opts: ChartSegmentsOptions): void;
64
+ declare function renderStack(el: HTMLElement, opts: ChartSegmentsOptions): HTMLElement;
54
65
  /** 环形图(SVG stroke-dasharray 累加)+ 图例百分比 */
55
- declare function renderDonut(el: HTMLElement, opts: ChartSegmentsOptions): void;
66
+ declare function renderDonut(el: HTMLElement, opts: ChartSegmentsOptions): HTMLElement;
56
67
  /** 折线图(面积渐变 + 网格 + 数据点 + 底部 ≤7 个轴标签;series 多系列走调色盘 + 可切换图例) */
57
68
  interface ChartLineOptions extends ChartSeriesOptions {
58
69
  /** 多系列(labels 共用);缺省回落单系列 values */
@@ -60,12 +71,12 @@ interface ChartLineOptions extends ChartSeriesOptions {
60
71
  /** 多系列时是否填充面积(默认首系列填充;area 类型全填充) */
61
72
  fill?: boolean;
62
73
  }
63
- declare function renderLine(el: HTMLElement, opts: ChartLineOptions): void;
74
+ declare function renderLine(el: HTMLElement, opts: ChartLineOptions): HTMLElement;
64
75
  /** 面积图(与折线同族,以面积填充为视觉主体) */
65
- declare function renderArea(el: HTMLElement, opts: ChartSeriesOptions): void;
76
+ declare function renderArea(el: HTMLElement, opts: ChartSeriesOptions): HTMLElement;
66
77
  interface RadarSeries {
67
78
  name: string;
68
- /** 各轴的值(0..max,顺序与 axes 一致)。元素类型须可转 number。 */
79
+ /** 各轴的值(0..max,顺序与 axes 一致) */
69
80
  values: number[];
70
81
  tone?: ChartTone;
71
82
  }
@@ -82,12 +93,23 @@ interface ChartRadarOptions extends ChartChromeOptions {
82
93
  formatValue?: (value: number) => string;
83
94
  }
84
95
  /** 雷达图(N 轴蛛网 + 多系列多边形 + 图例)。 */
85
- declare function renderRadar(el: HTMLElement, opts: ChartRadarOptions): void;
96
+ declare function renderRadar(el: HTMLElement, opts: ChartRadarOptions): HTMLElement;
86
97
  interface HeatmapDatum {
87
98
  /** YYYY-MM-DD;仅用于 tooltip 与首周对齐 */
88
99
  date: string;
89
100
  value: number;
90
101
  }
102
+ /** calendar/heatmap 本地化文案:纯字符串描述符,保持 JSON 可序列化(ChartSpec 是 AI 可调用的纯 JSON 契约,禁函数) */
103
+ interface ChartI18nLabels {
104
+ /** 周标签(7 项,行序与 weekStart 对齐;缺省 ['一','','三','','五','','日'],weekStart=0 时自动旋转为周日首) */
105
+ weekdays?: string[];
106
+ /** 月标签(12 项,索引即月 0..11;缺省 `${m+1}月`) */
107
+ months?: string[];
108
+ /** 色阶图例左端文案(默认「少」) */
109
+ less?: string;
110
+ /** 色阶图例右端文案(默认「多」) */
111
+ more?: string;
112
+ }
91
113
  interface ChartHeatmapOptions extends ChartChromeOptions {
92
114
  /** 精确形态:日期 + 值(旧 → 新)。与 values 二选一,data 优先。 */
93
115
  data?: HeatmapDatum[];
@@ -96,13 +118,16 @@ interface ChartHeatmapOptions extends ChartChromeOptions {
96
118
  /** 列数(周),默认按数据量推算(向上取整到整周) */
97
119
  weeks?: number;
98
120
  tone?: ChartTone;
121
+ /** 本地化:周首日(0=周日,默认 1=周一;与 date-picker 的 data-date-picker-week-start 语义对齐)与标签文案(纯字符串,保持 JSON 可序列化) */
122
+ weekStart?: 0 | 1;
123
+ labels?: ChartI18nLabels;
99
124
  emptyLabel?: string;
100
125
  formatValue?: (value: number) => string;
101
126
  }
102
- /** GitHub 贡献图式热力格:7 行(周一 → 周日)× N 周列,5 档色阶。 */
103
- declare function renderHeatmap(el: HTMLElement, opts: ChartHeatmapOptions): void;
127
+ /** GitHub 贡献图式热力格:7 行(默认周一 → 周日,weekStart=0 则周日起)× N 周列,5 档色阶。 */
128
+ declare function renderHeatmap(el: HTMLElement, opts: ChartHeatmapOptions): HTMLElement;
104
129
  /** 迷你趋势线(无轴小图,适合嵌入指标卡)。 */
105
- declare function renderSparkline(el: HTMLElement, opts: ChartSeriesOptions): void;
130
+ declare function renderSparkline(el: HTMLElement, opts: ChartSeriesOptions): HTMLElement;
106
131
  interface ChartGaugeOptions {
107
132
  value: number;
108
133
  max?: number;
@@ -112,7 +137,7 @@ interface ChartGaugeOptions {
112
137
  formatValue?: (value: number) => string;
113
138
  }
114
139
  /** 进度环(环形单值 + 中心百分比)。 */
115
- declare function renderGauge(el: HTMLElement, opts: ChartGaugeOptions): void;
140
+ declare function renderGauge(el: HTMLElement, opts: ChartGaugeOptions): HTMLElement;
116
141
  interface ChartCalendarOptions extends ChartChromeOptions {
117
142
  /** ISO 日期数组(YYYY-MM-DD,与 values 配对;或用 data) */
118
143
  dates?: string[];
@@ -120,11 +145,14 @@ interface ChartCalendarOptions extends ChartChromeOptions {
120
145
  /** 精确形态:{date, value}[](与 dates+values 二选一,优先) */
121
146
  data?: HeatmapDatum[];
122
147
  tone?: ChartTone;
148
+ /** 本地化:周首日(0=周日,默认 1=周一;与 date-picker 的 data-date-picker-week-start 语义对齐)与标签文案(纯字符串,保持 JSON 可序列化) */
149
+ weekStart?: 0 | 1;
150
+ labels?: ChartI18nLabels;
123
151
  emptyLabel?: string;
124
152
  formatValue?: (value: number) => string;
125
153
  }
126
- /** 贡献日历(calendar heatmap):dates → 自动周布局 + 月份标签,GitHub 同款 */
127
- declare function renderCalendar(el: HTMLElement, opts: ChartCalendarOptions): void;
154
+ /** 贡献日历(calendar heatmap):dates → 自动周布局 + 月份标签,GitHub 同款。周首日与文案可经 weekStart/labels 本地化。 */
155
+ declare function renderCalendar(el: HTMLElement, opts: ChartCalendarOptions): HTMLElement;
128
156
  interface ChartPointSpec {
129
157
  x: number;
130
158
  y: number;
@@ -142,7 +170,7 @@ interface ChartScatterOptions extends ChartChromeOptions {
142
170
  formatValue?: (value: number) => string;
143
171
  }
144
172
  /** 散点图(可选 size 第三维 → 气泡);坐标域自动 nice 取整 + 边界刻度 */
145
- declare function renderScatter(el: HTMLElement, opts: ChartScatterOptions): void;
173
+ declare function renderScatter(el: HTMLElement, opts: ChartScatterOptions): HTMLElement;
146
174
  type ChartType = 'line' | 'area' | 'vbar' | 'hbar' | 'stack' | 'donut' | 'radar' | 'heatmap' | 'calendar' | 'sparkline' | 'gauge' | 'scatter';
147
175
  /** 数值格式化描述符(替代函数回调——可 JSON 序列化,AI 可给) */
148
176
  interface ChartValueFormat {
@@ -203,6 +231,10 @@ interface ChartSpec {
203
231
  /** 图例:false = 初始隐藏(头部行的小眼睛仍可再展开);true/缺省 = 显示 */
204
232
  legend?: boolean;
205
233
  emptyLabel?: string;
234
+ /** 本地化透传(calendar/heatmap):weekStart 0=周日/1=周一 与标签文案,纯字符串保持 JSON 可序列化 */
235
+ i18n?: ChartI18nLabels & {
236
+ weekStart?: 0 | 1;
237
+ };
206
238
  }
207
239
  /** 格式化描述符 → 函数(底层渲染器的 formatValue 槽) */
208
240
  declare function chartFormatValue(format?: ChartValueFormat): (value: number) => string;
@@ -235,9 +267,23 @@ interface ChartHandle {
235
267
  update(next: ChartSpec | unknown): void;
236
268
  /** icen:chart-<name> 监听糖(hover/click/dblclick/contextmenu);返回解绑函数 */
237
269
  on(name: ChartEventName, listener: (detail: ChartEventDetail, event: Event) => void): () => void;
238
- /** 清空渲染并摘除绑定标记(委托随 el 生存期,destroy 后可重新 renderChart) */
270
+ /** 清空渲染并解绑交互委托(destroy 后可重新 renderChart) */
239
271
  destroy(): void;
240
272
  }
273
+ /**
274
+ * 在图表容器上挂交互委托(幂等,沿用 __icenChartBound 标记):pointer / click /
275
+ * dblclick / contextmenu 归一到 [data-chart-mark] 标记 → icen:chart-hover
276
+ * (phase enter/move/leave)/ icen:chart-click / icen:chart-dblclick /
277
+ * icen:chart-contextmenu(均 bubbles,detail 含 index/seriesIndex/seriesName/
278
+ * label/value/指针坐标;右键默认 preventDefault),内置 tooltip portal 跟随指针。
279
+ *
280
+ * renderChart 内部即调它;12 个底层渲染器(renderVBar…renderScatter)收尾也会
281
+ * 自动调用——**直调底层渲染器同样能收 icen:chart-\* 事件**,无需经过 renderChart
282
+ * (detail.chart 报该渲染器的图型)。容器已处于某个绑定了委托的外层图表容器
283
+ * 内时自动跳过(renderChart → 底层渲染器路径,外层已覆盖该子树,防重复派发)。
284
+ * 返回解绑函数(移除全部监听并复位标记;解绑后可重新 bind / 重新渲染)。
285
+ */
286
+ declare function bindChartEvents(root: HTMLElement): () => void;
241
287
  /**
242
288
  * 统一入口:normalizeChartSpec → inferChartType(type 缺省时)→ 分发到底层
243
289
  * 渲染器,并在 el 上挂交互委托(hover/click/dblclick/contextmenu → icen:chart-*,
@@ -247,4 +293,4 @@ interface ChartHandle {
247
293
  */
248
294
  declare function renderChart(el: HTMLElement, raw: ChartSpec | unknown): ChartHandle;
249
295
 
250
- export { type ChartCalendarOptions, type ChartChromeOptions, type ChartDims, type ChartEventDetail, type ChartEventName, type ChartGaugeOptions, type ChartHandle, type ChartHeatmapOptions, type ChartLegendState, type ChartLineOptions, type ChartMarkData, type ChartPointSpec, type ChartRadarOptions, type ChartScatterOptions, type ChartSegment, type ChartSegmentsOptions, type ChartSeriesOptions, type ChartSeriesSpec, type ChartSpec, type ChartTone, type ChartType, type ChartVBarOptions, type ChartValueFormat, type HeatmapDatum, type RadarSeries, chartFormatValue, inferChartType, normalizeChartSpec, renderArea, renderCalendar, renderChart, renderDonut, renderGauge, renderHBar, renderHeatmap, renderLine, renderRadar, renderScatter, renderSparkline, renderStack, renderVBar };
296
+ export { type ChartCalendarOptions, type ChartChromeOptions, type ChartDims, type ChartEventDetail, type ChartEventName, type ChartGaugeOptions, type ChartHandle, type ChartHeatmapOptions, type ChartI18nLabels, type ChartLineOptions, type ChartMarkData, type ChartPointSpec, type ChartRadarOptions, type ChartScatterOptions, type ChartSegment, type ChartSegmentsOptions, type ChartSeriesOptions, type ChartSeriesSpec, type ChartSpec, type ChartTone, type ChartType, type ChartVBarOptions, type ChartValueFormat, type HeatmapDatum, type RadarSeries, bindChartEvents, chartFormatValue, inferChartType, normalizeChartSpec, registerChartTone, renderArea, renderCalendar, renderChart, renderDonut, renderGauge, renderHBar, renderHeatmap, renderLine, renderRadar, renderScatter, renderSparkline, renderStack, renderVBar };