{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "segmented-gauge",
  "title": "Segmented Gauge",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-vue/components/charts/segmented-gauge/SegmentedGauge.vue",
      "content": "<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { HTMLAttributes } from 'vue'\nimport { cn } from '@/lib/utils'\n\ninterface GaugeSegment {\n  /** Relative size of the segment. Segments are normalised by their sum. */\n  value: number\n  /** Optional override; defaults to chart-1..N from the registry palette. */\n  color?: string\n  /** Optional label, surfaced via the default slot for consumers that\n   *  want to render their own legend. */\n  label?: string\n}\n\ninterface Props {\n  segments: GaugeSegment[]\n  /** Container height (px when numeric, raw CSS when string). Default 200. */\n  height?: number | string\n  /** Stroke width of the arc in SVG units. Default 18. */\n  stroke?: number\n  /** Angular gap between segments, in degrees. Default 4. */\n  gap?: number\n  /** Optional fallback palette when `color` is omitted on a segment. */\n  colors?: string[]\n  /** Show a faint background track behind the arc. Default true. */\n  showTrack?: boolean\n  class?: HTMLAttributes['class']\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n  height: 200,\n  stroke: 18,\n  gap: 4,\n  showTrack: true,\n  colors: () => ['#3b82f6', '#0ea5e9', '#34d399', '#facc15', '#fb7185', '#a855f7'],\n})\n\n// SVG geometry. The viewBox uses the centre + radius + stroke so the\n// canvas grows with the stroke width and the labels in the default slot\n// can sit underneath without overlapping the arc.\nconst cx = 140\nconst cy = 124\nconst r = 100\n\nfunction polar(angleDeg: number) {\n  const a = ((angleDeg - 90) * Math.PI) / 180\n  return [cx + r * Math.cos(a), cy + r * Math.sin(a)] as const\n}\n\nfunction arcPath(startA: number, endA: number) {\n  const [sx, sy] = polar(startA)\n  const [ex, ey] = polar(endA)\n  const largeArc = endA - startA > 180 ? 1 : 0\n  return `M ${sx.toFixed(2)} ${sy.toFixed(2)} A ${r} ${r} 0 ${largeArc} 1 ${ex.toFixed(2)} ${ey.toFixed(2)}`\n}\n\nconst startAngle = 180\nconst sweep = 180\n\nconst arcs = computed(() => {\n  const total = props.segments.reduce((acc, s) => acc + s.value, 0) || 1\n  let cursor = startAngle\n  return props.segments.map((s, i) => {\n    const span = (s.value / total) * sweep\n    const isLast = i === props.segments.length - 1\n    const segEnd = cursor + span - (isLast ? 0 : props.gap)\n    const arc = { d: arcPath(cursor, segEnd), color: s.color ?? props.colors[i % props.colors.length] }\n    cursor = cursor + span\n    return arc\n  })\n})\n\nconst trackPath = computed(() => arcPath(startAngle, startAngle + sweep))\n\nconst heightStyle = computed(() => (/^\\d+$/.test(String(props.height)) ? `${props.height}px` : String(props.height)))\n</script>\n\n<template>\n  <div\n    data-uipkge\n    data-slot=\"segmented-gauge\"\n    tabindex=\"0\"\n    :style=\"{ height: heightStyle }\"\n    :class=\"cn('focus-visible:ring-ring relative w-full focus-visible:ring-2 focus-visible:outline-none', props.class)\"\n  >\n    <svg\n      :viewBox=\"`0 0 ${cx * 2} ${cy + stroke}`\"\n      class=\"block h-full w-full\"\n      preserveAspectRatio=\"xMidYMid meet\"\n      role=\"img\"\n    >\n      <path\n        v-if=\"showTrack\"\n        :d=\"trackPath\"\n        fill=\"none\"\n        stroke=\"currentColor\"\n        :stroke-width=\"stroke\"\n        stroke-linecap=\"round\"\n        class=\"text-muted/40\"\n        opacity=\"0.35\"\n      />\n      <path\n        v-for=\"(a, i) in arcs\"\n        :key=\"i\"\n        :d=\"a.d\"\n        fill=\"none\"\n        :stroke=\"a.color\"\n        :stroke-width=\"stroke\"\n        stroke-linecap=\"round\"\n      />\n    </svg>\n    <div v-if=\"$slots.center\" class=\"pointer-events-none absolute inset-x-0 bottom-[8%] flex flex-col items-center\">\n      <slot name=\"center\" />\n    </div>\n  </div>\n</template>\n",
      "type": "registry:ui",
      "target": "~/app/components/ui/charts/segmented-gauge/SegmentedGauge.vue"
    },
    {
      "path": "packages/registry-vue/components/charts/segmented-gauge/index.ts",
      "content": "export { default as SegmentedGauge } from './SegmentedGauge.vue'\n",
      "type": "registry:ui",
      "target": "~/app/components/ui/charts/segmented-gauge/index.ts"
    }
  ],
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [],
  "description": "Semicircular SVG gauge split into colored segments by relative value. Pure SVG (no ECharts). Rounded line caps + an angular gap between segments produce the pill-shaped look; a center slot lets consumers drop a KPI value + label into the dish.",
  "categories": [
    "chart"
  ]
}