@epoch32/visage 1.1.3 → 1.1.4
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/dist/api/index.js +55 -4085
- package/dist/charts/index.js +48 -2806
- package/dist/devtools/index.js +18 -4771
- package/dist/dom/index.js +32 -1639
- package/dist/form/index.js +13 -1498
- package/dist/index-061jf06a.js +848 -0
- package/dist/index-0madxn60.js +442 -0
- package/dist/index-1xtrtz1t.js +256 -0
- package/dist/index-2zz0g2n2.js +212 -0
- package/dist/index-5s255b3w.js +303 -0
- package/dist/index-6kfe1nr4.js +1179 -0
- package/dist/index-8czhpea8.js +338 -0
- package/dist/index-8x8xz80v.js +727 -0
- package/dist/index-921pn75b.js +0 -0
- package/dist/index-965ryh36.js +537 -0
- package/dist/index-9fvarkrx.js +98 -0
- package/dist/index-a4xns6cc.js +219 -0
- package/dist/index-b5wc752a.js +1696 -0
- package/dist/index-df5e614s.js +334 -0
- package/dist/index-dyvgtp43.js +1094 -0
- package/dist/index-grhdtcb5.js +234 -0
- package/dist/index-h6tjqk6e.js +158 -0
- package/dist/index-js199er4.js +101 -0
- package/dist/index-x2rs3vab.js +124 -0
- package/dist/index-y9bq7h9g.js +1162 -0
- package/dist/index-zr6cvset.js +2092 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +458 -11920
- package/dist/jsx-runtime/index.js +13 -1719
- package/dist/query/index.js +47 -2505
- package/dist/router/index.js +25 -1945
- package/dist/rpc/index.js +39 -3567
- package/dist/server/index.js +11 -1256
- package/dist/signals/index.js +52 -1160
- package/dist/style/index.js +77 -2429
- package/dist/template/index.js +7 -1232
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +150 -4249
- package/dist/ui/tabs.d.ts +23 -1
- package/dist/virtual/index.js +12 -2044
- package/dist/vite/index.js +5 -744
- package/package.json +2 -2
- package/src/dom/render.ts +20 -7
- package/src/index.ts +2 -0
- package/src/signals/computed.ts +19 -12
- package/src/signals/effect.ts +7 -7
- package/src/signals/signal.ts +16 -12
- package/src/signals/system.ts +50 -21
- package/src/ui/index.ts +2 -0
- package/src/ui/tabs.tsx +211 -10
- package/src/ui/utils.ts +1 -3
|
@@ -0,0 +1,1094 @@
|
|
|
1
|
+
import {
|
|
2
|
+
untrack2,
|
|
3
|
+
computed2,
|
|
4
|
+
resolveValue2,
|
|
5
|
+
onCleanup2,
|
|
6
|
+
createContext2,
|
|
7
|
+
useContext2,
|
|
8
|
+
signal2
|
|
9
|
+
} from "./index-6kfe1nr4.js";
|
|
10
|
+
import {
|
|
11
|
+
jsx2,
|
|
12
|
+
jsxs2
|
|
13
|
+
} from "./index-9fvarkrx.js";
|
|
14
|
+
|
|
15
|
+
// src/charts/context.ts
|
|
16
|
+
var ChartContext2 = createContext2(undefined);
|
|
17
|
+
function useChartContext2() {
|
|
18
|
+
const ctx = useContext2(ChartContext2);
|
|
19
|
+
if (!ctx) {
|
|
20
|
+
throw new Error("Visage Chart child component must be rendered within a <Chart> container.");
|
|
21
|
+
}
|
|
22
|
+
return ctx;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// src/charts/path.ts
|
|
26
|
+
function pathLine2(points, options = {}) {
|
|
27
|
+
if (points.length === 0)
|
|
28
|
+
return "";
|
|
29
|
+
if (points.length === 1) {
|
|
30
|
+
const p = points[0];
|
|
31
|
+
return `M ${p.x.toFixed(2)},${p.y.toFixed(2)}`;
|
|
32
|
+
}
|
|
33
|
+
const curve = options.curve ?? "linear";
|
|
34
|
+
if (curve === "smooth" && points.length >= 2) {
|
|
35
|
+
if (points.length === 2) {
|
|
36
|
+
const p0 = points[0];
|
|
37
|
+
const p1 = points[1];
|
|
38
|
+
return `M ${p0.x.toFixed(2)},${p0.y.toFixed(2)} L ${p1.x.toFixed(2)},${p1.y.toFixed(2)}`;
|
|
39
|
+
}
|
|
40
|
+
const n = points.length;
|
|
41
|
+
const dx = [];
|
|
42
|
+
const dy = [];
|
|
43
|
+
const slopes = [];
|
|
44
|
+
for (let i = 0;i < n - 1; i++) {
|
|
45
|
+
const pA = points[i];
|
|
46
|
+
const pB = points[i + 1];
|
|
47
|
+
const deltaX = pB.x - pA.x;
|
|
48
|
+
const deltaY = pB.y - pA.y;
|
|
49
|
+
dx.push(deltaX);
|
|
50
|
+
dy.push(deltaY);
|
|
51
|
+
slopes.push(deltaX === 0 ? 0 : deltaY / deltaX);
|
|
52
|
+
}
|
|
53
|
+
const m = new Array(n).fill(0);
|
|
54
|
+
m[0] = slopes[0];
|
|
55
|
+
m[n - 1] = slopes[n - 2];
|
|
56
|
+
for (let i = 1;i < n - 1; i++) {
|
|
57
|
+
const sPrev = slopes[i - 1];
|
|
58
|
+
const sNext = slopes[i];
|
|
59
|
+
if (sPrev * sNext <= 0) {
|
|
60
|
+
m[i] = 0;
|
|
61
|
+
} else {
|
|
62
|
+
const dxPrev = dx[i - 1];
|
|
63
|
+
const dxNext = dx[i];
|
|
64
|
+
const common = dxPrev + dxNext;
|
|
65
|
+
m[i] = common === 0 ? 0 : 3 * common / ((common + dxNext) / sPrev + (common + dxPrev) / sNext);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
let d = `M ${points[0].x.toFixed(2)},${points[0].y.toFixed(2)}`;
|
|
69
|
+
for (let i = 0;i < n - 1; i++) {
|
|
70
|
+
const p1 = points[i];
|
|
71
|
+
const p2 = points[i + 1];
|
|
72
|
+
const deltaX = dx[i];
|
|
73
|
+
const cp1x = p1.x + deltaX / 3;
|
|
74
|
+
const cp1y = p1.y + m[i] * deltaX / 3;
|
|
75
|
+
const cp2x = p2.x - deltaX / 3;
|
|
76
|
+
const cp2y = p2.y - m[i + 1] * deltaX / 3;
|
|
77
|
+
d += ` C ${cp1x.toFixed(2)},${cp1y.toFixed(2)} ${cp2x.toFixed(2)},${cp2y.toFixed(2)} ${p2.x.toFixed(2)},${p2.y.toFixed(2)}`;
|
|
78
|
+
}
|
|
79
|
+
return d;
|
|
80
|
+
}
|
|
81
|
+
if (curve === "step") {
|
|
82
|
+
let d = `M ${points[0].x.toFixed(2)},${points[0].y.toFixed(2)}`;
|
|
83
|
+
for (let i = 0;i < points.length - 1; i++) {
|
|
84
|
+
const p1 = points[i];
|
|
85
|
+
const p2 = points[i + 1];
|
|
86
|
+
const midX = (p1.x + p2.x) / 2;
|
|
87
|
+
d += ` L ${midX.toFixed(2)},${p1.y.toFixed(2)} L ${midX.toFixed(2)},${p2.y.toFixed(2)} L ${p2.x.toFixed(2)},${p2.y.toFixed(2)}`;
|
|
88
|
+
}
|
|
89
|
+
return d;
|
|
90
|
+
}
|
|
91
|
+
let d = `M ${points[0].x.toFixed(2)},${points[0].y.toFixed(2)}`;
|
|
92
|
+
for (let i = 1;i < points.length; i++) {
|
|
93
|
+
d += ` L ${points[i].x.toFixed(2)},${points[i].y.toFixed(2)}`;
|
|
94
|
+
}
|
|
95
|
+
return d;
|
|
96
|
+
}
|
|
97
|
+
function pathArea2(points, baselineY, options = {}) {
|
|
98
|
+
if (points.length === 0)
|
|
99
|
+
return "";
|
|
100
|
+
const lineD = pathLine2(points, options);
|
|
101
|
+
if (!lineD)
|
|
102
|
+
return "";
|
|
103
|
+
const first = points[0];
|
|
104
|
+
const last = points[points.length - 1];
|
|
105
|
+
return `${lineD} L ${last.x.toFixed(2)},${baselineY.toFixed(2)} L ${first.x.toFixed(2)},${baselineY.toFixed(2)} Z`;
|
|
106
|
+
}
|
|
107
|
+
function pathArc2(options) {
|
|
108
|
+
const { cx, cy, innerRadius, outerRadius, startAngle, endAngle } = options;
|
|
109
|
+
const cosStart = Math.cos(startAngle);
|
|
110
|
+
const sinStart = Math.sin(startAngle);
|
|
111
|
+
const cosEnd = Math.cos(endAngle);
|
|
112
|
+
const sinEnd = Math.sin(endAngle);
|
|
113
|
+
const x0 = cx + outerRadius * cosStart;
|
|
114
|
+
const y0 = cy + outerRadius * sinStart;
|
|
115
|
+
const x1 = cx + outerRadius * cosEnd;
|
|
116
|
+
const y1 = cy + outerRadius * sinEnd;
|
|
117
|
+
const largeArcFlag = endAngle - startAngle <= Math.PI ? 0 : 1;
|
|
118
|
+
if (innerRadius <= 0) {
|
|
119
|
+
return `M ${cx.toFixed(2)},${cy.toFixed(2)} L ${x0.toFixed(2)},${y0.toFixed(2)} A ${outerRadius.toFixed(2)},${outerRadius.toFixed(2)} 0 ${largeArcFlag} 1 ${x1.toFixed(2)},${y1.toFixed(2)} Z`;
|
|
120
|
+
}
|
|
121
|
+
const x2 = cx + innerRadius * cosEnd;
|
|
122
|
+
const y2 = cy + innerRadius * sinEnd;
|
|
123
|
+
const x3 = cx + innerRadius * cosStart;
|
|
124
|
+
const y3 = cy + innerRadius * sinStart;
|
|
125
|
+
return `M ${x0.toFixed(2)},${y0.toFixed(2)} A ${outerRadius.toFixed(2)},${outerRadius.toFixed(2)} 0 ${largeArcFlag} 1 ${x1.toFixed(2)},${y1.toFixed(2)} L ${x2.toFixed(2)},${y2.toFixed(2)} A ${innerRadius.toFixed(2)},${innerRadius.toFixed(2)} 0 ${largeArcFlag} 0 ${x3.toFixed(2)},${y3.toFixed(2)} Z`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// src/charts/Area.tsx
|
|
129
|
+
function Area2(props) {
|
|
130
|
+
return () => {
|
|
131
|
+
const ctx = useChartContext2();
|
|
132
|
+
const stroke = props.stroke ?? "#a855f7";
|
|
133
|
+
const strokeWidth = props.strokeWidth ?? 2;
|
|
134
|
+
const fill = props.fill ?? "rgba(168, 85, 247, 0.15)";
|
|
135
|
+
const fillOpacity = props.fillOpacity ?? 1;
|
|
136
|
+
const curve = props.curve ?? "smooth";
|
|
137
|
+
const id = `area-${props.dataKey}-${Math.random().toString(36).slice(2, 7)}`;
|
|
138
|
+
ctx.registerSeries({
|
|
139
|
+
id,
|
|
140
|
+
dataKey: props.dataKey,
|
|
141
|
+
type: "area",
|
|
142
|
+
color: stroke,
|
|
143
|
+
name: props.name ?? props.dataKey
|
|
144
|
+
});
|
|
145
|
+
onCleanup2(() => {
|
|
146
|
+
ctx.unregisterSeries(id);
|
|
147
|
+
});
|
|
148
|
+
return /* @__PURE__ */ jsx2("g", {
|
|
149
|
+
class: `visage-area-${props.dataKey}`,
|
|
150
|
+
opacity: props.opacity ?? 1,
|
|
151
|
+
children: () => {
|
|
152
|
+
const dataArr = ctx.data();
|
|
153
|
+
if (dataArr.length === 0)
|
|
154
|
+
return null;
|
|
155
|
+
const xScale = ctx.xScale();
|
|
156
|
+
const yScale = ctx.yScale();
|
|
157
|
+
const baselineY = ctx.innerHeight();
|
|
158
|
+
const points = [];
|
|
159
|
+
for (let i = 0;i < dataArr.length; i++) {
|
|
160
|
+
const item = dataArr[i];
|
|
161
|
+
const val = item[props.dataKey];
|
|
162
|
+
if (typeof val !== "number" || Number.isNaN(val))
|
|
163
|
+
continue;
|
|
164
|
+
let x = 0;
|
|
165
|
+
if (xScale.type === "band") {
|
|
166
|
+
x = xScale(i) + xScale.bandwidth() / 2;
|
|
167
|
+
} else {
|
|
168
|
+
x = xScale(i);
|
|
169
|
+
}
|
|
170
|
+
const y = yScale(val);
|
|
171
|
+
points.push({ x, y });
|
|
172
|
+
}
|
|
173
|
+
const areaD = pathArea2(points, baselineY, { curve });
|
|
174
|
+
const lineD = pathLine2(points, { curve });
|
|
175
|
+
const dots = [];
|
|
176
|
+
if (props.dot && points.length > 0) {
|
|
177
|
+
const dotCfg = typeof props.dot === "object" ? props.dot : {};
|
|
178
|
+
const r = dotCfg.r ?? 3.5;
|
|
179
|
+
const dotFill = dotCfg.fill ?? "#ffffff";
|
|
180
|
+
const dotStroke = dotCfg.stroke ?? stroke;
|
|
181
|
+
for (let i = 0;i < points.length; i++) {
|
|
182
|
+
const p = points[i];
|
|
183
|
+
dots.push(/* @__PURE__ */ jsx2("circle", {
|
|
184
|
+
cx: p.x,
|
|
185
|
+
cy: p.y,
|
|
186
|
+
r,
|
|
187
|
+
fill: dotFill,
|
|
188
|
+
stroke: dotStroke,
|
|
189
|
+
"stroke-width": 2
|
|
190
|
+
}));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return [
|
|
194
|
+
/* @__PURE__ */ jsx2("path", {
|
|
195
|
+
d: areaD,
|
|
196
|
+
fill,
|
|
197
|
+
"fill-opacity": fillOpacity
|
|
198
|
+
}),
|
|
199
|
+
/* @__PURE__ */ jsx2("path", {
|
|
200
|
+
d: lineD,
|
|
201
|
+
fill: "none",
|
|
202
|
+
stroke,
|
|
203
|
+
"stroke-width": strokeWidth,
|
|
204
|
+
"stroke-linejoin": "round",
|
|
205
|
+
"stroke-linecap": "round"
|
|
206
|
+
}),
|
|
207
|
+
...dots
|
|
208
|
+
];
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// src/charts/Axis.tsx
|
|
215
|
+
function XAxis2(props) {
|
|
216
|
+
return () => {
|
|
217
|
+
const ctx = useChartContext2();
|
|
218
|
+
if (props.dataKey) {
|
|
219
|
+
ctx.setXDataKey(props.dataKey);
|
|
220
|
+
onCleanup2(() => {
|
|
221
|
+
if (ctx.xDataKey() === props.dataKey) {
|
|
222
|
+
ctx.setXDataKey("");
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
const stroke = props.stroke ?? "#94a3b8";
|
|
227
|
+
const fontSize = props.fontSize ?? 11;
|
|
228
|
+
const hideLine = props.hideLine ?? false;
|
|
229
|
+
const w = ctx.innerWidth();
|
|
230
|
+
const h = ctx.innerHeight();
|
|
231
|
+
const xScale = ctx.xScale();
|
|
232
|
+
const dataArr = ctx.data();
|
|
233
|
+
const elements = [];
|
|
234
|
+
if (!hideLine) {
|
|
235
|
+
elements.push(/* @__PURE__ */ jsx2("line", {
|
|
236
|
+
x1: 0,
|
|
237
|
+
y1: h,
|
|
238
|
+
x2: w,
|
|
239
|
+
y2: h,
|
|
240
|
+
stroke,
|
|
241
|
+
"stroke-width": 1
|
|
242
|
+
}));
|
|
243
|
+
}
|
|
244
|
+
if (xScale.type === "band") {
|
|
245
|
+
const ticks = xScale.ticks();
|
|
246
|
+
const bw = xScale.bandwidth();
|
|
247
|
+
for (let i = 0;i < ticks.length; i++) {
|
|
248
|
+
const val = ticks[i];
|
|
249
|
+
const x = xScale(i) + bw / 2;
|
|
250
|
+
const text = props.tickFormat ? props.tickFormat(val, i) : String(val);
|
|
251
|
+
elements.push(/* @__PURE__ */ jsx2("text", {
|
|
252
|
+
x,
|
|
253
|
+
y: h + 16,
|
|
254
|
+
"text-anchor": "middle",
|
|
255
|
+
"font-size": fontSize,
|
|
256
|
+
fill: stroke,
|
|
257
|
+
children: text
|
|
258
|
+
}));
|
|
259
|
+
}
|
|
260
|
+
} else {
|
|
261
|
+
const count = props.tickCount ?? 5;
|
|
262
|
+
const ticks = xScale.ticks(count);
|
|
263
|
+
for (let i = 0;i < ticks.length; i++) {
|
|
264
|
+
const tickIdx = ticks[i];
|
|
265
|
+
const x = xScale(tickIdx);
|
|
266
|
+
const idx = Math.max(0, Math.min(dataArr.length - 1, Math.round(tickIdx)));
|
|
267
|
+
const rawItem = dataArr[idx];
|
|
268
|
+
const rawVal = props.dataKey && rawItem ? rawItem[props.dataKey] : idx;
|
|
269
|
+
const text = props.tickFormat ? props.tickFormat(rawVal, i) : String(rawVal ?? idx);
|
|
270
|
+
elements.push(/* @__PURE__ */ jsx2("text", {
|
|
271
|
+
x,
|
|
272
|
+
y: h + 16,
|
|
273
|
+
"text-anchor": "middle",
|
|
274
|
+
"font-size": fontSize,
|
|
275
|
+
fill: stroke,
|
|
276
|
+
children: text
|
|
277
|
+
}));
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return /* @__PURE__ */ jsx2("g", {
|
|
281
|
+
class: "visage-x-axis",
|
|
282
|
+
children: elements
|
|
283
|
+
});
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
function YAxis2(props) {
|
|
287
|
+
return () => {
|
|
288
|
+
const ctx = useChartContext2();
|
|
289
|
+
const stroke = props.stroke ?? "#94a3b8";
|
|
290
|
+
const fontSize = props.fontSize ?? 11;
|
|
291
|
+
const hideLine = props.hideLine ?? true;
|
|
292
|
+
const unit = props.unit ?? "";
|
|
293
|
+
const h = ctx.innerHeight();
|
|
294
|
+
const yScale = ctx.yScale();
|
|
295
|
+
const ticks = yScale.ticks(props.tickCount ?? 5);
|
|
296
|
+
const elements = [];
|
|
297
|
+
if (!hideLine) {
|
|
298
|
+
elements.push(/* @__PURE__ */ jsx2("line", {
|
|
299
|
+
x1: 0,
|
|
300
|
+
y1: 0,
|
|
301
|
+
x2: 0,
|
|
302
|
+
y2: h,
|
|
303
|
+
stroke,
|
|
304
|
+
"stroke-width": 1
|
|
305
|
+
}));
|
|
306
|
+
}
|
|
307
|
+
for (let i = 0;i < ticks.length; i++) {
|
|
308
|
+
const val = ticks[i];
|
|
309
|
+
const y = yScale(val);
|
|
310
|
+
const formatted = props.tickFormat ? props.tickFormat(val, i) : unit ? `${val}${unit}` : String(val);
|
|
311
|
+
elements.push(/* @__PURE__ */ jsx2("text", {
|
|
312
|
+
x: -8,
|
|
313
|
+
y: y + 4,
|
|
314
|
+
"text-anchor": "end",
|
|
315
|
+
"font-size": fontSize,
|
|
316
|
+
fill: stroke,
|
|
317
|
+
children: formatted
|
|
318
|
+
}));
|
|
319
|
+
}
|
|
320
|
+
return /* @__PURE__ */ jsx2("g", {
|
|
321
|
+
class: "visage-y-axis",
|
|
322
|
+
children: elements
|
|
323
|
+
});
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// src/charts/Bar.tsx
|
|
328
|
+
function Bar2(props) {
|
|
329
|
+
return () => {
|
|
330
|
+
const ctx = useChartContext2();
|
|
331
|
+
const fill = props.fill ?? "#6366f1";
|
|
332
|
+
const radius = props.radius ?? 4;
|
|
333
|
+
const id = `bar-${props.dataKey}-${Math.random().toString(36).slice(2, 7)}`;
|
|
334
|
+
ctx.registerSeries({
|
|
335
|
+
id,
|
|
336
|
+
dataKey: props.dataKey,
|
|
337
|
+
type: "bar",
|
|
338
|
+
color: fill,
|
|
339
|
+
name: props.name ?? props.dataKey
|
|
340
|
+
});
|
|
341
|
+
onCleanup2(() => {
|
|
342
|
+
ctx.unregisterSeries(id);
|
|
343
|
+
});
|
|
344
|
+
return /* @__PURE__ */ jsx2("g", {
|
|
345
|
+
class: `visage-bar-${props.dataKey}`,
|
|
346
|
+
opacity: props.opacity ?? 1,
|
|
347
|
+
children: () => {
|
|
348
|
+
const dataArr = ctx.data();
|
|
349
|
+
if (dataArr.length === 0)
|
|
350
|
+
return null;
|
|
351
|
+
const xScale = ctx.xScale();
|
|
352
|
+
const yScale = ctx.yScale();
|
|
353
|
+
const baselineY = ctx.innerHeight();
|
|
354
|
+
const allBars = ctx.series().filter((s) => s.type === "bar");
|
|
355
|
+
const barIndex = allBars.findIndex((s) => s.id === id);
|
|
356
|
+
const totalBars = Math.max(1, allBars.length);
|
|
357
|
+
const bars = [];
|
|
358
|
+
for (let i = 0;i < dataArr.length; i++) {
|
|
359
|
+
const item = dataArr[i];
|
|
360
|
+
const val = item[props.dataKey];
|
|
361
|
+
if (typeof val !== "number" || Number.isNaN(val))
|
|
362
|
+
continue;
|
|
363
|
+
let slotX = 0;
|
|
364
|
+
let slotW = 20;
|
|
365
|
+
if (xScale.type === "band") {
|
|
366
|
+
slotX = xScale(i);
|
|
367
|
+
slotW = xScale.bandwidth();
|
|
368
|
+
} else {
|
|
369
|
+
const stepW = ctx.innerWidth() / Math.max(1, dataArr.length);
|
|
370
|
+
slotX = xScale(i) - stepW / 2;
|
|
371
|
+
slotW = stepW * 0.8;
|
|
372
|
+
}
|
|
373
|
+
const subBarW = slotW / totalBars;
|
|
374
|
+
const barW = props.maxWidth ? Math.min(props.maxWidth, subBarW) : subBarW;
|
|
375
|
+
const barX = slotX + (barIndex >= 0 ? barIndex * subBarW : 0) + (subBarW - barW) / 2;
|
|
376
|
+
const y = yScale(val);
|
|
377
|
+
const h = Math.max(0, baselineY - y);
|
|
378
|
+
bars.push(/* @__PURE__ */ jsx2("rect", {
|
|
379
|
+
x: barX,
|
|
380
|
+
y,
|
|
381
|
+
width: barW,
|
|
382
|
+
height: h,
|
|
383
|
+
rx: radius,
|
|
384
|
+
ry: radius,
|
|
385
|
+
fill
|
|
386
|
+
}));
|
|
387
|
+
}
|
|
388
|
+
return bars;
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// src/charts/CartesianGrid.tsx
|
|
395
|
+
function CartesianGrid2(props) {
|
|
396
|
+
return () => {
|
|
397
|
+
const ctx = useChartContext2();
|
|
398
|
+
const horizontal = props.horizontal ?? true;
|
|
399
|
+
const vertical = props.vertical ?? false;
|
|
400
|
+
const stroke = props.stroke ?? "#e2e8f0";
|
|
401
|
+
const strokeWidth = props.strokeWidth ?? 1;
|
|
402
|
+
const strokeDasharray = props.strokeDasharray;
|
|
403
|
+
const opacity = props.opacity ?? 0.8;
|
|
404
|
+
const lines = [];
|
|
405
|
+
const w = ctx.innerWidth();
|
|
406
|
+
const h = ctx.innerHeight();
|
|
407
|
+
const yScale = ctx.yScale();
|
|
408
|
+
const xScale = ctx.xScale();
|
|
409
|
+
if (horizontal) {
|
|
410
|
+
const ticks = yScale.ticks(5);
|
|
411
|
+
for (const t of ticks) {
|
|
412
|
+
const y = yScale(t);
|
|
413
|
+
lines.push(/* @__PURE__ */ jsx2("line", {
|
|
414
|
+
x1: 0,
|
|
415
|
+
y1: y,
|
|
416
|
+
x2: w,
|
|
417
|
+
y2: y,
|
|
418
|
+
stroke,
|
|
419
|
+
"stroke-width": strokeWidth,
|
|
420
|
+
"stroke-dasharray": strokeDasharray
|
|
421
|
+
}));
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
if (vertical) {
|
|
425
|
+
const ticks = xScale.ticks(5);
|
|
426
|
+
for (const t of ticks) {
|
|
427
|
+
const x = xScale(t);
|
|
428
|
+
lines.push(/* @__PURE__ */ jsx2("line", {
|
|
429
|
+
x1: x,
|
|
430
|
+
y1: 0,
|
|
431
|
+
x2: x,
|
|
432
|
+
y2: h,
|
|
433
|
+
stroke,
|
|
434
|
+
"stroke-width": strokeWidth,
|
|
435
|
+
"stroke-dasharray": strokeDasharray
|
|
436
|
+
}));
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
return /* @__PURE__ */ jsx2("g", {
|
|
440
|
+
class: "visage-cartesian-grid",
|
|
441
|
+
opacity,
|
|
442
|
+
children: lines
|
|
443
|
+
});
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// src/charts/scale.ts
|
|
448
|
+
function generateNiceTicks2(min, max, count = 5) {
|
|
449
|
+
if (min === max)
|
|
450
|
+
return [min];
|
|
451
|
+
if (count <= 0)
|
|
452
|
+
return [];
|
|
453
|
+
const span = max - min;
|
|
454
|
+
const rawStep = span / count;
|
|
455
|
+
const magnitude = 10 ** Math.floor(Math.log10(rawStep));
|
|
456
|
+
const err = rawStep / magnitude;
|
|
457
|
+
let step;
|
|
458
|
+
if (err >= 7.5) {
|
|
459
|
+
step = 10 * magnitude;
|
|
460
|
+
} else if (err >= 3.5) {
|
|
461
|
+
step = 5 * magnitude;
|
|
462
|
+
} else if (err >= 1.5) {
|
|
463
|
+
step = 2 * magnitude;
|
|
464
|
+
} else {
|
|
465
|
+
step = 1 * magnitude;
|
|
466
|
+
}
|
|
467
|
+
const start = Math.floor(min / step) * step;
|
|
468
|
+
const end = Math.ceil(max / step) * step;
|
|
469
|
+
const ticks = [];
|
|
470
|
+
for (let current = start;current <= end + step * 0.5; current += step) {
|
|
471
|
+
const rounded = Number(current.toPrecision(12));
|
|
472
|
+
ticks.push(rounded);
|
|
473
|
+
}
|
|
474
|
+
return ticks;
|
|
475
|
+
}
|
|
476
|
+
function createLinearScale2(domain, range, options = {}) {
|
|
477
|
+
let [d0, d1] = domain;
|
|
478
|
+
const [r0, r1] = range;
|
|
479
|
+
if (options.nice && d0 !== d1) {
|
|
480
|
+
const ticks = generateNiceTicks2(d0, d1, 5);
|
|
481
|
+
if (ticks.length > 0) {
|
|
482
|
+
d0 = Math.min(d0, ticks[0]);
|
|
483
|
+
d1 = Math.max(d1, ticks[ticks.length - 1]);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
const fn = (val) => {
|
|
487
|
+
let v = val;
|
|
488
|
+
if (options.clamp) {
|
|
489
|
+
const minD = Math.min(d0, d1);
|
|
490
|
+
const maxD = Math.max(d0, d1);
|
|
491
|
+
v = Math.max(minD, Math.min(maxD, v));
|
|
492
|
+
}
|
|
493
|
+
const ratio = d1 === d0 ? 0 : (v - d0) / (d1 - d0);
|
|
494
|
+
return r0 + ratio * (r1 - r0);
|
|
495
|
+
};
|
|
496
|
+
fn.type = "linear";
|
|
497
|
+
fn.domain = [d0, d1];
|
|
498
|
+
fn.range = [r0, r1];
|
|
499
|
+
fn.invert = (pixel) => {
|
|
500
|
+
const ratio = r1 === r0 ? 0 : (pixel - r0) / (r1 - r0);
|
|
501
|
+
return d0 + ratio * (d1 - d0);
|
|
502
|
+
};
|
|
503
|
+
fn.ticks = (count = 5) => {
|
|
504
|
+
return generateNiceTicks2(d0, d1, count);
|
|
505
|
+
};
|
|
506
|
+
return fn;
|
|
507
|
+
}
|
|
508
|
+
function createBandScale2(domain, range, options = {}) {
|
|
509
|
+
const paddingInner = options.paddingInner ?? 0.2;
|
|
510
|
+
const paddingOuter = options.paddingOuter ?? 0.1;
|
|
511
|
+
const n = domain.length;
|
|
512
|
+
const totalSteps = Math.max(1, n - paddingInner + 2 * paddingOuter);
|
|
513
|
+
const step = (range[1] - range[0]) / totalSteps;
|
|
514
|
+
const bandwidth = step * (1 - paddingInner);
|
|
515
|
+
const fn = (val) => {
|
|
516
|
+
let idx = -1;
|
|
517
|
+
if (typeof val === "number" && Number.isInteger(val) && val >= 0 && val < domain.length) {
|
|
518
|
+
idx = val;
|
|
519
|
+
} else {
|
|
520
|
+
idx = domain.indexOf(val);
|
|
521
|
+
}
|
|
522
|
+
if (idx === -1)
|
|
523
|
+
return range[0];
|
|
524
|
+
return range[0] + (idx + paddingOuter) * step;
|
|
525
|
+
};
|
|
526
|
+
fn.type = "band";
|
|
527
|
+
fn.domain = [...domain];
|
|
528
|
+
fn.range = [range[0], range[1]];
|
|
529
|
+
fn.bandwidth = () => bandwidth;
|
|
530
|
+
fn.step = () => step;
|
|
531
|
+
fn.ticks = () => [...domain];
|
|
532
|
+
return fn;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// src/charts/Chart.tsx
|
|
536
|
+
var DEFAULT_MARGIN = {
|
|
537
|
+
top: 16,
|
|
538
|
+
right: 16,
|
|
539
|
+
bottom: 24,
|
|
540
|
+
left: 36
|
|
541
|
+
};
|
|
542
|
+
function Chart2(props) {
|
|
543
|
+
const margin = {
|
|
544
|
+
...DEFAULT_MARGIN,
|
|
545
|
+
...props.margin
|
|
546
|
+
};
|
|
547
|
+
const initialW = typeof props.width === "number" ? props.width : 500;
|
|
548
|
+
const initialH = typeof props.height === "number" ? props.height : 300;
|
|
549
|
+
const measuredWidth = signal2(initialW);
|
|
550
|
+
const measuredHeight = signal2(initialH);
|
|
551
|
+
let containerEl = null;
|
|
552
|
+
const handleRef = (el) => {
|
|
553
|
+
containerEl = el;
|
|
554
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
555
|
+
const ro = new ResizeObserver((entries) => {
|
|
556
|
+
for (const entry of entries) {
|
|
557
|
+
const cr = entry.contentRect;
|
|
558
|
+
if (cr.width > 0)
|
|
559
|
+
measuredWidth.set(cr.width);
|
|
560
|
+
if (cr.height > 0)
|
|
561
|
+
measuredHeight.set(cr.height);
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
ro.observe(el);
|
|
565
|
+
onCleanup2(() => ro.disconnect());
|
|
566
|
+
} else {
|
|
567
|
+
if (el.clientWidth > 0)
|
|
568
|
+
measuredWidth.set(el.clientWidth);
|
|
569
|
+
if (el.clientHeight > 0)
|
|
570
|
+
measuredHeight.set(el.clientHeight);
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
const innerWidth = computed2(() => Math.max(10, measuredWidth() - margin.left - margin.right));
|
|
574
|
+
const innerHeight = computed2(() => Math.max(10, measuredHeight() - margin.top - margin.bottom));
|
|
575
|
+
const rawData = () => resolveValue2(props.data) || [];
|
|
576
|
+
const seriesList = signal2([]);
|
|
577
|
+
const xDataKey = signal2(undefined);
|
|
578
|
+
const registerSeries = (meta) => {
|
|
579
|
+
untrack2(() => {
|
|
580
|
+
seriesList.update((prev) => {
|
|
581
|
+
if (prev.some((s) => s.id === meta.id))
|
|
582
|
+
return prev;
|
|
583
|
+
return [...prev, meta];
|
|
584
|
+
});
|
|
585
|
+
});
|
|
586
|
+
};
|
|
587
|
+
const unregisterSeries = (id) => {
|
|
588
|
+
untrack2(() => {
|
|
589
|
+
seriesList.update((prev) => prev.filter((s) => s.id !== id));
|
|
590
|
+
});
|
|
591
|
+
};
|
|
592
|
+
const hoverState = signal2({
|
|
593
|
+
active: false,
|
|
594
|
+
x: 0,
|
|
595
|
+
y: 0,
|
|
596
|
+
index: -1
|
|
597
|
+
});
|
|
598
|
+
const xScale = computed2(() => {
|
|
599
|
+
const dataArr = rawData();
|
|
600
|
+
const w = innerWidth();
|
|
601
|
+
const key = xDataKey();
|
|
602
|
+
const hasBarSeries = untrack2(() => seriesList().some((s) => s.type === "bar"));
|
|
603
|
+
if (hasBarSeries && key && dataArr.length > 0) {
|
|
604
|
+
const categories = dataArr.map((d) => String(d[key]));
|
|
605
|
+
return createBandScale2(categories, [0, w], {
|
|
606
|
+
paddingInner: 0.1,
|
|
607
|
+
paddingOuter: 0.05
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
const maxIdx = Math.max(1, dataArr.length - 1);
|
|
611
|
+
return createLinearScale2([0, maxIdx], [0, w]);
|
|
612
|
+
});
|
|
613
|
+
const yScale = computed2(() => {
|
|
614
|
+
const h = innerHeight();
|
|
615
|
+
const dataArr = rawData();
|
|
616
|
+
const currentSeries = seriesList();
|
|
617
|
+
let minY = 0;
|
|
618
|
+
let maxY = 10;
|
|
619
|
+
if (props.yDomain) {
|
|
620
|
+
minY = props.yDomain[0];
|
|
621
|
+
maxY = props.yDomain[1];
|
|
622
|
+
} else if (dataArr.length > 0 && currentSeries.length > 0) {
|
|
623
|
+
let foundMin = Infinity;
|
|
624
|
+
let foundMax = -Infinity;
|
|
625
|
+
for (const item of dataArr) {
|
|
626
|
+
for (const s of currentSeries) {
|
|
627
|
+
const val = item[s.dataKey];
|
|
628
|
+
if (typeof val === "number" && !Number.isNaN(val)) {
|
|
629
|
+
if (val < foundMin)
|
|
630
|
+
foundMin = val;
|
|
631
|
+
if (val > foundMax)
|
|
632
|
+
foundMax = val;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
if (foundMax > -Infinity) {
|
|
637
|
+
minY = Math.min(0, foundMin);
|
|
638
|
+
maxY = foundMax === 0 ? 1 : foundMax * 1.1;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
return createLinearScale2([minY, maxY], [h, 0], { nice: true });
|
|
642
|
+
});
|
|
643
|
+
const handlePointer = (clientX, clientY) => {
|
|
644
|
+
if (!containerEl)
|
|
645
|
+
return;
|
|
646
|
+
const rect = containerEl.getBoundingClientRect();
|
|
647
|
+
const relX = clientX - rect.left - margin.left;
|
|
648
|
+
const relY = clientY - rect.top - margin.top;
|
|
649
|
+
const w = innerWidth();
|
|
650
|
+
const h = innerHeight();
|
|
651
|
+
if (relX < 0 || relX > w || relY < 0 || relY > h) {
|
|
652
|
+
hoverState.set({ active: false, x: 0, y: 0, index: -1 });
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
const dataArr = rawData();
|
|
656
|
+
if (dataArr.length === 0)
|
|
657
|
+
return;
|
|
658
|
+
const count = dataArr.length;
|
|
659
|
+
const stepW = w / Math.max(1, count - 1);
|
|
660
|
+
const rawIdx = Math.round(relX / stepW);
|
|
661
|
+
const clampedIdx = Math.max(0, Math.min(count - 1, rawIdx));
|
|
662
|
+
hoverState.set({
|
|
663
|
+
active: true,
|
|
664
|
+
x: relX + margin.left,
|
|
665
|
+
y: relY + margin.top,
|
|
666
|
+
index: clampedIdx,
|
|
667
|
+
datum: dataArr[clampedIdx]
|
|
668
|
+
});
|
|
669
|
+
};
|
|
670
|
+
const handleMouseMove = (e) => {
|
|
671
|
+
handlePointer(e.clientX, e.clientY);
|
|
672
|
+
};
|
|
673
|
+
const handleMouseLeave = () => {
|
|
674
|
+
hoverState.set({ active: false, x: 0, y: 0, index: -1 });
|
|
675
|
+
};
|
|
676
|
+
const handleTouchMove = (e) => {
|
|
677
|
+
const touch = e.touches[0];
|
|
678
|
+
if (touch)
|
|
679
|
+
handlePointer(touch.clientX, touch.clientY);
|
|
680
|
+
};
|
|
681
|
+
const handleTouchEnd = () => {
|
|
682
|
+
hoverState.set({ active: false, x: 0, y: 0, index: -1 });
|
|
683
|
+
};
|
|
684
|
+
const ctxValue = {
|
|
685
|
+
data: rawData,
|
|
686
|
+
width: () => measuredWidth(),
|
|
687
|
+
height: () => measuredHeight(),
|
|
688
|
+
margin,
|
|
689
|
+
innerWidth: () => innerWidth(),
|
|
690
|
+
innerHeight: () => innerHeight(),
|
|
691
|
+
xScale: () => xScale(),
|
|
692
|
+
yScale: () => yScale(),
|
|
693
|
+
hoverState: () => hoverState(),
|
|
694
|
+
setHoverState: (s) => hoverState.set(s),
|
|
695
|
+
xDataKey: () => xDataKey(),
|
|
696
|
+
setXDataKey: (k) => xDataKey.set(k),
|
|
697
|
+
series: () => seriesList(),
|
|
698
|
+
registerSeries,
|
|
699
|
+
unregisterSeries
|
|
700
|
+
};
|
|
701
|
+
const containerStyle = {
|
|
702
|
+
position: "relative",
|
|
703
|
+
width: typeof props.width === "number" ? `${props.width}px` : props.width ?? "100%",
|
|
704
|
+
height: typeof props.height === "number" ? `${props.height}px` : props.height ?? "300px",
|
|
705
|
+
touchAction: "none",
|
|
706
|
+
userSelect: "none",
|
|
707
|
+
...props.style
|
|
708
|
+
};
|
|
709
|
+
const rawChildren = Array.isArray(props.children) ? props.children : [props.children];
|
|
710
|
+
const childrenList = [];
|
|
711
|
+
const stack = [...rawChildren];
|
|
712
|
+
while (stack.length > 0) {
|
|
713
|
+
const item = stack.shift();
|
|
714
|
+
if (Array.isArray(item)) {
|
|
715
|
+
stack.unshift(...item);
|
|
716
|
+
} else if (item !== null && item !== undefined && item !== false) {
|
|
717
|
+
childrenList.push(item);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
const svgChildren = [];
|
|
721
|
+
const overlayChildren = [];
|
|
722
|
+
for (const child of childrenList) {
|
|
723
|
+
if (typeof child === "function" && child.__visage_overlay) {
|
|
724
|
+
overlayChildren.push(child);
|
|
725
|
+
} else {
|
|
726
|
+
svgChildren.push(child);
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
return ChartContext2.Provider({
|
|
730
|
+
value: ctxValue,
|
|
731
|
+
children: () => /* @__PURE__ */ jsxs2("div", {
|
|
732
|
+
ref: handleRef,
|
|
733
|
+
class: props.class || props.className,
|
|
734
|
+
style: containerStyle,
|
|
735
|
+
onMouseMove: handleMouseMove,
|
|
736
|
+
onMouseLeave: handleMouseLeave,
|
|
737
|
+
onTouchMove: handleTouchMove,
|
|
738
|
+
onTouchEnd: handleTouchEnd,
|
|
739
|
+
children: [
|
|
740
|
+
/* @__PURE__ */ jsxs2("svg", {
|
|
741
|
+
role: "img",
|
|
742
|
+
"aria-label": props["aria-label"] ?? "Data visualization chart",
|
|
743
|
+
viewBox: () => `0 0 ${measuredWidth()} ${measuredHeight()}`,
|
|
744
|
+
width: "100%",
|
|
745
|
+
height: "100%",
|
|
746
|
+
style: { overflow: "visible", display: "block" },
|
|
747
|
+
children: [
|
|
748
|
+
/* @__PURE__ */ jsx2("title", {
|
|
749
|
+
children: props.title ?? "Data Visualization Chart"
|
|
750
|
+
}),
|
|
751
|
+
/* @__PURE__ */ jsx2("g", {
|
|
752
|
+
transform: `translate(${margin.left}, ${margin.top})`,
|
|
753
|
+
children: svgChildren
|
|
754
|
+
})
|
|
755
|
+
]
|
|
756
|
+
}),
|
|
757
|
+
overlayChildren
|
|
758
|
+
]
|
|
759
|
+
})
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// src/charts/Cursor.tsx
|
|
764
|
+
function ChartCursor2(props) {
|
|
765
|
+
return () => {
|
|
766
|
+
const ctx = useChartContext2();
|
|
767
|
+
const stroke = props.stroke ?? "#94a3b8";
|
|
768
|
+
const strokeWidth = props.strokeWidth ?? 1;
|
|
769
|
+
const strokeDasharray = props.strokeDasharray ?? "4 4";
|
|
770
|
+
const opacity = props.opacity ?? 0.8;
|
|
771
|
+
const hover = ctx.hoverState();
|
|
772
|
+
if (!hover.active)
|
|
773
|
+
return null;
|
|
774
|
+
const h = ctx.innerHeight();
|
|
775
|
+
const x = hover.x - ctx.margin.left;
|
|
776
|
+
return /* @__PURE__ */ jsx2("g", {
|
|
777
|
+
class: "visage-chart-cursor",
|
|
778
|
+
children: /* @__PURE__ */ jsx2("line", {
|
|
779
|
+
x1: x,
|
|
780
|
+
y1: 0,
|
|
781
|
+
x2: x,
|
|
782
|
+
y2: h,
|
|
783
|
+
stroke,
|
|
784
|
+
"stroke-width": strokeWidth,
|
|
785
|
+
"stroke-dasharray": strokeDasharray,
|
|
786
|
+
opacity
|
|
787
|
+
})
|
|
788
|
+
});
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// src/charts/Legend.tsx
|
|
793
|
+
function ChartLegend2(props) {
|
|
794
|
+
const render = () => {
|
|
795
|
+
const ctx = useChartContext2();
|
|
796
|
+
const align = props.align ?? "center";
|
|
797
|
+
const justifyMap = {
|
|
798
|
+
left: "flex-start",
|
|
799
|
+
center: "center",
|
|
800
|
+
right: "flex-end"
|
|
801
|
+
};
|
|
802
|
+
const series = ctx.series();
|
|
803
|
+
return /* @__PURE__ */ jsx2("div", {
|
|
804
|
+
class: props.class || props.className,
|
|
805
|
+
style: {
|
|
806
|
+
display: "flex",
|
|
807
|
+
alignItems: "center",
|
|
808
|
+
justifyContent: justifyMap[align],
|
|
809
|
+
gap: "16px",
|
|
810
|
+
paddingTop: "8px",
|
|
811
|
+
fontSize: "12px",
|
|
812
|
+
color: "#475569"
|
|
813
|
+
},
|
|
814
|
+
children: series.map((s) => /* @__PURE__ */ jsxs2("div", {
|
|
815
|
+
style: { display: "flex", alignItems: "center", gap: "6px" },
|
|
816
|
+
children: [
|
|
817
|
+
/* @__PURE__ */ jsx2("span", {
|
|
818
|
+
style: {
|
|
819
|
+
width: "10px",
|
|
820
|
+
height: "10px",
|
|
821
|
+
borderRadius: "3px",
|
|
822
|
+
background: s.color ?? "#8b5cf6"
|
|
823
|
+
}
|
|
824
|
+
}),
|
|
825
|
+
/* @__PURE__ */ jsx2("span", {
|
|
826
|
+
children: s.name ?? s.dataKey
|
|
827
|
+
})
|
|
828
|
+
]
|
|
829
|
+
}))
|
|
830
|
+
});
|
|
831
|
+
};
|
|
832
|
+
render.__visage_overlay = true;
|
|
833
|
+
return render;
|
|
834
|
+
}
|
|
835
|
+
var Legend2 = ChartLegend2;
|
|
836
|
+
|
|
837
|
+
// src/charts/Line.tsx
|
|
838
|
+
function Line2(props) {
|
|
839
|
+
return () => {
|
|
840
|
+
const ctx = useChartContext2();
|
|
841
|
+
const stroke = props.stroke ?? "#8b5cf6";
|
|
842
|
+
const strokeWidth = props.strokeWidth ?? 2;
|
|
843
|
+
const curve = props.curve ?? "linear";
|
|
844
|
+
const id = `line-${props.dataKey}-${Math.random().toString(36).slice(2, 7)}`;
|
|
845
|
+
ctx.registerSeries({
|
|
846
|
+
id,
|
|
847
|
+
dataKey: props.dataKey,
|
|
848
|
+
type: "line",
|
|
849
|
+
color: stroke,
|
|
850
|
+
name: props.name ?? props.dataKey
|
|
851
|
+
});
|
|
852
|
+
onCleanup2(() => {
|
|
853
|
+
ctx.unregisterSeries(id);
|
|
854
|
+
});
|
|
855
|
+
return /* @__PURE__ */ jsx2("g", {
|
|
856
|
+
class: `visage-line-${props.dataKey}`,
|
|
857
|
+
opacity: props.opacity ?? 1,
|
|
858
|
+
children: () => {
|
|
859
|
+
const dataArr = ctx.data();
|
|
860
|
+
if (dataArr.length === 0)
|
|
861
|
+
return null;
|
|
862
|
+
const xScale = ctx.xScale();
|
|
863
|
+
const yScale = ctx.yScale();
|
|
864
|
+
const points = [];
|
|
865
|
+
for (let i = 0;i < dataArr.length; i++) {
|
|
866
|
+
const item = dataArr[i];
|
|
867
|
+
const val = item[props.dataKey];
|
|
868
|
+
if (typeof val !== "number" || Number.isNaN(val))
|
|
869
|
+
continue;
|
|
870
|
+
let x = 0;
|
|
871
|
+
if (xScale.type === "band") {
|
|
872
|
+
x = xScale(i) + xScale.bandwidth() / 2;
|
|
873
|
+
} else {
|
|
874
|
+
x = xScale(i);
|
|
875
|
+
}
|
|
876
|
+
const y = yScale(val);
|
|
877
|
+
points.push({ x, y });
|
|
878
|
+
}
|
|
879
|
+
const d = pathLine2(points, { curve });
|
|
880
|
+
const dots = [];
|
|
881
|
+
if (props.dot && points.length > 0) {
|
|
882
|
+
const dotCfg = typeof props.dot === "object" ? props.dot : {};
|
|
883
|
+
const r = dotCfg.r ?? 3.5;
|
|
884
|
+
const fill = dotCfg.fill ?? "#ffffff";
|
|
885
|
+
const dotStroke = dotCfg.stroke ?? stroke;
|
|
886
|
+
const dotSw = dotCfg.strokeWidth ?? 2;
|
|
887
|
+
for (let i = 0;i < points.length; i++) {
|
|
888
|
+
const p = points[i];
|
|
889
|
+
dots.push(/* @__PURE__ */ jsx2("circle", {
|
|
890
|
+
cx: p.x,
|
|
891
|
+
cy: p.y,
|
|
892
|
+
r,
|
|
893
|
+
fill,
|
|
894
|
+
stroke: dotStroke,
|
|
895
|
+
"stroke-width": dotSw
|
|
896
|
+
}));
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
return [
|
|
900
|
+
/* @__PURE__ */ jsx2("path", {
|
|
901
|
+
d,
|
|
902
|
+
fill: "none",
|
|
903
|
+
stroke,
|
|
904
|
+
"stroke-width": strokeWidth,
|
|
905
|
+
"stroke-dasharray": props.strokeDasharray,
|
|
906
|
+
"stroke-linejoin": "round",
|
|
907
|
+
"stroke-linecap": "round"
|
|
908
|
+
}),
|
|
909
|
+
...dots
|
|
910
|
+
];
|
|
911
|
+
}
|
|
912
|
+
});
|
|
913
|
+
};
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
// src/charts/Pie.tsx
|
|
917
|
+
var DEFAULT_PALETTE = [
|
|
918
|
+
"#8b5cf6",
|
|
919
|
+
"#ec4899",
|
|
920
|
+
"#3b82f6",
|
|
921
|
+
"#10b981",
|
|
922
|
+
"#f59e0b",
|
|
923
|
+
"#6366f1",
|
|
924
|
+
"#14b8a6",
|
|
925
|
+
"#ef4444"
|
|
926
|
+
];
|
|
927
|
+
function Pie2(props) {
|
|
928
|
+
return () => {
|
|
929
|
+
const ctx = useChartContext2();
|
|
930
|
+
const innerRadius = props.innerRadius ?? 0;
|
|
931
|
+
const outerRadius = props.outerRadius ?? 80;
|
|
932
|
+
const colors = props.colors ?? DEFAULT_PALETTE;
|
|
933
|
+
const padAngle = props.padAngle ?? 0.02;
|
|
934
|
+
return /* @__PURE__ */ jsx2("g", {
|
|
935
|
+
class: "visage-pie",
|
|
936
|
+
children: () => {
|
|
937
|
+
const dataArr = ctx.data();
|
|
938
|
+
if (dataArr.length === 0)
|
|
939
|
+
return null;
|
|
940
|
+
const w = ctx.innerWidth();
|
|
941
|
+
const h = ctx.innerHeight();
|
|
942
|
+
const centerX = props.cx ?? w / 2;
|
|
943
|
+
const centerY = props.cy ?? h / 2;
|
|
944
|
+
let total = 0;
|
|
945
|
+
for (const item of dataArr) {
|
|
946
|
+
const val = Number(item[props.dataKey]) || 0;
|
|
947
|
+
total += val;
|
|
948
|
+
}
|
|
949
|
+
if (total === 0)
|
|
950
|
+
return null;
|
|
951
|
+
const slices = [];
|
|
952
|
+
let currentAngle = -Math.PI / 2;
|
|
953
|
+
for (let i = 0;i < dataArr.length; i++) {
|
|
954
|
+
const item = dataArr[i];
|
|
955
|
+
const val = Number(item[props.dataKey]) || 0;
|
|
956
|
+
const sliceAngle = val / total * (2 * Math.PI);
|
|
957
|
+
const startAngle = currentAngle + (val > 0 ? padAngle / 2 : 0);
|
|
958
|
+
const endAngle = currentAngle + sliceAngle - (val > 0 ? padAngle / 2 : 0);
|
|
959
|
+
currentAngle += sliceAngle;
|
|
960
|
+
if (val <= 0 || endAngle <= startAngle)
|
|
961
|
+
continue;
|
|
962
|
+
const d = pathArc2({
|
|
963
|
+
cx: centerX,
|
|
964
|
+
cy: centerY,
|
|
965
|
+
innerRadius,
|
|
966
|
+
outerRadius,
|
|
967
|
+
startAngle,
|
|
968
|
+
endAngle
|
|
969
|
+
});
|
|
970
|
+
const fill = colors[i % colors.length];
|
|
971
|
+
slices.push(/* @__PURE__ */ jsx2("path", {
|
|
972
|
+
d,
|
|
973
|
+
fill,
|
|
974
|
+
stroke: "#ffffff",
|
|
975
|
+
"stroke-width": 1.5
|
|
976
|
+
}));
|
|
977
|
+
}
|
|
978
|
+
return slices;
|
|
979
|
+
}
|
|
980
|
+
});
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
// src/charts/Tooltip.tsx
|
|
985
|
+
function ChartTooltip2(props) {
|
|
986
|
+
const render = () => {
|
|
987
|
+
const ctx = useChartContext2();
|
|
988
|
+
const hover = ctx.hoverState();
|
|
989
|
+
if (!hover.active || !hover.datum)
|
|
990
|
+
return null;
|
|
991
|
+
const w = ctx.width();
|
|
992
|
+
const datum = hover.datum;
|
|
993
|
+
const series = ctx.series();
|
|
994
|
+
const xKey = ctx.xDataKey();
|
|
995
|
+
const cardWidth = 160;
|
|
996
|
+
let left = hover.x + 14;
|
|
997
|
+
if (left + cardWidth > w) {
|
|
998
|
+
left = Math.max(10, hover.x - cardWidth - 14);
|
|
999
|
+
}
|
|
1000
|
+
const top = Math.max(10, hover.y - 30);
|
|
1001
|
+
if (props.content) {
|
|
1002
|
+
return /* @__PURE__ */ jsx2("div", {
|
|
1003
|
+
style: {
|
|
1004
|
+
position: "absolute",
|
|
1005
|
+
left: `${left}px`,
|
|
1006
|
+
top: `${top}px`,
|
|
1007
|
+
pointerEvents: "none",
|
|
1008
|
+
zIndex: 50
|
|
1009
|
+
},
|
|
1010
|
+
children: props.content(datum, series)
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1013
|
+
const label = xKey && datum[xKey] !== undefined ? datum[xKey] : `#${hover.index + 1}`;
|
|
1014
|
+
const formattedLabel = props.labelFormat ? props.labelFormat(label) : String(label);
|
|
1015
|
+
return /* @__PURE__ */ jsxs2("div", {
|
|
1016
|
+
class: props.class || props.className,
|
|
1017
|
+
style: {
|
|
1018
|
+
position: "absolute",
|
|
1019
|
+
left: `${left}px`,
|
|
1020
|
+
top: `${top}px`,
|
|
1021
|
+
pointerEvents: "none",
|
|
1022
|
+
zIndex: 50,
|
|
1023
|
+
minWidth: `${cardWidth}px`,
|
|
1024
|
+
padding: "8px 12px",
|
|
1025
|
+
borderRadius: "10px",
|
|
1026
|
+
background: "rgba(255, 255, 255, 0.92)",
|
|
1027
|
+
backdropFilter: "blur(12px)",
|
|
1028
|
+
WebkitBackdropFilter: "blur(12px)",
|
|
1029
|
+
border: "1px solid rgba(226, 232, 240, 0.8)",
|
|
1030
|
+
boxShadow: "0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -4px rgba(0, 0, 0, 0.05)",
|
|
1031
|
+
fontSize: "12px",
|
|
1032
|
+
color: "#1e293b",
|
|
1033
|
+
lineHeight: "1.4"
|
|
1034
|
+
},
|
|
1035
|
+
children: [
|
|
1036
|
+
/* @__PURE__ */ jsx2("div", {
|
|
1037
|
+
style: {
|
|
1038
|
+
fontWeight: "600",
|
|
1039
|
+
color: "#475569",
|
|
1040
|
+
marginBottom: "6px",
|
|
1041
|
+
borderBottom: "1px solid #f1f5f9",
|
|
1042
|
+
paddingBottom: "4px"
|
|
1043
|
+
},
|
|
1044
|
+
children: formattedLabel
|
|
1045
|
+
}),
|
|
1046
|
+
/* @__PURE__ */ jsx2("div", {
|
|
1047
|
+
style: { display: "flex", flexDirection: "column", gap: "4px" },
|
|
1048
|
+
children: series.map((s) => {
|
|
1049
|
+
const rawVal = datum[s.dataKey];
|
|
1050
|
+
if (rawVal === undefined || rawVal === null)
|
|
1051
|
+
return null;
|
|
1052
|
+
const valStr = props.format ? props.format(rawVal, s.name ?? s.dataKey) : String(rawVal);
|
|
1053
|
+
return /* @__PURE__ */ jsxs2("div", {
|
|
1054
|
+
style: {
|
|
1055
|
+
display: "flex",
|
|
1056
|
+
alignItems: "center",
|
|
1057
|
+
justifyContent: "space-between",
|
|
1058
|
+
gap: "8px"
|
|
1059
|
+
},
|
|
1060
|
+
children: [
|
|
1061
|
+
/* @__PURE__ */ jsxs2("div", {
|
|
1062
|
+
style: { display: "flex", alignItems: "center", gap: "6px" },
|
|
1063
|
+
children: [
|
|
1064
|
+
/* @__PURE__ */ jsx2("span", {
|
|
1065
|
+
style: {
|
|
1066
|
+
width: "8px",
|
|
1067
|
+
height: "8px",
|
|
1068
|
+
borderRadius: "50%",
|
|
1069
|
+
background: s.color ?? "#8b5cf6"
|
|
1070
|
+
}
|
|
1071
|
+
}),
|
|
1072
|
+
/* @__PURE__ */ jsx2("span", {
|
|
1073
|
+
style: { color: "#64748b" },
|
|
1074
|
+
children: s.name ?? s.dataKey
|
|
1075
|
+
})
|
|
1076
|
+
]
|
|
1077
|
+
}),
|
|
1078
|
+
/* @__PURE__ */ jsx2("span", {
|
|
1079
|
+
style: { fontWeight: "600", color: "#0f172a" },
|
|
1080
|
+
children: valStr
|
|
1081
|
+
})
|
|
1082
|
+
]
|
|
1083
|
+
});
|
|
1084
|
+
})
|
|
1085
|
+
})
|
|
1086
|
+
]
|
|
1087
|
+
});
|
|
1088
|
+
};
|
|
1089
|
+
render.__visage_overlay = true;
|
|
1090
|
+
return render;
|
|
1091
|
+
}
|
|
1092
|
+
var Tooltip2 = ChartTooltip2;
|
|
1093
|
+
|
|
1094
|
+
export { ChartContext2, useChartContext2, pathLine2, pathArea2, pathArc2, Area2, XAxis2, YAxis2, Bar2, CartesianGrid2, generateNiceTicks2, createLinearScale2, createBandScale2, Chart2, ChartCursor2, ChartLegend2, Legend2, Line2, Pie2, ChartTooltip2, Tooltip2 };
|