{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "chart", "title": "Chart", "description": "Chart components built on Recharts.", "dependencies": [ "recharts" ], "files": [ { "path": "registry/default/ui/chart.tsx", "content": "'use client';\n\nimport * as React from 'react';\nimport * as RechartsPrimitive from 'recharts';\n\nimport { cn } from '@/lib/utils';\n\nconst THEMES = { light: '', dark: '.dark' } as const;\n\nexport type TChartConfig = {\n [k in string]: {\n label?: React.ReactNode;\n icon?: React.ComponentType;\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record }\n );\n};\n\ntype TChartContextProps = {\n config: TChartConfig;\n};\n\nconst ChartContext = React.createContext(null);\n\nfunction useChart() {\n const context = React.useContext(ChartContext);\n if (!context) {\n throw new Error('useChart must be used within a ');\n }\n\n return context;\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n ...props\n}: React.ComponentProps<'div'> & {\n config: TChartConfig;\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >['children'];\n}) {\n const uniqueId = React.useId();\n const chartId = `chart-${id || uniqueId.replace(/:/g, '')}`;\n const context = React.useMemo(() => ({ config }), [config]);\n\n return (\n \n \n \n \n {children}\n \n \n \n );\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: TChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme || config.color\n );\n if (!colorConfig.length) return null;\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\n itemConfig.color;\n\n return color ? ` --color-${key}: ${color};` : null;\n })\n .join('\\n')}\n}\n`\n )\n .join('\\n'),\n }}\n />\n );\n};\n\nconst ChartTooltip = RechartsPrimitive.Tooltip;\n\ntype TTooltipValueType = number | string | Array;\ntype TTooltipNameType = number | string;\n\ntype TChartTooltipContentProps = React.ComponentProps<\n typeof RechartsPrimitive.Tooltip\n> &\n React.ComponentProps<'div'> & {\n hideLabel?: boolean;\n hideIndicator?: boolean;\n indicator?: 'line' | 'dot' | 'dashed';\n nameKey?: string;\n labelKey?: string;\n } & Omit<\n RechartsPrimitive.DefaultTooltipContentProps<\n TTooltipValueType,\n TTooltipNameType\n >,\n 'accessibilityLayer'\n >;\n\ntype TChartTooltipLabelProps = Pick<\n TChartTooltipContentProps,\n 'payload' | 'label' | 'labelKey' | 'labelClassName' | 'labelFormatter'\n> & { config: TChartConfig; hideLabel?: boolean };\n\nfunction ChartTooltipLabel({\n config,\n payload,\n label,\n labelKey,\n labelClassName,\n labelFormatter,\n hideLabel,\n}: TChartTooltipLabelProps) {\n if (hideLabel || !payload?.length) return null;\n\n const [item] = payload;\n const key = `${labelKey || item?.dataKey || item?.name || 'value'}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, key);\n const value =\n !labelKey && typeof label === 'string'\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label;\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n );\n }\n\n if (!value) return null;\n\n return
{value}
;\n}\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = 'dot',\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: TChartTooltipContentProps) {\n const { config } = useChart();\n\n if (!active || !payload?.length) return null;\n\n const tooltipLabel = (\n \n );\n\n const nestLabel = payload.length === 1 && indicator !== 'dot';\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload.map((item, index: number) => {\n const itemKey = `${nameKey || item.name || item.dataKey || 'value'}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, itemKey);\n const indicatorColor = color || item.payload?.fill || item.color;\n\n return (\n svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5',\n indicator === 'dot' && 'items-center'\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label || item.name}\n \n
\n {item.value && (\n \n {item.value.toLocaleString()}\n \n )}\n
\n \n )}\n \n );\n })}\n \n \n );\n}\n\nconst ChartLegend = RechartsPrimitive.Legend;\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = 'bottom',\n nameKey,\n}: React.ComponentProps<'div'> & {\n hideIcon?: boolean;\n nameKey?: string;\n} & RechartsPrimitive.DefaultLegendContentProps) {\n const { config } = useChart();\n if (!payload?.length) return null;\n\n return (\n \n {payload.map((item) => {\n const key = `${nameKey || item.dataKey || 'value'}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, key);\n\n return (\n svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3'\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n );\n })}\n \n );\n}\n\nfunction getPayloadConfigFromPayload(\n config: TChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== 'object' || payload === null) return undefined;\n const payloadPayload =\n 'payload' in payload &&\n typeof payload.payload === 'object' &&\n payload.payload !== null\n ? payload.payload\n : undefined;\n let configLabelKey: string = key;\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === 'string'\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string;\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === 'string'\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string;\n }\n\n return configLabelKey in config\n ? config[configLabelKey]\n : config[key as keyof typeof config];\n}\n\nexport {\n ChartContainer,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n ChartTooltip,\n ChartTooltipContent,\n};\n", "type": "registry:ui" } ], "type": "registry:ui" }