@icen.ai/ui 0.5.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.
- package/AGENTS.md +256 -0
- package/README.md +47 -13
- package/dist/base.css +31 -4
- package/dist/behaviors/accordion.d.mts +4 -0
- package/dist/behaviors/accordion.mjs +4 -3
- package/dist/behaviors/ai-chat.d.mts +57 -0
- package/dist/behaviors/ai-chat.mjs +557 -0
- package/dist/behaviors/ai-composer.d.mts +112 -0
- package/dist/behaviors/ai-composer.mjs +2032 -0
- package/dist/behaviors/ai-core.d.mts +151 -0
- package/dist/behaviors/ai-core.mjs +491 -0
- package/dist/behaviors/ai-diff.d.mts +53 -0
- package/dist/behaviors/ai-diff.mjs +282 -0
- package/dist/behaviors/ai-panel.d.mts +98 -0
- package/dist/behaviors/ai-panel.mjs +1012 -0
- package/dist/behaviors/ai-provider.d.mts +198 -0
- package/dist/behaviors/ai-provider.mjs +1055 -0
- package/dist/behaviors/ai-tool.d.mts +18 -0
- package/dist/behaviors/ai-tool.mjs +2125 -0
- package/dist/behaviors/ai-tools.d.mts +81 -0
- package/dist/behaviors/ai-tools.mjs +1658 -0
- package/dist/behaviors/back-top.d.mts +20 -0
- package/dist/behaviors/back-top.mjs +49 -32
- package/dist/behaviors/carousel.d.mts +4 -0
- package/dist/behaviors/carousel.mjs +34 -16
- package/dist/behaviors/charts.d.mts +250 -0
- package/dist/behaviors/charts.mjs +1301 -448
- package/dist/behaviors/command-palette.d.mts +8 -0
- package/dist/behaviors/command-palette.mjs +24 -12
- package/dist/behaviors/context-menu.d.mts +36 -0
- package/dist/behaviors/context-menu.mjs +6 -2
- package/dist/behaviors/copy.d.mts +4 -0
- package/dist/behaviors/copy.mjs +7 -6
- package/dist/behaviors/datatable.d.mts +78 -0
- package/dist/behaviors/datatable.mjs +54 -11
- package/dist/behaviors/date-picker.d.mts +4 -0
- package/dist/behaviors/date-picker.mjs +104 -36
- package/dist/behaviors/dropdown.d.mts +4 -0
- package/dist/behaviors/dropdown.mjs +7 -3
- package/dist/behaviors/input.d.mts +4 -0
- package/dist/behaviors/input.mjs +29 -22
- package/dist/behaviors/modal.d.mts +11 -0
- package/dist/behaviors/modal.mjs +11 -6
- package/dist/behaviors/nav.d.mts +7 -0
- package/dist/behaviors/nav.mjs +25 -9
- package/dist/behaviors/notification.d.mts +172 -0
- package/dist/behaviors/notification.mjs +243 -89
- package/dist/behaviors/popover.d.mts +46 -0
- package/dist/behaviors/popover.mjs +2 -1
- package/dist/behaviors/select.d.mts +4 -0
- package/dist/behaviors/select.mjs +131 -26
- package/dist/behaviors/sidebar.d.mts +4 -0
- package/dist/behaviors/sidebar.mjs +4 -3
- package/dist/behaviors/slider.d.mts +4 -0
- package/dist/behaviors/slider.mjs +4 -3
- package/dist/behaviors/split-pane.d.mts +4 -0
- package/dist/behaviors/split-pane.mjs +13 -13
- package/dist/behaviors/tabs.d.mts +8 -0
- package/dist/behaviors/tabs.mjs +44 -19
- package/dist/behaviors/tag-input.d.mts +4 -0
- package/dist/behaviors/tag-input.mjs +12 -3
- package/dist/behaviors/theme.d.mts +25 -0
- package/dist/behaviors/theme.mjs +3 -1
- package/dist/behaviors/toast.d.mts +26 -0
- package/dist/behaviors/toast.mjs +24 -18
- package/dist/behaviors/tree.d.mts +4 -0
- package/dist/behaviors/tree.mjs +4 -3
- package/dist/behaviors/upload.d.mts +4 -0
- package/dist/behaviors/upload.mjs +63 -26
- package/dist/components/ai-chat.css +1037 -0
- package/dist/components/ai-chat.mjs +3 -0
- package/dist/components/ai-composer.mjs +3 -0
- package/dist/components/ai-context.mjs +2 -0
- package/dist/components/ai-diff.css +311 -0
- package/dist/components/ai-diff.mjs +3 -0
- package/dist/components/ai-files.mjs +3 -0
- package/dist/components/ai-message.mjs +3 -0
- package/dist/components/ai-panel.css +682 -0
- package/dist/components/ai-reasoning.mjs +3 -0
- package/dist/components/ai-subagent.mjs +2 -0
- package/dist/components/ai-todo.mjs +2 -0
- package/dist/components/ai-tool-call.mjs +2 -0
- package/dist/components/ai-tool.css +532 -0
- package/dist/components/ai-usage.mjs +3 -0
- package/dist/components/badge.css +4 -8
- package/dist/components/breadcrumb.css +1 -5
- package/dist/components/btn.css +4 -7
- package/dist/components/card.css +3 -6
- package/dist/components/chart-bar.css +10 -0
- package/dist/components/chart-calendar.mjs +5 -0
- package/dist/components/chart-gauge.css +1 -1
- package/dist/components/chart-heatmap.css +40 -0
- package/dist/components/chart-scatter.css +24 -0
- package/dist/components/chart-scatter.mjs +4 -0
- package/dist/components/charts.css +86 -1
- package/dist/components/charts.mjs +1 -0
- package/dist/components/command-palette.css +2 -2
- package/dist/components/content.css +8 -9
- package/dist/components/copy.css +8 -8
- package/dist/components/datatable.css +4 -8
- package/dist/components/date-picker.css +3 -7
- package/dist/components/empty.css +0 -4
- package/dist/components/feedback.css +10 -17
- package/dist/components/form.css +13 -14
- package/dist/components/input.css +2 -2
- package/dist/components/layout.css +36 -36
- package/dist/components/media.css +12 -8
- package/dist/components/menu.css +2 -2
- package/dist/components/modal.css +1 -1
- package/dist/components/nav.css +11 -6
- package/dist/components/notification.css +28 -28
- package/dist/components/pagination.css +1 -1
- package/dist/components/panel.css +16 -16
- package/dist/components/pill.css +15 -15
- package/dist/components/segmented.css +5 -5
- package/dist/components/segmented.mjs +1 -0
- package/dist/components/select.css +12 -20
- package/dist/components/sidebar.css +1 -1
- package/dist/components/split-pane.css +0 -1
- package/dist/components/stat.css +14 -18
- package/dist/components/steps.css +2 -2
- package/dist/components/switch.css +8 -12
- package/dist/components/table.css +46 -47
- package/dist/components/tabs.css +35 -46
- package/dist/components/tag-input.css +4 -4
- package/dist/components/toast.css +16 -13
- package/dist/components/tooltip.css +2 -2
- package/dist/index.d.mts +37 -0
- package/dist/index.mjs +7890 -1199
- package/dist/registry.json +113 -4
- package/dist/retro-effects.css +21 -17
- package/dist/tokens/colors.css +4 -1
- package/dist/tokens/retro-effects.css +21 -17
- package/dist/tokens/style-profiles.css +21 -0
- package/dist/tokens.css +25 -1
- package/dist/ui.css +3168 -433
- package/docs/spec/ai-native.md +659 -0
- package/package.json +15 -5
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
interface BackTopOptions {
|
|
2
|
+
/** 是否自动创建一个默认按钮(portal 到 body) */
|
|
3
|
+
autoCreate?: boolean;
|
|
4
|
+
/** 显示阈值(px),默认 320 */
|
|
5
|
+
threshold?: number;
|
|
6
|
+
/** 滚动容器选择器,默认 window */
|
|
7
|
+
target?: string;
|
|
8
|
+
/** 滚动到多少 px,默认 0 */
|
|
9
|
+
offset?: number;
|
|
10
|
+
/** 扫描根节点,默认 document */
|
|
11
|
+
root?: ParentNode;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 初始化:扫描 root 下的 .back-top[data-back-top] 与 [data-back-top-auto]。
|
|
15
|
+
* 传 autoCreate 时自动创建一个默认按钮。
|
|
16
|
+
* 返回销毁函数:移除本次初始化挂上的全部 scroll/resize/click 监听。
|
|
17
|
+
*/
|
|
18
|
+
declare function initBackTop(opts?: BackTopOptions): () => void;
|
|
19
|
+
|
|
20
|
+
export { initBackTop };
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
// src/behaviors/back-top.ts
|
|
2
|
+
function numOr(value, fallback) {
|
|
3
|
+
if (value === void 0 || value === "") return fallback;
|
|
4
|
+
const n = Number(value);
|
|
5
|
+
return Number.isFinite(n) ? n : fallback;
|
|
6
|
+
}
|
|
2
7
|
var AUTO_BTN_SVG = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m18 15-6-6-6 6"/></svg>';
|
|
3
8
|
function prefersReducedMotion() {
|
|
4
9
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
|
|
@@ -26,11 +31,11 @@ function scrollToTop(target, offset = 0) {
|
|
|
26
31
|
}
|
|
27
32
|
function setup(btn, opts = {}) {
|
|
28
33
|
const el = btn;
|
|
29
|
-
if (el.__icenBackTopInit) return;
|
|
34
|
+
if (el.__icenBackTopInit) return void 0;
|
|
30
35
|
el.__icenBackTopInit = true;
|
|
31
|
-
const threshold =
|
|
36
|
+
const threshold = numOr(btn.dataset.backTopThreshold ?? opts.threshold, 320);
|
|
32
37
|
const target = btn.dataset.backTopTarget ?? opts.target;
|
|
33
|
-
const offset =
|
|
38
|
+
const offset = numOr(btn.dataset.backTopOffset ?? opts.offset, 0);
|
|
34
39
|
let ticking = false;
|
|
35
40
|
const apply = () => {
|
|
36
41
|
ticking = false;
|
|
@@ -43,41 +48,53 @@ function setup(btn, opts = {}) {
|
|
|
43
48
|
window.requestAnimationFrame(apply);
|
|
44
49
|
};
|
|
45
50
|
const { el: targetEl, isWindow } = getScrollTarget(target);
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
} else if (targetEl) {
|
|
49
|
-
targetEl.addEventListener("scroll", onScroll, { passive: true });
|
|
50
|
-
}
|
|
51
|
+
const scrollHost = !isWindow && targetEl ? targetEl : window;
|
|
52
|
+
scrollHost.addEventListener("scroll", onScroll, { passive: true });
|
|
51
53
|
window.addEventListener("resize", onScroll, { passive: true });
|
|
52
|
-
|
|
54
|
+
const onClick = () => scrollToTop(target, offset);
|
|
55
|
+
btn.addEventListener("click", onClick);
|
|
53
56
|
apply();
|
|
57
|
+
return () => {
|
|
58
|
+
scrollHost.removeEventListener("scroll", onScroll);
|
|
59
|
+
window.removeEventListener("resize", onScroll);
|
|
60
|
+
btn.removeEventListener("click", onClick);
|
|
61
|
+
el.__icenBackTopInit = false;
|
|
62
|
+
};
|
|
54
63
|
}
|
|
55
64
|
function initBackTop(opts = {}) {
|
|
56
|
-
|
|
57
|
-
if (typeof window
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
const cleanups = [];
|
|
66
|
+
if (typeof document !== "undefined" && typeof window !== "undefined") {
|
|
67
|
+
const root = opts.root ?? document;
|
|
68
|
+
if (opts.autoCreate) {
|
|
69
|
+
let btn = document.body.querySelector(".back-top[data-back-top-auto]");
|
|
70
|
+
if (!btn) {
|
|
71
|
+
btn = document.createElement("button");
|
|
72
|
+
btn.type = "button";
|
|
73
|
+
btn.className = "back-top";
|
|
74
|
+
btn.setAttribute("data-back-top", "");
|
|
75
|
+
btn.setAttribute("data-back-top-auto", "");
|
|
76
|
+
btn.setAttribute("aria-label", "\u56DE\u5230\u9876\u90E8");
|
|
77
|
+
const svg = new DOMParser().parseFromString(AUTO_BTN_SVG, "image/svg+xml").documentElement;
|
|
78
|
+
btn.appendChild(document.importNode(svg, true));
|
|
79
|
+
document.body.appendChild(btn);
|
|
80
|
+
}
|
|
81
|
+
const cleanup = setup(btn, opts);
|
|
82
|
+
if (cleanup) cleanups.push(cleanup);
|
|
83
|
+
}
|
|
84
|
+
const candidates = [];
|
|
85
|
+
if (root instanceof Element && root.matches(".back-top[data-back-top]")) candidates.push(root);
|
|
86
|
+
candidates.push(...Array.from(root.querySelectorAll(".back-top[data-back-top]")));
|
|
87
|
+
for (const c of candidates) {
|
|
88
|
+
const el = c;
|
|
89
|
+
if (el.hasAttribute("data-back-top-auto") && opts.autoCreate) continue;
|
|
90
|
+
const cleanup = setup(el, opts);
|
|
91
|
+
if (cleanup) cleanups.push(cleanup);
|
|
70
92
|
}
|
|
71
|
-
setup(btn, opts);
|
|
72
|
-
}
|
|
73
|
-
const candidates = [];
|
|
74
|
-
if (root instanceof Element && root.matches(".back-top[data-back-top]")) candidates.push(root);
|
|
75
|
-
candidates.push(...Array.from(root.querySelectorAll(".back-top[data-back-top]")));
|
|
76
|
-
for (const c of candidates) {
|
|
77
|
-
const el = c;
|
|
78
|
-
if (el.hasAttribute("data-back-top-auto") && opts.autoCreate) continue;
|
|
79
|
-
setup(el, opts);
|
|
80
93
|
}
|
|
94
|
+
return () => {
|
|
95
|
+
for (const fn of cleanups) fn();
|
|
96
|
+
cleanups.length = 0;
|
|
97
|
+
};
|
|
81
98
|
}
|
|
82
99
|
export {
|
|
83
100
|
initBackTop
|
|
@@ -3,17 +3,25 @@ function setup(carousel) {
|
|
|
3
3
|
const el = carousel;
|
|
4
4
|
if (el.__icenCarouselInit) return;
|
|
5
5
|
el.__icenCarouselInit = true;
|
|
6
|
-
const
|
|
7
|
-
if (!
|
|
8
|
-
const
|
|
9
|
-
const count = slides.length;
|
|
10
|
-
if (count === 0) return;
|
|
6
|
+
const trackQ = carousel.querySelector(":scope > .carousel-track");
|
|
7
|
+
if (!trackQ) return;
|
|
8
|
+
const track = trackQ;
|
|
11
9
|
const prev = carousel.querySelector(".carousel-arrow--prev");
|
|
12
10
|
const next = carousel.querySelector(".carousel-arrow--next");
|
|
13
11
|
const dotsBox = carousel.querySelector(".carousel-dots");
|
|
14
12
|
let index = 0;
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
let slides = querySlides();
|
|
14
|
+
let count = slides.length;
|
|
15
|
+
if (count === 0) return;
|
|
16
|
+
let dots = [];
|
|
17
|
+
function querySlides() {
|
|
18
|
+
return Array.from(track.querySelectorAll(":scope > .carousel-slide"));
|
|
19
|
+
}
|
|
20
|
+
function buildDots() {
|
|
21
|
+
if (!dotsBox) return;
|
|
22
|
+
while (dotsBox.firstChild) dotsBox.removeChild(dotsBox.firstChild);
|
|
23
|
+
dots = [];
|
|
24
|
+
if (count <= 1) return;
|
|
17
25
|
for (let i = 0; i < count; i++) {
|
|
18
26
|
const dot = document.createElement("button");
|
|
19
27
|
dot.type = "button";
|
|
@@ -24,23 +32,31 @@ function setup(carousel) {
|
|
|
24
32
|
dots.push(dot);
|
|
25
33
|
}
|
|
26
34
|
}
|
|
35
|
+
function syncSlides() {
|
|
36
|
+
slides = querySlides();
|
|
37
|
+
if (slides.length === count) return;
|
|
38
|
+
count = slides.length;
|
|
39
|
+
if (index >= count) index = Math.max(0, count - 1);
|
|
40
|
+
buildDots();
|
|
41
|
+
}
|
|
27
42
|
function render() {
|
|
28
|
-
if (!track) return;
|
|
29
43
|
track.style.transform = `translateX(${-index * 100}%)`;
|
|
30
44
|
slides.forEach((s, i) => s.setAttribute("aria-hidden", String(i !== index)));
|
|
31
45
|
dots.forEach((d, i) => {
|
|
32
|
-
d.classList.toggle("active", i === index);
|
|
46
|
+
d.classList.toggle("is-active", i === index);
|
|
33
47
|
if (i === index) d.setAttribute("aria-current", "true");
|
|
34
48
|
else d.removeAttribute("aria-current");
|
|
35
49
|
});
|
|
36
|
-
carousel.dispatchEvent(new CustomEvent("icen:carousel-change", {
|
|
37
|
-
bubbles: true,
|
|
38
|
-
detail: { index, count }
|
|
39
|
-
}));
|
|
40
50
|
}
|
|
41
51
|
function go(i) {
|
|
52
|
+
syncSlides();
|
|
53
|
+
if (count === 0) return;
|
|
42
54
|
index = (i % count + count) % count;
|
|
43
55
|
render();
|
|
56
|
+
carousel.dispatchEvent(new CustomEvent("icen:carousel-change", {
|
|
57
|
+
bubbles: true,
|
|
58
|
+
detail: { index, count }
|
|
59
|
+
}));
|
|
44
60
|
}
|
|
45
61
|
prev?.addEventListener("click", () => go(index - 1));
|
|
46
62
|
next?.addEventListener("click", () => go(index + 1));
|
|
@@ -65,13 +81,15 @@ function setup(carousel) {
|
|
|
65
81
|
break;
|
|
66
82
|
}
|
|
67
83
|
});
|
|
84
|
+
buildDots();
|
|
68
85
|
render();
|
|
69
86
|
}
|
|
70
|
-
function initCarousel(root
|
|
87
|
+
function initCarousel(root) {
|
|
71
88
|
if (typeof document === "undefined") return;
|
|
89
|
+
const scope = root ?? document;
|
|
72
90
|
const containers = [];
|
|
73
|
-
if (
|
|
74
|
-
containers.push(...Array.from(
|
|
91
|
+
if (scope instanceof Element && scope.matches(".carousel")) containers.push(scope);
|
|
92
|
+
containers.push(...Array.from(scope.querySelectorAll(".carousel")));
|
|
75
93
|
for (const c of containers) setup(c);
|
|
76
94
|
}
|
|
77
95
|
export {
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
type ChartTone = 'accent' | 'success' | 'warning' | 'error' | 'muted';
|
|
2
|
+
interface ChartSeriesOptions extends ChartChromeOptions {
|
|
3
|
+
labels: string[];
|
|
4
|
+
values: number[];
|
|
5
|
+
tone?: ChartTone;
|
|
6
|
+
emptyLabel?: string;
|
|
7
|
+
formatValue?: (value: number) => string;
|
|
8
|
+
}
|
|
9
|
+
interface ChartSegment {
|
|
10
|
+
label: string;
|
|
11
|
+
value: number;
|
|
12
|
+
tone?: ChartTone;
|
|
13
|
+
}
|
|
14
|
+
interface ChartSegmentsOptions extends ChartChromeOptions {
|
|
15
|
+
segments: ChartSegment[];
|
|
16
|
+
emptyLabel?: string;
|
|
17
|
+
formatValue?: (value: number) => string;
|
|
18
|
+
}
|
|
19
|
+
/** 多系列系列项(ChartSpec 的 series 与各图型共用形态);tone 可为语义名或调色盘序号 1..6 */
|
|
20
|
+
interface ChartSeriesSpec {
|
|
21
|
+
name: string;
|
|
22
|
+
values: number[];
|
|
23
|
+
tone?: ChartTone | number;
|
|
24
|
+
}
|
|
25
|
+
/** 交互事件携带的标记数据(renderChart 委托层据此派 icen:chart-* 事件) */
|
|
26
|
+
interface ChartMarkData {
|
|
27
|
+
index?: number;
|
|
28
|
+
seriesIndex?: number;
|
|
29
|
+
seriesName?: string;
|
|
30
|
+
label?: string;
|
|
31
|
+
value?: number;
|
|
32
|
+
}
|
|
33
|
+
/** chrome 选项(各渲染器 options 皆含):title 进头部行;legend=false 初始隐藏图例 */
|
|
34
|
+
interface ChartChromeOptions {
|
|
35
|
+
title?: string;
|
|
36
|
+
legend?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/** 跨渲染存活的图例隐藏状态(renderChart 的 update 复渲染沿用;直调不传=每次新状态) */
|
|
39
|
+
interface ChartLegendState {
|
|
40
|
+
hidden: boolean | null;
|
|
41
|
+
}
|
|
42
|
+
/** 垂直柱状图(单系列,或 series 多系列分组/堆叠——通用层与 renderChart 消费) */
|
|
43
|
+
interface ChartVBarOptions extends ChartSeriesOptions {
|
|
44
|
+
/** 多系列(labels 共用,values 长度对齐);缺省回落单系列 values */
|
|
45
|
+
series?: ChartSeriesSpec[];
|
|
46
|
+
/** 多系列时堆叠(默认分组并排) */
|
|
47
|
+
stacked?: boolean;
|
|
48
|
+
}
|
|
49
|
+
declare function renderVBar(el: HTMLElement, opts: ChartVBarOptions): void;
|
|
50
|
+
/** 水平条形图 */
|
|
51
|
+
declare function renderHBar(el: HTMLElement, opts: ChartSeriesOptions): void;
|
|
52
|
+
/** 堆叠条形图(单条 100% + 图例) */
|
|
53
|
+
declare function renderStack(el: HTMLElement, opts: ChartSegmentsOptions): void;
|
|
54
|
+
/** 环形图(SVG stroke-dasharray 累加)+ 图例百分比 */
|
|
55
|
+
declare function renderDonut(el: HTMLElement, opts: ChartSegmentsOptions): void;
|
|
56
|
+
/** 折线图(面积渐变 + 网格 + 数据点 + 底部 ≤7 个轴标签;series 多系列走调色盘 + 可切换图例) */
|
|
57
|
+
interface ChartLineOptions extends ChartSeriesOptions {
|
|
58
|
+
/** 多系列(labels 共用);缺省回落单系列 values */
|
|
59
|
+
series?: ChartSeriesSpec[];
|
|
60
|
+
/** 多系列时是否填充面积(默认首系列填充;area 类型全填充) */
|
|
61
|
+
fill?: boolean;
|
|
62
|
+
}
|
|
63
|
+
declare function renderLine(el: HTMLElement, opts: ChartLineOptions): void;
|
|
64
|
+
/** 面积图(与折线同族,以面积填充为视觉主体) */
|
|
65
|
+
declare function renderArea(el: HTMLElement, opts: ChartSeriesOptions): void;
|
|
66
|
+
interface RadarSeries {
|
|
67
|
+
name: string;
|
|
68
|
+
/** 各轴的值(0..max,顺序与 axes 一致)。元素类型须可转 number。 */
|
|
69
|
+
values: number[];
|
|
70
|
+
tone?: ChartTone;
|
|
71
|
+
}
|
|
72
|
+
interface ChartRadarOptions extends ChartChromeOptions {
|
|
73
|
+
/** 各轴名(顺时针排列,首轴指向正上方) */
|
|
74
|
+
axes: string[];
|
|
75
|
+
/** 一个或多个系列。values 长度须等于 axes 长度 */
|
|
76
|
+
series: RadarSeries[];
|
|
77
|
+
/** 各轴最大值(默认取全部系列该轴最大向上取整) */
|
|
78
|
+
max?: number;
|
|
79
|
+
/** 网格环层数(默认 4) */
|
|
80
|
+
levels?: number;
|
|
81
|
+
emptyLabel?: string;
|
|
82
|
+
formatValue?: (value: number) => string;
|
|
83
|
+
}
|
|
84
|
+
/** 雷达图(N 轴蛛网 + 多系列多边形 + 图例)。 */
|
|
85
|
+
declare function renderRadar(el: HTMLElement, opts: ChartRadarOptions): void;
|
|
86
|
+
interface HeatmapDatum {
|
|
87
|
+
/** YYYY-MM-DD;仅用于 tooltip 与首周对齐 */
|
|
88
|
+
date: string;
|
|
89
|
+
value: number;
|
|
90
|
+
}
|
|
91
|
+
interface ChartHeatmapOptions extends ChartChromeOptions {
|
|
92
|
+
/** 精确形态:日期 + 值(旧 → 新)。与 values 二选一,data 优先。 */
|
|
93
|
+
data?: HeatmapDatum[];
|
|
94
|
+
/** 便捷形态:最近 N 天的值(旧 → 新),日期从今天回推 */
|
|
95
|
+
values?: number[];
|
|
96
|
+
/** 列数(周),默认按数据量推算(向上取整到整周) */
|
|
97
|
+
weeks?: number;
|
|
98
|
+
tone?: ChartTone;
|
|
99
|
+
emptyLabel?: string;
|
|
100
|
+
formatValue?: (value: number) => string;
|
|
101
|
+
}
|
|
102
|
+
/** GitHub 贡献图式热力格:7 行(周一 → 周日)× N 周列,5 档色阶。 */
|
|
103
|
+
declare function renderHeatmap(el: HTMLElement, opts: ChartHeatmapOptions): void;
|
|
104
|
+
/** 迷你趋势线(无轴小图,适合嵌入指标卡)。 */
|
|
105
|
+
declare function renderSparkline(el: HTMLElement, opts: ChartSeriesOptions): void;
|
|
106
|
+
interface ChartGaugeOptions {
|
|
107
|
+
value: number;
|
|
108
|
+
max?: number;
|
|
109
|
+
tone?: ChartTone;
|
|
110
|
+
/** 中心百分比下方的小标签 */
|
|
111
|
+
label?: string;
|
|
112
|
+
formatValue?: (value: number) => string;
|
|
113
|
+
}
|
|
114
|
+
/** 进度环(环形单值 + 中心百分比)。 */
|
|
115
|
+
declare function renderGauge(el: HTMLElement, opts: ChartGaugeOptions): void;
|
|
116
|
+
interface ChartCalendarOptions extends ChartChromeOptions {
|
|
117
|
+
/** ISO 日期数组(YYYY-MM-DD,与 values 配对;或用 data) */
|
|
118
|
+
dates?: string[];
|
|
119
|
+
values?: number[];
|
|
120
|
+
/** 精确形态:{date, value}[](与 dates+values 二选一,优先) */
|
|
121
|
+
data?: HeatmapDatum[];
|
|
122
|
+
tone?: ChartTone;
|
|
123
|
+
emptyLabel?: string;
|
|
124
|
+
formatValue?: (value: number) => string;
|
|
125
|
+
}
|
|
126
|
+
/** 贡献日历(calendar heatmap):dates → 自动周布局 + 月份标签,GitHub 同款 */
|
|
127
|
+
declare function renderCalendar(el: HTMLElement, opts: ChartCalendarOptions): void;
|
|
128
|
+
interface ChartPointSpec {
|
|
129
|
+
x: number;
|
|
130
|
+
y: number;
|
|
131
|
+
/** 第三维:气泡大小(映射到半径 3–10) */
|
|
132
|
+
size?: number;
|
|
133
|
+
label?: string;
|
|
134
|
+
}
|
|
135
|
+
interface ChartScatterOptions extends ChartChromeOptions {
|
|
136
|
+
points: ChartPointSpec[];
|
|
137
|
+
tone?: ChartTone;
|
|
138
|
+
/** X 轴名称(图例/tooltip 用) */
|
|
139
|
+
xLabel?: string;
|
|
140
|
+
yLabel?: string;
|
|
141
|
+
emptyLabel?: string;
|
|
142
|
+
formatValue?: (value: number) => string;
|
|
143
|
+
}
|
|
144
|
+
/** 散点图(可选 size 第三维 → 气泡);坐标域自动 nice 取整 + 边界刻度 */
|
|
145
|
+
declare function renderScatter(el: HTMLElement, opts: ChartScatterOptions): void;
|
|
146
|
+
type ChartType = 'line' | 'area' | 'vbar' | 'hbar' | 'stack' | 'donut' | 'radar' | 'heatmap' | 'calendar' | 'sparkline' | 'gauge' | 'scatter';
|
|
147
|
+
/** 数值格式化描述符(替代函数回调——可 JSON 序列化,AI 可给) */
|
|
148
|
+
interface ChartValueFormat {
|
|
149
|
+
/** 值后缀单位("ms" / "¥" / "个") */
|
|
150
|
+
unit?: string;
|
|
151
|
+
/** compact:1.2k/3.4M;percent:原值即百分数补 %;ms:时长自适应(800ms/1.2s/3m);raw(默认) */
|
|
152
|
+
notation?: 'compact' | 'percent' | 'ms' | 'raw';
|
|
153
|
+
}
|
|
154
|
+
/** 任意维度数据记录 + 维度映射(data[] 路径:字段名可完全自定义) */
|
|
155
|
+
interface ChartDims {
|
|
156
|
+
/** 类目/横轴字段(默认 'label') */
|
|
157
|
+
label?: string;
|
|
158
|
+
/** 系列分组字段(默认 'series';存在即多系列) */
|
|
159
|
+
series?: string;
|
|
160
|
+
/** 数值字段(默认 'value') */
|
|
161
|
+
value?: string;
|
|
162
|
+
/** 散点 x 字段(默认 'x') */
|
|
163
|
+
x?: string;
|
|
164
|
+
/** 散点 y 字段(默认 'y') */
|
|
165
|
+
y?: string;
|
|
166
|
+
/** 散点 size 字段(默认 'size') */
|
|
167
|
+
size?: string;
|
|
168
|
+
}
|
|
169
|
+
/** 统一图表规格(纯 JSON;type 缺省由 inferChartType 推断) */
|
|
170
|
+
interface ChartSpec {
|
|
171
|
+
type?: string;
|
|
172
|
+
title?: string;
|
|
173
|
+
/** 类目轴(line/area/vbar/hbar) */
|
|
174
|
+
labels?: string[];
|
|
175
|
+
/** 单系列值(labels 配对;多系列用 series) */
|
|
176
|
+
values?: number[];
|
|
177
|
+
/** 多系列(line/vbar/radar) */
|
|
178
|
+
series?: ChartSeriesSpec[];
|
|
179
|
+
/** 占比型(donut/stack) */
|
|
180
|
+
segments?: ChartSegment[];
|
|
181
|
+
/** 雷达轴 */
|
|
182
|
+
axes?: string[];
|
|
183
|
+
/** 散点(或经 dims 从 data[] 提取) */
|
|
184
|
+
points?: ChartPointSpec[];
|
|
185
|
+
/** 任意维度原始记录 + dims 字段映射(pivot 到上述形态) */
|
|
186
|
+
data?: Record<string, unknown>[];
|
|
187
|
+
dims?: ChartDims;
|
|
188
|
+
/** 贡献日历:ISO 日期(与 values 配对) */
|
|
189
|
+
dates?: string[];
|
|
190
|
+
tone?: ChartTone;
|
|
191
|
+
/** vbar 多系列:堆叠(默认分组) */
|
|
192
|
+
stacked?: boolean;
|
|
193
|
+
/** line 多系列:填充面积 */
|
|
194
|
+
fill?: boolean;
|
|
195
|
+
weeks?: number;
|
|
196
|
+
/** radar/gauge 的值域上限 */
|
|
197
|
+
max?: number;
|
|
198
|
+
/** radar 网格层数 */
|
|
199
|
+
levels?: number;
|
|
200
|
+
format?: ChartValueFormat;
|
|
201
|
+
/** 内置 tooltip(默认开;false 关闭后只派事件) */
|
|
202
|
+
tooltip?: boolean;
|
|
203
|
+
/** 图例:false = 初始隐藏(头部行的小眼睛仍可再展开);true/缺省 = 显示 */
|
|
204
|
+
legend?: boolean;
|
|
205
|
+
emptyLabel?: string;
|
|
206
|
+
}
|
|
207
|
+
/** 格式化描述符 → 函数(底层渲染器的 formatValue 槽) */
|
|
208
|
+
declare function chartFormatValue(format?: ChartValueFormat): (value: number) => string;
|
|
209
|
+
/**
|
|
210
|
+
* 归一化 ChartSpec:字符串输入尝试 JSON.parse;类型别名纠正;数值容错转换;
|
|
211
|
+
* data[] + dims pivot 到 labels/values/series/points。不抛异常——纠不了的
|
|
212
|
+
* 字段丢弃,返回的 spec 一定可交给 infer/render(空数据走 .chart-empty)。
|
|
213
|
+
*/
|
|
214
|
+
declare function normalizeChartSpec(raw: unknown): ChartSpec;
|
|
215
|
+
/** 未指定 type 时的自动选型(确定性规则,AI 只给数据也能画对) */
|
|
216
|
+
declare function inferChartType(spec: ChartSpec): ChartType;
|
|
217
|
+
type ChartEventName = 'hover' | 'click' | 'dblclick' | 'contextmenu';
|
|
218
|
+
interface ChartEventDetail extends ChartMarkData {
|
|
219
|
+
type: ChartEventName;
|
|
220
|
+
/** hover 专有:enter / leave / move */
|
|
221
|
+
phase?: 'enter' | 'move' | 'leave';
|
|
222
|
+
/** 归一后的图型 */
|
|
223
|
+
chart: ChartType;
|
|
224
|
+
/** 事件发生时的标记元素 */
|
|
225
|
+
target?: Element;
|
|
226
|
+
/** 指针视口坐标(tooltip 定位/自定义浮层用) */
|
|
227
|
+
pointerX?: number;
|
|
228
|
+
pointerY?: number;
|
|
229
|
+
}
|
|
230
|
+
interface ChartHandle {
|
|
231
|
+
el: HTMLElement;
|
|
232
|
+
/** 归一 + 推断后的当前规格 */
|
|
233
|
+
spec: ChartSpec;
|
|
234
|
+
/** 原地重渲染(保留事件委托与句柄) */
|
|
235
|
+
update(next: ChartSpec | unknown): void;
|
|
236
|
+
/** icen:chart-<name> 监听糖(hover/click/dblclick/contextmenu);返回解绑函数 */
|
|
237
|
+
on(name: ChartEventName, listener: (detail: ChartEventDetail, event: Event) => void): () => void;
|
|
238
|
+
/** 清空渲染并摘除绑定标记(委托随 el 生存期,destroy 后可重新 renderChart) */
|
|
239
|
+
destroy(): void;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* 统一入口:normalizeChartSpec → inferChartType(type 缺省时)→ 分发到底层
|
|
243
|
+
* 渲染器,并在 el 上挂交互委托(hover/click/dblclick/contextmenu → icen:chart-*,
|
|
244
|
+
* bubbles,detail 含 index/seriesIndex/seriesName/label/value/指针坐标)与可选
|
|
245
|
+
* tooltip(spec.tooltip !== false 时 portal 跟随指针;右键默认 preventDefault)。
|
|
246
|
+
* spec.title 有值时渲染 .chart-title。返回 { el, spec, update, on, destroy }。
|
|
247
|
+
*/
|
|
248
|
+
declare function renderChart(el: HTMLElement, raw: ChartSpec | unknown): ChartHandle;
|
|
249
|
+
|
|
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 };
|