{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "segmented-gauge",
  "title": "Segmented Gauge",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-angular/components/charts/segmented-gauge/segmented-gauge.component.ts",
      "content": "import { Component, Input, booleanAttribute, ChangeDetectionStrategy } from '@angular/core'\nimport { cn } from '@/lib/utils'\n\nexport 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// SVG geometry mirrors React/Vue 1:1. The viewBox uses the centre + radius +\n// stroke so the canvas grows with the stroke width and the centre content can\n// sit underneath without overlapping the arc.\nconst SG_CX = 140\nconst SG_CY = 124\nconst SG_R = 100\nconst SG_START = 180\nconst SG_SWEEP = 180\n\nfunction sgPolar(angleDeg: number): readonly [number, number] {\n  const a = ((angleDeg - 90) * Math.PI) / 180\n  return [SG_CX + SG_R * Math.cos(a), SG_CY + SG_R * Math.sin(a)] as const\n}\n\nfunction sgArcPath(startA: number, endA: number): string {\n  const [sx, sy] = sgPolar(startA)\n  const [ex, ey] = sgPolar(endA)\n  const largeArc = endA - startA > 180 ? 1 : 0\n  return `M ${sx.toFixed(2)} ${sy.toFixed(2)} A ${SG_R} ${SG_R} 0 ${largeArc} 1 ${ex.toFixed(2)} ${ey.toFixed(2)}`\n}\n\n/**\n * Angular port of the UIPKGE SegmentedGauge — pure SVG, no ECharts.\n * Semicircular gauge split into colored pill segments by relative value;\n * projected content lands in the dish centre (the Vue `center` slot).\n */\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-segmented-gauge, [ui-segmented-gauge]',\n  standalone: true,\n  host: {\n    '[attr.data-slot]': '\"segmented-gauge\"',\n    '[attr.data-uipkge]': '\"\"',\n    '[attr.tabindex]': '0',\n    '[class]': 'hostClass',\n    '[style.height]': 'heightStyle',\n  },\n  template: `\n    <svg\n      [attr.viewBox]=\"viewBox()\"\n      class=\"block h-full w-full\"\n      preserveAspectRatio=\"xMidYMid meet\"\n      role=\"img\"\n      [attr.aria-label]=\"ariaLabel || 'Chart'\"\n    >\n      @if (showTrack) {\n        <path\n          [attr.d]=\"trackPath()\"\n          fill=\"none\"\n          stroke=\"currentColor\"\n          [attr.stroke-width]=\"stroke\"\n          stroke-linecap=\"round\"\n          class=\"text-muted/40\"\n          opacity=\"0.35\"\n        />\n      }\n      @for (arc of arcs(); track $index) {\n        <path [attr.d]=\"arc.d\" fill=\"none\" [attr.stroke]=\"arc.color\" [attr.stroke-width]=\"stroke\" stroke-linecap=\"round\" />\n      }\n    </svg>\n    <div class=\"pointer-events-none absolute inset-x-0 bottom-[8%] flex flex-col items-center\">\n      <ng-content />\n    </div>\n  `,\n})\nexport class UiSegmentedGaugeComponent {\n  @Input() segments: GaugeSegment[] = []\n  /** Container height (px when numeric, raw CSS when string). Default 200. */\n  @Input() height: number | string = 200\n  /** Stroke width of the arc in SVG units. Default 18. */\n  @Input() stroke = 18\n  /** Angular gap between segments, in degrees. Default 4. */\n  @Input() gap = 4\n  /** Fallback palette when `color` is omitted on a segment. */\n  @Input() colors = ['var(--chart-1)', 'var(--chart-2)', 'var(--chart-3)', 'var(--chart-4)', 'var(--chart-5)']\n  /** Show a faint background track behind the arc. Default true. */\n  @Input({ transform: booleanAttribute }) showTrack = true\n  /** Accessible name announced for the chart image. Defaults to \"Chart\". */\n  @Input() ariaLabel?: string\n  @Input('class') className?: string\n\n  get hostClass(): string {\n    return cn('focus-visible:ring-ring relative w-full focus-visible:ring-2 focus-visible:outline-none', this.className)\n  }\n\n  get heightStyle(): string {\n    return /^\\d+$/.test(String(this.height)) ? `${this.height}px` : String(this.height)\n  }\n\n  viewBox(): string {\n    return `0 0 ${SG_CX * 2} ${SG_CY + this.stroke}`\n  }\n\n  trackPath(): string {\n    return sgArcPath(SG_START, SG_START + SG_SWEEP)\n  }\n\n  /** Segment arcs normalised by the value sum, with the gap cut between them. Pure. */\n  arcs(): { d: string; color: string }[] {\n    const total = this.segments.reduce((acc, s) => acc + s.value, 0) || 1\n    let cursor = SG_START\n    return this.segments.map((s, i) => {\n      const span = (s.value / total) * SG_SWEEP\n      const isLast = i === this.segments.length - 1\n      const segEnd = cursor + span - (isLast ? 0 : this.gap)\n      const arc = { d: sgArcPath(cursor, segEnd), color: s.color ?? this.colors[i % this.colors.length]! }\n      cursor = cursor + span\n      return arc\n    })\n  }\n}\n",
      "type": "registry:ui",
      "target": "~/src/app/components/ui/charts/segmented-gauge/segmented-gauge.component.ts"
    },
    {
      "path": "packages/registry-angular/components/charts/segmented-gauge/index.ts",
      "content": "export { UiSegmentedGaugeComponent, type GaugeSegment } from './segmented-gauge.component'\n",
      "type": "registry:ui",
      "target": "~/src/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"
  ]
}