@treeui/vue 0.12.0 → 0.14.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/README.md +5 -1
- package/dist/components/TButton.cjs.map +1 -1
- package/dist/components/TButton.js.map +1 -1
- package/dist/components/TButton.vue.d.ts +2 -2
- package/dist/components/TButton.vue.d.ts.map +1 -1
- package/dist/components/TButton.vue_vue_type_script_setup_true_lang.cjs +1 -1
- package/dist/components/TButton.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
- package/dist/components/TButton.vue_vue_type_script_setup_true_lang.js +2 -1
- package/dist/components/TButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/TChart.cjs +2 -0
- package/dist/components/TChart.cjs.map +1 -0
- package/dist/components/TChart.js +7 -0
- package/dist/components/TChart.js.map +1 -0
- package/dist/components/TChart.vue.d.ts +123 -0
- package/dist/components/TChart.vue.d.ts.map +1 -0
- package/dist/components/TChart.vue_vue_type_script_setup_true_lang.cjs +2 -0
- package/dist/components/TChart.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
- package/dist/components/TChart.vue_vue_type_script_setup_true_lang.js +370 -0
- package/dist/components/TChart.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/TDonutChart.cjs +2 -0
- package/dist/components/TDonutChart.cjs.map +1 -0
- package/dist/components/TDonutChart.js +7 -0
- package/dist/components/TDonutChart.js.map +1 -0
- package/dist/components/TDonutChart.vue.d.ts +75 -0
- package/dist/components/TDonutChart.vue.d.ts.map +1 -0
- package/dist/components/TDonutChart.vue_vue_type_script_setup_true_lang.cjs +2 -0
- package/dist/components/TDonutChart.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
- package/dist/components/TDonutChart.vue_vue_type_script_setup_true_lang.js +168 -0
- package/dist/components/TDonutChart.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/TFileUpload.cjs.map +1 -1
- package/dist/components/TFileUpload.js.map +1 -1
- package/dist/components/TFileUpload.vue.d.ts +77 -10
- package/dist/components/TFileUpload.vue.d.ts.map +1 -1
- package/dist/components/TFileUpload.vue_vue_type_script_setup_true_lang.cjs +1 -1
- package/dist/components/TFileUpload.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
- package/dist/components/TFileUpload.vue_vue_type_script_setup_true_lang.js +393 -144
- package/dist/components/TFileUpload.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/TGrid.vue.d.ts +1 -1
- package/dist/components/TGrid.vue.d.ts.map +1 -1
- package/dist/components/TNavMenu.cjs.map +1 -1
- package/dist/components/TNavMenu.js.map +1 -1
- package/dist/components/TNavMenu.vue.d.ts +9 -0
- package/dist/components/TNavMenu.vue.d.ts.map +1 -1
- package/dist/components/TNavMenu.vue_vue_type_script_setup_true_lang.cjs +1 -1
- package/dist/components/TNavMenu.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
- package/dist/components/TNavMenu.vue_vue_type_script_setup_true_lang.js +67 -55
- package/dist/components/TNavMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/TPage.cjs +2 -0
- package/dist/components/TPage.cjs.map +1 -0
- package/dist/components/TPage.js +7 -0
- package/dist/components/TPage.js.map +1 -0
- package/dist/components/TPage.vue.d.ts +35 -0
- package/dist/components/TPage.vue.d.ts.map +1 -0
- package/dist/components/TPage.vue_vue_type_script_setup_true_lang.cjs +2 -0
- package/dist/components/TPage.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
- package/dist/components/TPage.vue_vue_type_script_setup_true_lang.js +49 -0
- package/dist/components/TPage.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/TPageHeader.cjs +2 -0
- package/dist/components/TPageHeader.cjs.map +1 -0
- package/dist/components/TPageHeader.js +7 -0
- package/dist/components/TPageHeader.js.map +1 -0
- package/dist/components/TPageHeader.vue.d.ts +40 -0
- package/dist/components/TPageHeader.vue.d.ts.map +1 -0
- package/dist/components/TPageHeader.vue_vue_type_script_setup_true_lang.cjs +2 -0
- package/dist/components/TPageHeader.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
- package/dist/components/TPageHeader.vue_vue_type_script_setup_true_lang.js +54 -0
- package/dist/components/TPageHeader.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/TSidebar.vue_vue_type_script_setup_true_lang.cjs +1 -1
- package/dist/components/TSidebar.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
- package/dist/components/TSidebar.vue_vue_type_script_setup_true_lang.js +1 -4
- package/dist/components/TSidebar.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/TSparkline.cjs +2 -0
- package/dist/components/TSparkline.cjs.map +1 -0
- package/dist/components/TSparkline.js +7 -0
- package/dist/components/TSparkline.js.map +1 -0
- package/dist/components/TSparkline.vue.d.ts +40 -0
- package/dist/components/TSparkline.vue.d.ts.map +1 -0
- package/dist/components/TSparkline.vue_vue_type_script_setup_true_lang.cjs +2 -0
- package/dist/components/TSparkline.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
- package/dist/components/TSparkline.vue_vue_type_script_setup_true_lang.js +107 -0
- package/dist/components/TSparkline.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/TStack.vue.d.ts +1 -1
- package/dist/components/TStack.vue.d.ts.map +1 -1
- package/dist/components/index.d.ts +9 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +51 -46
- package/dist/plugin.cjs +1 -1
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +100 -90
- package/dist/plugin.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
import { Fragment as e, computed as t, createCommentVNode as n, createElementBlock as r, createElementVNode as i, createTextVNode as a, defineComponent as o, guardReactiveProps as s, normalizeClass as c, normalizeProps as l, normalizeStyle as u, onBeforeUnmount as d, onMounted as f, openBlock as p, ref as m, renderList as h, renderSlot as g, toDisplayString as _, vShow as v, withDirectives as y } from "vue";
|
|
2
|
+
import { buildAreaPath as b, buildLinePath as x, linearScale as S, niceScale as C } from "@treeui/utils";
|
|
3
|
+
//#region src/components/TChart.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
+
var ee = {
|
|
5
|
+
key: 0,
|
|
6
|
+
class: "t-chart__loading"
|
|
7
|
+
}, te = {
|
|
8
|
+
key: 1,
|
|
9
|
+
class: "t-chart__empty"
|
|
10
|
+
}, ne = [
|
|
11
|
+
"width",
|
|
12
|
+
"height",
|
|
13
|
+
"viewBox"
|
|
14
|
+
], re = { class: "t-chart__grid" }, ie = [
|
|
15
|
+
"x1",
|
|
16
|
+
"x2",
|
|
17
|
+
"y1",
|
|
18
|
+
"y2"
|
|
19
|
+
], ae = ["x", "y"], oe = { class: "t-chart__areas" }, se = ["d"], ce = { class: "t-chart__bars" }, le = [
|
|
20
|
+
"x",
|
|
21
|
+
"y",
|
|
22
|
+
"width",
|
|
23
|
+
"height",
|
|
24
|
+
"rx"
|
|
25
|
+
], ue = { class: "t-chart__lines" }, de = ["d"], fe = ["cx", "cy"], pe = {
|
|
26
|
+
key: 0,
|
|
27
|
+
class: "t-chart__hover"
|
|
28
|
+
}, me = [
|
|
29
|
+
"x1",
|
|
30
|
+
"x2",
|
|
31
|
+
"y1",
|
|
32
|
+
"y2"
|
|
33
|
+
], he = ["cx", "cy"], ge = {
|
|
34
|
+
key: 1,
|
|
35
|
+
class: "t-chart__x-axis"
|
|
36
|
+
}, _e = ["x", "y"], ve = { class: "t-chart__tooltip-label" }, ye = { class: "t-chart__tooltip-list" }, be = { class: "t-chart__tooltip-name" }, xe = { class: "t-chart__tooltip-value" }, w = {
|
|
37
|
+
key: 0,
|
|
38
|
+
class: "t-chart__legend"
|
|
39
|
+
}, T = { class: "t-chart__a11y t-visually-hidden" }, E = { scope: "row" }, D = 24, O = 2, k = /*@__PURE__*/ o({
|
|
40
|
+
__name: "TChart",
|
|
41
|
+
props: {
|
|
42
|
+
type: { default: "line" },
|
|
43
|
+
series: { default: () => [] },
|
|
44
|
+
labels: { default: () => [] },
|
|
45
|
+
height: { default: 260 },
|
|
46
|
+
smooth: {
|
|
47
|
+
type: Boolean,
|
|
48
|
+
default: !1
|
|
49
|
+
},
|
|
50
|
+
stacked: {
|
|
51
|
+
type: Boolean,
|
|
52
|
+
default: !1
|
|
53
|
+
},
|
|
54
|
+
showGrid: {
|
|
55
|
+
type: Boolean,
|
|
56
|
+
default: !0
|
|
57
|
+
},
|
|
58
|
+
showLegend: {
|
|
59
|
+
type: Boolean,
|
|
60
|
+
default: void 0
|
|
61
|
+
},
|
|
62
|
+
showXAxis: {
|
|
63
|
+
type: Boolean,
|
|
64
|
+
default: !0
|
|
65
|
+
},
|
|
66
|
+
showYAxis: {
|
|
67
|
+
type: Boolean,
|
|
68
|
+
default: !0
|
|
69
|
+
},
|
|
70
|
+
showTooltip: {
|
|
71
|
+
type: Boolean,
|
|
72
|
+
default: !0
|
|
73
|
+
},
|
|
74
|
+
showPoints: {
|
|
75
|
+
type: Boolean,
|
|
76
|
+
default: !1
|
|
77
|
+
},
|
|
78
|
+
yTicks: { default: 5 },
|
|
79
|
+
valueFormat: {
|
|
80
|
+
type: Function,
|
|
81
|
+
default: void 0
|
|
82
|
+
},
|
|
83
|
+
minY: { default: void 0 },
|
|
84
|
+
maxY: { default: void 0 },
|
|
85
|
+
animated: {
|
|
86
|
+
type: Boolean,
|
|
87
|
+
default: !0
|
|
88
|
+
},
|
|
89
|
+
loading: {
|
|
90
|
+
type: Boolean,
|
|
91
|
+
default: !1
|
|
92
|
+
},
|
|
93
|
+
ariaLabel: { default: void 0 }
|
|
94
|
+
},
|
|
95
|
+
emits: ["point-click"],
|
|
96
|
+
setup(o, { emit: k }) {
|
|
97
|
+
let A = o, j = k, M = m(null), N = m(640), P = null;
|
|
98
|
+
f(() => {
|
|
99
|
+
let e = M.value;
|
|
100
|
+
e && (N.value = e.clientWidth || N.value, typeof ResizeObserver < "u" && (P = new ResizeObserver((e) => {
|
|
101
|
+
let t = e[0]?.contentRect.width;
|
|
102
|
+
t && (N.value = t);
|
|
103
|
+
}), P.observe(e)));
|
|
104
|
+
}), d(() => P?.disconnect());
|
|
105
|
+
let F = t(() => A.series.filter((e) => e.data.length > 0)), I = t(() => Math.max(0, ...F.value.map((e) => e.data.length))), L = t(() => Array.from({ length: I.value }, (e, t) => t)), R = t(() => F.value.length > 0 && I.value > 0), Se = t(() => A.showLegend ?? F.value.length > 1), z = (e, t) => t.color ?? `var(--tree-color-chart-${e % 8 + 1})`, B = t(() => F.value.map((e, t) => ({
|
|
106
|
+
name: e.name,
|
|
107
|
+
color: z(t, e)
|
|
108
|
+
}))), V = (e) => A.valueFormat ? A.valueFormat(e) : Math.abs(e) >= 1e3 ? e.toLocaleString("en-US") : `${e}`, Ce = t(() => ({
|
|
109
|
+
top: 12,
|
|
110
|
+
right: 12,
|
|
111
|
+
bottom: A.showXAxis && A.labels.length ? 28 : 10,
|
|
112
|
+
left: A.showYAxis ? 44 : 10
|
|
113
|
+
})), H = t(() => {
|
|
114
|
+
let { top: e, right: t, bottom: n, left: r } = Ce.value;
|
|
115
|
+
return {
|
|
116
|
+
left: r,
|
|
117
|
+
right: N.value - t,
|
|
118
|
+
top: e,
|
|
119
|
+
bottom: A.height - n,
|
|
120
|
+
get innerWidth() {
|
|
121
|
+
return this.right - this.left;
|
|
122
|
+
},
|
|
123
|
+
get innerHeight() {
|
|
124
|
+
return this.bottom - this.top;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
}), we = t(() => !A.stacked || A.type !== "bar" ? [] : Array.from({ length: I.value }, (e, t) => F.value.reduce((e, n) => e + Math.max(0, n.data[t] ?? 0), 0))), U = t(() => {
|
|
128
|
+
let e = A.type === "bar" || A.type === "area", t = F.value.flatMap((e) => e.data), n = A.stacked && A.type === "bar" ? we.value : t, r = n.length ? Math.min(...n) : 0, i = n.length ? Math.max(...n) : 1, a = A.minY ?? (e ? Math.min(0, r) : r);
|
|
129
|
+
return C(a, A.maxY ?? Math.max(i, a + 1), A.yTicks);
|
|
130
|
+
}), W = t(() => S([U.value.min, U.value.max], [H.value.bottom, H.value.top])), G = t(() => W.value(Math.max(U.value.min, 0))), K = (e) => {
|
|
131
|
+
let t = I.value;
|
|
132
|
+
return t <= 1 ? H.value.left + H.value.innerWidth / 2 : H.value.left + e / (t - 1) * H.value.innerWidth;
|
|
133
|
+
}, q = t(() => H.value.innerWidth / Math.max(1, I.value)), J = (e) => H.value.left + q.value * (e + .5), Y = (e) => A.type === "bar" ? J(e) : K(e), X = t(() => A.type === "bar" ? [] : F.value.map((e, t) => {
|
|
134
|
+
let n = e.data.map((e, t) => ({
|
|
135
|
+
x: K(t),
|
|
136
|
+
y: W.value(e)
|
|
137
|
+
}));
|
|
138
|
+
return {
|
|
139
|
+
color: z(t, e),
|
|
140
|
+
line: x(n, A.smooth),
|
|
141
|
+
area: A.type === "area" ? b(n, H.value.bottom, A.smooth) : "",
|
|
142
|
+
points: n
|
|
143
|
+
};
|
|
144
|
+
})), Te = t(() => {
|
|
145
|
+
if (A.type !== "bar") return [];
|
|
146
|
+
let e = [], t = q.value, n = Math.min(t * .72, D * F.value.length + O);
|
|
147
|
+
for (let t = 0; t < I.value; t += 1) {
|
|
148
|
+
let r = J(t);
|
|
149
|
+
if (A.stacked) {
|
|
150
|
+
let i = Math.min(n, D), a = G.value;
|
|
151
|
+
F.value.forEach((n, o) => {
|
|
152
|
+
let s = Math.max(0, n.data[t] ?? 0), c = G.value - W.value(s);
|
|
153
|
+
if (c <= 0) return;
|
|
154
|
+
let l = a - c;
|
|
155
|
+
e.push({
|
|
156
|
+
x: r - i / 2,
|
|
157
|
+
y: l,
|
|
158
|
+
height: Math.max(0, c - O),
|
|
159
|
+
width: i,
|
|
160
|
+
color: z(o, n),
|
|
161
|
+
seriesIndex: o,
|
|
162
|
+
index: t
|
|
163
|
+
}), a = l;
|
|
164
|
+
});
|
|
165
|
+
} else {
|
|
166
|
+
let i = Math.max(1, (n - O * (F.value.length - 1)) / F.value.length);
|
|
167
|
+
F.value.forEach((a, o) => {
|
|
168
|
+
let s = a.data[t] ?? 0, c = W.value(s), l = r - n / 2 + o * (i + O);
|
|
169
|
+
e.push({
|
|
170
|
+
x: l,
|
|
171
|
+
y: Math.min(c, G.value),
|
|
172
|
+
width: i,
|
|
173
|
+
height: Math.abs(G.value - c),
|
|
174
|
+
color: z(o, a),
|
|
175
|
+
seriesIndex: o,
|
|
176
|
+
index: t
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return e;
|
|
182
|
+
}), Ee = t(() => U.value.ticks.map((e) => ({
|
|
183
|
+
value: e,
|
|
184
|
+
y: W.value(e),
|
|
185
|
+
label: V(e)
|
|
186
|
+
}))), De = t(() => {
|
|
187
|
+
if (!A.showXAxis) return [];
|
|
188
|
+
let e = I.value, t = Math.max(2, Math.floor(H.value.innerWidth / 52)), n = Math.max(1, Math.ceil(e / t));
|
|
189
|
+
return A.labels.slice(0, e).map((t, r) => ({
|
|
190
|
+
label: t,
|
|
191
|
+
x: Y(r),
|
|
192
|
+
show: r % n === 0 || r === e - 1
|
|
193
|
+
}));
|
|
194
|
+
}), Z = m(null), Oe = (e) => {
|
|
195
|
+
let t = M.value;
|
|
196
|
+
if (!t) return null;
|
|
197
|
+
let n = e - t.getBoundingClientRect().left, r = I.value;
|
|
198
|
+
if (r === 0) return null;
|
|
199
|
+
if (A.type === "bar") {
|
|
200
|
+
let e = Math.floor((n - H.value.left) / q.value);
|
|
201
|
+
return Math.min(r - 1, Math.max(0, e));
|
|
202
|
+
}
|
|
203
|
+
let i = (n - H.value.left) / Math.max(1, H.value.innerWidth);
|
|
204
|
+
return Math.min(r - 1, Math.max(0, Math.round(i * (r - 1))));
|
|
205
|
+
}, Q = (e) => {
|
|
206
|
+
!A.showTooltip || !R.value || (Z.value = Oe(e.clientX));
|
|
207
|
+
}, ke = () => {
|
|
208
|
+
Z.value = null;
|
|
209
|
+
}, $ = t(() => {
|
|
210
|
+
let e = Z.value;
|
|
211
|
+
return e === null ? null : {
|
|
212
|
+
index: e,
|
|
213
|
+
label: A.labels[e] ?? `#${e + 1}`,
|
|
214
|
+
values: F.value.map((t, n) => ({
|
|
215
|
+
name: t.name,
|
|
216
|
+
value: t.data[e] ?? 0,
|
|
217
|
+
color: z(n, t)
|
|
218
|
+
}))
|
|
219
|
+
};
|
|
220
|
+
}), Ae = t(() => {
|
|
221
|
+
let e = Z.value;
|
|
222
|
+
if (e === null) return {};
|
|
223
|
+
let t = Y(e);
|
|
224
|
+
return {
|
|
225
|
+
left: `${Math.min(Math.max(t, 64), N.value - 64)}px`,
|
|
226
|
+
top: `${H.value.top}px`
|
|
227
|
+
};
|
|
228
|
+
}), je = t(() => {
|
|
229
|
+
let e = Z.value;
|
|
230
|
+
return e === null || A.type === "bar" ? [] : X.value.map((t) => ({
|
|
231
|
+
x: t.points[e]?.x ?? 0,
|
|
232
|
+
y: t.points[e]?.y ?? 0,
|
|
233
|
+
color: t.color
|
|
234
|
+
}));
|
|
235
|
+
}), Me = () => {
|
|
236
|
+
$.value && j("point-click", $.value);
|
|
237
|
+
}, Ne = t(() => A.ariaLabel ?? `${A.type} chart with ${F.value.length} series`), Pe = t(() => [
|
|
238
|
+
"t-chart",
|
|
239
|
+
`t-chart--${A.type}`,
|
|
240
|
+
{
|
|
241
|
+
"is-animated": A.animated,
|
|
242
|
+
"is-loading": A.loading
|
|
243
|
+
}
|
|
244
|
+
]);
|
|
245
|
+
return (t, d) => (p(), r("div", { class: c(Pe.value) }, [
|
|
246
|
+
i("div", {
|
|
247
|
+
ref_key: "canvasRef",
|
|
248
|
+
ref: M,
|
|
249
|
+
class: "t-chart__canvas",
|
|
250
|
+
style: u({ height: `${o.height}px` })
|
|
251
|
+
}, [o.loading ? (p(), r("div", ee, [(p(), r(e, null, h(5, (e) => i("span", {
|
|
252
|
+
key: e,
|
|
253
|
+
class: "t-chart__loading-bar",
|
|
254
|
+
style: u({ height: `${30 + e * 37 % 60}%` })
|
|
255
|
+
}, null, 4)), 64))])) : R.value ? (p(), r(e, { key: 2 }, [(p(), r("svg", {
|
|
256
|
+
class: "t-chart__svg",
|
|
257
|
+
width: N.value,
|
|
258
|
+
height: o.height,
|
|
259
|
+
viewBox: `0 0 ${N.value} ${o.height}`,
|
|
260
|
+
"aria-hidden": "true",
|
|
261
|
+
onPointermove: Q,
|
|
262
|
+
onPointerleave: ke,
|
|
263
|
+
onClick: Me
|
|
264
|
+
}, [
|
|
265
|
+
i("g", re, [(p(!0), r(e, null, h(Ee.value, (t) => (p(), r(e, { key: t.value }, [o.showGrid ? (p(), r("line", {
|
|
266
|
+
key: 0,
|
|
267
|
+
class: "t-chart__gridline",
|
|
268
|
+
x1: H.value.left,
|
|
269
|
+
x2: H.value.right,
|
|
270
|
+
y1: t.y,
|
|
271
|
+
y2: t.y
|
|
272
|
+
}, null, 8, ie)) : n("", !0), o.showYAxis ? (p(), r("text", {
|
|
273
|
+
key: 1,
|
|
274
|
+
class: "t-chart__axis-label t-chart__axis-label--y",
|
|
275
|
+
x: H.value.left - 8,
|
|
276
|
+
y: t.y
|
|
277
|
+
}, _(t.label), 9, ae)) : n("", !0)], 64))), 128))]),
|
|
278
|
+
i("g", oe, [(p(!0), r(e, null, h(X.value, (e, t) => y((p(), r("path", {
|
|
279
|
+
key: `area-${t}`,
|
|
280
|
+
class: "t-chart__area",
|
|
281
|
+
d: e.area,
|
|
282
|
+
style: u({ color: e.color })
|
|
283
|
+
}, null, 12, se)), [[v, o.type === "area"]])), 128))]),
|
|
284
|
+
i("g", ce, [(p(!0), r(e, null, h(Te.value, (e, t) => (p(), r("rect", {
|
|
285
|
+
key: `bar-${t}`,
|
|
286
|
+
class: c(["t-chart__bar", { "is-active": Z.value === e.index }]),
|
|
287
|
+
x: e.x,
|
|
288
|
+
y: e.y,
|
|
289
|
+
width: e.width,
|
|
290
|
+
height: e.height,
|
|
291
|
+
rx: Math.min(4, e.width / 2),
|
|
292
|
+
style: u({
|
|
293
|
+
color: e.color,
|
|
294
|
+
animationDelay: `${e.index * 40}ms`
|
|
295
|
+
})
|
|
296
|
+
}, null, 14, le))), 128))]),
|
|
297
|
+
i("g", ue, [(p(!0), r(e, null, h(X.value, (t, i) => (p(), r(e, { key: `line-${i}` }, [o.type === "bar" ? n("", !0) : (p(), r("path", {
|
|
298
|
+
key: 0,
|
|
299
|
+
class: "t-chart__line",
|
|
300
|
+
d: t.line,
|
|
301
|
+
"path-length": "1",
|
|
302
|
+
style: u({ color: t.color })
|
|
303
|
+
}, null, 12, de)), o.showPoints && o.type !== "bar" ? (p(!0), r(e, { key: 1 }, h(t.points, (e, n) => (p(), r("circle", {
|
|
304
|
+
key: `point-${i}-${n}`,
|
|
305
|
+
class: "t-chart__point",
|
|
306
|
+
cx: e.x,
|
|
307
|
+
cy: e.y,
|
|
308
|
+
r: "3",
|
|
309
|
+
style: u({ color: t.color })
|
|
310
|
+
}, null, 12, fe))), 128)) : n("", !0)], 64))), 128))]),
|
|
311
|
+
Z.value !== null && o.showTooltip ? (p(), r("g", pe, [i("line", {
|
|
312
|
+
class: "t-chart__crosshair",
|
|
313
|
+
x1: Y(Z.value),
|
|
314
|
+
x2: Y(Z.value),
|
|
315
|
+
y1: H.value.top,
|
|
316
|
+
y2: H.value.bottom
|
|
317
|
+
}, null, 8, me), (p(!0), r(e, null, h(je.value, (e, t) => (p(), r("circle", {
|
|
318
|
+
key: `marker-${t}`,
|
|
319
|
+
class: "t-chart__marker",
|
|
320
|
+
cx: e.x,
|
|
321
|
+
cy: e.y,
|
|
322
|
+
r: "4",
|
|
323
|
+
style: u({ color: e.color })
|
|
324
|
+
}, null, 12, he))), 128))])) : n("", !0),
|
|
325
|
+
o.showXAxis ? (p(), r("g", ge, [(p(!0), r(e, null, h(De.value, (e, t) => y((p(), r("text", {
|
|
326
|
+
key: `x-${t}`,
|
|
327
|
+
class: "t-chart__axis-label t-chart__axis-label--x",
|
|
328
|
+
x: e.x,
|
|
329
|
+
y: o.height - 8
|
|
330
|
+
}, _(e.label), 9, _e)), [[v, e.show]])), 128))])) : n("", !0)
|
|
331
|
+
], 40, ne)), o.showTooltip && $.value ? (p(), r("div", {
|
|
332
|
+
key: 0,
|
|
333
|
+
class: "t-chart__tooltip",
|
|
334
|
+
style: u(Ae.value),
|
|
335
|
+
role: "presentation"
|
|
336
|
+
}, [g(t.$slots, "tooltip", l(s($.value)), () => [i("p", ve, _($.value.label), 1), i("ul", ye, [(p(!0), r(e, null, h($.value.values, (e, t) => (p(), r("li", {
|
|
337
|
+
key: t,
|
|
338
|
+
class: "t-chart__tooltip-item"
|
|
339
|
+
}, [
|
|
340
|
+
i("span", {
|
|
341
|
+
class: "t-chart__tooltip-dot",
|
|
342
|
+
style: u({ background: e.color }),
|
|
343
|
+
"aria-hidden": "true"
|
|
344
|
+
}, null, 4),
|
|
345
|
+
i("span", be, _(e.name), 1),
|
|
346
|
+
i("span", xe, _(V(e.value)), 1)
|
|
347
|
+
]))), 128))])])], 4)) : n("", !0)], 64)) : (p(), r("div", te, [g(t.$slots, "empty", {}, () => [d[0] ||= a(" No data to display ", -1)])]))], 4),
|
|
348
|
+
Se.value && R.value ? (p(), r("div", w, [g(t.$slots, "legend", { series: B.value }, () => [(p(!0), r(e, null, h(B.value, (e, t) => (p(), r("span", {
|
|
349
|
+
key: t,
|
|
350
|
+
class: "t-chart__legend-item"
|
|
351
|
+
}, [i("span", {
|
|
352
|
+
class: "t-chart__legend-swatch",
|
|
353
|
+
style: u({ background: e.color }),
|
|
354
|
+
"aria-hidden": "true"
|
|
355
|
+
}, null, 4), a(" " + _(e.name), 1)]))), 128))])])) : n("", !0),
|
|
356
|
+
i("table", T, [
|
|
357
|
+
i("caption", null, _(Ne.value), 1),
|
|
358
|
+
i("thead", null, [i("tr", null, [d[1] ||= i("th", { scope: "col" }, " Series ", -1), (p(!0), r(e, null, h(L.value, (e) => (p(), r("th", {
|
|
359
|
+
key: e,
|
|
360
|
+
scope: "col"
|
|
361
|
+
}, _(o.labels[e] ?? ""), 1))), 128))])]),
|
|
362
|
+
i("tbody", null, [(p(!0), r(e, null, h(F.value, (t, n) => (p(), r("tr", { key: n }, [i("th", E, _(t.name), 1), (p(!0), r(e, null, h(L.value, (e) => (p(), r("td", { key: e }, _(t.data[e] === void 0 ? "" : V(t.data[e])), 1))), 128))]))), 128))])
|
|
363
|
+
])
|
|
364
|
+
], 2));
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
//#endregion
|
|
368
|
+
export { k as default };
|
|
369
|
+
|
|
370
|
+
//# sourceMappingURL=TChart.vue_vue_type_script_setup_true_lang.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TChart.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../src/components/TChart.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref } from 'vue';\nimport {\n buildAreaPath,\n buildLinePath,\n linearScale,\n niceScale,\n type ChartPoint,\n} from '@treeui/utils';\n\nexport type TChartType = 'line' | 'area' | 'bar';\n\nexport interface TChartSeries {\n /** Legend/tooltip name for the series. */\n name: string;\n /** One value per category, aligned to `labels`. */\n data: number[];\n /** Override the series color; defaults to a chart palette token. */\n color?: string;\n}\n\nexport interface TChartActivePayload {\n index: number;\n label: string;\n values: Array<{ name: string; value: number; color: string }>;\n}\n\nconst props = withDefaults(\n defineProps<{\n /** Visual form of the plot. */\n type?: TChartType;\n /** One or more data series. */\n series?: TChartSeries[];\n /** Category labels for the x-axis, aligned to each series' data. */\n labels?: string[];\n /** Plot height in px (width is fluid). */\n height?: number;\n /** Smooth (curved) line/area. */\n smooth?: boolean;\n /**\n * Stack bar series on top of each other instead of grouping side by side.\n * Negative values are clamped to 0 in stacked mode (grouped mode renders them).\n */\n stacked?: boolean;\n /** Draw horizontal gridlines. */\n showGrid?: boolean;\n /** Show the legend. Defaults to on when there is more than one series. */\n showLegend?: boolean;\n /** Show x-axis category labels. */\n showXAxis?: boolean;\n /** Show y-axis value ticks. */\n showYAxis?: boolean;\n /** Show the hover crosshair + tooltip. */\n showTooltip?: boolean;\n /** Always render markers on line/area points (not just on hover). */\n showPoints?: boolean;\n /** Target number of y-axis ticks. */\n yTicks?: number;\n /** Format axis + tooltip values. */\n valueFormat?: (value: number) => string;\n /** Force the low end of the y domain. */\n minY?: number;\n /** Force the high end of the y domain. */\n maxY?: number;\n /** Animate marks on first render (respects prefers-reduced-motion). */\n animated?: boolean;\n /** Render skeleton placeholders instead of the plot. */\n loading?: boolean;\n /** Accessible summary of the chart. */\n ariaLabel?: string;\n }>(),\n {\n type: 'line',\n series: () => [],\n labels: () => [],\n height: 260,\n smooth: false,\n stacked: false,\n showGrid: true,\n showLegend: undefined,\n showXAxis: true,\n showYAxis: true,\n showTooltip: true,\n showPoints: false,\n yTicks: 5,\n valueFormat: undefined,\n minY: undefined,\n maxY: undefined,\n animated: true,\n loading: false,\n ariaLabel: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'point-click': [payload: TChartActivePayload];\n}>();\n\ndefineSlots<{\n legend?: (props: { series: Array<{ name: string; color: string }> }) => unknown;\n tooltip?: (props: TChartActivePayload) => unknown;\n empty?: () => unknown;\n}>();\n\n// --- measurement ----------------------------------------------------------\nconst canvasRef = ref<HTMLElement | null>(null);\nconst width = ref(640);\nlet observer: ResizeObserver | null = null;\n\nonMounted(() => {\n const element = canvasRef.value;\n if (!element) return;\n width.value = element.clientWidth || width.value;\n\n if (typeof ResizeObserver !== 'undefined') {\n observer = new ResizeObserver((entries) => {\n const measured = entries[0]?.contentRect.width;\n if (measured) width.value = measured;\n });\n observer.observe(element);\n }\n});\n\nonBeforeUnmount(() => observer?.disconnect());\n\n// --- derived data ---------------------------------------------------------\nconst validSeries = computed(() => props.series.filter((item) => item.data.length > 0));\n\nconst categoryCount = computed(() =>\n Math.max(0, ...validSeries.value.map((item) => item.data.length)),\n);\n\n// Shared category index range, so the a11y table stays rectangular even when\n// series have different lengths.\nconst axisIndices = computed(() =>\n Array.from({ length: categoryCount.value }, (_, index) => index),\n);\n\nconst hasData = computed(() => validSeries.value.length > 0 && categoryCount.value > 0);\n\nconst resolvedShowLegend = computed(() =>\n props.showLegend ?? validSeries.value.length > 1,\n);\n\nconst colorFor = (index: number, series: TChartSeries) =>\n series.color ?? `var(--tree-color-chart-${(index % 8) + 1})`;\n\nconst legendItems = computed(() =>\n validSeries.value.map((series, index) => ({\n name: series.name,\n color: colorFor(index, series),\n })),\n);\n\nconst formatValue = (value: number) => {\n if (props.valueFormat) return props.valueFormat(value);\n if (Math.abs(value) >= 1000) return value.toLocaleString('en-US');\n return `${value}`;\n};\n\n// --- layout ---------------------------------------------------------------\nconst margin = computed(() => ({\n top: 12,\n right: 12,\n bottom: props.showXAxis && props.labels.length ? 28 : 10,\n left: props.showYAxis ? 44 : 10,\n}));\n\nconst plot = computed(() => {\n const { top, right, bottom, left } = margin.value;\n return {\n left,\n right: width.value - right,\n top,\n bottom: props.height - bottom,\n get innerWidth() {\n return this.right - this.left;\n },\n get innerHeight() {\n return this.bottom - this.top;\n },\n };\n});\n\nconst stackedTotals = computed(() => {\n if (!props.stacked || props.type !== 'bar') return [];\n return Array.from({ length: categoryCount.value }, (_, index) =>\n validSeries.value.reduce((sum, series) => sum + Math.max(0, series.data[index] ?? 0), 0),\n );\n});\n\nconst scale = computed(() => {\n const baselineZero = props.type === 'bar' || props.type === 'area';\n const flat = validSeries.value.flatMap((series) => series.data);\n\n const source = props.stacked && props.type === 'bar' ? stackedTotals.value : flat;\n const rawMin = source.length ? Math.min(...source) : 0;\n const rawMax = source.length ? Math.max(...source) : 1;\n\n const min = props.minY ?? (baselineZero ? Math.min(0, rawMin) : rawMin);\n const max = props.maxY ?? Math.max(rawMax, min + 1);\n\n return niceScale(min, max, props.yTicks);\n});\n\nconst yScale = computed(() =>\n linearScale([scale.value.min, scale.value.max], [plot.value.bottom, plot.value.top]),\n);\n\nconst baselineY = computed(() => yScale.value(Math.max(scale.value.min, 0)));\n\n// x-position helpers -------------------------------------------------------\nconst pointX = (index: number) => {\n const count = categoryCount.value;\n if (count <= 1) return plot.value.left + plot.value.innerWidth / 2;\n return plot.value.left + (index / (count - 1)) * plot.value.innerWidth;\n};\n\nconst band = computed(() => plot.value.innerWidth / Math.max(1, categoryCount.value));\nconst bandCenter = (index: number) => plot.value.left + band.value * (index + 0.5);\n\n// active category (for line/area points and axis labels)\nconst activeX = (index: number) =>\n props.type === 'bar' ? bandCenter(index) : pointX(index);\n\n// --- line / area geometry -------------------------------------------------\nconst linePaths = computed(() =>\n props.type === 'bar'\n ? []\n : validSeries.value.map((series, seriesIndex) => {\n const points: ChartPoint[] = series.data.map((value, index) => ({\n x: pointX(index),\n y: yScale.value(value),\n }));\n return {\n color: colorFor(seriesIndex, series),\n line: buildLinePath(points, props.smooth),\n area: props.type === 'area' ? buildAreaPath(points, plot.value.bottom, props.smooth) : '',\n points,\n };\n }),\n);\n\n// --- bar geometry ---------------------------------------------------------\nconst BAR_MAX = 24;\nconst BAR_GAP = 2;\n\nconst bars = computed(() => {\n if (props.type !== 'bar') return [];\n const output: Array<{\n x: number;\n y: number;\n width: number;\n height: number;\n color: string;\n seriesIndex: number;\n index: number;\n }> = [];\n\n const bandWidth = band.value;\n const groupWidth = Math.min(bandWidth * 0.72, BAR_MAX * validSeries.value.length + BAR_GAP);\n\n for (let index = 0; index < categoryCount.value; index += 1) {\n const center = bandCenter(index);\n\n if (props.stacked) {\n const barWidth = Math.min(groupWidth, BAR_MAX);\n let cursorBottom = baselineY.value;\n validSeries.value.forEach((series, seriesIndex) => {\n const value = Math.max(0, series.data[index] ?? 0);\n // Pixel height is proportional to the segment's own value.\n const segmentHeight = baselineY.value - yScale.value(value);\n if (segmentHeight <= 0) return;\n const top = cursorBottom - segmentHeight;\n output.push({\n x: center - barWidth / 2,\n y: top,\n // Trim 2px off each segment for a surface gap between stacked marks.\n height: Math.max(0, segmentHeight - BAR_GAP),\n width: barWidth,\n color: colorFor(seriesIndex, series),\n seriesIndex,\n index,\n });\n cursorBottom = top;\n });\n } else {\n const barWidth = Math.max(1, (groupWidth - BAR_GAP * (validSeries.value.length - 1)) / validSeries.value.length);\n validSeries.value.forEach((series, seriesIndex) => {\n const value = series.data[index] ?? 0;\n const top = yScale.value(value);\n const start = center - groupWidth / 2 + seriesIndex * (barWidth + BAR_GAP);\n output.push({\n x: start,\n y: Math.min(top, baselineY.value),\n width: barWidth,\n height: Math.abs(baselineY.value - top),\n color: colorFor(seriesIndex, series),\n seriesIndex,\n index,\n });\n });\n }\n }\n\n return output;\n});\n\n// --- gridlines & axes -----------------------------------------------------\nconst gridLines = computed(() =>\n scale.value.ticks.map((tick) => ({\n value: tick,\n y: yScale.value(tick),\n label: formatValue(tick),\n })),\n);\n\nconst xLabels = computed(() => {\n if (!props.showXAxis) return [];\n const count = categoryCount.value;\n const maxLabels = Math.max(2, Math.floor(plot.value.innerWidth / 52));\n const step = Math.max(1, Math.ceil(count / maxLabels));\n return props.labels.slice(0, count).map((label, index) => ({\n label,\n x: activeX(index),\n show: index % step === 0 || index === count - 1,\n }));\n});\n\n// --- interaction ----------------------------------------------------------\nconst activeIndex = ref<number | null>(null);\n\nconst pointerToIndex = (clientX: number) => {\n const element = canvasRef.value;\n if (!element) return null;\n const rect = element.getBoundingClientRect();\n const x = clientX - rect.left;\n const count = categoryCount.value;\n if (count === 0) return null;\n\n if (props.type === 'bar') {\n const index = Math.floor((x - plot.value.left) / band.value);\n return Math.min(count - 1, Math.max(0, index));\n }\n\n const ratio = (x - plot.value.left) / Math.max(1, plot.value.innerWidth);\n return Math.min(count - 1, Math.max(0, Math.round(ratio * (count - 1))));\n};\n\nconst onPointerMove = (event: PointerEvent) => {\n if (!props.showTooltip || !hasData.value) return;\n activeIndex.value = pointerToIndex(event.clientX);\n};\n\nconst onPointerLeave = () => {\n activeIndex.value = null;\n};\n\nconst activePayload = computed<TChartActivePayload | null>(() => {\n const index = activeIndex.value;\n if (index === null) return null;\n return {\n index,\n label: props.labels[index] ?? `#${index + 1}`,\n values: validSeries.value.map((series, seriesIndex) => ({\n name: series.name,\n value: series.data[index] ?? 0,\n color: colorFor(seriesIndex, series),\n })),\n };\n});\n\nconst tooltipStyle = computed(() => {\n const index = activeIndex.value;\n if (index === null) return {};\n const x = activeX(index);\n const clamped = Math.min(Math.max(x, 64), width.value - 64);\n return { left: `${clamped}px`, top: `${plot.value.top}px` };\n});\n\nconst activeMarkers = computed(() => {\n const index = activeIndex.value;\n if (index === null || props.type === 'bar') return [];\n return linePaths.value.map((path) => ({\n x: path.points[index]?.x ?? 0,\n y: path.points[index]?.y ?? 0,\n color: path.color,\n }));\n});\n\nconst onClick = () => {\n if (activePayload.value) emit('point-click', activePayload.value);\n};\n\nconst resolvedLabel = computed(\n () => props.ariaLabel ?? `${props.type} chart with ${validSeries.value.length} series`,\n);\n\nconst rootClasses = computed(() => [\n 't-chart',\n `t-chart--${props.type}`,\n {\n 'is-animated': props.animated,\n 'is-loading': props.loading,\n },\n]);\n</script>\n\n<template>\n <div :class=\"rootClasses\">\n <div\n ref=\"canvasRef\"\n class=\"t-chart__canvas\"\n :style=\"{ height: `${height}px` }\"\n >\n <div\n v-if=\"loading\"\n class=\"t-chart__loading\"\n >\n <span\n v-for=\"n in 5\"\n :key=\"n\"\n class=\"t-chart__loading-bar\"\n :style=\"{ height: `${30 + ((n * 37) % 60)}%` }\"\n />\n </div>\n\n <div\n v-else-if=\"!hasData\"\n class=\"t-chart__empty\"\n >\n <slot name=\"empty\">\n No data to display\n </slot>\n </div>\n\n <template v-else>\n <svg\n class=\"t-chart__svg\"\n :width=\"width\"\n :height=\"height\"\n :viewBox=\"`0 0 ${width} ${height}`\"\n aria-hidden=\"true\"\n @pointermove=\"onPointerMove\"\n @pointerleave=\"onPointerLeave\"\n @click=\"onClick\"\n >\n <!-- gridlines + y ticks -->\n <g class=\"t-chart__grid\">\n <template\n v-for=\"line in gridLines\"\n :key=\"line.value\"\n >\n <line\n v-if=\"showGrid\"\n class=\"t-chart__gridline\"\n :x1=\"plot.left\"\n :x2=\"plot.right\"\n :y1=\"line.y\"\n :y2=\"line.y\"\n />\n <text\n v-if=\"showYAxis\"\n class=\"t-chart__axis-label t-chart__axis-label--y\"\n :x=\"plot.left - 8\"\n :y=\"line.y\"\n >\n {{ line.label }}\n </text>\n </template>\n </g>\n\n <!-- area fills -->\n <g class=\"t-chart__areas\">\n <path\n v-for=\"(path, index) in linePaths\"\n v-show=\"type === 'area'\"\n :key=\"`area-${index}`\"\n class=\"t-chart__area\"\n :d=\"path.area\"\n :style=\"{ color: path.color }\"\n />\n </g>\n\n <!-- bars -->\n <g class=\"t-chart__bars\">\n <rect\n v-for=\"(bar, index) in bars\"\n :key=\"`bar-${index}`\"\n class=\"t-chart__bar\"\n :x=\"bar.x\"\n :y=\"bar.y\"\n :width=\"bar.width\"\n :height=\"bar.height\"\n :rx=\"Math.min(4, bar.width / 2)\"\n :style=\"{ color: bar.color, animationDelay: `${bar.index * 40}ms` }\"\n :class=\"{ 'is-active': activeIndex === bar.index }\"\n />\n </g>\n\n <!-- lines + optional static points -->\n <g class=\"t-chart__lines\">\n <template\n v-for=\"(path, index) in linePaths\"\n :key=\"`line-${index}`\"\n >\n <path\n v-if=\"type !== 'bar'\"\n class=\"t-chart__line\"\n :d=\"path.line\"\n path-length=\"1\"\n :style=\"{ color: path.color }\"\n />\n <template v-if=\"showPoints && type !== 'bar'\">\n <circle\n v-for=\"(point, pointIndex) in path.points\"\n :key=\"`point-${index}-${pointIndex}`\"\n class=\"t-chart__point\"\n :cx=\"point.x\"\n :cy=\"point.y\"\n r=\"3\"\n :style=\"{ color: path.color }\"\n />\n </template>\n </template>\n </g>\n\n <!-- hover crosshair + active markers -->\n <g\n v-if=\"activeIndex !== null && showTooltip\"\n class=\"t-chart__hover\"\n >\n <line\n class=\"t-chart__crosshair\"\n :x1=\"activeX(activeIndex)\"\n :x2=\"activeX(activeIndex)\"\n :y1=\"plot.top\"\n :y2=\"plot.bottom\"\n />\n <circle\n v-for=\"(marker, index) in activeMarkers\"\n :key=\"`marker-${index}`\"\n class=\"t-chart__marker\"\n :cx=\"marker.x\"\n :cy=\"marker.y\"\n r=\"4\"\n :style=\"{ color: marker.color }\"\n />\n </g>\n\n <!-- x-axis labels -->\n <g\n v-if=\"showXAxis\"\n class=\"t-chart__x-axis\"\n >\n <text\n v-for=\"(item, index) in xLabels\"\n v-show=\"item.show\"\n :key=\"`x-${index}`\"\n class=\"t-chart__axis-label t-chart__axis-label--x\"\n :x=\"item.x\"\n :y=\"height - 8\"\n >\n {{ item.label }}\n </text>\n </g>\n </svg>\n\n <div\n v-if=\"showTooltip && activePayload\"\n class=\"t-chart__tooltip\"\n :style=\"tooltipStyle\"\n role=\"presentation\"\n >\n <slot\n name=\"tooltip\"\n v-bind=\"activePayload\"\n >\n <p class=\"t-chart__tooltip-label\">\n {{ activePayload.label }}\n </p>\n <ul class=\"t-chart__tooltip-list\">\n <li\n v-for=\"(item, index) in activePayload.values\"\n :key=\"index\"\n class=\"t-chart__tooltip-item\"\n >\n <span\n class=\"t-chart__tooltip-dot\"\n :style=\"{ background: item.color }\"\n aria-hidden=\"true\"\n />\n <span class=\"t-chart__tooltip-name\">{{ item.name }}</span>\n <span class=\"t-chart__tooltip-value\">{{ formatValue(item.value) }}</span>\n </li>\n </ul>\n </slot>\n </div>\n </template>\n </div>\n\n <div\n v-if=\"resolvedShowLegend && hasData\"\n class=\"t-chart__legend\"\n >\n <slot\n name=\"legend\"\n :series=\"legendItems\"\n >\n <span\n v-for=\"(item, index) in legendItems\"\n :key=\"index\"\n class=\"t-chart__legend-item\"\n >\n <span\n class=\"t-chart__legend-swatch\"\n :style=\"{ background: item.color }\"\n aria-hidden=\"true\"\n />\n {{ item.name }}\n </span>\n </slot>\n </div>\n\n <!-- Accessible data table: the chart's data as text for assistive tech. -->\n <table class=\"t-chart__a11y t-visually-hidden\">\n <caption>{{ resolvedLabel }}</caption>\n <thead>\n <tr>\n <th scope=\"col\">\n Series\n </th>\n <th\n v-for=\"index in axisIndices\"\n :key=\"index\"\n scope=\"col\"\n >\n {{ labels[index] ?? '' }}\n </th>\n </tr>\n </thead>\n <tbody>\n <tr\n v-for=\"(row, rowIndex) in validSeries\"\n :key=\"rowIndex\"\n >\n <th scope=\"row\">\n {{ row.name }}\n </th>\n <td\n v-for=\"index in axisIndices\"\n :key=\"index\"\n >\n {{ row.data[index] === undefined ? '' : formatValue(row.data[index]) }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TDonutChart.cjs","names":[],"sources":["../../src/components/TDonutChart.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref } from 'vue';\nimport { donutSegments } from '@treeui/utils';\n\nexport interface TDonutSegment {\n /** Legend + tooltip label. */\n label: string;\n /** Slice magnitude; non-positive values are omitted. */\n value: number;\n /** Override the slice color; defaults to a chart palette token. */\n color?: string;\n}\n\nconst props = withDefaults(\n defineProps<{\n /** Slices to draw, in order. */\n segments?: TDonutSegment[];\n /** Square canvas size in px. */\n size?: number;\n /** Ring thickness in px. `0` renders a full pie. */\n thickness?: number;\n /** Gap between slices, in degrees. */\n gap?: number;\n /** Round the ends of donut segments (adds a larger gap to make room). */\n rounded?: boolean;\n /** Show the legend with values. */\n showLegend?: boolean;\n /** Show each slice's percentage in the legend. */\n showPercent?: boolean;\n /** Static label under the center value (donut only). */\n centerLabel?: string;\n /** Static value shown in the center (donut only). Overrides the auto total. */\n centerValue?: string | number;\n /** Format legend + center values. */\n valueFormat?: (value: number) => string;\n /** Render skeleton placeholders instead of the chart. */\n loading?: boolean;\n /** Accessible summary of the chart. */\n ariaLabel?: string;\n }>(),\n {\n segments: () => [],\n size: 200,\n thickness: 26,\n gap: 2,\n rounded: false,\n showLegend: true,\n showPercent: true,\n centerLabel: undefined,\n centerValue: undefined,\n valueFormat: undefined,\n loading: false,\n ariaLabel: undefined,\n },\n);\n\ndefineSlots<{\n center?: (props: { total: number; active: TDonutSegment | null }) => unknown;\n empty?: () => unknown;\n}>();\n\nconst activeIndex = ref<number | null>(null);\n\nconst visibleSegments = computed(() => props.segments.filter((item) => item.value > 0));\n\nconst total = computed(() =>\n visibleSegments.value.reduce((sum, item) => sum + item.value, 0),\n);\n\nconst hasData = computed(() => total.value > 0);\n\nconst isDonut = computed(() => props.thickness > 0);\n\nconst center = computed(() => props.size / 2);\n\nconst colorFor = (index: number, segment: TDonutSegment) =>\n segment.color ?? `var(--tree-color-chart-${(index % 8) + 1})`;\n\n// Donut segments are drawn as stroked arcs on a mid-radius circle, so the ring\n// stays perfectly smooth and gaps are one consistent width. Pie slices need a\n// filled wedge to the center, so they keep the path geometry.\nconst geometry = computed(() => {\n const single = visibleSegments.value.length === 1;\n\n if (isDonut.value) {\n // Leave room for the stroke width and the hover growth so nothing clips.\n const pad = props.thickness / 2 + 3;\n const midRadius = props.size / 2 - pad;\n const circumference = 2 * Math.PI * midRadius;\n const degreeGap = (props.gap / 360) * circumference;\n const gapPx = single\n ? 0\n : props.rounded\n ? Math.max(degreeGap, props.thickness + 2)\n : Math.max(degreeGap, 2);\n\n let start = 0;\n return visibleSegments.value.map((item, index) => {\n const fraction = item.value / total.value;\n const length = fraction * circumference;\n const on = Math.max(0.5, length - gapPx);\n const arc = {\n mode: 'arc' as const,\n r: midRadius,\n circumference,\n dashArray: `${on} ${circumference - on}`,\n dashOffset: -start,\n color: colorFor(index, item),\n label: item.label,\n value: item.value,\n fraction,\n };\n start += length;\n return arc;\n });\n }\n\n const radius = props.size / 2 - 2;\n const arcs = donutSegments(\n visibleSegments.value.map((item) => item.value),\n { cx: center.value, cy: center.value, radius, innerRadius: 0, gap: single ? 0 : props.gap },\n );\n\n return arcs.map((arc, index) => {\n const source = visibleSegments.value[index];\n return {\n mode: 'wedge' as const,\n path: arc.path,\n fraction: arc.fraction,\n color: colorFor(index, source),\n label: source.label,\n value: source.value,\n };\n });\n});\n\nconst formatValue = (value: number) => {\n if (props.valueFormat) return props.valueFormat(value);\n if (Math.abs(value) >= 1000) return value.toLocaleString('en-US');\n return `${value}`;\n};\n\nconst formatPercent = (fraction: number) => `${Math.round(fraction * 100)}%`;\n\nconst activeSegment = computed(() =>\n activeIndex.value === null ? null : visibleSegments.value[activeIndex.value] ?? null,\n);\n\nconst centerPrimary = computed(() => {\n if (activeSegment.value) return formatValue(activeSegment.value.value);\n if (props.centerValue !== undefined) return `${props.centerValue}`;\n return formatValue(total.value);\n});\n\nconst centerSecondary = computed(() => {\n if (activeSegment.value) return activeSegment.value.label;\n return props.centerLabel ?? 'Total';\n});\n\nconst resolvedLabel = computed(\n () => props.ariaLabel ?? `${isDonut.value ? 'Donut' : 'Pie'} chart with ${visibleSegments.value.length} segments`,\n);\n\nconst rootClasses = computed(() => [\n 't-donut-chart',\n { 'is-loading': props.loading, 'has-legend': props.showLegend },\n]);\n</script>\n\n<template>\n <div :class=\"rootClasses\">\n <div\n class=\"t-donut-chart__figure\"\n :style=\"{ width: `${size}px`, height: `${size}px` }\"\n >\n <div\n v-if=\"loading\"\n class=\"t-donut-chart__skeleton\"\n />\n\n <div\n v-else-if=\"!hasData\"\n class=\"t-donut-chart__empty\"\n >\n <slot name=\"empty\">\n No data\n </slot>\n </div>\n\n <template v-else>\n <svg\n class=\"t-donut-chart__svg\"\n :width=\"size\"\n :height=\"size\"\n :viewBox=\"`0 0 ${size} ${size}`\"\n role=\"img\"\n :aria-label=\"resolvedLabel\"\n >\n <g :transform=\"isDonut ? `rotate(-90 ${center} ${center})` : undefined\">\n <template\n v-for=\"(segment, index) in geometry\"\n :key=\"index\"\n >\n <circle\n v-if=\"segment.mode === 'arc'\"\n class=\"t-donut-chart__segment t-donut-chart__segment--arc\"\n :class=\"{ 'is-dimmed': activeIndex !== null && activeIndex !== index }\"\n :cx=\"center\"\n :cy=\"center\"\n :r=\"segment.r\"\n fill=\"none\"\n :stroke=\"segment.color\"\n :stroke-width=\"activeIndex === index ? thickness + 4 : thickness\"\n :stroke-linecap=\"rounded ? 'round' : 'butt'\"\n :stroke-dasharray=\"segment.dashArray\"\n :stroke-dashoffset=\"segment.dashOffset\"\n :style=\"{ animationDelay: `${index * 70}ms` }\"\n @pointerenter=\"activeIndex = index\"\n @pointerleave=\"activeIndex = null\"\n />\n <path\n v-else\n class=\"t-donut-chart__segment t-donut-chart__segment--wedge\"\n :class=\"{ 'is-dimmed': activeIndex !== null && activeIndex !== index }\"\n :d=\"segment.path\"\n :style=\"{ fill: segment.color, animationDelay: `${index * 70}ms` }\"\n @pointerenter=\"activeIndex = index\"\n @pointerleave=\"activeIndex = null\"\n />\n </template>\n </g>\n </svg>\n\n <div\n v-if=\"isDonut\"\n class=\"t-donut-chart__center\"\n >\n <slot\n name=\"center\"\n :total=\"total\"\n :active=\"activeSegment\"\n >\n <span class=\"t-donut-chart__center-value\">{{ centerPrimary }}</span>\n <span class=\"t-donut-chart__center-label\">{{ centerSecondary }}</span>\n </slot>\n </div>\n </template>\n </div>\n\n <ul\n v-if=\"showLegend && hasData\"\n class=\"t-donut-chart__legend\"\n >\n <li\n v-for=\"(segment, index) in geometry\"\n :key=\"index\"\n class=\"t-donut-chart__legend-item\"\n :class=\"{ 'is-active': activeIndex === index }\"\n @pointerenter=\"activeIndex = index\"\n @pointerleave=\"activeIndex = null\"\n >\n <span\n class=\"t-donut-chart__legend-swatch\"\n :style=\"{ background: segment.color }\"\n aria-hidden=\"true\"\n />\n <span class=\"t-donut-chart__legend-label\">{{ segment.label }}</span>\n <span class=\"t-donut-chart__legend-value\">{{ formatValue(segment.value) }}</span>\n <span\n v-if=\"showPercent\"\n class=\"t-donut-chart__legend-percent\"\n >{{ formatPercent(segment.fraction) }}</span>\n </li>\n </ul>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TDonutChart.js","names":[],"sources":["../../src/components/TDonutChart.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref } from 'vue';\nimport { donutSegments } from '@treeui/utils';\n\nexport interface TDonutSegment {\n /** Legend + tooltip label. */\n label: string;\n /** Slice magnitude; non-positive values are omitted. */\n value: number;\n /** Override the slice color; defaults to a chart palette token. */\n color?: string;\n}\n\nconst props = withDefaults(\n defineProps<{\n /** Slices to draw, in order. */\n segments?: TDonutSegment[];\n /** Square canvas size in px. */\n size?: number;\n /** Ring thickness in px. `0` renders a full pie. */\n thickness?: number;\n /** Gap between slices, in degrees. */\n gap?: number;\n /** Round the ends of donut segments (adds a larger gap to make room). */\n rounded?: boolean;\n /** Show the legend with values. */\n showLegend?: boolean;\n /** Show each slice's percentage in the legend. */\n showPercent?: boolean;\n /** Static label under the center value (donut only). */\n centerLabel?: string;\n /** Static value shown in the center (donut only). Overrides the auto total. */\n centerValue?: string | number;\n /** Format legend + center values. */\n valueFormat?: (value: number) => string;\n /** Render skeleton placeholders instead of the chart. */\n loading?: boolean;\n /** Accessible summary of the chart. */\n ariaLabel?: string;\n }>(),\n {\n segments: () => [],\n size: 200,\n thickness: 26,\n gap: 2,\n rounded: false,\n showLegend: true,\n showPercent: true,\n centerLabel: undefined,\n centerValue: undefined,\n valueFormat: undefined,\n loading: false,\n ariaLabel: undefined,\n },\n);\n\ndefineSlots<{\n center?: (props: { total: number; active: TDonutSegment | null }) => unknown;\n empty?: () => unknown;\n}>();\n\nconst activeIndex = ref<number | null>(null);\n\nconst visibleSegments = computed(() => props.segments.filter((item) => item.value > 0));\n\nconst total = computed(() =>\n visibleSegments.value.reduce((sum, item) => sum + item.value, 0),\n);\n\nconst hasData = computed(() => total.value > 0);\n\nconst isDonut = computed(() => props.thickness > 0);\n\nconst center = computed(() => props.size / 2);\n\nconst colorFor = (index: number, segment: TDonutSegment) =>\n segment.color ?? `var(--tree-color-chart-${(index % 8) + 1})`;\n\n// Donut segments are drawn as stroked arcs on a mid-radius circle, so the ring\n// stays perfectly smooth and gaps are one consistent width. Pie slices need a\n// filled wedge to the center, so they keep the path geometry.\nconst geometry = computed(() => {\n const single = visibleSegments.value.length === 1;\n\n if (isDonut.value) {\n // Leave room for the stroke width and the hover growth so nothing clips.\n const pad = props.thickness / 2 + 3;\n const midRadius = props.size / 2 - pad;\n const circumference = 2 * Math.PI * midRadius;\n const degreeGap = (props.gap / 360) * circumference;\n const gapPx = single\n ? 0\n : props.rounded\n ? Math.max(degreeGap, props.thickness + 2)\n : Math.max(degreeGap, 2);\n\n let start = 0;\n return visibleSegments.value.map((item, index) => {\n const fraction = item.value / total.value;\n const length = fraction * circumference;\n const on = Math.max(0.5, length - gapPx);\n const arc = {\n mode: 'arc' as const,\n r: midRadius,\n circumference,\n dashArray: `${on} ${circumference - on}`,\n dashOffset: -start,\n color: colorFor(index, item),\n label: item.label,\n value: item.value,\n fraction,\n };\n start += length;\n return arc;\n });\n }\n\n const radius = props.size / 2 - 2;\n const arcs = donutSegments(\n visibleSegments.value.map((item) => item.value),\n { cx: center.value, cy: center.value, radius, innerRadius: 0, gap: single ? 0 : props.gap },\n );\n\n return arcs.map((arc, index) => {\n const source = visibleSegments.value[index];\n return {\n mode: 'wedge' as const,\n path: arc.path,\n fraction: arc.fraction,\n color: colorFor(index, source),\n label: source.label,\n value: source.value,\n };\n });\n});\n\nconst formatValue = (value: number) => {\n if (props.valueFormat) return props.valueFormat(value);\n if (Math.abs(value) >= 1000) return value.toLocaleString('en-US');\n return `${value}`;\n};\n\nconst formatPercent = (fraction: number) => `${Math.round(fraction * 100)}%`;\n\nconst activeSegment = computed(() =>\n activeIndex.value === null ? null : visibleSegments.value[activeIndex.value] ?? null,\n);\n\nconst centerPrimary = computed(() => {\n if (activeSegment.value) return formatValue(activeSegment.value.value);\n if (props.centerValue !== undefined) return `${props.centerValue}`;\n return formatValue(total.value);\n});\n\nconst centerSecondary = computed(() => {\n if (activeSegment.value) return activeSegment.value.label;\n return props.centerLabel ?? 'Total';\n});\n\nconst resolvedLabel = computed(\n () => props.ariaLabel ?? `${isDonut.value ? 'Donut' : 'Pie'} chart with ${visibleSegments.value.length} segments`,\n);\n\nconst rootClasses = computed(() => [\n 't-donut-chart',\n { 'is-loading': props.loading, 'has-legend': props.showLegend },\n]);\n</script>\n\n<template>\n <div :class=\"rootClasses\">\n <div\n class=\"t-donut-chart__figure\"\n :style=\"{ width: `${size}px`, height: `${size}px` }\"\n >\n <div\n v-if=\"loading\"\n class=\"t-donut-chart__skeleton\"\n />\n\n <div\n v-else-if=\"!hasData\"\n class=\"t-donut-chart__empty\"\n >\n <slot name=\"empty\">\n No data\n </slot>\n </div>\n\n <template v-else>\n <svg\n class=\"t-donut-chart__svg\"\n :width=\"size\"\n :height=\"size\"\n :viewBox=\"`0 0 ${size} ${size}`\"\n role=\"img\"\n :aria-label=\"resolvedLabel\"\n >\n <g :transform=\"isDonut ? `rotate(-90 ${center} ${center})` : undefined\">\n <template\n v-for=\"(segment, index) in geometry\"\n :key=\"index\"\n >\n <circle\n v-if=\"segment.mode === 'arc'\"\n class=\"t-donut-chart__segment t-donut-chart__segment--arc\"\n :class=\"{ 'is-dimmed': activeIndex !== null && activeIndex !== index }\"\n :cx=\"center\"\n :cy=\"center\"\n :r=\"segment.r\"\n fill=\"none\"\n :stroke=\"segment.color\"\n :stroke-width=\"activeIndex === index ? thickness + 4 : thickness\"\n :stroke-linecap=\"rounded ? 'round' : 'butt'\"\n :stroke-dasharray=\"segment.dashArray\"\n :stroke-dashoffset=\"segment.dashOffset\"\n :style=\"{ animationDelay: `${index * 70}ms` }\"\n @pointerenter=\"activeIndex = index\"\n @pointerleave=\"activeIndex = null\"\n />\n <path\n v-else\n class=\"t-donut-chart__segment t-donut-chart__segment--wedge\"\n :class=\"{ 'is-dimmed': activeIndex !== null && activeIndex !== index }\"\n :d=\"segment.path\"\n :style=\"{ fill: segment.color, animationDelay: `${index * 70}ms` }\"\n @pointerenter=\"activeIndex = index\"\n @pointerleave=\"activeIndex = null\"\n />\n </template>\n </g>\n </svg>\n\n <div\n v-if=\"isDonut\"\n class=\"t-donut-chart__center\"\n >\n <slot\n name=\"center\"\n :total=\"total\"\n :active=\"activeSegment\"\n >\n <span class=\"t-donut-chart__center-value\">{{ centerPrimary }}</span>\n <span class=\"t-donut-chart__center-label\">{{ centerSecondary }}</span>\n </slot>\n </div>\n </template>\n </div>\n\n <ul\n v-if=\"showLegend && hasData\"\n class=\"t-donut-chart__legend\"\n >\n <li\n v-for=\"(segment, index) in geometry\"\n :key=\"index\"\n class=\"t-donut-chart__legend-item\"\n :class=\"{ 'is-active': activeIndex === index }\"\n @pointerenter=\"activeIndex = index\"\n @pointerleave=\"activeIndex = null\"\n >\n <span\n class=\"t-donut-chart__legend-swatch\"\n :style=\"{ background: segment.color }\"\n aria-hidden=\"true\"\n />\n <span class=\"t-donut-chart__legend-label\">{{ segment.label }}</span>\n <span class=\"t-donut-chart__legend-value\">{{ formatValue(segment.value) }}</span>\n <span\n v-if=\"showPercent\"\n class=\"t-donut-chart__legend-percent\"\n >{{ formatPercent(segment.fraction) }}</span>\n </li>\n </ul>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
export interface TDonutSegment {
|
|
2
|
+
/** Legend + tooltip label. */
|
|
3
|
+
label: string;
|
|
4
|
+
/** Slice magnitude; non-positive values are omitted. */
|
|
5
|
+
value: number;
|
|
6
|
+
/** Override the slice color; defaults to a chart palette token. */
|
|
7
|
+
color?: string;
|
|
8
|
+
}
|
|
9
|
+
type __VLS_Props = {
|
|
10
|
+
/** Slices to draw, in order. */
|
|
11
|
+
segments?: TDonutSegment[];
|
|
12
|
+
/** Square canvas size in px. */
|
|
13
|
+
size?: number;
|
|
14
|
+
/** Ring thickness in px. `0` renders a full pie. */
|
|
15
|
+
thickness?: number;
|
|
16
|
+
/** Gap between slices, in degrees. */
|
|
17
|
+
gap?: number;
|
|
18
|
+
/** Round the ends of donut segments (adds a larger gap to make room). */
|
|
19
|
+
rounded?: boolean;
|
|
20
|
+
/** Show the legend with values. */
|
|
21
|
+
showLegend?: boolean;
|
|
22
|
+
/** Show each slice's percentage in the legend. */
|
|
23
|
+
showPercent?: boolean;
|
|
24
|
+
/** Static label under the center value (donut only). */
|
|
25
|
+
centerLabel?: string;
|
|
26
|
+
/** Static value shown in the center (donut only). Overrides the auto total. */
|
|
27
|
+
centerValue?: string | number;
|
|
28
|
+
/** Format legend + center values. */
|
|
29
|
+
valueFormat?: (value: number) => string;
|
|
30
|
+
/** Render skeleton placeholders instead of the chart. */
|
|
31
|
+
loading?: boolean;
|
|
32
|
+
/** Accessible summary of the chart. */
|
|
33
|
+
ariaLabel?: string;
|
|
34
|
+
};
|
|
35
|
+
declare function __VLS_template(): {
|
|
36
|
+
attrs: Partial<{}>;
|
|
37
|
+
slots: Readonly<{
|
|
38
|
+
center?: (props: {
|
|
39
|
+
total: number;
|
|
40
|
+
active: TDonutSegment | null;
|
|
41
|
+
}) => unknown;
|
|
42
|
+
empty?: () => unknown;
|
|
43
|
+
}> & {
|
|
44
|
+
center?: (props: {
|
|
45
|
+
total: number;
|
|
46
|
+
active: TDonutSegment | null;
|
|
47
|
+
}) => unknown;
|
|
48
|
+
empty?: () => unknown;
|
|
49
|
+
};
|
|
50
|
+
refs: {};
|
|
51
|
+
rootEl: HTMLDivElement;
|
|
52
|
+
};
|
|
53
|
+
type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
|
|
54
|
+
declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
55
|
+
size: number;
|
|
56
|
+
gap: number;
|
|
57
|
+
loading: boolean;
|
|
58
|
+
showLegend: boolean;
|
|
59
|
+
valueFormat: (value: number) => string;
|
|
60
|
+
ariaLabel: string;
|
|
61
|
+
segments: TDonutSegment[];
|
|
62
|
+
thickness: number;
|
|
63
|
+
rounded: boolean;
|
|
64
|
+
showPercent: boolean;
|
|
65
|
+
centerLabel: string;
|
|
66
|
+
centerValue: string | number;
|
|
67
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
68
|
+
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
|
|
69
|
+
export default _default;
|
|
70
|
+
type __VLS_WithTemplateSlots<T, S> = T & {
|
|
71
|
+
new (): {
|
|
72
|
+
$slots: S;
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=TDonutChart.vue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TDonutChart.vue.d.ts","sourceRoot":"","sources":["../../src/components/TDonutChart.vue"],"names":[],"mappings":"AAyRA,MAAM,WAAW,aAAa;IAC5B,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,KAAK,WAAW,GAAG;IACf,gCAAgC;IAChC,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;IAC3B,gCAAgC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mCAAmC;IACnC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kDAAkD;IAClD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,qCAAqC;IACrC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,yDAAyD;IACzD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAmJJ,iBAAS,cAAc;WA2JT,OAAO,IAA6B;;iBA1RvC,CAAC,KAAK,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAAA;SAAE,KAAK,OAAO;gBACpE,MAAM,OAAO;;iBADZ,CAAC,KAAK,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAAA;SAAE,KAAK,OAAO;gBACpE,MAAM,OAAO;;;;EA8RtB;AAsBD,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAC9D,QAAA,MAAM,eAAe;UA/VV,MAAM;SAIP,MAAM;aAcF,OAAO;gBAVJ,OAAO;iBAQN,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM;eAI3B,MAAM;cAtBP,aAAa,EAAE;eAId,MAAM;aAIR,OAAO;iBAIH,OAAO;iBAEP,MAAM;iBAEN,MAAM,GAAG,MAAM;wFAyV/B,CAAC;wBACkB,uBAAuB,CAAC,OAAO,eAAe,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAAnG,wBAAoG;AAapG,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IACxC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
let e=require("vue"),t=require("@treeui/utils");var n={key:0,class:`t-donut-chart__skeleton`},r={key:1,class:`t-donut-chart__empty`},i=[`width`,`height`,`viewBox`,`aria-label`],a=[`transform`],o=[`cx`,`cy`,`r`,`stroke`,`stroke-width`,`stroke-linecap`,`stroke-dasharray`,`stroke-dashoffset`,`onPointerenter`],s=[`d`,`onPointerenter`],c={key:0,class:`t-donut-chart__center`},l={class:`t-donut-chart__center-value`},u={class:`t-donut-chart__center-label`},d={key:0,class:`t-donut-chart__legend`},f=[`onPointerenter`],p={class:`t-donut-chart__legend-label`},m={class:`t-donut-chart__legend-value`},h={key:0,class:`t-donut-chart__legend-percent`},g=(0,e.defineComponent)({__name:`TDonutChart`,props:{segments:{default:()=>[]},size:{default:200},thickness:{default:26},gap:{default:2},rounded:{type:Boolean,default:!1},showLegend:{type:Boolean,default:!0},showPercent:{type:Boolean,default:!0},centerLabel:{default:void 0},centerValue:{default:void 0},valueFormat:{type:Function,default:void 0},loading:{type:Boolean,default:!1},ariaLabel:{default:void 0}},setup(g){let _=g,v=(0,e.ref)(null),y=(0,e.computed)(()=>_.segments.filter(e=>e.value>0)),b=(0,e.computed)(()=>y.value.reduce((e,t)=>e+t.value,0)),x=(0,e.computed)(()=>b.value>0),S=(0,e.computed)(()=>_.thickness>0),C=(0,e.computed)(()=>_.size/2),w=(e,t)=>t.color??`var(--tree-color-chart-${e%8+1})`,T=(0,e.computed)(()=>{let e=y.value.length===1;if(S.value){let t=_.thickness/2+3,n=_.size/2-t,r=2*Math.PI*n,i=_.gap/360*r,a=e?0:_.rounded?Math.max(i,_.thickness+2):Math.max(i,2),o=0;return y.value.map((e,t)=>{let i=e.value/b.value,s=i*r,c=Math.max(.5,s-a),l={mode:`arc`,r:n,circumference:r,dashArray:`${c} ${r-c}`,dashOffset:-o,color:w(t,e),label:e.label,value:e.value,fraction:i};return o+=s,l})}let n=_.size/2-2;return(0,t.donutSegments)(y.value.map(e=>e.value),{cx:C.value,cy:C.value,radius:n,innerRadius:0,gap:e?0:_.gap}).map((e,t)=>{let n=y.value[t];return{mode:`wedge`,path:e.path,fraction:e.fraction,color:w(t,n),label:n.label,value:n.value}})}),E=e=>_.valueFormat?_.valueFormat(e):Math.abs(e)>=1e3?e.toLocaleString(`en-US`):`${e}`,D=e=>`${Math.round(e*100)}%`,O=(0,e.computed)(()=>v.value===null?null:y.value[v.value]??null),k=(0,e.computed)(()=>O.value?E(O.value.value):_.centerValue===void 0?E(b.value):`${_.centerValue}`),A=(0,e.computed)(()=>O.value?O.value.label:_.centerLabel??`Total`),j=(0,e.computed)(()=>_.ariaLabel??`${S.value?`Donut`:`Pie`} chart with ${y.value.length} segments`),M=(0,e.computed)(()=>[`t-donut-chart`,{"is-loading":_.loading,"has-legend":_.showLegend}]);return(t,_)=>((0,e.openBlock)(),(0,e.createElementBlock)(`div`,{class:(0,e.normalizeClass)(M.value)},[(0,e.createElementVNode)(`div`,{class:`t-donut-chart__figure`,style:(0,e.normalizeStyle)({width:`${g.size}px`,height:`${g.size}px`})},[g.loading?((0,e.openBlock)(),(0,e.createElementBlock)(`div`,n)):x.value?((0,e.openBlock)(),(0,e.createElementBlock)(e.Fragment,{key:2},[((0,e.openBlock)(),(0,e.createElementBlock)(`svg`,{class:`t-donut-chart__svg`,width:g.size,height:g.size,viewBox:`0 0 ${g.size} ${g.size}`,role:`img`,"aria-label":j.value},[(0,e.createElementVNode)(`g`,{transform:S.value?`rotate(-90 ${C.value} ${C.value})`:void 0},[((0,e.openBlock)(!0),(0,e.createElementBlock)(e.Fragment,null,(0,e.renderList)(T.value,(t,n)=>((0,e.openBlock)(),(0,e.createElementBlock)(e.Fragment,{key:n},[t.mode===`arc`?((0,e.openBlock)(),(0,e.createElementBlock)(`circle`,{key:0,class:(0,e.normalizeClass)([`t-donut-chart__segment t-donut-chart__segment--arc`,{"is-dimmed":v.value!==null&&v.value!==n}]),cx:C.value,cy:C.value,r:t.r,fill:`none`,stroke:t.color,"stroke-width":v.value===n?g.thickness+4:g.thickness,"stroke-linecap":g.rounded?`round`:`butt`,"stroke-dasharray":t.dashArray,"stroke-dashoffset":t.dashOffset,style:(0,e.normalizeStyle)({animationDelay:`${n*70}ms`}),onPointerenter:e=>v.value=n,onPointerleave:_[0]||=e=>v.value=null},null,46,o)):((0,e.openBlock)(),(0,e.createElementBlock)(`path`,{key:1,class:(0,e.normalizeClass)([`t-donut-chart__segment t-donut-chart__segment--wedge`,{"is-dimmed":v.value!==null&&v.value!==n}]),d:t.path,style:(0,e.normalizeStyle)({fill:t.color,animationDelay:`${n*70}ms`}),onPointerenter:e=>v.value=n,onPointerleave:_[1]||=e=>v.value=null},null,46,s))],64))),128))],8,a)],8,i)),S.value?((0,e.openBlock)(),(0,e.createElementBlock)(`div`,c,[(0,e.renderSlot)(t.$slots,`center`,{total:b.value,active:O.value},()=>[(0,e.createElementVNode)(`span`,l,(0,e.toDisplayString)(k.value),1),(0,e.createElementVNode)(`span`,u,(0,e.toDisplayString)(A.value),1)])])):(0,e.createCommentVNode)(``,!0)],64)):((0,e.openBlock)(),(0,e.createElementBlock)(`div`,r,[(0,e.renderSlot)(t.$slots,`empty`,{},()=>[_[3]||=(0,e.createTextVNode)(` No data `,-1)])]))],4),g.showLegend&&x.value?((0,e.openBlock)(),(0,e.createElementBlock)(`ul`,d,[((0,e.openBlock)(!0),(0,e.createElementBlock)(e.Fragment,null,(0,e.renderList)(T.value,(t,n)=>((0,e.openBlock)(),(0,e.createElementBlock)(`li`,{key:n,class:(0,e.normalizeClass)([`t-donut-chart__legend-item`,{"is-active":v.value===n}]),onPointerenter:e=>v.value=n,onPointerleave:_[2]||=e=>v.value=null},[(0,e.createElementVNode)(`span`,{class:`t-donut-chart__legend-swatch`,style:(0,e.normalizeStyle)({background:t.color}),"aria-hidden":`true`},null,4),(0,e.createElementVNode)(`span`,p,(0,e.toDisplayString)(t.label),1),(0,e.createElementVNode)(`span`,m,(0,e.toDisplayString)(E(t.value)),1),g.showPercent?((0,e.openBlock)(),(0,e.createElementBlock)(`span`,h,(0,e.toDisplayString)(D(t.fraction)),1)):(0,e.createCommentVNode)(``,!0)],42,f))),128))])):(0,e.createCommentVNode)(``,!0)],2))}});exports.default=g;
|
|
2
|
+
//# sourceMappingURL=TDonutChart.vue_vue_type_script_setup_true_lang.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TDonutChart.vue_vue_type_script_setup_true_lang.cjs","names":[],"sources":["../../src/components/TDonutChart.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref } from 'vue';\nimport { donutSegments } from '@treeui/utils';\n\nexport interface TDonutSegment {\n /** Legend + tooltip label. */\n label: string;\n /** Slice magnitude; non-positive values are omitted. */\n value: number;\n /** Override the slice color; defaults to a chart palette token. */\n color?: string;\n}\n\nconst props = withDefaults(\n defineProps<{\n /** Slices to draw, in order. */\n segments?: TDonutSegment[];\n /** Square canvas size in px. */\n size?: number;\n /** Ring thickness in px. `0` renders a full pie. */\n thickness?: number;\n /** Gap between slices, in degrees. */\n gap?: number;\n /** Round the ends of donut segments (adds a larger gap to make room). */\n rounded?: boolean;\n /** Show the legend with values. */\n showLegend?: boolean;\n /** Show each slice's percentage in the legend. */\n showPercent?: boolean;\n /** Static label under the center value (donut only). */\n centerLabel?: string;\n /** Static value shown in the center (donut only). Overrides the auto total. */\n centerValue?: string | number;\n /** Format legend + center values. */\n valueFormat?: (value: number) => string;\n /** Render skeleton placeholders instead of the chart. */\n loading?: boolean;\n /** Accessible summary of the chart. */\n ariaLabel?: string;\n }>(),\n {\n segments: () => [],\n size: 200,\n thickness: 26,\n gap: 2,\n rounded: false,\n showLegend: true,\n showPercent: true,\n centerLabel: undefined,\n centerValue: undefined,\n valueFormat: undefined,\n loading: false,\n ariaLabel: undefined,\n },\n);\n\ndefineSlots<{\n center?: (props: { total: number; active: TDonutSegment | null }) => unknown;\n empty?: () => unknown;\n}>();\n\nconst activeIndex = ref<number | null>(null);\n\nconst visibleSegments = computed(() => props.segments.filter((item) => item.value > 0));\n\nconst total = computed(() =>\n visibleSegments.value.reduce((sum, item) => sum + item.value, 0),\n);\n\nconst hasData = computed(() => total.value > 0);\n\nconst isDonut = computed(() => props.thickness > 0);\n\nconst center = computed(() => props.size / 2);\n\nconst colorFor = (index: number, segment: TDonutSegment) =>\n segment.color ?? `var(--tree-color-chart-${(index % 8) + 1})`;\n\n// Donut segments are drawn as stroked arcs on a mid-radius circle, so the ring\n// stays perfectly smooth and gaps are one consistent width. Pie slices need a\n// filled wedge to the center, so they keep the path geometry.\nconst geometry = computed(() => {\n const single = visibleSegments.value.length === 1;\n\n if (isDonut.value) {\n // Leave room for the stroke width and the hover growth so nothing clips.\n const pad = props.thickness / 2 + 3;\n const midRadius = props.size / 2 - pad;\n const circumference = 2 * Math.PI * midRadius;\n const degreeGap = (props.gap / 360) * circumference;\n const gapPx = single\n ? 0\n : props.rounded\n ? Math.max(degreeGap, props.thickness + 2)\n : Math.max(degreeGap, 2);\n\n let start = 0;\n return visibleSegments.value.map((item, index) => {\n const fraction = item.value / total.value;\n const length = fraction * circumference;\n const on = Math.max(0.5, length - gapPx);\n const arc = {\n mode: 'arc' as const,\n r: midRadius,\n circumference,\n dashArray: `${on} ${circumference - on}`,\n dashOffset: -start,\n color: colorFor(index, item),\n label: item.label,\n value: item.value,\n fraction,\n };\n start += length;\n return arc;\n });\n }\n\n const radius = props.size / 2 - 2;\n const arcs = donutSegments(\n visibleSegments.value.map((item) => item.value),\n { cx: center.value, cy: center.value, radius, innerRadius: 0, gap: single ? 0 : props.gap },\n );\n\n return arcs.map((arc, index) => {\n const source = visibleSegments.value[index];\n return {\n mode: 'wedge' as const,\n path: arc.path,\n fraction: arc.fraction,\n color: colorFor(index, source),\n label: source.label,\n value: source.value,\n };\n });\n});\n\nconst formatValue = (value: number) => {\n if (props.valueFormat) return props.valueFormat(value);\n if (Math.abs(value) >= 1000) return value.toLocaleString('en-US');\n return `${value}`;\n};\n\nconst formatPercent = (fraction: number) => `${Math.round(fraction * 100)}%`;\n\nconst activeSegment = computed(() =>\n activeIndex.value === null ? null : visibleSegments.value[activeIndex.value] ?? null,\n);\n\nconst centerPrimary = computed(() => {\n if (activeSegment.value) return formatValue(activeSegment.value.value);\n if (props.centerValue !== undefined) return `${props.centerValue}`;\n return formatValue(total.value);\n});\n\nconst centerSecondary = computed(() => {\n if (activeSegment.value) return activeSegment.value.label;\n return props.centerLabel ?? 'Total';\n});\n\nconst resolvedLabel = computed(\n () => props.ariaLabel ?? `${isDonut.value ? 'Donut' : 'Pie'} chart with ${visibleSegments.value.length} segments`,\n);\n\nconst rootClasses = computed(() => [\n 't-donut-chart',\n { 'is-loading': props.loading, 'has-legend': props.showLegend },\n]);\n</script>\n\n<template>\n <div :class=\"rootClasses\">\n <div\n class=\"t-donut-chart__figure\"\n :style=\"{ width: `${size}px`, height: `${size}px` }\"\n >\n <div\n v-if=\"loading\"\n class=\"t-donut-chart__skeleton\"\n />\n\n <div\n v-else-if=\"!hasData\"\n class=\"t-donut-chart__empty\"\n >\n <slot name=\"empty\">\n No data\n </slot>\n </div>\n\n <template v-else>\n <svg\n class=\"t-donut-chart__svg\"\n :width=\"size\"\n :height=\"size\"\n :viewBox=\"`0 0 ${size} ${size}`\"\n role=\"img\"\n :aria-label=\"resolvedLabel\"\n >\n <g :transform=\"isDonut ? `rotate(-90 ${center} ${center})` : undefined\">\n <template\n v-for=\"(segment, index) in geometry\"\n :key=\"index\"\n >\n <circle\n v-if=\"segment.mode === 'arc'\"\n class=\"t-donut-chart__segment t-donut-chart__segment--arc\"\n :class=\"{ 'is-dimmed': activeIndex !== null && activeIndex !== index }\"\n :cx=\"center\"\n :cy=\"center\"\n :r=\"segment.r\"\n fill=\"none\"\n :stroke=\"segment.color\"\n :stroke-width=\"activeIndex === index ? thickness + 4 : thickness\"\n :stroke-linecap=\"rounded ? 'round' : 'butt'\"\n :stroke-dasharray=\"segment.dashArray\"\n :stroke-dashoffset=\"segment.dashOffset\"\n :style=\"{ animationDelay: `${index * 70}ms` }\"\n @pointerenter=\"activeIndex = index\"\n @pointerleave=\"activeIndex = null\"\n />\n <path\n v-else\n class=\"t-donut-chart__segment t-donut-chart__segment--wedge\"\n :class=\"{ 'is-dimmed': activeIndex !== null && activeIndex !== index }\"\n :d=\"segment.path\"\n :style=\"{ fill: segment.color, animationDelay: `${index * 70}ms` }\"\n @pointerenter=\"activeIndex = index\"\n @pointerleave=\"activeIndex = null\"\n />\n </template>\n </g>\n </svg>\n\n <div\n v-if=\"isDonut\"\n class=\"t-donut-chart__center\"\n >\n <slot\n name=\"center\"\n :total=\"total\"\n :active=\"activeSegment\"\n >\n <span class=\"t-donut-chart__center-value\">{{ centerPrimary }}</span>\n <span class=\"t-donut-chart__center-label\">{{ centerSecondary }}</span>\n </slot>\n </div>\n </template>\n </div>\n\n <ul\n v-if=\"showLegend && hasData\"\n class=\"t-donut-chart__legend\"\n >\n <li\n v-for=\"(segment, index) in geometry\"\n :key=\"index\"\n class=\"t-donut-chart__legend-item\"\n :class=\"{ 'is-active': activeIndex === index }\"\n @pointerenter=\"activeIndex = index\"\n @pointerleave=\"activeIndex = null\"\n >\n <span\n class=\"t-donut-chart__legend-swatch\"\n :style=\"{ background: segment.color }\"\n aria-hidden=\"true\"\n />\n <span class=\"t-donut-chart__legend-label\">{{ segment.label }}</span>\n <span class=\"t-donut-chart__legend-value\">{{ formatValue(segment.value) }}</span>\n <span\n v-if=\"showPercent\"\n class=\"t-donut-chart__legend-percent\"\n >{{ formatPercent(segment.fraction) }}</span>\n </li>\n </ul>\n </div>\n</template>\n"],"mappings":"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"}
|