{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "chart",
  "type": "registry:ui",
  "title": "Chart",
  "dependencies": [
    "recharts",
    "lucide-react"
  ],
  "registryDependencies": [
    "https://neobrutalism.dev/r/ncard.json"
  ],
  "files": [
    {
      "path": "src/components/ui/chart.tsx",
      "content": "\"use client\"\r\n\r\nimport * as RechartsPrimitive from \"recharts\"\r\n\r\nimport * as React from \"react\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\n// Format: { THEME_NAME: CSS_SELECTOR }\r\nconst THEMES = { light: \"\", dark: \".dark\" } as const\r\n\r\nexport type ChartConfig = {\r\n  [k in string]: {\r\n    label?: React.ReactNode\r\n    icon?: React.ComponentType\r\n  } & (\r\n    | { color?: string; theme?: never }\r\n    | { color?: never; theme: Record<keyof typeof THEMES, string> }\r\n  )\r\n}\r\n\r\ntype ChartContextProps = {\r\n  config: ChartConfig\r\n}\r\n\r\nconst ChartContext = React.createContext<ChartContextProps | null>(null)\r\n\r\nfunction useChart() {\r\n  const context = React.useContext(ChartContext)\r\n\r\n  if (!context) {\r\n    throw new Error(\"useChart must be used within a <ChartContainer />\")\r\n  }\r\n\r\n  return context\r\n}\r\n\r\nfunction ChartContainer({\r\n  id,\r\n  className,\r\n  children,\r\n  config,\r\n  ...props\r\n}: React.ComponentProps<\"div\"> & {\r\n  config: ChartConfig\r\n  children: React.ComponentProps<\r\n    typeof RechartsPrimitive.ResponsiveContainer\r\n  >[\"children\"]\r\n}) {\r\n  const uniqueId = React.useId()\r\n  const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`\r\n\r\n  return (\r\n    <ChartContext.Provider value={{ config }}>\r\n      <div\r\n        data-slot=\"chart\"\r\n        data-chart={chartId}\r\n        className={cn(\r\n          \"[&_.recharts-cartesian-axis-tick_text]:fill-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-[#80808080] [&_.recharts-curve.recharts-tooltip-cursor]:stroke-[#80808080] [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-black [&_.recharts-polar-grid_[stroke='#ccc']]:dark:stroke-white [&_.recharts-reference-line_[stroke='#ccc']]:stroke-black [&_.recharts-reference-line_[stroke='#ccc']]:dark:stroke-white flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-border [&_.recharts-surface]:outline-hidden\",\r\n          \"[&_.recharts-layer_path]:[fill-opacity:1] [&_.recharts-layer_path]:[stroke-width:2] [&_.recharts-layer_path]:[stroke:var(--color-border)]\",\r\n          className,\r\n        )}\r\n        {...props}\r\n      >\r\n        <ChartStyle id={chartId} config={config} />\r\n        <RechartsPrimitive.ResponsiveContainer>\r\n          {children}\r\n        </RechartsPrimitive.ResponsiveContainer>\r\n      </div>\r\n    </ChartContext.Provider>\r\n  )\r\n}\r\n\r\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\r\n  const colorConfig = Object.entries(config).filter(\r\n    ([, config]) => config.theme || config.color,\r\n  )\r\n\r\n  if (!colorConfig.length) {\r\n    return null\r\n  }\r\n\r\n  return (\r\n    <style\r\n      dangerouslySetInnerHTML={{\r\n        __html: Object.entries(THEMES)\r\n          .map(\r\n            ([theme, prefix]) => `\r\n${prefix} [data-chart=${id}] {\r\n${colorConfig\r\n  .map(([key, itemConfig]) => {\r\n    const color =\r\n      itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\r\n      itemConfig.color\r\n    return color ? `  --color-${key}: ${color};` : null\r\n  })\r\n  .join(\"\\n\")}\r\n}\r\n`,\r\n          )\r\n          .join(\"\\n\"),\r\n      }}\r\n    />\r\n  )\r\n}\r\n\r\nconst ChartTooltip = RechartsPrimitive.Tooltip\r\n\r\nfunction ChartTooltipContent({\r\n  active,\r\n  payload,\r\n  className,\r\n  indicator = \"dot\",\r\n  hideLabel = false,\r\n  hideIndicator = false,\r\n  label,\r\n  labelFormatter,\r\n  labelClassName,\r\n  formatter,\r\n  color,\r\n  nameKey,\r\n  labelKey,\r\n}: React.ComponentProps<typeof RechartsPrimitive.Tooltip> &\r\n  React.ComponentProps<\"div\"> & {\r\n    hideLabel?: boolean\r\n    hideIndicator?: boolean\r\n    indicator?: \"line\" | \"dot\" | \"dashed\"\r\n    nameKey?: string\r\n    labelKey?: string\r\n  }) {\r\n  const { config } = useChart()\r\n\r\n  const tooltipLabel = React.useMemo(() => {\r\n    if (hideLabel || !payload?.length) {\r\n      return null\r\n    }\r\n\r\n    const [item] = payload\r\n    const key = `${labelKey || item?.dataKey || item?.name || \"value\"}`\r\n    const itemConfig = getPayloadConfigFromPayload(config, item, key)\r\n    const value =\r\n      !labelKey && typeof label === \"string\"\r\n        ? config[label as keyof typeof config]?.label || label\r\n        : itemConfig?.label\r\n\r\n    if (labelFormatter) {\r\n      return (\r\n        <div className={cn(\"font-heading\", labelClassName)}>\r\n          {labelFormatter(value, payload)}\r\n        </div>\r\n      )\r\n    }\r\n\r\n    if (!value) {\r\n      return null\r\n    }\r\n\r\n    return <div className={cn(\"font-base\", labelClassName)}>{value}</div>\r\n  }, [\r\n    label,\r\n    labelFormatter,\r\n    payload,\r\n    hideLabel,\r\n    labelClassName,\r\n    config,\r\n    labelKey,\r\n  ])\r\n\r\n  if (!active || !payload?.length) {\r\n    return null\r\n  }\r\n\r\n  const nestLabel = payload.length === 1 && indicator !== \"dot\"\r\n\r\n  return (\r\n    <div\r\n      className={cn(\r\n        \"border-border bg-background grid min-w-[8rem] items-start gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl\",\r\n        className,\r\n      )}\r\n    >\r\n      {!nestLabel ? tooltipLabel : null}\r\n      <div className=\"grid gap-1.5\">\r\n        {payload.map((item, index) => {\r\n          const key = `${nameKey || item.name || item.dataKey || \"value\"}`\r\n          const itemConfig = getPayloadConfigFromPayload(config, item, key)\r\n          const indicatorColor = color || item.payload.fill || item.color\r\n\r\n          return (\r\n            <div\r\n              key={item.dataKey}\r\n              className={cn(\r\n                \"[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 \",\r\n                indicator === \"dot\" && \"items-center\",\r\n              )}\r\n            >\r\n              {formatter && item?.value !== undefined && item.name ? (\r\n                formatter(item.value, item.name, item, index, item.payload)\r\n              ) : (\r\n                <>\r\n                  {itemConfig?.icon ? (\r\n                    <itemConfig.icon />\r\n                  ) : (\r\n                    !hideIndicator && (\r\n                      <div\r\n                        className={cn(\r\n                          \"shrink-0 rounded-[2px] bg-(--color-bg)\",\r\n                          {\r\n                            \"size-2.5 border border-border\":\r\n                              indicator === \"dot\",\r\n                            \"w-1\": indicator === \"line\",\r\n                            \"w-0 border-[1.5px] border-dashed bg-transparent\":\r\n                              indicator === \"dashed\",\r\n                            \"my-0.5\": nestLabel && indicator === \"dashed\",\r\n                          },\r\n                        )}\r\n                        style={\r\n                          {\r\n                            \"--color-bg\": indicatorColor,\r\n                            \"--color-border\": indicatorColor,\r\n                          } as React.CSSProperties\r\n                        }\r\n                      />\r\n                    )\r\n                  )}\r\n                  <div\r\n                    className={cn(\r\n                      \"flex flex-1 justify-between leading-none\",\r\n                      nestLabel ? \"items-end\" : \"items-center\",\r\n                    )}\r\n                  >\r\n                    <div className=\"grid gap-1.5\">\r\n                      {nestLabel ? tooltipLabel : null}\r\n                      <span className=\"text-muted-foreground\">\r\n                        {itemConfig?.label || item.name}\r\n                      </span>\r\n                    </div>\r\n                    {item.value && (\r\n                      <span className=\"text-foreground font-mono font-medium tabular-nums\">\r\n                        {item.value.toLocaleString()}\r\n                      </span>\r\n                    )}\r\n                  </div>\r\n                </>\r\n              )}\r\n            </div>\r\n          )\r\n        })}\r\n      </div>\r\n    </div>\r\n  )\r\n}\r\n\r\nconst ChartLegend = RechartsPrimitive.Legend\r\n\r\nfunction ChartLegendContent({\r\n  className,\r\n  hideIcon = false,\r\n  payload,\r\n  verticalAlign = \"bottom\",\r\n  nameKey,\r\n}: React.ComponentProps<\"div\"> &\r\n  Pick<RechartsPrimitive.LegendProps, \"payload\" | \"verticalAlign\"> & {\r\n    hideIcon?: boolean\r\n    nameKey?: string\r\n  }) {\r\n  const { config } = useChart()\r\n\r\n  if (!payload?.length) {\r\n    return null\r\n  }\r\n\r\n  return (\r\n    <div\r\n      className={cn(\r\n        \"flex items-center justify-center gap-4\",\r\n        verticalAlign === \"top\" ? \"pb-3\" : \"pt-3\",\r\n        className,\r\n      )}\r\n    >\r\n      {payload.map((item) => {\r\n        const key = `${nameKey || item.dataKey || \"value\"}`\r\n        const itemConfig = getPayloadConfigFromPayload(config, item, key)\r\n\r\n        return (\r\n          <div\r\n            key={item.value}\r\n            className={cn(\r\n              \"[&>svg]:text-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3\",\r\n            )}\r\n          >\r\n            {itemConfig?.icon && !hideIcon ? (\r\n              <itemConfig.icon />\r\n            ) : (\r\n              <div\r\n                className=\"h-2 w-2 border border-border shrink-0 rounded-[2px]\"\r\n                style={{\r\n                  backgroundColor: item.color,\r\n                }}\r\n              />\r\n            )}\r\n            {itemConfig?.label}\r\n          </div>\r\n        )\r\n      })}\r\n    </div>\r\n  )\r\n}\r\n\r\n// Helper to extract item config from a payload.\r\nfunction getPayloadConfigFromPayload(\r\n  config: ChartConfig,\r\n  payload: unknown,\r\n  key: string,\r\n) {\r\n  if (typeof payload !== \"object\" || payload === null) {\r\n    return undefined\r\n  }\r\n\r\n  const payloadPayload =\r\n    \"payload\" in payload &&\r\n    typeof payload.payload === \"object\" &&\r\n    payload.payload !== null\r\n      ? payload.payload\r\n      : undefined\r\n\r\n  let configLabelKey: string = key\r\n\r\n  if (\r\n    key in payload &&\r\n    typeof payload[key as keyof typeof payload] === \"string\"\r\n  ) {\r\n    configLabelKey = payload[key as keyof typeof payload] as string\r\n  } else if (\r\n    payloadPayload &&\r\n    key in payloadPayload &&\r\n    typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\r\n  ) {\r\n    configLabelKey = payloadPayload[\r\n      key as keyof typeof payloadPayload\r\n    ] as string\r\n  }\r\n\r\n  return configLabelKey in config\r\n    ? config[configLabelKey]\r\n    : config[key as keyof typeof config]\r\n}\r\n\r\nexport {\r\n  ChartContainer,\r\n  ChartTooltip,\r\n  ChartTooltipContent,\r\n  ChartLegend,\r\n  ChartLegendContent,\r\n  ChartStyle,\r\n}\r\n",
      "type": "registry:ui"
    }
  ]
}