import * as React from "react"; import { Tooltip as RechartsTooltip, ResponsiveContainer, type TooltipProps, } from "recharts"; import { cn } from "@/lib/utils"; export type ChartConfig = Record< string, { label?: React.ReactNode; icon?: React.ComponentType<{ className?: string }>; color?: string; } >; const ChartConfigContext = React.createContext(null); const useChartConfig = () => React.useContext(ChartConfigContext); const ChartStyle: React.FC<{ id: string; config: ChartConfig }> = ({ id, config, }) => { const entries = Object.entries(config).filter(([, value]) => value.color); if (entries.length === 0) return null; return ( ); }; export const ChartContainer = React.forwardRef< HTMLDivElement, React.HTMLAttributes & { config: ChartConfig; children?: React.ReactElement | null; } >(({ id, className, children, config, ...props }, ref) => { const generatedId = React.useId(); const chartId = id ?? generatedId; return (
{React.isValidElement(children) ? ( {children} ) : null}
); }); ChartContainer.displayName = "ChartContainer"; export const ChartTooltip = RechartsTooltip; export type ChartTooltipContentProps = React.ComponentPropsWithoutRef<"div"> & Pick, "active" | "payload" | "label"> & { indicator?: "dot" | "line" | "dashed"; labelFormatter?: (value: unknown, payload: unknown[]) => React.ReactNode; formatter?: ( value: unknown, name: string, item: unknown, index: number, ) => React.ReactNode; nameKey?: string; }; export const ChartTooltipContent = React.forwardRef< HTMLDivElement, ChartTooltipContentProps >( ( { active, payload, label, className, indicator = "dot", labelFormatter, formatter, nameKey, ...props }, ref, ) => { const config = useChartConfig() ?? {}; if (!active || !payload?.length) return null; const formattedLabel = labelFormatter ? labelFormatter(label, payload) : label; return (
{formattedLabel ? (
{formattedLabel}
) : null}
{payload.map((item, index) => { const dataKey = String(item.dataKey ?? item.name ?? ""); const configKey = nameKey ?? dataKey; const entry = config[configKey] ?? config[dataKey]; const IndicatorIcon = entry?.icon; const value = formatter ? formatter(item.value, dataKey, item, index) : item.value; const labelText = entry?.label ?? item.name ?? dataKey; const indicatorColor = entry?.color ?? item.color ?? item.fill ?? "currentColor"; return (
{IndicatorIcon ? ( ) : ( )} {labelText}
{typeof value === "number" ? value.toLocaleString() : (value as React.ReactNode)}
); })}
); }, ); ChartTooltipContent.displayName = "ChartTooltipContent";