@coinmeca/ui
Version:
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
157 lines • 6.1 kB
JSX
"use client";
import { Chart } from "chart.js/auto";
import { Suspense, useEffect, useRef, useState } from "react";
export default function ChartJS(props) {
const chartRef = useRef(null);
const [data, setData] = useState();
const key = {
time: typeof props?.field === "object" ? props?.field.time : "time",
value: typeof props?.field === "object" ? props?.field.value : typeof props?.field === "string" ? props?.field : "value",
};
const theme = props?.color?.theme && props?.color?.theme === "light" ? "0,0,0" : "255,255,255";
const color = {
default: props?.color?.default ? `rgb(${props?.color?.default})` : `rgb(${theme})`,
theme: {
strong: `rgba(${theme}, 0.6)`,
semi: `rgba(${theme}, 0.45)`,
medium: `rgba(${theme}, 0.3)`,
regular: `rgba(${theme}, 0.15)`,
light: `rgba(${theme}, 0.05)`,
},
};
const initial = 8;
const padding = {
top: props?.padding && (typeof props?.padding[0] === "number" ? props?.padding[0] : initial),
right: props?.padding &&
(props?.padding?.length === 1
? typeof props?.padding[0] === "number"
? props?.padding[0]
: initial
: props?.padding?.length > 1 && typeof props?.padding[1] === "number"
? props?.padding[1]
: initial),
bottom: props?.padding &&
(props?.padding?.length === 1
? typeof props?.padding[0] === "number"
? props?.padding[0]
: initial
: props?.padding?.length > 2 && typeof props?.padding[2] === "number"
? props?.padding[2]
: initial),
left: props?.padding &&
(props?.padding?.length === 1
? typeof props?.padding[0] === "number"
? props?.padding[0]
: initial
: props?.padding?.length > 3 && typeof props?.padding[3] === "number"
? props?.padding[3]
: props?.padding?.length > 1 && typeof props?.padding[1] === "number"
? props?.padding[1]
: initial),
};
const options = {
responsive: true,
maintainAspectRatio: false,
layout: {
padding,
},
scales: {
x: {
display: false,
},
y: {
display: false,
beginAtZero: true,
},
},
interaction: {
// mode: 'nearest',
// position: 'nearest',
includeInvisible: true,
intersect: false,
},
plugins: {
legend: {
display: false,
},
title: {
display: true,
},
tooltip: {
enabled: true,
padding: 0,
borderColor: "transparent",
backgroundColor: "transparent",
callbacks: {
// labelPointStyle: (context) => {
// return {
// pointStyle: 'triangle',
// rotation: 0
// };
// },
label: (value) => {
if (typeof props?.onHover === "function")
props?.onHover(value);
return "";
},
title: () => {
return "";
},
},
},
},
};
useEffect(() => {
if (props?.data && props?.data?.length > 0) {
setData({
labels: props?.data?.map((data) => data?.[key?.time]),
datasets: [
{
data: props?.data?.map((data) => data?.[key?.value]),
borderColor: color.theme.medium,
pointBorderColor: "transparent",
pointBackgroundColor: color.theme.strong,
pointHoverBackgroundColor: `rgb(${theme})`,
pointRadius: 2,
pointHoverRadius: 4,
...(props?.type !== "line" && { backgroundColor: color.theme.regular }),
...(props?.type === "bar" && { hoverBackgroundColor: color.theme.strong }),
},
],
});
}
}, [props?.data]);
useEffect(() => {
if (chartRef?.current) {
const chart = new Chart(chartRef?.current?.getContext("2d"), {
type: props?.type,
data,
options,
});
chart.resize();
chart.canvas?.addEventListener("resize", () => chart.resize());
chart.canvas?.addEventListener("mouseout", (e) => {
const meta = chart.getDatasetMeta(0); // Assuming you're working with the first dataset
const last = meta.data.length - 1; // Index of the last data point
if (meta.data[last]) {
const eventPosition = {
x: meta.data[last].x,
y: meta.data[last].y,
};
// Set active elements to focus on the last data point
chart.tooltip?.setActiveElements([{ datasetIndex: 0, index: last }], eventPosition);
chart.update();
}
if (typeof props?.onLeave === "function")
props?.onLeave(e, meta);
});
return () => {
chart.destroy();
};
}
}, [props?.type, chartRef, data]);
return (<Suspense fallback={props?.fallback || <div>Loading...</div>}>
<canvas ref={chartRef}/>
</Suspense>);
}
//# sourceMappingURL=ChartJS.jsx.map