| // src/components/genui/ChartComponent.tsx | |
| import { useMemo } from "react"; | |
| import { | |
| BarChart, Bar, LineChart, Line, PieChart, Pie, AreaChart, Area, | |
| ScatterChart, Scatter, XAxis, YAxis, CartesianGrid, Tooltip, | |
| Legend, ResponsiveContainer, Cell, | |
| } from "recharts"; | |
| const COLORS = ["#0d9488", "#2563eb", "#7c3aed", "#db2777", "#ea580c", "#ca8a04", "#16a34a"]; | |
| interface ChartComponentProps { | |
| chartType: "bar" | "line" | "pie" | "area" | "scatter"; | |
| title: string; | |
| labels: string[]; | |
| datasets: { label: string; data: number[]; color?: string }[]; | |
| xLabel?: string; | |
| yLabel?: string; | |
| height?: number; | |
| isStreaming?: boolean; | |
| onAction?: (action: string, data: any) => void; | |
| } | |
| export function ChartComponent({ chartType, title, labels, datasets, xLabel, yLabel, height = 300, isStreaming, onAction }: ChartComponentProps) { | |
| const data = useMemo(() => | |
| labels.map((label, i) => { | |
| const row: Record<string, any> = { name: label }; | |
| datasets.forEach(ds => { row[ds.label] = ds.data[i] ?? 0; }); | |
| return row; | |
| }), | |
| [labels, datasets] | |
| ); | |
| const renderChart = () => { | |
| switch (chartType) { | |
| case "bar": | |
| return ( | |
| <BarChart data={data}> | |
| <CartesianGrid strokeDasharray="3 3" stroke="#e5e7eb" /> | |
| <XAxis dataKey="name" tick={{ fontSize: 11 }} /> | |
| <YAxis tick={{ fontSize: 11 }} /> | |
| <Tooltip /> | |
| <Legend /> | |
| {datasets.map((ds, i) => ( | |
| <Bar key={ds.label} dataKey={ds.label} fill={ds.color ?? COLORS[i % COLORS.length]} radius={[4, 4, 0, 0]} /> | |
| ))} | |
| </BarChart> | |
| ); | |
| case "line": | |
| return ( | |
| <LineChart data={data}> | |
| <CartesianGrid strokeDasharray="3 3" stroke="#e5e7eb" /> | |
| <XAxis dataKey="name" tick={{ fontSize: 11 }} /> | |
| <YAxis tick={{ fontSize: 11 }} /> | |
| <Tooltip /> | |
| <Legend /> | |
| {datasets.map((ds, i) => ( | |
| <Line key={ds.label} type="monotone" dataKey={ds.label} stroke={ds.color ?? COLORS[i % COLORS.length]} strokeWidth={2} dot={{ r: 3 }} /> | |
| ))} | |
| </LineChart> | |
| ); | |
| case "pie": | |
| const pieData = labels.map((label, i) => ({ | |
| name: label, | |
| value: datasets[0]?.data[i] ?? 0, | |
| })); | |
| return ( | |
| <PieChart> | |
| <Pie data={pieData} dataKey="value" nameKey="name" cx="50%" cy="50%" outerRadius={80} label> | |
| {pieData.map((_, i) => <Cell key={i} fill={COLORS[i % COLORS.length]} />)} | |
| </Pie> | |
| <Tooltip /> | |
| <Legend /> | |
| </PieChart> | |
| ); | |
| case "area": | |
| return ( | |
| <AreaChart data={data}> | |
| <CartesianGrid strokeDasharray="3 3" stroke="#e5e7eb" /> | |
| <XAxis dataKey="name" tick={{ fontSize: 11 }} /> | |
| <YAxis tick={{ fontSize: 11 }} /> | |
| <Tooltip /> | |
| <Legend /> | |
| {datasets.map((ds, i) => ( | |
| <Area key={ds.label} type="monotone" dataKey={ds.label} fill={ds.color ?? COLORS[i % COLORS.length]} stroke={ds.color ?? COLORS[i % COLORS.length]} fillOpacity={0.3} /> | |
| ))} | |
| </AreaChart> | |
| ); | |
| case "scatter": | |
| return ( | |
| <ScatterChart> | |
| <CartesianGrid strokeDasharray="3 3" stroke="#e5e7eb" /> | |
| <XAxis dataKey="x" name={xLabel ?? "X"} tick={{ fontSize: 11 }} /> | |
| <YAxis dataKey="y" name={yLabel ?? "Y"} tick={{ fontSize: 11 }} /> | |
| <Tooltip cursor={{ strokeDasharray: "3 3" }} /> | |
| <Legend /> | |
| {datasets.map((ds, i) => ( | |
| <Scatter key={ds.label} name={ds.label} data={ds.data.map((v, j) => ({ x: j, y: v }))} fill={ds.color ?? COLORS[i % COLORS.length]} /> | |
| ))} | |
| </ScatterChart> | |
| ); | |
| default: | |
| return <p>Unsupported chart type</p>; | |
| } | |
| }; | |
| return ( | |
| <div className="space-y-2"> | |
| <h3 className="font-semibold text-sm">{title}</h3> | |
| <ResponsiveContainer width="100%" height={height}> | |
| {renderChart()} | |
| </ResponsiveContainer> | |
| <div className="flex gap-2"> | |
| {(["bar","line","pie","area"] as const).map(t => ( | |
| <button | |
| key={t} | |
| onClick={() => onAction?.("change_chart_type", { chartType: t })} | |
| className={`text-[10px] px-2 py-0.5 rounded-full ${chartType === t ? "bg-primary text-white" : "bg-gray-100 dark:bg-gray-700 text-gray-500"}`} | |
| > | |
| {t} | |
| </button> | |
| ))} | |
| </div> | |
| </div> | |
| ); | |
| } |
Xet Storage Details
- Size:
- 4.57 kB
- Xet hash:
- 44021de320e4f2d1df42de0511b0d19d3dd0aca028ffff5785d9eccec59e1372
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.