{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "steps-card",
  "title": "Steps Chart",
  "description": "Weekly steps bars with a goal marker, week switcher, and count-up total.",
  "dependencies": [
    "recharts@^3.10.1"
  ],
  "registryDependencies": [
    "https://components.exe.xyz/r/chart-card.json"
  ],
  "files": [
    {
      "path": "src/components/charts/steps-card.tsx",
      "content": "import { useState } from \"react\"\nimport {\n  Bar,\n  BarChart,\n  CartesianGrid,\n  ReferenceLine,\n  ResponsiveContainer,\n  Tooltip,\n  XAxis,\n  YAxis,\n} from \"recharts\"\n\nimport {\n  ChartCard,\n  ChartPlot,\n  ChartWeekRange,\n  axisTick,\n  formatNumber,\n  usePrefersReducedMotion,\n} from \"@/components/charts/chart-card\"\n\nexport type StepsDay = { label: string; value: number }\n\nexport type StepsWeek = {\n  rangeLabel: string\n  days: StepsDay[]\n}\n\nconst DEFAULT_WEEKS: StepsWeek[] = [\n  {\n    rangeLabel: \"22–28 Jun\",\n    days: [\n      { label: \"Mon\", value: 3900 },\n      { label: \"Tue\", value: 5120 },\n      { label: \"Wed\", value: 6400 },\n      { label: \"Thu\", value: 4710 },\n      { label: \"Fri\", value: 3280 },\n      { label: \"Sat\", value: 2100 },\n      { label: \"Sun\", value: 3390 },\n    ],\n  },\n  {\n    rangeLabel: \"29 Jun–5 Jul\",\n    days: [\n      { label: \"Mon\", value: 4120 },\n      { label: \"Tue\", value: 6420 },\n      { label: \"Wed\", value: 8100 },\n      { label: \"Thu\", value: 7800 },\n      { label: \"Fri\", value: 2910 },\n      { label: \"Sat\", value: 1240 },\n      { label: \"Sun\", value: 1010 },\n    ],\n  },\n  {\n    rangeLabel: \"6–12 Jul\",\n    days: [\n      { label: \"Mon\", value: 4680 },\n      { label: \"Tue\", value: 5210 },\n      { label: \"Wed\", value: 6940 },\n      { label: \"Thu\", value: 4580 },\n      { label: \"Fri\", value: 3720 },\n      { label: \"Sat\", value: 2410 },\n      { label: \"Sun\", value: 2560 },\n    ],\n  },\n]\n\nfunction StepsTooltip({\n  active,\n  payload,\n  label,\n}: {\n  active?: boolean\n  payload?: ReadonlyArray<{ value?: unknown }>\n  label?: string | number\n}) {\n  if (!active || !payload?.length) return null\n  const value = payload[0]?.value\n  if (typeof value !== \"number\") return null\n  return (\n    <div className=\"rounded-[2px] border border-border bg-card px-2.5 py-1.5 text-xs shadow-sm\">\n      <p className=\"font-mono text-[11px] tabular-nums\">\n        {label} · {formatNumber(value)} steps\n      </p>\n    </div>\n  )\n}\n\nexport function StepsCard({\n  title = \"Total steps\",\n  days,\n  goal = 8000,\n  rangeLabel,\n  onPrevRange,\n  onNextRange,\n  className,\n}: {\n  title?: string\n  days?: StepsDay[]\n  goal?: number\n  rangeLabel?: string\n  onPrevRange?: () => void\n  onNextRange?: () => void\n  className?: string\n}) {\n  const reduced = usePrefersReducedMotion()\n  const [weekIndex, setWeekIndex] = useState(1)\n  const mock = DEFAULT_WEEKS[weekIndex] ?? DEFAULT_WEEKS[1]\n  const plotDays = days ?? mock.days\n  const plotRange = rangeLabel ?? mock.rangeLabel\n  const total = plotDays.reduce((sum, day) => sum + day.value, 0)\n  const peak = Math.max(goal, ...plotDays.map((day) => day.value), 1)\n  const summary = `${title} ${formatNumber(total)}. Goal ${formatNumber(goal)} steps per day. ${plotRange}.`\n\n  const handlePrev = () => {\n    if (days == null) setWeekIndex((index) => Math.max(0, index - 1))\n    onPrevRange?.()\n  }\n  const handleNext = () => {\n    if (days == null) {\n      setWeekIndex((index) => Math.min(DEFAULT_WEEKS.length - 1, index + 1))\n    }\n    onNextRange?.()\n  }\n\n  return (\n    <ChartCard\n      title={title}\n      headline={total}\n      className={className}\n      periodControl={\n        <ChartWeekRange\n          label={plotRange}\n          onPrev={handlePrev}\n          onNext={handleNext}\n        />\n      }\n      summary={summary}\n    >\n      <ChartPlot height={220} summary={summary}>\n        <ResponsiveContainer width=\"100%\" height=\"100%\">\n          <BarChart\n            data={plotDays}\n            margin={{ top: 8, right: 8, left: 0, bottom: 0 }}\n            barCategoryGap=\"22%\"\n          >\n            <CartesianGrid\n              vertical={false}\n              stroke=\"var(--border)\"\n              strokeDasharray=\"1 4\"\n            />\n            <XAxis\n              dataKey=\"label\"\n              tick={axisTick}\n              tickLine={false}\n              axisLine={{ stroke: \"var(--border)\" }}\n            />\n            <YAxis\n              tick={axisTick}\n              tickLine={false}\n              axisLine={false}\n              width={40}\n              domain={[0, Math.ceil((peak * 1.12) / 1000) * 1000]}\n              tickFormatter={(value: number) =>\n                value >= 1000\n                  ? `${Math.round(value / 100) / 10}k`\n                  : String(value)\n              }\n            />\n            <ReferenceLine\n              y={goal}\n              stroke=\"var(--chart-5)\"\n              strokeDasharray=\"4 4\"\n              ifOverflow=\"extendDomain\"\n            />\n            <Tooltip cursor={false} content={<StepsTooltip />} />\n            <Bar\n              dataKey=\"value\"\n              name=\"Steps\"\n              fill=\"var(--chart-1)\"\n              radius={2}\n              maxBarSize={42}\n              isAnimationActive={!reduced}\n              activeBar={{\n                fill: \"var(--chart-1)\",\n                stroke: \"var(--ring)\",\n                strokeWidth: 2,\n                radius: 2,\n              }}\n            />\n          </BarChart>\n        </ResponsiveContainer>\n      </ChartPlot>\n      <p className=\"sr-only\">\n        Goal {formatNumber(goal)} steps per day, shown as a dashed line.\n      </p>\n    </ChartCard>\n  )\n}\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:block"
}