{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "sparkline",
  "title": "Sparkline",
  "author": "Ballmac <https://ui.ballmac.com>",
  "description": "A lightweight accessible SVG trend line with a marked latest value and no chart dependency.",
  "registryDependencies": [
    "utils",
    "https://ui.ballmac.com/r/i18n.json"
  ],
  "files": [
    {
      "path": "registry/ballmac/components/sparkline.tsx",
      "content": "// Ballmac UI: Sparkline. https://ui.ballmac.com/components/sparkline\n\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/lib/utils\"\nimport { useMessages } from \"@/lib/ballmac/i18n\"\n\ntype SparklineProps = Omit<React.ComponentProps<\"svg\">, \"values\"> & {\n  /** Ordered numeric samples. */ values: number[]\n  /** Accessible description of the series. */ label: string\n  /** Height in pixels. */ height?: number\n  /** Show the last data point. */ showEnd?: boolean\n}\nfunction Sparkline({\n  className,\n  values,\n  label,\n  height = 48,\n  showEnd = true,\n  ...props\n}: SparklineProps) {\n  const msg = useMessages()\n  const safe = values.filter(Number.isFinite)\n  const minimum = Math.min(...safe)\n  const maximum = Math.max(...safe)\n  const span = maximum - minimum || 1\n  const points = safe.map((value, index) => ({\n    x: safe.length === 1 ? 50 : 4 + (index / (safe.length - 1)) * 92,\n    y: 42 - ((value - minimum) / span) * 34,\n  }))\n  const path = points\n    .map(\n      (point, index) =>\n        `${index ? \"L\" : \"M\"}${point.x.toFixed(2)} ${point.y.toFixed(2)}`,\n    )\n    .join(\" \")\n  const last = points.at(-1)\n  return (\n    <svg\n      data-slot=\"sparkline\"\n      role=\"img\"\n      aria-label={safe.length ? msg(\"sparkline.range\", \"{label}: from {from} to {to}\", { label, from: safe[0], to: safe.at(-1) ?? \"\" }) : msg(\"sparkline.noData\", \"{label}: no data\", { label })}\n      viewBox=\"0 0 100 48\"\n      preserveAspectRatio=\"none\"\n      height={height}\n      className={cn(\"text-primary w-full overflow-visible\", className)}\n      {...props}\n    >\n      {safe.length > 1 && (\n        <path\n          d={path}\n          fill=\"none\"\n          stroke=\"currentColor\"\n          strokeWidth=\"2.5\"\n          strokeLinecap=\"round\"\n          strokeLinejoin=\"round\"\n          vectorEffect=\"non-scaling-stroke\"\n        />\n      )}\n      {showEnd && last && (\n        <circle\n          cx={last.x}\n          cy={last.y}\n          r=\"3\"\n          fill=\"currentColor\"\n          vectorEffect=\"non-scaling-stroke\"\n        />\n      )}\n    </svg>\n  )\n}\nexport { Sparkline, type SparklineProps }\n",
      "type": "registry:ui",
      "target": "@components/ballmac/sparkline.tsx"
    }
  ],
  "meta": {
    "schema": 1,
    "tier": "free",
    "tags": [
      "chart",
      "trend",
      "data"
    ],
    "version": "1.0.0",
    "updated": "2026-09-30",
    "ai": {
      "summary": "A lightweight accessible SVG trend line with a marked latest value and no chart dependency.",
      "whenToUse": [
        "Show a small trend beside a metric"
      ],
      "whenNotToUse": [
        "Use a full chart for axes and detailed inspection"
      ],
      "composesWith": [
        "stat-card"
      ],
      "a11y": [
        {
          "keys": "None",
          "action": "Trend description is announced as an image"
        }
      ],
      "customization": [
        "Content, layout, and token-based className styling"
      ]
    },
    "examples": [
      "sparkline-demo",
      "sparkline-states"
    ],
    "url": "https://ui.ballmac.com/components/sparkline"
  },
  "categories": [
    "data-display"
  ],
  "type": "registry:ui"
}