add charts
This commit is contained in:
parent
e09ca57c61
commit
bf2745b4e1
|
|
@ -0,0 +1,6 @@
|
||||||
|
export { AreaChart } from "@/comps/charts/area";
|
||||||
|
export { BarChart } from "@/comps/charts/bar";
|
||||||
|
export { DoughnutChart } from "@/comps/charts/doughnut";
|
||||||
|
export { LineChart } from "@/comps/charts/line";
|
||||||
|
export { PieChart } from "@/comps/charts/pie";
|
||||||
|
export { PolarAreaChart } from "@/comps/charts/polar";
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
import { useLocal } from "@/utils/use-local";
|
||||||
|
import { FC, useEffect } from "react";
|
||||||
|
import { loadChart } from "./loader";
|
||||||
|
import type { Line } from "react-chartjs-2";
|
||||||
|
import type { ChartData } from "chart.js";
|
||||||
|
|
||||||
|
type ItemData = ChartData<"line", number[], unknown>;
|
||||||
|
|
||||||
|
const getRandomInt = (min: number, max: number) => {
|
||||||
|
min = Math.ceil(min);
|
||||||
|
max = Math.floor(max);
|
||||||
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AreaChart: FC<{
|
||||||
|
data: () => ItemData;
|
||||||
|
legend?: any;
|
||||||
|
}> = ({ data, legend }) => {
|
||||||
|
const local = useLocal({
|
||||||
|
data: null as unknown as ItemData,
|
||||||
|
Line: null as null | typeof Line,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
local.data = data();
|
||||||
|
local.render();
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
// lazy load: Line Chart
|
||||||
|
if (!local.Line) {
|
||||||
|
loadChart().then((chart) => {
|
||||||
|
local.Line = chart.Line;
|
||||||
|
local.render();
|
||||||
|
});
|
||||||
|
return <>Loading...</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<local.Line
|
||||||
|
datasetIdKey="id"
|
||||||
|
options={{
|
||||||
|
responsive: true,
|
||||||
|
plugins:
|
||||||
|
legend === "none"
|
||||||
|
? {
|
||||||
|
legend: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
legend: {
|
||||||
|
position: legend as any,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
data={local.data}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
import { useLocal } from "@/utils/use-local";
|
||||||
|
import { FC, useEffect } from "react";
|
||||||
|
import { loadChart } from "./loader";
|
||||||
|
import type { Bar } from "react-chartjs-2";
|
||||||
|
import type { ChartData } from "chart.js";
|
||||||
|
|
||||||
|
type ItemData = ChartData<"bar", number[], unknown>;
|
||||||
|
|
||||||
|
const getRandomInt = (min: number, max: number) => {
|
||||||
|
min = Math.ceil(min);
|
||||||
|
max = Math.floor(max);
|
||||||
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const BarChart: FC<{
|
||||||
|
data: () => ItemData;
|
||||||
|
legend?: any
|
||||||
|
}> = ({ data, legend }) => {
|
||||||
|
const local = useLocal({
|
||||||
|
data: null as unknown as ItemData,
|
||||||
|
Bar: null as null | typeof Bar,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
local.data = data();
|
||||||
|
local.render();
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
// lazy load: Line Chart
|
||||||
|
if (!local.Bar) {
|
||||||
|
loadChart().then((chart) => {
|
||||||
|
local.Bar = chart.Bar;
|
||||||
|
local.render();
|
||||||
|
});
|
||||||
|
return <>Loading...</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<local.Bar
|
||||||
|
datasetIdKey="id"
|
||||||
|
options={{
|
||||||
|
responsive: true,
|
||||||
|
plugins:
|
||||||
|
legend === "none"
|
||||||
|
? {
|
||||||
|
legend: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
legend: {
|
||||||
|
position: legend as any,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
data={local.data}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
import { useLocal } from "@/utils/use-local";
|
||||||
|
import { FC, useEffect } from "react";
|
||||||
|
import { loadChart } from "./loader";
|
||||||
|
import type { Doughnut } from "react-chartjs-2";
|
||||||
|
import type { ChartData } from "chart.js";
|
||||||
|
|
||||||
|
type ItemData = ChartData<"doughnut", number[], unknown>;
|
||||||
|
|
||||||
|
const getRandomInt = (min: number, max: number) => {
|
||||||
|
min = Math.ceil(min);
|
||||||
|
max = Math.floor(max);
|
||||||
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DoughnutChart: FC<{
|
||||||
|
data: () => ItemData;
|
||||||
|
legend?: any;
|
||||||
|
}> = ({ data, legend }) => {
|
||||||
|
const local = useLocal({
|
||||||
|
data: null as unknown as ItemData,
|
||||||
|
Doughnut: null as null | typeof Doughnut,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
local.data = data();
|
||||||
|
local.render();
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
// lazy load: Line Chart
|
||||||
|
if (!local.Doughnut) {
|
||||||
|
loadChart().then((chart) => {
|
||||||
|
local.Doughnut = chart.Doughnut;
|
||||||
|
local.render();
|
||||||
|
});
|
||||||
|
return <>Loading...</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// const labels = ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<local.Doughnut
|
||||||
|
datasetIdKey="id"
|
||||||
|
options={{
|
||||||
|
responsive: true,
|
||||||
|
plugins:
|
||||||
|
legend === "none"
|
||||||
|
? {
|
||||||
|
legend: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
legend: {
|
||||||
|
position: legend as any,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
data={local.data}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// [
|
||||||
|
// {
|
||||||
|
// label: "# of Votes",
|
||||||
|
// data: [12, 19, 3, 5, 2, 3],
|
||||||
|
// backgroundColor: [
|
||||||
|
// "rgba(255, 99, 132, 0.2)",
|
||||||
|
// "rgba(54, 162, 235, 0.2)",
|
||||||
|
// "rgba(255, 206, 86, 0.2)",
|
||||||
|
// "rgba(75, 192, 192, 0.2)",
|
||||||
|
// "rgba(153, 102, 255, 0.2)",
|
||||||
|
// "rgba(255, 159, 64, 0.2)",
|
||||||
|
// ],
|
||||||
|
// borderColor: [
|
||||||
|
// "rgba(255, 99, 132, 1)",
|
||||||
|
// "rgba(54, 162, 235, 1)",
|
||||||
|
// "rgba(255, 206, 86, 1)",
|
||||||
|
// "rgba(75, 192, 192, 1)",
|
||||||
|
// "rgba(153, 102, 255, 1)",
|
||||||
|
// "rgba(255, 159, 64, 1)",
|
||||||
|
// ],
|
||||||
|
// borderWidth: 1,
|
||||||
|
// },
|
||||||
|
// ]
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
import { useLocal } from "@/utils/use-local";
|
||||||
|
import { FC, useEffect } from "react";
|
||||||
|
import { loadChart } from "./loader";
|
||||||
|
import type { Line } from "react-chartjs-2";
|
||||||
|
import type { ChartData } from "chart.js";
|
||||||
|
|
||||||
|
type ItemData = ChartData<"line", number[], unknown>;
|
||||||
|
|
||||||
|
const getRandomInt = (min: number, max: number) => {
|
||||||
|
min = Math.ceil(min);
|
||||||
|
max = Math.floor(max);
|
||||||
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LineChart: FC<{
|
||||||
|
data: () => ItemData;
|
||||||
|
legend?: any;
|
||||||
|
}> = ({ data, legend }) => {
|
||||||
|
const local = useLocal({
|
||||||
|
data: null as unknown as ItemData,
|
||||||
|
Line: null as null | typeof Line,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
local.data = data();
|
||||||
|
local.render();
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
// lazy load: Line Chart
|
||||||
|
if (!local.Line) {
|
||||||
|
loadChart().then((chart) => {
|
||||||
|
local.Line = chart.Line;
|
||||||
|
local.render();
|
||||||
|
});
|
||||||
|
return <>Loading...</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<local.Line
|
||||||
|
datasetIdKey="id"
|
||||||
|
options={{
|
||||||
|
responsive: true,
|
||||||
|
plugins:
|
||||||
|
legend === "none"
|
||||||
|
? {
|
||||||
|
legend: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
legend: {
|
||||||
|
position: legend as any,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
data={local.data}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// [
|
||||||
|
// {
|
||||||
|
// label: 'Dataset 1',
|
||||||
|
// data: labels.map(() => getRandomInt(10, 100)),
|
||||||
|
// borderColor: 'rgb(255, 99, 132)',
|
||||||
|
// backgroundColor: 'rgba(255, 99, 132, 0.5)',
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// label: 'Dataset 2',
|
||||||
|
// data: labels.map(() => getRandomInt(10, 100)),
|
||||||
|
// borderColor: 'rgb(53, 162, 235)',
|
||||||
|
// backgroundColor: 'rgba(53, 162, 235, 0.5)',
|
||||||
|
// },
|
||||||
|
// ]
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
import { lazy } from "react";
|
||||||
|
import type { Bar, Line, Pie, Doughnut, PolarArea } from "react-chartjs-2";
|
||||||
|
|
||||||
|
export type Loader = {
|
||||||
|
Line: typeof Line;
|
||||||
|
Bar: typeof Bar;
|
||||||
|
Pie: typeof Pie;
|
||||||
|
Doughnut: typeof Doughnut;
|
||||||
|
PolarArea: typeof PolarArea;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const w = window as unknown as {
|
||||||
|
chartjs_loaded?: Partial<Loader> & { _import: any };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const loadChart = async () => {
|
||||||
|
if (!w.chartjs_loaded) {
|
||||||
|
w.chartjs_loaded = { _import: null };
|
||||||
|
}
|
||||||
|
|
||||||
|
const load = async () => {
|
||||||
|
if (w.chartjs_loaded) {
|
||||||
|
if (!w.chartjs_loaded._import) {
|
||||||
|
const {
|
||||||
|
CategoryScale,
|
||||||
|
Chart: ChartJS,
|
||||||
|
Legend,
|
||||||
|
LineElement,
|
||||||
|
LinearScale,
|
||||||
|
PointElement,
|
||||||
|
Title,
|
||||||
|
Tooltip,
|
||||||
|
Filler,
|
||||||
|
BarElement,
|
||||||
|
ArcElement,
|
||||||
|
RadialLinearScale,
|
||||||
|
} = await import("chart.js");
|
||||||
|
|
||||||
|
ChartJS.register(
|
||||||
|
CategoryScale,
|
||||||
|
LinearScale,
|
||||||
|
PointElement,
|
||||||
|
LineElement,
|
||||||
|
Title,
|
||||||
|
Tooltip,
|
||||||
|
Legend,
|
||||||
|
Filler,
|
||||||
|
BarElement,
|
||||||
|
ArcElement,
|
||||||
|
RadialLinearScale
|
||||||
|
);
|
||||||
|
|
||||||
|
const { Line } = await import("react-chartjs-2");
|
||||||
|
const { Bar } = await import("react-chartjs-2");
|
||||||
|
const { Pie } = await import("react-chartjs-2");
|
||||||
|
const { Doughnut } = await import("react-chartjs-2");
|
||||||
|
const { PolarArea } = await import("react-chartjs-2");
|
||||||
|
w.chartjs_loaded.Line = Line;
|
||||||
|
w.chartjs_loaded.Bar = Bar;
|
||||||
|
w.chartjs_loaded.Pie = Pie;
|
||||||
|
w.chartjs_loaded.Doughnut = Doughnut;
|
||||||
|
w.chartjs_loaded.PolarArea = PolarArea;
|
||||||
|
w.chartjs_loaded._import = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return w.chartjs_loaded as Loader;
|
||||||
|
};
|
||||||
|
const c = await load();
|
||||||
|
|
||||||
|
return {
|
||||||
|
Line: lazy(async () => {
|
||||||
|
return { default: c.Line };
|
||||||
|
}),
|
||||||
|
Bar: lazy(async () => {
|
||||||
|
return { default: c.Bar };
|
||||||
|
}),
|
||||||
|
Pie: lazy(async () => {
|
||||||
|
return { default: c.Pie };
|
||||||
|
}),
|
||||||
|
Doughnut: lazy(async () => {
|
||||||
|
return { default: c.Doughnut };
|
||||||
|
}),
|
||||||
|
PolarArea: lazy(async () => {
|
||||||
|
return { default: c.PolarArea };
|
||||||
|
}),
|
||||||
|
} as Loader;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
import { useLocal } from "@/utils/use-local";
|
||||||
|
import { FC, useEffect } from "react";
|
||||||
|
import { loadChart } from "./loader";
|
||||||
|
import type { Pie } from "react-chartjs-2";
|
||||||
|
import type { ChartData } from "chart.js";
|
||||||
|
|
||||||
|
type ItemData = ChartData<"pie", number[], unknown>;
|
||||||
|
|
||||||
|
const getRandomInt = (min: number, max: number) => {
|
||||||
|
min = Math.ceil(min);
|
||||||
|
max = Math.floor(max);
|
||||||
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PieChart: FC<{
|
||||||
|
data: () => ItemData;
|
||||||
|
legend?: any;
|
||||||
|
}> = ({ data, legend }) => {
|
||||||
|
const local = useLocal({
|
||||||
|
data: null as unknown as ItemData,
|
||||||
|
Pie: null as null | typeof Pie,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
local.data = data();
|
||||||
|
local.render();
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
// lazy load: Line Chart
|
||||||
|
if (!local.Pie) {
|
||||||
|
loadChart().then((chart) => {
|
||||||
|
local.Pie = chart.Pie;
|
||||||
|
local.render();
|
||||||
|
});
|
||||||
|
return <>Loading...</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<local.Pie
|
||||||
|
datasetIdKey="id"
|
||||||
|
options={{
|
||||||
|
responsive: true,
|
||||||
|
plugins:
|
||||||
|
legend === "none"
|
||||||
|
? {
|
||||||
|
legend: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
legend: {
|
||||||
|
position: legend as any,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
data={local.data}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// [
|
||||||
|
// {
|
||||||
|
// label: "# of Votes",
|
||||||
|
// data: [12, 19, 3, 5, 2, 3],
|
||||||
|
// backgroundColor: [
|
||||||
|
// "rgba(255, 99, 132, 0.2)",
|
||||||
|
// "rgba(54, 162, 235, 0.2)",
|
||||||
|
// "rgba(255, 206, 86, 0.2)",
|
||||||
|
// "rgba(75, 192, 192, 0.2)",
|
||||||
|
// "rgba(153, 102, 255, 0.2)",
|
||||||
|
// "rgba(255, 159, 64, 0.2)",
|
||||||
|
// ],
|
||||||
|
// borderColor: [
|
||||||
|
// "rgba(255, 99, 132, 1)",
|
||||||
|
// "rgba(54, 162, 235, 1)",
|
||||||
|
// "rgba(255, 206, 86, 1)",
|
||||||
|
// "rgba(75, 192, 192, 1)",
|
||||||
|
// "rgba(153, 102, 255, 1)",
|
||||||
|
// "rgba(255, 159, 64, 1)",
|
||||||
|
// ],
|
||||||
|
// borderWidth: 1,
|
||||||
|
// },
|
||||||
|
// ]
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
import { useLocal } from "@/utils/use-local";
|
||||||
|
import { FC, useEffect } from "react";
|
||||||
|
import { loadChart } from "./loader";
|
||||||
|
import type { PolarArea } from "react-chartjs-2";
|
||||||
|
|
||||||
|
type ItemData = {
|
||||||
|
label: string;
|
||||||
|
data: number[];
|
||||||
|
backgroundColor: string[];
|
||||||
|
borderColor: string[];
|
||||||
|
borderWidth: number;
|
||||||
|
}; // { }
|
||||||
|
type ItemLabel = string;
|
||||||
|
type TitleType = string;
|
||||||
|
|
||||||
|
const getRandomInt = (min: number, max: number) => {
|
||||||
|
min = Math.ceil(min);
|
||||||
|
max = Math.floor(max);
|
||||||
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PolarAreaChart: FC<{
|
||||||
|
data: () => ItemData[];
|
||||||
|
labels: ItemLabel[];
|
||||||
|
title: TitleType;
|
||||||
|
}> = ({ data, labels, title }) => {
|
||||||
|
const local = useLocal({
|
||||||
|
data: [] as ItemData[],
|
||||||
|
labels: [] as ItemLabel[],
|
||||||
|
title: '' as TitleType,
|
||||||
|
PolarArea: null as null | typeof PolarArea,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
local.data = data();
|
||||||
|
local.labels = labels;
|
||||||
|
local.title = title;
|
||||||
|
local.render();
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
// lazy load: Line Chart
|
||||||
|
if (!local.PolarArea) {
|
||||||
|
loadChart().then((chart) => {
|
||||||
|
local.PolarArea = chart.PolarArea;
|
||||||
|
local.render();
|
||||||
|
});
|
||||||
|
return <>Loading...</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// const labels = ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<local.PolarArea
|
||||||
|
datasetIdKey="id"
|
||||||
|
options={{
|
||||||
|
responsive: true,
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
position: "top" as const,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: local.title,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
data={{
|
||||||
|
labels: local.labels,
|
||||||
|
datasets: local.data.map((e) => {
|
||||||
|
return {
|
||||||
|
label: e.label,
|
||||||
|
data: e.data,
|
||||||
|
backgroundColor: e.backgroundColor,
|
||||||
|
borderColor: e.borderColor,
|
||||||
|
borderWidth: e.borderWidth
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// [
|
||||||
|
// {
|
||||||
|
// label: "# of Votes",
|
||||||
|
// data: [12, 19, 3, 5, 2, 3],
|
||||||
|
// backgroundColor: [
|
||||||
|
// "rgba(255, 99, 132, 0.2)",
|
||||||
|
// "rgba(54, 162, 235, 0.2)",
|
||||||
|
// "rgba(255, 206, 86, 0.2)",
|
||||||
|
// "rgba(75, 192, 192, 0.2)",
|
||||||
|
// "rgba(153, 102, 255, 0.2)",
|
||||||
|
// "rgba(255, 159, 64, 0.2)",
|
||||||
|
// ],
|
||||||
|
// borderColor: [
|
||||||
|
// "rgba(255, 99, 132, 1)",
|
||||||
|
// "rgba(54, 162, 235, 1)",
|
||||||
|
// "rgba(255, 206, 86, 1)",
|
||||||
|
// "rgba(75, 192, 192, 1)",
|
||||||
|
// "rgba(153, 102, 255, 1)",
|
||||||
|
// "rgba(255, 159, 64, 1)",
|
||||||
|
// ],
|
||||||
|
// borderWidth: 1,
|
||||||
|
// },
|
||||||
|
// ]
|
||||||
Loading…
Reference in New Issue