{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "hover-trace-bar-chart",
  "description": "Bar chart with active value line and animated marker",
  "dependencies": [
    "recharts",
    "motion",
    "@number-flow/react"
  ],
  "registryDependencies": [
    "@evilcharts/recharts-chart"
  ],
  "files": [
    {
      "path": "src/registry/blocks/recharts/b-hover-trace-bar-chart.tsx",
      "content": "\"use client\";\n\nimport {\n  Bar,\n  BarChart,\n  Rectangle,\n  ReferenceLine,\n  Tooltip,\n  XAxis,\n  type BarShapeProps,\n  type CartesianViewBox,\n} from \"recharts\";\nimport { type ChartConfig, ChartContainer } from \"@/registry/ui/recharts-chart\";\nimport { useMotionValueEvent, useSpring } from \"motion/react\";\nimport NumberFlow from \"@number-flow/react\";\nimport * as React from \"react\";\n\nconst CHART_MARGIN = 38;\n\nconst chartData = [\n  { month: \"January\", desktop: 342 },\n  { month: \"February\", desktop: 676 },\n  { month: \"March\", desktop: 512 },\n  { month: \"April\", desktop: 629 },\n  { month: \"May\", desktop: 458 },\n  { month: \"June\", desktop: 781 },\n  { month: \"July\", desktop: 394 },\n  { month: \"August\", desktop: 924 },\n  { month: \"September\", desktop: 647 },\n  { month: \"October\", desktop: 532 },\n  { month: \"November\", desktop: 803 },\n  { month: \"December\", desktop: 271 },\n  { month: \"January\", desktop: 342 },\n  { month: \"February\", desktop: 876 },\n  { month: \"March\", desktop: 512 },\n  { month: \"April\", desktop: 629 },\n];\n\nconst chartConfig = {\n  desktop: {\n    label: \"Desktop\",\n    colors: {\n      light: [\"#18181b\"],\n      dark: [\"#fafafa\"],\n    },\n  },\n} satisfies ChartConfig;\n\nexport function EvilHoverTraceBarChart() {\n  const [activeIndex, setActiveIndex] = React.useState<number | null>(null);\n\n  const maxData = React.useMemo(\n    () =>\n      chartData.reduce(\n        (max, item, index) =>\n          item.desktop > max.value ? { index, month: item.month, value: item.desktop } : max,\n        { index: 0, month: chartData[0].month, value: chartData[0].desktop },\n      ),\n    [],\n  );\n\n  const selectedData =\n    activeIndex != null && chartData[activeIndex]\n      ? {\n          index: activeIndex,\n          month: chartData[activeIndex].month,\n          value: chartData[activeIndex].desktop,\n        }\n      : maxData;\n\n  const valueSpring = useSpring(selectedData.value, {\n    stiffness: 110,\n    damping: 20,\n  });\n  const [springValue, setSpringValue] = React.useState(selectedData.value);\n\n  const handleBarHover = React.useCallback(\n    (index: number) => {\n      setActiveIndex(index);\n      valueSpring.set(chartData[index]?.desktop ?? maxData.value);\n    },\n    [maxData.value, valueSpring],\n  );\n\n  useMotionValueEvent(valueSpring, \"change\", (latest) => {\n    setSpringValue(Math.round(latest));\n  });\n\n  return (\n    <div className=\"flex h-full flex-col p-4\">\n      <div className=\"mb-4 flex items-end justify-between\">\n        <div className=\"space-y-1\">\n          <p className=\"text-muted-foreground font-mono text-xs\">{\"[desktop] Value\"}</p>\n          <p className=\"text-primary font-mono text-3xl tracking-tighter\">\n            <NumberFlow\n              value={selectedData.value}\n              format={{ style: \"currency\", currency: \"USD\", currencyDisplay: \"narrowSymbol\" }}\n            />\n          </p>\n        </div>\n\n        <div className=\"space-y-1 text-right\">\n          <p className=\"text-muted-foreground font-mono text-[10px]\">{\"[month]\"}</p>\n          <p className=\"text-primary font-mono text-xs\">{selectedData.month}</p>\n        </div>\n      </div>\n\n      <ChartContainer config={chartConfig}>\n        <BarChart\n          accessibilityLayer\n          data={chartData}\n          margin={{ left: CHART_MARGIN }}\n          onMouseMove={(state) => {\n            if (state?.activeTooltipIndex != null) {\n              handleBarHover(Number(state.activeTooltipIndex));\n            }\n          }}\n          onMouseLeave={() => {\n            setActiveIndex(null);\n            valueSpring.set(maxData.value);\n          }}\n        >\n          <XAxis\n            dataKey=\"month\"\n            tickLine={false}\n            tickMargin={10}\n            axisLine={false}\n            tickFormatter={(value: string) => value.slice(0, 3)}\n          />\n\n          <Tooltip cursor={false} content={() => null} />\n\n          <Bar\n            dataKey=\"desktop\"\n            fill=\"var(--color-desktop-0)\"\n            radius={4}\n            shape={(props: BarShapeProps) => (\n              <HoverTraceBarShape {...props} highlightedIndex={selectedData.index} />\n            )}\n            activeBar={(props: BarShapeProps) => (\n              <HoverTraceBarShape {...props} highlightedIndex={selectedData.index} />\n            )}\n          />\n\n          <ReferenceLine\n            y={springValue}\n            stroke=\"var(--foreground)\"\n            strokeDasharray=\"3 3\"\n            label={<HoverTraceLabel value={selectedData.value} />}\n          />\n        </BarChart>\n      </ChartContainer>\n    </div>\n  );\n}\n\ninterface HoverTraceLabelProps {\n  viewBox?: CartesianViewBox;\n  value: number;\n}\n\nconst HoverTraceLabel = ({ viewBox, value }: HoverTraceLabelProps) => {\n  const x = viewBox?.x ?? 0;\n  const y = viewBox?.y ?? 0;\n  const formattedValue = value.toLocaleString();\n  const width = formattedValue.length * 8 + 12;\n\n  return (\n    <>\n      <rect\n        x={x - CHART_MARGIN}\n        y={y - 9}\n        width={width}\n        height={18}\n        fill=\"var(--foreground)\"\n        rx={4}\n      />\n      <text\n        className=\"font-mono text-[11px]\"\n        fontWeight={600}\n        x={x - CHART_MARGIN + 7}\n        y={y + 4}\n        fill=\"var(--background)\"\n      >\n        {formattedValue}\n      </text>\n      <ellipse cx={\"99.5%\"} cy={y} rx={3} ry={3} fill=\"var(--foreground)\" />\n    </>\n  );\n};\n\ntype HoverTraceBarShapeProps = BarShapeProps & {\n  highlightedIndex: number;\n};\n\nconst HoverTraceBarShape = (props: HoverTraceBarShapeProps) => {\n  const { x, y, width, height, fill, index, isActive, highlightedIndex } = props;\n\n  const fillOpacity = isActive || index === highlightedIndex ? 1 : 0.2;\n\n  return (\n    <g>\n      <Rectangle {...props} fill=\"transparent\" pointerEvents=\"all\" />\n      <Rectangle\n        x={x}\n        y={y}\n        width={width}\n        height={height}\n        radius={4}\n        fill={fill}\n        fillOpacity={fillOpacity}\n        stroke={isActive ? \"var(--foreground)\" : undefined}\n        strokeOpacity={isActive ? 0.35 : undefined}\n        strokeWidth={isActive ? 1 : undefined}\n        className=\"transition-opacity duration-200\"\n      />\n    </g>\n  );\n};\n",
      "type": "registry:block",
      "target": "components/evilcharts/blocks/hover-trace-bar-chart.tsx"
    }
  ],
  "type": "registry:block"
}