import * as React from "react"; import * as RechartsPrimitive from "recharts"; import type { TooltipValueType } from "recharts"; import { cn } from "../lib/utils"; // Format: { THEME_NAME: CSS_SELECTOR } const THEMES = { light: "", dark: ".dark" } as const; const INITIAL_DIMENSION = { width: 320, height: 200 } as const; type TooltipNameType = number | string; export type ChartConfig = Record< string, { label?: React.ReactNode; icon?: React.ComponentType; } & ( | { color?: string; theme?: never } | { color?: never; theme: Record } ) >; type ChartContextProps = { config: ChartConfig; }; const cssIdentifierPattern = /^[A-Za-z_][A-Za-z0-9_-]*$/; const cssColorPattern = /^(?:#[0-9A-Fa-f]{3,8}|(?:rgb|hsl)a?\(\s*[-+0-9.%]+\s*(?:,\s*[-+0-9.%]+\s*){2}(?:,\s*[-+0-9.]+\s*)?\)|(?:rgb|hsl)a?\(\s*[-+0-9.%]+\s+[-+0-9.%]+\s+[-+0-9.%]+(?:\s*\/\s*[-+0-9.%]+)?\s*\)|[A-Za-z]+|var\(--[A-Za-z0-9_-]+\))$/; export const chartCssVariableName = (key: string): string | null => cssIdentifierPattern.test(key) ? `--color-${key}` : null; export const chartCssColorValue = (color: string): string | null => { const trimmed = color.trim(); return cssColorPattern.test(trimmed) ? trimmed : null; }; const ChartContext = React.createContext(null); function useChart() { const context = React.useContext(ChartContext); if (!context) { throw new Error("useChart must be used within a "); } return context; } function ChartContainer({ id, className, children, config, initialDimension = INITIAL_DIMENSION, ...props }: React.ComponentProps<"div"> & { config: ChartConfig; children: React.ComponentProps["children"]; initialDimension?: { width: number; height: number; }; }) { const uniqueId = React.useId(); const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`; return (
{children}
); } const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { const colorConfig = Object.entries(config).filter(([, config]) => config.theme ?? config.color); if (!colorConfig.length) { return null; } return (