{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "gauge-chart",
  "title": "Gauge Chart",
  "description": "Semicircular gauge for a single value within a range.",
  "dependencies": [
    "@vllnt/ui@^0.2.1"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/default/gauge-chart/gauge-chart.tsx",
      "content": "import * as React from \"react\";\n\nimport { cn } from \"@vllnt/ui\";\n\n/**\n * Props for {@link GaugeChart}.\n *\n * @public\n */\nexport type GaugeChartProps = {\n  /** Color of the filled arc. Defaults to `currentColor`. */\n  color?: string;\n  /** Optional caption under the value. */\n  label?: string;\n  /** Upper bound of the scale. @defaultValue 100 */\n  max?: number;\n  /** Lower bound of the scale. @defaultValue 0 */\n  min?: number;\n  /** Draw the value in the center. @defaultValue true */\n  showValue?: boolean;\n  /** Square viewport width in pixels; the height spans about half. @defaultValue 200 */\n  size?: number;\n  /** Arc thickness in pixels. @defaultValue 16 */\n  thickness?: number;\n  /** Current value. The chart clamps it to `[min, max]`. */\n  value: number;\n} & React.HTMLAttributes<HTMLDivElement>;\n\nconst DEFAULT_SIZE = 200;\nconst DEFAULT_MIN = 0;\nconst DEFAULT_MAX = 100;\nconst DEFAULT_THICKNESS = 16;\n\ntype Point = { x: number; y: number };\ntype ArcGeom = { center: Point; end: number; radius: number; start: number };\n\nfunction clamp(value: number, low: number, high: number): number {\n  return Math.min(Math.max(value, low), high);\n}\n\nfunction polar(center: Point, radius: number, degrees: number): Point {\n  const radians = (degrees * Math.PI) / 180;\n  return {\n    x: center.x + radius * Math.cos(radians),\n    y: center.y + radius * Math.sin(radians),\n  };\n}\n\nfunction arc(geom: ArcGeom): string {\n  const from = polar(geom.center, geom.radius, geom.start);\n  const to = polar(geom.center, geom.radius, geom.end);\n  const largeArc = geom.end - geom.start > 180 ? 1 : 0;\n  return `M ${from.x.toFixed(2)} ${from.y.toFixed(2)} A ${geom.radius} ${geom.radius} 0 ${largeArc} 1 ${to.x.toFixed(2)} ${to.y.toFixed(2)}`;\n}\n\nfunction GaugeText({\n  center,\n  label,\n  showValue,\n  size,\n  value,\n}: {\n  center: Point;\n  label?: string;\n  showValue: boolean;\n  size: number;\n  value: number;\n}) {\n  return (\n    <>\n      {showValue ? (\n        <text\n          className=\"fill-foreground font-semibold\"\n          dominantBaseline=\"middle\"\n          fontSize={size * 0.16}\n          textAnchor=\"middle\"\n          x={center.x}\n          y={center.y - size * 0.06}\n        >\n          {Math.round(value).toLocaleString()}\n        </text>\n      ) : null}\n      {label ? (\n        <text\n          className=\"fill-muted-foreground text-xs\"\n          dominantBaseline=\"middle\"\n          textAnchor=\"middle\"\n          x={center.x}\n          y={center.y + size * 0.1}\n        >\n          {label}\n        </text>\n      ) : null}\n    </>\n  );\n}\n\n/**\n * Token-styled SVG gauge (semicircular meter).\n *\n * Pure SVG, no chart dependency. The track uses the `muted` token and the\n * filled arc uses `currentColor`, so the gauge follows the active theme. The\n * chart clamps `value` to `[min, max]`.\n *\n * @example\n * ```tsx\n * <GaugeChart className=\"text-primary\" label=\"CPU load\" value={72} />\n * ```\n *\n * @public\n */\nexport const GaugeChart = ({\n  className,\n  color = \"currentColor\",\n  label,\n  max = DEFAULT_MAX,\n  min = DEFAULT_MIN,\n  ref,\n  showValue = true,\n  size = DEFAULT_SIZE,\n  thickness = DEFAULT_THICKNESS,\n  value,\n  ...props\n}: GaugeChartProps & { ref?: React.Ref<HTMLDivElement> }) => {\n  const span = max - min;\n  const fraction = span > 0 ? clamp((value - min) / span, 0, 1) : 0;\n  const center: Point = { x: size / 2, y: size / 2 };\n  const radius = size / 2 - thickness / 2;\n  const viewHeight = size / 2 + thickness + 28;\n\n  return (\n    <div\n      className={cn(\n        \"rounded-2xl border border-border bg-background/40 p-3\",\n        className,\n      )}\n      ref={ref}\n      {...props}\n    >\n      <svg\n        aria-label=\"Gauge chart\"\n        className=\"h-full w-full\"\n        height={viewHeight}\n        role=\"img\"\n        viewBox={`0 0 ${size} ${viewHeight}`}\n        width={size}\n      >\n        <path\n          className=\"stroke-muted\"\n          d={arc({ center, end: 360, radius, start: 180 })}\n          fill=\"none\"\n          strokeLinecap=\"round\"\n          strokeWidth={thickness}\n        />\n        {fraction > 0 ? (\n          <path\n            d={arc({ center, end: 180 + fraction * 180, radius, start: 180 })}\n            fill=\"none\"\n            stroke={color}\n            strokeLinecap=\"round\"\n            strokeWidth={thickness}\n          />\n        ) : null}\n        <GaugeText\n          center={center}\n          label={label}\n          showValue={showValue}\n          size={size}\n          value={value}\n        />\n      </svg>\n    </div>\n  );\n};\n\nGaugeChart.displayName = \"GaugeChart\";\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component",
  "version": "0.2.1",
  "stability": "stable"
}
