{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "dependencies": [
    "recharts@2"
  ],
  "files": [
    {
      "content": "export * from \"./chart\";\nexport * as Chart from \"./namespace\";\n",
      "path": "src/registry/ui/chart/index.ts",
      "type": "registry:ui"
    },
    {
      "content": "\"use client\";\n\nimport { createContext, use, useId, useMemo } from \"react\";\nimport {\n  Legend,\n  type LegendProps,\n  ResponsiveContainer,\n  Tooltip,\n} from \"recharts\";\nimport { cn } from \"~/registry/lib/cva\";\nimport { ChartStyles } from \"./styles\";\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { dark: \".dark\", light: \"\" } as const;\n\nexport type ChartConfig = {\n  [k in string]: {\n    label?: React.ReactNode;\n    icon?: React.ComponentType;\n  } & (\n    | { color?: string; theme?: never }\n    | { color?: never; theme: Record<keyof typeof THEMES, string> }\n  );\n};\n\ninterface ChartContextProps {\n  // Changed from type to interface\n  config: ChartConfig;\n}\n\nconst ChartContext = createContext<ChartContextProps | null>(null);\n\nfunction useChart() {\n  const context = use(ChartContext);\n\n  if (!context) {\n    throw new Error(\"useChart must be used within a <ChartRoot />\");\n  }\n\n  return context;\n}\n\nexport interface ChartRootProps extends React.ComponentProps<\"div\"> {\n  children: React.ComponentProps<typeof ResponsiveContainer>[\"children\"];\n  config: ChartConfig;\n}\n\nexport function ChartRoot({\n  id,\n  className,\n  children,\n  config,\n  ...props\n}: ChartRootProps) {\n  const uniqueId = useId();\n  const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`;\n\n  return (\n    <ChartContext value={{ config }}>\n      <div\n        className={ChartStyles.Root({ className })}\n        data-chart={chartId}\n        data-slot=\"chart-root\"\n        {...props}\n      >\n        <ChartStyle config={config} id={chartId} />\n        <ResponsiveContainer>{children}</ResponsiveContainer>\n      </div>\n    </ChartContext>\n  );\n}\n\nexport interface ChartStyleProps {\n  config: ChartConfig;\n  id: string;\n}\n\nexport const ChartStyle = ({ id, config }: ChartStyleProps) => {\n  const colorConfig = Object.entries(config).filter(\n    ([, config]) => config.theme || config.color\n  );\n\n  if (!colorConfig) {\n    return null;\n  }\n\n  return (\n    <style\n      // biome-ignore lint/security/noDangerouslySetInnerHtml: This is fine.\n      dangerouslySetInnerHTML={{\n        __html: Object.entries(THEMES)\n          .map(\n            ([theme, prefix]) => `\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    return color ? `  --color-${key}: ${color};` : null;\n  })\n  .join(\"\\n\")}\n}\n`\n          )\n          .join(\"\\n\"),\n      }}\n    />\n  );\n};\n\nexport const ChartTooltip = Tooltip;\n\nexport interface ChartTooltipContentProps\n  extends React.ComponentProps<typeof Tooltip>,\n    Omit<React.ComponentProps<\"div\">, \"content\"> {\n  hideIndicator?: boolean;\n  hideLabel?: boolean;\n  indicator?: \"line\" | \"dot\" | \"dashed\";\n  labelKey?: string;\n  nameKey?: string;\n}\n\nexport function 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}: ChartTooltipContentProps) {\n  const { config } = useChart();\n\n  const tooltipLabel = useMemo(() => {\n    if (hideLabel || !payload) {\n      return null;\n    }\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        <div\n          className={ChartStyles.TooltipContentLabel({ class: labelClassName })}\n        >\n          {labelFormatter(value, payload)}\n        </div>\n      );\n    }\n\n    if (!value) {\n      return null;\n    }\n\n    return (\n      <div\n        className={ChartStyles.TooltipContentLabel({ class: labelClassName })}\n      >\n        {value}\n      </div>\n    );\n  }, [\n    label,\n    labelFormatter,\n    payload,\n    hideLabel,\n    labelClassName,\n    config,\n    labelKey,\n  ]);\n\n  if (!(active && payload)) {\n    return null;\n  }\n\n  const nestLabel = payload.length === 1 && indicator !== \"dot\";\n\n  return (\n    <div className={ChartStyles.TooltipContent({ className })}>\n      {nestLabel ? null : tooltipLabel}\n      <div className=\"grid gap-1.5\">\n        {payload.map((item, index) => {\n          const key = `${nameKey || item.name || item.dataKey || \"value\"}`;\n          const itemConfig = getPayloadConfigFromPayload(config, item, key);\n          const indicatorColor = color || item.payload.fill || item.color;\n\n          return (\n            <div\n              className={cn(\n                \"flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n                indicator === \"dot\" && \"items-center\"\n              )}\n              key={item.dataKey}\n            >\n              {formatter && item?.value !== undefined && item.name ? (\n                formatter(item.value, item.name, item, index, item.payload)\n              ) : (\n                <>\n                  {itemConfig?.icon ? (\n                    <itemConfig.icon />\n                  ) : (\n                    !hideIndicator && (\n                      <div\n                        className={cn(\n                          \"shrink-0 rounded-[2px] border-(--color-border) bg-(--color-background)\",\n                          {\n                            \"h-2.5 w-2.5\": indicator === \"dot\",\n                            \"my-0.5\": nestLabel && indicator === \"dashed\",\n                            \"w-0 border-[1.5px] border-dashed bg-transparent\":\n                              indicator === \"dashed\",\n                            \"w-1\": indicator === \"line\",\n                          }\n                        )}\n                        style={\n                          {\n                            \"--color-background\": indicatorColor,\n                            \"--color-border\": indicatorColor,\n                          } as React.CSSProperties\n                        }\n                      />\n                    )\n                  )}\n                  <div\n                    className={cn(\n                      \"flex flex-1 justify-between leading-none\",\n                      nestLabel ? \"items-end\" : \"items-center\"\n                    )}\n                  >\n                    <div className=\"grid gap-1.5\">\n                      {nestLabel ? tooltipLabel : null}\n                      <span className=\"text-muted-foreground\">\n                        {itemConfig?.label || item.name}\n                      </span>\n                    </div>\n                    {item.value && (\n                      <span className=\"font-medium font-mono text-foreground tabular-nums\">\n                        {item.value.toLocaleString()}\n                      </span>\n                    )}\n                  </div>\n                </>\n              )}\n            </div>\n          );\n        })}\n      </div>\n    </div>\n  );\n}\n\nexport const ChartLegend = Legend;\n\nexport interface ChartLegendContentProps\n  extends React.ComponentProps<\"div\">,\n    Pick<LegendProps, \"payload\" | \"verticalAlign\"> {\n  hideIcon?: boolean;\n  nameKey?: string;\n}\n\nexport function ChartLegendContent({\n  className,\n  hideIcon = false,\n  payload,\n  verticalAlign = \"bottom\",\n  nameKey,\n}: ChartLegendContentProps) {\n  const { config } = useChart();\n\n  if (!payload) {\n    return null;\n  }\n\n  return (\n    <div\n      className={cn(\n        \"flex items-center justify-center gap-4\",\n        verticalAlign === \"top\" ? \"pb-3\" : \"pt-3\",\n        className\n      )}\n    >\n      {payload.map((item) => {\n        const key = `${nameKey || item.dataKey || \"value\"}`;\n        const itemConfig = getPayloadConfigFromPayload(config, item, key);\n\n        return (\n          <div\n            className={cn(\n              \"flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n            )}\n            key={item.value}\n          >\n            {itemConfig?.icon && !hideIcon ? (\n              <itemConfig.icon />\n            ) : (\n              <div\n                className=\"h-2 w-2 shrink-0 rounded-[2px]\"\n                style={{\n                  backgroundColor: item.color,\n                }}\n              />\n            )}\n            {itemConfig?.label}\n          </div>\n        );\n      })}\n    </div>\n  );\n}\n\n// Helper to extract item config from a payload.\nfunction getPayloadConfigFromPayload(\n  config: ChartConfig,\n  payload: unknown,\n  key: string\n) {\n  if (typeof payload !== \"object\" || payload === null) {\n    return;\n  }\n\n  const payloadPayload =\n    \"payload\" in payload &&\n    typeof payload.payload === \"object\" &&\n    payload.payload !== null\n      ? payload.payload\n      : undefined;\n\n  let configLabelKey: string = key;\n\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",
      "path": "src/registry/ui/chart/chart.tsx",
      "type": "registry:ui"
    },
    {
      "content": "import { cva } from \"~/registry/lib/cva\";\n\nexport const ChartStyles = {\n  Root: cva({\n    base: [\n      \"flex aspect-video justify-center text-xs\",\n      \"[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50\",\n      \"[&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent\",\n      \"[&_.recharts-layer]:outline-hidden [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border\",\n      \"[&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted\",\n      \"[&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent\",\n      \"[&_.recharts-sector]:outline-hidden [&_.recharts-surface]:outline-hidden\",\n    ],\n  }),\n  TooltipContent: cva({\n    base: [\n      \"grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl\",\n    ],\n  }),\n  TooltipContentLabel: cva({\n    base: [\"font-medium\"],\n  }),\n};\n",
      "path": "src/registry/ui/chart/styles.ts",
      "type": "registry:ui"
    },
    {
      "content": "export {\n  ChartLegend as Legend,\n  ChartLegendContent as LegendContent,\n  ChartRoot as Root,\n  ChartTooltip as Tooltip,\n  ChartTooltipContent as TooltipContent,\n} from \"./chart\";\n",
      "path": "src/registry/ui/chart/namespace.ts",
      "type": "registry:ui"
    }
  ],
  "name": "chart",
  "registryDependencies": [
    "@kanpeki/cva",
    "@kanpeki/custom-plugin"
  ],
  "type": "registry:ui"
}