@terryavg/neptune-ai-chatbot 1.0.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 +16 -0
- package/dist/chart-component-RCLR3IKU.mjs +887 -0
- package/dist/chat-input-L5LIF4NP.mjs +452 -0
- package/dist/chat-message-FTACCRMO.mjs +1904 -0
- package/dist/chunk-5VL3YPMQ.mjs +406 -0
- package/dist/chunk-C2VGAYER.mjs +295 -0
- package/dist/chunk-FWCSY2DS.mjs +37 -0
- package/dist/index.css +2805 -0
- package/dist/index.d.mts +88 -0
- package/dist/index.d.ts +88 -0
- package/dist/index.js +6787 -0
- package/dist/index.mjs +2869 -0
- package/dist/styles.css +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,887 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__spreadProps,
|
|
3
|
+
__spreadValues
|
|
4
|
+
} from "./chunk-FWCSY2DS.mjs";
|
|
5
|
+
|
|
6
|
+
// app/components/chart-component.tsx
|
|
7
|
+
import {
|
|
8
|
+
Chart as ChartJS,
|
|
9
|
+
CategoryScale,
|
|
10
|
+
LinearScale,
|
|
11
|
+
PointElement,
|
|
12
|
+
LineElement,
|
|
13
|
+
BarElement,
|
|
14
|
+
ArcElement,
|
|
15
|
+
RadialLinearScale,
|
|
16
|
+
Title,
|
|
17
|
+
Tooltip,
|
|
18
|
+
Legend,
|
|
19
|
+
Filler
|
|
20
|
+
} from "chart.js";
|
|
21
|
+
import zoomPlugin from "chartjs-plugin-zoom";
|
|
22
|
+
import {
|
|
23
|
+
Line,
|
|
24
|
+
Bar,
|
|
25
|
+
Pie,
|
|
26
|
+
Doughnut,
|
|
27
|
+
Scatter,
|
|
28
|
+
Radar,
|
|
29
|
+
Bubble,
|
|
30
|
+
PolarArea
|
|
31
|
+
} from "react-chartjs-2";
|
|
32
|
+
import { useState, useEffect, useRef } from "react";
|
|
33
|
+
import { Component } from "react";
|
|
34
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
35
|
+
ChartJS.register(
|
|
36
|
+
CategoryScale,
|
|
37
|
+
LinearScale,
|
|
38
|
+
PointElement,
|
|
39
|
+
LineElement,
|
|
40
|
+
BarElement,
|
|
41
|
+
ArcElement,
|
|
42
|
+
RadialLinearScale,
|
|
43
|
+
Title,
|
|
44
|
+
Tooltip,
|
|
45
|
+
Legend,
|
|
46
|
+
Filler,
|
|
47
|
+
zoomPlugin
|
|
48
|
+
);
|
|
49
|
+
var ChartErrorBoundary = class extends Component {
|
|
50
|
+
constructor(props) {
|
|
51
|
+
super(props);
|
|
52
|
+
this.state = { hasError: false };
|
|
53
|
+
}
|
|
54
|
+
static getDerivedStateFromError(error) {
|
|
55
|
+
var _a, _b;
|
|
56
|
+
console.error("Chart Error Boundary caught an error:", error);
|
|
57
|
+
if (((_a = error.message) == null ? void 0 : _a.includes("cp1x")) || ((_b = error.message) == null ? void 0 : _b.includes("control point"))) {
|
|
58
|
+
console.warn(
|
|
59
|
+
"Chart.js control point error detected - this usually indicates data structure issues"
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
return { hasError: true, error };
|
|
63
|
+
}
|
|
64
|
+
componentDidCatch(error, errorInfo) {
|
|
65
|
+
var _a, _b;
|
|
66
|
+
console.error("Chart Error Boundary caught an error:", error, errorInfo);
|
|
67
|
+
if (((_a = error.message) == null ? void 0 : _a.includes("cp1x")) || ((_b = error.message) == null ? void 0 : _b.includes("control point"))) {
|
|
68
|
+
console.error(
|
|
69
|
+
"This appears to be a Chart.js control point error. Common causes:"
|
|
70
|
+
);
|
|
71
|
+
console.error("- Invalid data structure for line charts");
|
|
72
|
+
console.error("- Missing or null data points");
|
|
73
|
+
console.error("- Improper tension values");
|
|
74
|
+
console.error("- Chart rendered before data validation complete");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
render() {
|
|
78
|
+
if (this.state.hasError) {
|
|
79
|
+
return this.props.fallback;
|
|
80
|
+
}
|
|
81
|
+
return this.props.children;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
function ChartComponent({
|
|
85
|
+
type,
|
|
86
|
+
data,
|
|
87
|
+
theme
|
|
88
|
+
}) {
|
|
89
|
+
const [error, setError] = useState(null);
|
|
90
|
+
const [chartOptions, setChartOptions] = useState({});
|
|
91
|
+
const [isRecovering, setIsRecovering] = useState(false);
|
|
92
|
+
const [renderError, setRenderError] = useState(false);
|
|
93
|
+
const [isReady, setIsReady] = useState(false);
|
|
94
|
+
const chartRef = useRef(null);
|
|
95
|
+
const containerRef = useRef(null);
|
|
96
|
+
const recoveryTimeoutRef = useRef(null);
|
|
97
|
+
const mountedRef = useRef(true);
|
|
98
|
+
const readyTimeoutRef = useRef(null);
|
|
99
|
+
const scrollTimeoutRef = useRef(null);
|
|
100
|
+
const cleanupChart = () => {
|
|
101
|
+
if (chartRef.current) {
|
|
102
|
+
try {
|
|
103
|
+
if (typeof chartRef.current.destroy === "function") {
|
|
104
|
+
chartRef.current.destroy();
|
|
105
|
+
}
|
|
106
|
+
} catch (err) {
|
|
107
|
+
console.warn("Error destroying chart instance:", err);
|
|
108
|
+
}
|
|
109
|
+
chartRef.current = null;
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
var _a;
|
|
114
|
+
if (!((_a = chartRef.current) == null ? void 0 : _a.canvas)) return;
|
|
115
|
+
const canvas = chartRef.current.canvas;
|
|
116
|
+
const blockWheelEvents = (e) => {
|
|
117
|
+
e.preventDefault();
|
|
118
|
+
e.stopPropagation();
|
|
119
|
+
let scrollableParent = canvas.parentElement;
|
|
120
|
+
while (scrollableParent && scrollableParent !== document.body) {
|
|
121
|
+
const style = window.getComputedStyle(scrollableParent);
|
|
122
|
+
if (style.overflowY === "auto" || style.overflowY === "scroll") {
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
scrollableParent = scrollableParent.parentElement;
|
|
126
|
+
}
|
|
127
|
+
const target = scrollableParent || window;
|
|
128
|
+
if (target === window) {
|
|
129
|
+
window.scrollBy(0, e.deltaY);
|
|
130
|
+
} else {
|
|
131
|
+
scrollableParent.scrollTop += e.deltaY;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
canvas.addEventListener("wheel", blockWheelEvents, { passive: false });
|
|
135
|
+
const observer = new MutationObserver((mutations) => {
|
|
136
|
+
mutations.forEach((mutation) => {
|
|
137
|
+
if (mutation.type === "attributes" && mutation.attributeName === "style") {
|
|
138
|
+
canvas.style.position = "static";
|
|
139
|
+
canvas.style.transform = "none";
|
|
140
|
+
canvas.style.willChange = "auto";
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
observer.observe(canvas, {
|
|
145
|
+
attributes: true,
|
|
146
|
+
attributeFilter: ["style"]
|
|
147
|
+
});
|
|
148
|
+
return () => {
|
|
149
|
+
observer.disconnect();
|
|
150
|
+
canvas.removeEventListener("wheel", blockWheelEvents);
|
|
151
|
+
};
|
|
152
|
+
}, [isReady]);
|
|
153
|
+
const recoverFromError = () => {
|
|
154
|
+
if (!mountedRef.current) return;
|
|
155
|
+
setIsRecovering(true);
|
|
156
|
+
setRenderError(false);
|
|
157
|
+
setIsReady(false);
|
|
158
|
+
cleanupChart();
|
|
159
|
+
if (recoveryTimeoutRef.current) {
|
|
160
|
+
clearTimeout(recoveryTimeoutRef.current);
|
|
161
|
+
}
|
|
162
|
+
recoveryTimeoutRef.current = setTimeout(() => {
|
|
163
|
+
if (mountedRef.current) {
|
|
164
|
+
setError(null);
|
|
165
|
+
setIsRecovering(false);
|
|
166
|
+
setTimeout(() => {
|
|
167
|
+
if (mountedRef.current) {
|
|
168
|
+
setIsReady(true);
|
|
169
|
+
}
|
|
170
|
+
}, 100);
|
|
171
|
+
}
|
|
172
|
+
}, 500);
|
|
173
|
+
};
|
|
174
|
+
useEffect(() => {
|
|
175
|
+
mountedRef.current = true;
|
|
176
|
+
readyTimeoutRef.current = setTimeout(() => {
|
|
177
|
+
if (mountedRef.current) {
|
|
178
|
+
setIsReady(true);
|
|
179
|
+
}
|
|
180
|
+
}, 50);
|
|
181
|
+
return () => {
|
|
182
|
+
mountedRef.current = false;
|
|
183
|
+
cleanupChart();
|
|
184
|
+
if (recoveryTimeoutRef.current) {
|
|
185
|
+
clearTimeout(recoveryTimeoutRef.current);
|
|
186
|
+
}
|
|
187
|
+
if (readyTimeoutRef.current) {
|
|
188
|
+
clearTimeout(readyTimeoutRef.current);
|
|
189
|
+
}
|
|
190
|
+
if (scrollTimeoutRef.current) {
|
|
191
|
+
clearTimeout(scrollTimeoutRef.current);
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}, []);
|
|
195
|
+
const getThemeColors = (currentTheme) => {
|
|
196
|
+
const isDark = currentTheme === "dark" || !currentTheme && document.documentElement.classList.contains("dark");
|
|
197
|
+
return {
|
|
198
|
+
textColor: isDark ? "white" : "black",
|
|
199
|
+
tickColor: isDark ? "rgba(255, 255, 255, 0.7)" : "rgba(0, 0, 0, 0.7)",
|
|
200
|
+
gridColor: isDark ? "rgba(255, 255, 255, 0.1)" : "rgba(0, 0, 0, 0.1)"
|
|
201
|
+
};
|
|
202
|
+
};
|
|
203
|
+
useEffect(() => {
|
|
204
|
+
if (isRecovering) return;
|
|
205
|
+
setError(null);
|
|
206
|
+
try {
|
|
207
|
+
if (!data || !data.data) {
|
|
208
|
+
setError("Chart data missing required 'data' property");
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
const sanitizedData = JSON.parse(JSON.stringify(data.data));
|
|
212
|
+
const chartType = type.toLowerCase();
|
|
213
|
+
if (["line", "bar", "area"].includes(chartType)) {
|
|
214
|
+
if (!sanitizedData.labels || !Array.isArray(sanitizedData.labels)) {
|
|
215
|
+
setError("Missing or invalid 'labels' array for this chart type");
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (!sanitizedData.datasets || !Array.isArray(sanitizedData.datasets)) {
|
|
219
|
+
setError("Missing or invalid 'datasets' array for this chart type");
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
for (let i = 0; i < sanitizedData.datasets.length; i++) {
|
|
223
|
+
const dataset = sanitizedData.datasets[i];
|
|
224
|
+
if (!dataset.data || !Array.isArray(dataset.data)) {
|
|
225
|
+
setError(`Dataset ${i + 1} missing or invalid data array`);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
if (chartType === "line" || chartType === "area") {
|
|
229
|
+
if (dataset.data.length < 2) {
|
|
230
|
+
setError(
|
|
231
|
+
`Line charts require at least 2 data points. Dataset ${i + 1} has ${dataset.data.length} points.`
|
|
232
|
+
);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const validData = dataset.data.map((point, index) => {
|
|
237
|
+
if (typeof point === "number" && !isNaN(point) && isFinite(point)) {
|
|
238
|
+
return point;
|
|
239
|
+
} else if (typeof point === "object" && point !== null) {
|
|
240
|
+
if (typeof point.y === "number" && isFinite(point.y)) {
|
|
241
|
+
return {
|
|
242
|
+
x: point.x !== void 0 ? point.x : index,
|
|
243
|
+
y: point.y
|
|
244
|
+
};
|
|
245
|
+
} else if (typeof point.x === "number" && typeof point.y === "number") {
|
|
246
|
+
return {
|
|
247
|
+
x: isFinite(point.x) ? point.x : index,
|
|
248
|
+
y: isFinite(point.y) ? point.y : 0
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return 0;
|
|
253
|
+
});
|
|
254
|
+
dataset.data = validData;
|
|
255
|
+
if (chartType === "line" || chartType === "area") {
|
|
256
|
+
if (typeof dataset.tension !== "number" || isNaN(dataset.tension) || !isFinite(dataset.tension)) {
|
|
257
|
+
dataset.tension = 0.1;
|
|
258
|
+
} else {
|
|
259
|
+
dataset.tension = Math.max(0, Math.min(1, dataset.tension));
|
|
260
|
+
}
|
|
261
|
+
if (!dataset.borderColor) {
|
|
262
|
+
dataset.borderColor = "#4BC0C0";
|
|
263
|
+
}
|
|
264
|
+
if (chartType === "area" && !dataset.backgroundColor) {
|
|
265
|
+
dataset.backgroundColor = "rgba(75, 192, 192, 0.2)";
|
|
266
|
+
}
|
|
267
|
+
Object.keys(dataset).forEach((key) => {
|
|
268
|
+
if (dataset[key] === void 0 || dataset[key] === null) {
|
|
269
|
+
delete dataset[key];
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
if (dataset.fill !== void 0 && typeof dataset.fill === "string") {
|
|
274
|
+
const validFillValues = ["origin", "start", "end", "stack"];
|
|
275
|
+
if (!validFillValues.includes(dataset.fill) && !dataset.fill.match(/^\d+$/)) {
|
|
276
|
+
dataset.fill = true;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
const maxDataLength = Math.max(
|
|
281
|
+
...sanitizedData.datasets.map((d) => d.data.length)
|
|
282
|
+
);
|
|
283
|
+
if (sanitizedData.labels.length !== maxDataLength) {
|
|
284
|
+
console.warn(
|
|
285
|
+
"Labels length does not match data length, adjusting..."
|
|
286
|
+
);
|
|
287
|
+
if (sanitizedData.labels.length < maxDataLength) {
|
|
288
|
+
for (let i = sanitizedData.labels.length; i < maxDataLength; i++) {
|
|
289
|
+
sanitizedData.labels.push(`Point ${i + 1}`);
|
|
290
|
+
}
|
|
291
|
+
} else {
|
|
292
|
+
sanitizedData.labels = sanitizedData.labels.slice(0, maxDataLength);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
sanitizedData.labels = sanitizedData.labels.map(
|
|
296
|
+
(label, index) => {
|
|
297
|
+
if (typeof label === "string") return label;
|
|
298
|
+
if (typeof label === "number") return label.toString();
|
|
299
|
+
return `Label ${index + 1}`;
|
|
300
|
+
}
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
if (["pie", "doughnut", "polararea"].includes(chartType)) {
|
|
304
|
+
if (!sanitizedData.datasets || !Array.isArray(sanitizedData.datasets) || sanitizedData.datasets.length === 0) {
|
|
305
|
+
setError("Missing dataset information for this chart type");
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
if (chartType === "polararea") {
|
|
309
|
+
for (let i = 0; i < sanitizedData.datasets.length; i++) {
|
|
310
|
+
const dataset = sanitizedData.datasets[i];
|
|
311
|
+
if (!dataset.data || !Array.isArray(dataset.data)) {
|
|
312
|
+
setError(
|
|
313
|
+
`Polar area chart dataset ${i + 1} missing or invalid data array`
|
|
314
|
+
);
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
const validData = dataset.data.map((point) => {
|
|
318
|
+
if (typeof point === "number" && !isNaN(point) && isFinite(point)) {
|
|
319
|
+
return Math.max(0, point);
|
|
320
|
+
}
|
|
321
|
+
return 0;
|
|
322
|
+
});
|
|
323
|
+
dataset.data = validData;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (chartType === "scatter" && (!sanitizedData.datasets || !Array.isArray(sanitizedData.datasets))) {
|
|
328
|
+
setError("Missing or invalid dataset for scatter chart");
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
if (chartType === "bubble") {
|
|
332
|
+
if (!sanitizedData.datasets || !Array.isArray(sanitizedData.datasets)) {
|
|
333
|
+
setError("Missing or invalid dataset for bubble chart");
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
for (let i = 0; i < sanitizedData.datasets.length; i++) {
|
|
337
|
+
const dataset = sanitizedData.datasets[i];
|
|
338
|
+
if (!dataset.data || !Array.isArray(dataset.data)) {
|
|
339
|
+
setError(
|
|
340
|
+
`Bubble chart dataset ${i + 1} missing or invalid data array`
|
|
341
|
+
);
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
const validBubbleData = dataset.data.map(
|
|
345
|
+
(point, index) => {
|
|
346
|
+
if (typeof point === "object" && point !== null) {
|
|
347
|
+
const x = typeof point.x === "number" && isFinite(point.x) ? point.x : index;
|
|
348
|
+
const y = typeof point.y === "number" && isFinite(point.y) ? point.y : 0;
|
|
349
|
+
const r = typeof point.r === "number" && isFinite(point.r) && point.r > 0 ? point.r : 5;
|
|
350
|
+
return { x, y, r };
|
|
351
|
+
}
|
|
352
|
+
return { x: index, y: 0, r: 5 };
|
|
353
|
+
}
|
|
354
|
+
);
|
|
355
|
+
dataset.data = validBubbleData;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
if (sanitizedData.datasets && sanitizedData.datasets.length === 0) {
|
|
359
|
+
setError("No data to display in chart");
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
if (sanitizedData.datasets) {
|
|
363
|
+
for (const dataset of sanitizedData.datasets) {
|
|
364
|
+
if (!dataset.data || !Array.isArray(dataset.data) && typeof dataset.data !== "object") {
|
|
365
|
+
setError("Invalid dataset data structure");
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
data.data = sanitizedData;
|
|
371
|
+
} catch (err) {
|
|
372
|
+
setError("An error occurred while processing chart data");
|
|
373
|
+
console.error("Chart validation error:", err);
|
|
374
|
+
setTimeout(recoverFromError, 500);
|
|
375
|
+
}
|
|
376
|
+
}, [type, data, isRecovering]);
|
|
377
|
+
useEffect(() => {
|
|
378
|
+
var _a, _b, _c, _d;
|
|
379
|
+
const colors = getThemeColors(theme);
|
|
380
|
+
const newOptions = {
|
|
381
|
+
responsive: true,
|
|
382
|
+
maintainAspectRatio: false,
|
|
383
|
+
resizeDelay: 50,
|
|
384
|
+
devicePixelRatio: window.devicePixelRatio || 1,
|
|
385
|
+
animation: false,
|
|
386
|
+
events: ["mousemove", "mouseout", "click", "touchstart", "touchmove"],
|
|
387
|
+
onResize: (chart) => {
|
|
388
|
+
if (chart && chart.canvas) {
|
|
389
|
+
chart.canvas.style.position = "static";
|
|
390
|
+
chart.canvas.style.display = "block";
|
|
391
|
+
chart.canvas.style.transform = "none";
|
|
392
|
+
chart.canvas.style.willChange = "auto";
|
|
393
|
+
}
|
|
394
|
+
},
|
|
395
|
+
plugins: {
|
|
396
|
+
legend: {
|
|
397
|
+
position: "top",
|
|
398
|
+
labels: {
|
|
399
|
+
color: colors.textColor,
|
|
400
|
+
boxWidth: 12,
|
|
401
|
+
padding: 15,
|
|
402
|
+
font: {
|
|
403
|
+
size: 12
|
|
404
|
+
},
|
|
405
|
+
usePointStyle: true
|
|
406
|
+
}
|
|
407
|
+
},
|
|
408
|
+
title: {
|
|
409
|
+
display: true,
|
|
410
|
+
text: ((_c = (_b = (_a = data.options) == null ? void 0 : _a.plugins) == null ? void 0 : _b.title) == null ? void 0 : _c.text) || "Chart",
|
|
411
|
+
color: colors.textColor,
|
|
412
|
+
font: {
|
|
413
|
+
size: 14,
|
|
414
|
+
weight: "bold"
|
|
415
|
+
},
|
|
416
|
+
padding: {
|
|
417
|
+
top: 10,
|
|
418
|
+
bottom: 10
|
|
419
|
+
}
|
|
420
|
+
},
|
|
421
|
+
zoom: {
|
|
422
|
+
zoom: {
|
|
423
|
+
wheel: {
|
|
424
|
+
enabled: false
|
|
425
|
+
},
|
|
426
|
+
pinch: {
|
|
427
|
+
enabled: false
|
|
428
|
+
},
|
|
429
|
+
mode: "xy"
|
|
430
|
+
},
|
|
431
|
+
pan: {
|
|
432
|
+
enabled: false
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
},
|
|
436
|
+
elements: {
|
|
437
|
+
point: {
|
|
438
|
+
hoverRadius: 6,
|
|
439
|
+
radius: 3
|
|
440
|
+
},
|
|
441
|
+
line: {
|
|
442
|
+
tension: 0.1
|
|
443
|
+
}
|
|
444
|
+
},
|
|
445
|
+
interaction: {
|
|
446
|
+
intersect: false,
|
|
447
|
+
mode: "index",
|
|
448
|
+
includeInvisible: false
|
|
449
|
+
},
|
|
450
|
+
scales: {
|
|
451
|
+
x: {
|
|
452
|
+
ticks: {
|
|
453
|
+
color: colors.tickColor,
|
|
454
|
+
maxRotation: 45,
|
|
455
|
+
minRotation: 0,
|
|
456
|
+
autoSkip: true,
|
|
457
|
+
autoSkipPadding: 5
|
|
458
|
+
},
|
|
459
|
+
grid: {
|
|
460
|
+
color: colors.gridColor
|
|
461
|
+
}
|
|
462
|
+
},
|
|
463
|
+
y: {
|
|
464
|
+
ticks: {
|
|
465
|
+
color: colors.tickColor
|
|
466
|
+
},
|
|
467
|
+
grid: {
|
|
468
|
+
color: colors.gridColor
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
},
|
|
472
|
+
layout: {
|
|
473
|
+
padding: {
|
|
474
|
+
left: 10,
|
|
475
|
+
right: 10,
|
|
476
|
+
top: 0,
|
|
477
|
+
bottom: 5
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
const finalOptions = __spreadProps(__spreadValues(__spreadValues({}, newOptions), data.options), {
|
|
482
|
+
plugins: __spreadValues(__spreadValues({}, newOptions.plugins), (_d = data.options) == null ? void 0 : _d.plugins)
|
|
483
|
+
});
|
|
484
|
+
setChartOptions(finalOptions);
|
|
485
|
+
}, [theme, data]);
|
|
486
|
+
const renderChart = () => {
|
|
487
|
+
var _a, _b, _c, _d;
|
|
488
|
+
if (renderError) {
|
|
489
|
+
return /* @__PURE__ */ jsxs("div", { className: "p-6 bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-300 rounded-lg border border-red-100 dark:border-red-800", children: [
|
|
490
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 mb-2", children: [
|
|
491
|
+
/* @__PURE__ */ jsx(
|
|
492
|
+
"svg",
|
|
493
|
+
{
|
|
494
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
495
|
+
className: "h-5 w-5",
|
|
496
|
+
viewBox: "0 0 20 20",
|
|
497
|
+
fill: "currentColor",
|
|
498
|
+
children: /* @__PURE__ */ jsx(
|
|
499
|
+
"path",
|
|
500
|
+
{
|
|
501
|
+
fillRule: "evenodd",
|
|
502
|
+
d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z",
|
|
503
|
+
clipRule: "evenodd"
|
|
504
|
+
}
|
|
505
|
+
)
|
|
506
|
+
}
|
|
507
|
+
),
|
|
508
|
+
/* @__PURE__ */ jsx("h3", { className: "font-medium", children: "Chart rendering failed" })
|
|
509
|
+
] }),
|
|
510
|
+
/* @__PURE__ */ jsx("p", { className: "ml-8 text-sm mb-3", children: "The chart could not be rendered due to a technical error." }),
|
|
511
|
+
/* @__PURE__ */ jsx(
|
|
512
|
+
"button",
|
|
513
|
+
{
|
|
514
|
+
onClick: recoverFromError,
|
|
515
|
+
className: "ml-8 px-3 py-1 text-xs bg-red-100 dark:bg-red-800 text-red-700 dark:text-red-200 rounded hover:bg-red-200 dark:hover:bg-red-700 transition-colors",
|
|
516
|
+
disabled: isRecovering,
|
|
517
|
+
children: isRecovering ? "Recovering..." : "Try Again"
|
|
518
|
+
}
|
|
519
|
+
)
|
|
520
|
+
] });
|
|
521
|
+
}
|
|
522
|
+
if (!data || !data.data || !chartOptions) {
|
|
523
|
+
return null;
|
|
524
|
+
}
|
|
525
|
+
try {
|
|
526
|
+
const safeChartData = JSON.parse(JSON.stringify(data.data));
|
|
527
|
+
const safeChartOptions = JSON.parse(JSON.stringify(chartOptions));
|
|
528
|
+
if (type.toLowerCase() === "line" || type.toLowerCase() === "area") {
|
|
529
|
+
safeChartData.datasets = safeChartData.datasets.map((dataset) => __spreadProps(__spreadValues({}, dataset), {
|
|
530
|
+
tension: typeof dataset.tension === "number" && isFinite(dataset.tension) ? dataset.tension : 0.1,
|
|
531
|
+
borderColor: dataset.borderColor || "#4BC0C0",
|
|
532
|
+
pointRadius: dataset.pointRadius !== void 0 ? dataset.pointRadius : 3,
|
|
533
|
+
pointHoverRadius: dataset.pointHoverRadius !== void 0 ? dataset.pointHoverRadius : 6,
|
|
534
|
+
spanGaps: true
|
|
535
|
+
// This helps with missing data points
|
|
536
|
+
}));
|
|
537
|
+
safeChartOptions.scales = __spreadProps(__spreadValues({}, safeChartOptions.scales), {
|
|
538
|
+
x: __spreadProps(__spreadValues({}, (_a = safeChartOptions.scales) == null ? void 0 : _a.x), {
|
|
539
|
+
type: "category"
|
|
540
|
+
}),
|
|
541
|
+
y: __spreadProps(__spreadValues({}, (_b = safeChartOptions.scales) == null ? void 0 : _b.y), {
|
|
542
|
+
type: "linear"
|
|
543
|
+
})
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
switch (type.toLowerCase()) {
|
|
547
|
+
case "line":
|
|
548
|
+
return /* @__PURE__ */ jsx(
|
|
549
|
+
Line,
|
|
550
|
+
{
|
|
551
|
+
ref: chartRef,
|
|
552
|
+
data: safeChartData,
|
|
553
|
+
options: safeChartOptions,
|
|
554
|
+
style: {
|
|
555
|
+
width: "100%",
|
|
556
|
+
height: "100%",
|
|
557
|
+
display: "block",
|
|
558
|
+
position: "static"
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
);
|
|
562
|
+
case "bar":
|
|
563
|
+
return /* @__PURE__ */ jsx(
|
|
564
|
+
Bar,
|
|
565
|
+
{
|
|
566
|
+
ref: chartRef,
|
|
567
|
+
data: safeChartData,
|
|
568
|
+
options: safeChartOptions,
|
|
569
|
+
style: {
|
|
570
|
+
width: "100%",
|
|
571
|
+
height: "100%",
|
|
572
|
+
display: "block",
|
|
573
|
+
position: "static"
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
);
|
|
577
|
+
case "pie":
|
|
578
|
+
return /* @__PURE__ */ jsx(
|
|
579
|
+
Pie,
|
|
580
|
+
{
|
|
581
|
+
ref: chartRef,
|
|
582
|
+
data: safeChartData,
|
|
583
|
+
options: safeChartOptions,
|
|
584
|
+
style: {
|
|
585
|
+
width: "100%",
|
|
586
|
+
height: "100%",
|
|
587
|
+
display: "block",
|
|
588
|
+
position: "static"
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
);
|
|
592
|
+
case "doughnut":
|
|
593
|
+
return /* @__PURE__ */ jsx(
|
|
594
|
+
Doughnut,
|
|
595
|
+
{
|
|
596
|
+
ref: chartRef,
|
|
597
|
+
data: safeChartData,
|
|
598
|
+
options: safeChartOptions,
|
|
599
|
+
style: {
|
|
600
|
+
width: "100%",
|
|
601
|
+
height: "100%",
|
|
602
|
+
display: "block",
|
|
603
|
+
position: "static"
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
);
|
|
607
|
+
case "polararea":
|
|
608
|
+
return /* @__PURE__ */ jsx(
|
|
609
|
+
PolarArea,
|
|
610
|
+
{
|
|
611
|
+
ref: chartRef,
|
|
612
|
+
data: safeChartData,
|
|
613
|
+
options: safeChartOptions,
|
|
614
|
+
style: {
|
|
615
|
+
width: "100%",
|
|
616
|
+
height: "100%",
|
|
617
|
+
display: "block",
|
|
618
|
+
position: "static"
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
);
|
|
622
|
+
case "scatter":
|
|
623
|
+
return /* @__PURE__ */ jsx(
|
|
624
|
+
Scatter,
|
|
625
|
+
{
|
|
626
|
+
ref: chartRef,
|
|
627
|
+
data: safeChartData,
|
|
628
|
+
options: safeChartOptions,
|
|
629
|
+
style: {
|
|
630
|
+
width: "100%",
|
|
631
|
+
height: "100%",
|
|
632
|
+
display: "block",
|
|
633
|
+
position: "static"
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
);
|
|
637
|
+
case "bubble":
|
|
638
|
+
return /* @__PURE__ */ jsx(
|
|
639
|
+
Bubble,
|
|
640
|
+
{
|
|
641
|
+
ref: chartRef,
|
|
642
|
+
data: safeChartData,
|
|
643
|
+
options: safeChartOptions,
|
|
644
|
+
style: {
|
|
645
|
+
width: "100%",
|
|
646
|
+
height: "100%",
|
|
647
|
+
display: "block",
|
|
648
|
+
position: "static"
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
);
|
|
652
|
+
case "radar":
|
|
653
|
+
return /* @__PURE__ */ jsx(
|
|
654
|
+
Radar,
|
|
655
|
+
{
|
|
656
|
+
ref: chartRef,
|
|
657
|
+
data: safeChartData,
|
|
658
|
+
options: safeChartOptions,
|
|
659
|
+
style: {
|
|
660
|
+
width: "100%",
|
|
661
|
+
height: "100%",
|
|
662
|
+
display: "block",
|
|
663
|
+
position: "static"
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
);
|
|
667
|
+
case "area":
|
|
668
|
+
const areaData = __spreadProps(__spreadValues({}, safeChartData), {
|
|
669
|
+
datasets: safeChartData.datasets.map((dataset) => __spreadProps(__spreadValues({}, dataset), {
|
|
670
|
+
fill: true,
|
|
671
|
+
backgroundColor: dataset.backgroundColor || "rgba(75, 192, 192, 0.2)",
|
|
672
|
+
borderColor: dataset.borderColor || "rgba(75, 192, 192, 1)",
|
|
673
|
+
tension: typeof dataset.tension === "number" && isFinite(dataset.tension) ? dataset.tension : 0.4,
|
|
674
|
+
pointRadius: dataset.pointRadius !== void 0 ? dataset.pointRadius : 3,
|
|
675
|
+
pointHoverRadius: dataset.pointHoverRadius !== void 0 ? dataset.pointHoverRadius : 6,
|
|
676
|
+
spanGaps: true
|
|
677
|
+
}))
|
|
678
|
+
});
|
|
679
|
+
return /* @__PURE__ */ jsx(
|
|
680
|
+
Line,
|
|
681
|
+
{
|
|
682
|
+
ref: chartRef,
|
|
683
|
+
data: areaData,
|
|
684
|
+
options: safeChartOptions,
|
|
685
|
+
style: {
|
|
686
|
+
width: "100%",
|
|
687
|
+
height: "100%",
|
|
688
|
+
display: "block",
|
|
689
|
+
position: "static"
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
);
|
|
693
|
+
default:
|
|
694
|
+
return /* @__PURE__ */ jsxs("div", { className: "p-6 bg-amber-50 dark:bg-amber-900/20 text-amber-600 dark:text-amber-300 rounded-lg border border-amber-100 dark:border-amber-800 w-full max-w-full", children: [
|
|
695
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
696
|
+
/* @__PURE__ */ jsx(
|
|
697
|
+
"svg",
|
|
698
|
+
{
|
|
699
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
700
|
+
className: "h-5 w-5",
|
|
701
|
+
viewBox: "0 0 20 20",
|
|
702
|
+
fill: "currentColor",
|
|
703
|
+
children: /* @__PURE__ */ jsx(
|
|
704
|
+
"path",
|
|
705
|
+
{
|
|
706
|
+
fillRule: "evenodd",
|
|
707
|
+
d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v4a1 1 0 002 0V6a1 1 0 00-1-1z",
|
|
708
|
+
clipRule: "evenodd"
|
|
709
|
+
}
|
|
710
|
+
)
|
|
711
|
+
}
|
|
712
|
+
),
|
|
713
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
714
|
+
"Unsupported chart type: ",
|
|
715
|
+
type
|
|
716
|
+
] })
|
|
717
|
+
] }),
|
|
718
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm mt-2 ml-8", children: "Supported types: line, bar, pie, doughnut, polararea, scatter, bubble, radar, area" })
|
|
719
|
+
] });
|
|
720
|
+
}
|
|
721
|
+
} catch (renderError2) {
|
|
722
|
+
console.error("Chart rendering error:", renderError2);
|
|
723
|
+
if (((_c = renderError2.message) == null ? void 0 : _c.includes("cp1x")) || ((_d = renderError2.message) == null ? void 0 : _d.includes("control point"))) {
|
|
724
|
+
console.error(
|
|
725
|
+
"Chart.js control point error detected during render. Chart data:",
|
|
726
|
+
JSON.stringify(data, null, 2)
|
|
727
|
+
);
|
|
728
|
+
setError(
|
|
729
|
+
"Chart rendering failed due to data structure issues. Please check your data format."
|
|
730
|
+
);
|
|
731
|
+
} else {
|
|
732
|
+
console.error("General chart rendering error:", renderError2.message);
|
|
733
|
+
setRenderError(true);
|
|
734
|
+
}
|
|
735
|
+
return null;
|
|
736
|
+
}
|
|
737
|
+
};
|
|
738
|
+
const ErrorFallback = () => /* @__PURE__ */ jsx("div", { className: "w-full h-64 md:h-96 max-w-full overflow-hidden flex items-center justify-center bg-red-50 dark:bg-red-900/20 rounded-lg border border-red-100 dark:border-red-800", children: /* @__PURE__ */ jsxs("div", { className: "text-center p-6", children: [
|
|
739
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-3 mb-3 text-red-600 dark:text-red-300", children: [
|
|
740
|
+
/* @__PURE__ */ jsx(
|
|
741
|
+
"svg",
|
|
742
|
+
{
|
|
743
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
744
|
+
className: "h-8 w-8",
|
|
745
|
+
viewBox: "0 0 20 20",
|
|
746
|
+
fill: "currentColor",
|
|
747
|
+
children: /* @__PURE__ */ jsx(
|
|
748
|
+
"path",
|
|
749
|
+
{
|
|
750
|
+
fillRule: "evenodd",
|
|
751
|
+
d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z",
|
|
752
|
+
clipRule: "evenodd"
|
|
753
|
+
}
|
|
754
|
+
)
|
|
755
|
+
}
|
|
756
|
+
),
|
|
757
|
+
/* @__PURE__ */ jsx("h3", { className: "font-medium text-lg", children: "Chart Error" })
|
|
758
|
+
] }),
|
|
759
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm text-red-600 dark:text-red-300 mb-4", children: [
|
|
760
|
+
"Something went wrong while rendering the ",
|
|
761
|
+
type,
|
|
762
|
+
" chart."
|
|
763
|
+
] }),
|
|
764
|
+
/* @__PURE__ */ jsx(
|
|
765
|
+
"button",
|
|
766
|
+
{
|
|
767
|
+
onClick: recoverFromError,
|
|
768
|
+
className: "px-4 py-2 text-sm bg-red-100 dark:bg-red-800 text-red-700 dark:text-red-200 rounded hover:bg-red-200 dark:hover:bg-red-700 transition-colors",
|
|
769
|
+
disabled: isRecovering,
|
|
770
|
+
children: isRecovering ? "Recovering..." : "Try Again"
|
|
771
|
+
}
|
|
772
|
+
)
|
|
773
|
+
] }) });
|
|
774
|
+
const MainChart = () => {
|
|
775
|
+
if (error) {
|
|
776
|
+
return /* @__PURE__ */ jsxs("div", { className: "p-6 bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-300 rounded-lg border border-red-100 dark:border-red-800 w-full max-w-full", children: [
|
|
777
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 mb-2", children: [
|
|
778
|
+
/* @__PURE__ */ jsx(
|
|
779
|
+
"svg",
|
|
780
|
+
{
|
|
781
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
782
|
+
className: "h-5 w-5",
|
|
783
|
+
viewBox: "0 0 20 20",
|
|
784
|
+
fill: "currentColor",
|
|
785
|
+
children: /* @__PURE__ */ jsx(
|
|
786
|
+
"path",
|
|
787
|
+
{
|
|
788
|
+
fillRule: "evenodd",
|
|
789
|
+
d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z",
|
|
790
|
+
clipRule: "evenodd"
|
|
791
|
+
}
|
|
792
|
+
)
|
|
793
|
+
}
|
|
794
|
+
),
|
|
795
|
+
/* @__PURE__ */ jsx("h3", { className: "font-medium", children: "Chart data issue" })
|
|
796
|
+
] }),
|
|
797
|
+
/* @__PURE__ */ jsx("p", { className: "ml-8 text-sm mb-3", children: error }),
|
|
798
|
+
/* @__PURE__ */ jsx(
|
|
799
|
+
"button",
|
|
800
|
+
{
|
|
801
|
+
onClick: recoverFromError,
|
|
802
|
+
className: "ml-8 px-3 py-1 text-xs bg-red-100 dark:bg-red-800 text-red-700 dark:text-red-200 rounded hover:bg-red-200 dark:hover:bg-red-700 transition-colors",
|
|
803
|
+
disabled: isRecovering,
|
|
804
|
+
children: isRecovering ? "Recovering..." : "Try Again"
|
|
805
|
+
}
|
|
806
|
+
)
|
|
807
|
+
] });
|
|
808
|
+
}
|
|
809
|
+
if (isRecovering || !isReady) {
|
|
810
|
+
return /* @__PURE__ */ jsx("div", { className: "w-full h-64 md:h-96 max-w-full overflow-hidden flex items-center justify-center bg-gray-50 dark:bg-gray-800 rounded-lg", children: /* @__PURE__ */ jsxs("div", { className: "text-gray-500 dark:text-gray-400", children: [
|
|
811
|
+
/* @__PURE__ */ jsxs(
|
|
812
|
+
"svg",
|
|
813
|
+
{
|
|
814
|
+
className: "animate-spin h-8 w-8 mx-auto mb-2",
|
|
815
|
+
fill: "none",
|
|
816
|
+
viewBox: "0 0 24 24",
|
|
817
|
+
children: [
|
|
818
|
+
/* @__PURE__ */ jsx(
|
|
819
|
+
"circle",
|
|
820
|
+
{
|
|
821
|
+
className: "opacity-25",
|
|
822
|
+
cx: "12",
|
|
823
|
+
cy: "12",
|
|
824
|
+
r: "10",
|
|
825
|
+
stroke: "currentColor",
|
|
826
|
+
strokeWidth: "4"
|
|
827
|
+
}
|
|
828
|
+
),
|
|
829
|
+
/* @__PURE__ */ jsx(
|
|
830
|
+
"path",
|
|
831
|
+
{
|
|
832
|
+
className: "opacity-75",
|
|
833
|
+
fill: "currentColor",
|
|
834
|
+
d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
835
|
+
}
|
|
836
|
+
)
|
|
837
|
+
]
|
|
838
|
+
}
|
|
839
|
+
),
|
|
840
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm", children: isRecovering ? "Recovering chart..." : "Initializing chart..." })
|
|
841
|
+
] }) });
|
|
842
|
+
}
|
|
843
|
+
try {
|
|
844
|
+
return /* @__PURE__ */ jsx(
|
|
845
|
+
"div",
|
|
846
|
+
{
|
|
847
|
+
ref: containerRef,
|
|
848
|
+
className: "w-full h-64 md:h-96 max-w-full overflow-hidden relative isolate",
|
|
849
|
+
style: {
|
|
850
|
+
contain: "layout style paint",
|
|
851
|
+
overscrollBehavior: "contain",
|
|
852
|
+
scrollSnapAlign: "start",
|
|
853
|
+
scrollMargin: "1rem",
|
|
854
|
+
isolation: "isolate"
|
|
855
|
+
},
|
|
856
|
+
children: /* @__PURE__ */ jsx(
|
|
857
|
+
"div",
|
|
858
|
+
{
|
|
859
|
+
className: "w-full h-full",
|
|
860
|
+
style: {
|
|
861
|
+
contain: "layout style paint",
|
|
862
|
+
display: "block",
|
|
863
|
+
position: "static",
|
|
864
|
+
width: "100%",
|
|
865
|
+
height: "100%"
|
|
866
|
+
},
|
|
867
|
+
children: renderChart()
|
|
868
|
+
}
|
|
869
|
+
)
|
|
870
|
+
}
|
|
871
|
+
);
|
|
872
|
+
} catch (err) {
|
|
873
|
+
console.error("Main chart render error:", err);
|
|
874
|
+
setRenderError(true);
|
|
875
|
+
return /* @__PURE__ */ jsx(ErrorFallback, {});
|
|
876
|
+
}
|
|
877
|
+
};
|
|
878
|
+
try {
|
|
879
|
+
return /* @__PURE__ */ jsx(ChartErrorBoundary, { fallback: /* @__PURE__ */ jsx(ErrorFallback, {}), children: /* @__PURE__ */ jsx(MainChart, {}) });
|
|
880
|
+
} catch (err) {
|
|
881
|
+
console.error("Error rendering chart:", err);
|
|
882
|
+
return /* @__PURE__ */ jsx(ErrorFallback, {});
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
export {
|
|
886
|
+
ChartComponent as default
|
|
887
|
+
};
|