{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "segmented-gauge",
  "title": "Segmented Gauge",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-svelte/components/segmented-gauge/SegmentedGauge.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { Snippet } from 'svelte'\n  import type { HTMLAttributes } from 'svelte/elements'\n\n  export interface 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 for consumers that want to render their own legend. */\n    label?: string\n  }\n\n  export interface SegmentedGaugeProps extends HTMLAttributes<HTMLDivElement> {\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    /** Accessible name announced for the chart image. Defaults to \"Chart\". */\n    ariaLabel?: string\n    /** KPI value + label dropped into the dish of the gauge. */\n    center?: Snippet\n    ref?: HTMLDivElement | null\n  }\n</script>\n\n<script lang=\"ts\">\n  import { cn } from '$lib/utils'\n\n  let {\n    class: className,\n    segments,\n    height = 200,\n    stroke = 18,\n    gap = 4,\n    colors = ['var(--chart-1)', 'var(--chart-2)', 'var(--chart-3)', 'var(--chart-4)', 'var(--chart-5)'],\n    showTrack = true,\n    ariaLabel,\n    center,\n    ref = $bindable(null),\n    ...restProps\n  }: SegmentedGaugeProps = $props()\n\n  // SVG geometry. The viewBox uses the centre + radius + stroke so the\n  // canvas grows with the stroke width and the center snippet can sit\n  // underneath without overlapping the arc.\n  const cx = 140\n  const cy = 124\n  const r = 100\n\n  function 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\n  function 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\n  const startAngle = 180\n  const sweep = 180\n\n  const arcs = $derived.by(() => {\n    const total = segments.reduce((acc, s) => acc + s.value, 0) || 1\n    let cursor = startAngle\n    return segments.map((s, i) => {\n      const span = (s.value / total) * sweep\n      const isLast = i === segments.length - 1\n      const segEnd = cursor + span - (isLast ? 0 : gap)\n      const arc = { d: arcPath(cursor, segEnd), color: s.color ?? colors[i % colors.length] }\n      cursor = cursor + span\n      return arc\n    })\n  })\n\n  const trackPath = arcPath(startAngle, startAngle + sweep)\n  const heightStyle = $derived(/^\\d+$/.test(String(height)) ? `${height}px` : String(height))\n</script>\n\n<div\n  bind:this={ref}\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', className)}\n  {...restProps}\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    aria-label={ariaLabel || 'Chart'}\n  >\n    {#if showTrack}\n      <path\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    {/if}\n    {#each arcs as a (a.d)}\n      <path d={a.d} fill=\"none\" stroke={a.color} stroke-width={stroke} stroke-linecap=\"round\" />\n    {/each}\n  </svg>\n  {#if center}\n    <div class=\"pointer-events-none absolute inset-x-0 bottom-[8%] flex flex-col items-center\">\n      {@render center()}\n    </div>\n  {/if}\n</div>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/segmented-gauge/SegmentedGauge.svelte"
    },
    {
      "path": "packages/registry-svelte/components/segmented-gauge/index.ts",
      "content": "export { default as SegmentedGauge, type SegmentedGaugeProps, type GaugeSegment } from './SegmentedGauge.svelte'\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/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"
  ]
}