{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "chart",
  "type": "registry:ui",
  "dependencies": [
    "chart.js"
  ],
  "files": [
    {
      "path": "ui/chart.tsx",
      "content": "import type { Component, ComponentProps, JSX } from \"solid-js\"\nimport {\n  createContext,\n  createEffect,\n  mergeProps,\n  onCleanup,\n  splitProps,\n  useContext\n} from \"solid-js\"\n\nimport type { ChartConfiguration, ChartData, ChartOptions, ChartType } from \"chart.js\"\nimport {\n  ArcElement,\n  BarController,\n  BarElement,\n  CategoryScale,\n  Chart as ChartJS,\n  Tooltip as ChartJSTooltip,\n  DoughnutController,\n  Filler,\n  Legend,\n  LinearScale,\n  LineController,\n  LineElement,\n  PieController,\n  PointElement,\n  RadarController,\n  RadialLinearScale,\n  ScatterController\n} from \"chart.js\"\n\nimport { cn } from \"@/lib/utils\"\n\nChartJS.register(\n  ArcElement,\n  BarController,\n  BarElement,\n  CategoryScale,\n  DoughnutController,\n  Filler,\n  Legend,\n  LineController,\n  LineElement,\n  LinearScale,\n  PieController,\n  PointElement,\n  RadarController,\n  RadialLinearScale,\n  ScatterController,\n  ChartJSTooltip\n)\n\n// ---------------------------------------------------------------------------\n// Chart config types\n// ---------------------------------------------------------------------------\n\nexport type ChartConfig = Record<\n  string,\n  {\n    label?: string\n    color?: string\n    icon?: Component\n  }\n>\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ntype ChartContextValue = {\n  config: ChartConfig\n}\n\nconst ChartContext = createContext<ChartContextValue>({ config: {} })\n\nfunction useChart() {\n  return useContext(ChartContext)\n}\n\n// ---------------------------------------------------------------------------\n// CSS variables helper\n// ---------------------------------------------------------------------------\n\nfunction chartConfigToCssVars(config: ChartConfig): Record<string, string> {\n  const vars: Record<string, string> = {}\n  let index = 0\n  for (const [, value] of Object.entries(config)) {\n    if (value.color) {\n      vars[`--chart-${index + 1}`] = value.color\n    }\n    index++\n  }\n  return vars\n}\n\n// ---------------------------------------------------------------------------\n// ChartContainer\n// ---------------------------------------------------------------------------\n\ntype ChartContainerProps = ComponentProps<\"div\"> & {\n  config: ChartConfig\n  children: JSX.Element\n}\n\nconst ChartContainer: Component<ChartContainerProps> = (rawProps) => {\n  const [local, others] = splitProps(rawProps, [\"class\", \"children\", \"config\", \"style\"])\n\n  const cssVars = () => chartConfigToCssVars(local.config)\n\n  return (\n    <ChartContext.Provider value={{ config: local.config }}>\n      <div\n        class={cn(\n          \"flex aspect-video justify-center text-xs [&_canvas]:max-h-[inherit] [&_canvas]:max-w-full\",\n          local.class\n        )}\n        data-slot=\"chart\"\n        style={{\n          ...(typeof local.style === \"object\" ? local.style : {}),\n          ...cssVars()\n        }}\n        {...others}\n      >\n        {local.children}\n      </div>\n    </ChartContext.Provider>\n  )\n}\n\n// ---------------------------------------------------------------------------\n// Core Chart component\n// ---------------------------------------------------------------------------\n\ntype ChartProps<T extends ChartType = ChartType> = ComponentProps<\"canvas\"> & {\n  type: T\n  data: ChartData<T>\n  options?: ChartOptions<T>\n}\n\nfunction Chart<T extends ChartType = ChartType>(rawProps: ChartProps<T>) {\n  const props = mergeProps({ options: {} as ChartOptions<T> }, rawProps)\n  const [local, others] = splitProps(props, [\"type\", \"data\", \"options\", \"class\"])\n\n  let canvasRef!: HTMLCanvasElement\n  let chartInstance: ChartJS | undefined\n\n  const resolvedOptions = (): ChartOptions<T> => {\n    const base: ChartOptions = {\n      responsive: true,\n      maintainAspectRatio: false,\n      plugins: {\n        legend: {\n          display: true,\n          position: \"bottom\" as const,\n          labels: {\n            usePointStyle: true,\n            padding: 16\n          }\n        },\n        tooltip: {\n          enabled: true,\n          backgroundColor: \"hsl(var(--popover))\",\n          titleColor: \"hsl(var(--popover-foreground))\",\n          bodyColor: \"hsl(var(--popover-foreground))\",\n          borderColor: \"hsl(var(--border))\",\n          borderWidth: 1,\n          cornerRadius: 6,\n          padding: 8,\n          boxPadding: 4\n        }\n      }\n    }\n\n    return mergeChartOptions(base, local.options ?? {}) as ChartOptions<T>\n  }\n\n  createEffect(() => {\n    const type = local.type\n    const data = local.data\n    const options = resolvedOptions()\n\n    if (chartInstance) {\n      chartInstance.data = data as ChartData\n      chartInstance.options = options as ChartOptions\n      chartInstance.update()\n    } else if (canvasRef) {\n      chartInstance = new ChartJS(canvasRef, {\n        type,\n        data: data as ChartData,\n        options: options as ChartOptions\n      } as ChartConfiguration)\n    }\n  })\n\n  onCleanup(() => {\n    chartInstance?.destroy()\n    chartInstance = undefined\n  })\n\n  return (\n    <canvas\n      class={cn(local.class)}\n      data-slot=\"chart-canvas\"\n      ref={canvasRef!}\n      role=\"img\"\n      {...others}\n    />\n  )\n}\n\n// ---------------------------------------------------------------------------\n// Convenience chart components\n// ---------------------------------------------------------------------------\n\ntype TypedChartProps<T extends ChartType> = Omit<ChartProps<T>, \"type\">\n\nconst LineChart: Component<TypedChartProps<\"line\">> = (props) => {\n  return <Chart type=\"line\" {...props} />\n}\n\nconst BarChart: Component<TypedChartProps<\"bar\">> = (props) => {\n  return <Chart type=\"bar\" {...props} />\n}\n\nconst PieChart: Component<TypedChartProps<\"pie\">> = (props) => {\n  return <Chart type=\"pie\" {...props} />\n}\n\nconst DoughnutChart: Component<TypedChartProps<\"doughnut\">> = (props) => {\n  return <Chart type=\"doughnut\" {...props} />\n}\n\nconst RadarChart: Component<TypedChartProps<\"radar\">> = (props) => {\n  return <Chart type=\"radar\" {...props} />\n}\n\nconst ScatterChart: Component<TypedChartProps<\"scatter\">> = (props) => {\n  return <Chart type=\"scatter\" {...props} />\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction mergeChartOptions(\n  base: Record<string, any>,\n  override: Record<string, any>\n): Record<string, any> {\n  const result = { ...base }\n  for (const key of Object.keys(override)) {\n    if (\n      override[key] &&\n      typeof override[key] === \"object\" &&\n      !Array.isArray(override[key]) &&\n      base[key] &&\n      typeof base[key] === \"object\" &&\n      !Array.isArray(base[key])\n    ) {\n      result[key] = mergeChartOptions(base[key], override[key])\n    } else {\n      result[key] = override[key]\n    }\n  }\n  return result\n}\n\nexport {\n  Chart,\n  ChartContainer,\n  LineChart,\n  BarChart,\n  PieChart,\n  DoughnutChart,\n  RadarChart,\n  ScatterChart,\n  useChart,\n  type ChartProps\n}\n",
      "type": "registry:ui"
    }
  ]
}