{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "radar-chart",
  "type": "registry:ui",
  "title": "Radar Chart",
  "description": "SVG radar/spider chart with configurable axes, animated fade-in, grid polygons, and four color variants.",
  "dependencies": [],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "ui/radar-chart/radar-chart.tsx",
      "type": "registry:ui",
      "content": "'use client'\n\nimport * as React from 'react'\nimport { cn } from '@/lib/utils'\n\nexport type RadarChartVariant = 'DEFAULT' | 'ACTIVE' | 'WARNING' | 'CRITICAL'\n\nexport interface RadarChartEntry {\n  axis: string\n  value: number  // 0–100\n}\n\nexport interface RadarChartProps extends React.HTMLAttributes<HTMLDivElement> {\n  data: RadarChartEntry[]\n  variant?: RadarChartVariant\n  title?: string\n  size?: number\n  showGrid?: boolean\n  showLabels?: boolean\n  showValues?: boolean\n}\n\nconst VARIANT_COLORS: Record<RadarChartVariant, string> = {\n  DEFAULT:  'var(--text-secondary)',\n  ACTIVE:   'var(--color-green)',\n  WARNING:  'var(--color-amber)',\n  CRITICAL: 'var(--color-red)',\n}\n\nconst LABEL_PAD = 36\n\nconst RadarChart = React.forwardRef<HTMLDivElement, RadarChartProps>(\n  (\n    {\n      className,\n      data,\n      variant    = 'ACTIVE',\n      title,\n      size       = 240,\n      showGrid   = true,\n      showLabels = true,\n      showValues = false,\n      style,\n      ...props\n    },\n    ref\n  ) => {\n    const [visible, setVisible] = React.useState(false)\n    React.useEffect(() => {\n      const id = requestAnimationFrame(() => setVisible(true))\n      return () => cancelAnimationFrame(id)\n    }, [])\n\n    const color = VARIANT_COLORS[variant]\n    const cx = size / 2\n    const cy = size / 2\n    const r  = size / 2 - LABEL_PAD\n    const N  = data.length\n\n    function axisAngle(i: number) {\n      return (i / N) * 2 * Math.PI - Math.PI / 2\n    }\n\n    function gridPolygon(frac: number): string {\n      return data\n        .map((_, i) => {\n          const a = axisAngle(i)\n          return `${(cx + frac * r * Math.cos(a)).toFixed(2)},${(cy + frac * r * Math.sin(a)).toFixed(2)}`\n        })\n        .join(' ')\n    }\n\n    const points = data.map((entry, i) => {\n      const a    = axisAngle(i)\n      const frac = Math.max(0, Math.min(1, entry.value / 100))\n      return {\n        x:     cx + frac * r * Math.cos(a),\n        y:     cy + frac * r * Math.sin(a),\n        ax:    cx + r * Math.cos(a),\n        ay:    cy + r * Math.sin(a),\n        a,\n        label: entry.axis,\n        value: entry.value,\n      }\n    })\n\n    const dataPolygon = points.map(p => `${p.x.toFixed(2)},${p.y.toFixed(2)}`).join(' ')\n\n    function labelAnchor(a: number): React.SVGAttributes<SVGTextElement>['textAnchor'] {\n      const c = Math.cos(a)\n      if (Math.abs(c) < 0.3) return 'middle'\n      return c > 0 ? 'start' : 'end'\n    }\n\n    function labelBaseline(a: number): React.SVGAttributes<SVGTextElement>['dominantBaseline'] {\n      const s = Math.sin(a)\n      if (s < -0.7) return 'auto'\n      if (s > 0.7)  return 'hanging'\n      return 'middle'\n    }\n\n    return (\n      <div\n        ref={ref}\n        className={cn(className)}\n        style={{\n          border:     '1px solid var(--border)',\n          background: 'var(--surface)',\n          fontFamily: 'var(--font-mono)',\n          overflow:   'hidden',\n          display:    'inline-block',\n          ...style,\n        }}\n        {...props}\n      >\n        {title && (\n          <div\n            style={{\n              padding:       '0.4rem 0.75rem',\n              borderBottom:  '1px solid var(--border)',\n              background:    'var(--surface-raised)',\n              fontSize:      '0.6rem',\n              color:         'var(--text-muted)',\n              letterSpacing: '0.12em',\n              textTransform: 'uppercase',\n            }}\n          >\n            {title}\n          </div>\n        )}\n\n        <svg\n          width={size}\n          height={size}\n          viewBox={`-24 -24 ${size + 48} ${size + 48}`}\n          style={{ display: 'block' }}\n        >\n          {/* Grid polygons */}\n          {showGrid && [1 / 3, 2 / 3, 1].map((frac, gi) => (\n            <polygon\n              key={gi}\n              points={gridPolygon(frac)}\n              stroke=\"var(--border)\"\n              fill=\"none\"\n              strokeWidth={0.5}\n              strokeDasharray=\"2 2\"\n            />\n          ))}\n\n          {/* Axis lines */}\n          {points.map((p, i) => (\n            <line\n              key={i}\n              x1={cx}\n              y1={cy}\n              x2={p.ax.toFixed(2)}\n              y2={p.ay.toFixed(2)}\n              stroke=\"var(--border)\"\n              strokeWidth={0.5}\n            />\n          ))}\n\n          {/* Data polygon group (animated fade-in) */}\n          <g\n            style={{\n              opacity:    visible ? 1 : 0,\n              transition: 'opacity 0.6s ease',\n            }}\n          >\n            {/* Glow */}\n            <polygon\n              points={dataPolygon}\n              stroke={color}\n              strokeWidth={6}\n              fill=\"none\"\n              opacity={0.1}\n            />\n\n            {/* Main polygon */}\n            <polygon\n              points={dataPolygon}\n              stroke={color}\n              strokeWidth={1.5}\n              fill={color}\n              fillOpacity={0.15}\n            />\n\n            {/* Vertex dots */}\n            {points.map((p, i) => (\n              <circle\n                key={i}\n                cx={p.x.toFixed(2)}\n                cy={p.y.toFixed(2)}\n                r={3}\n                fill={color}\n              />\n            ))}\n\n            {/* Value labels */}\n            {showValues && points.map((p, i) => (\n              <text\n                key={i}\n                x={(p.x + Math.cos(p.a) * 10).toFixed(2)}\n                y={(p.y + Math.sin(p.a) * 10).toFixed(2)}\n                textAnchor={labelAnchor(p.a)}\n                dominantBaseline=\"middle\"\n                fontSize={8}\n                fill={color}\n                fontFamily=\"var(--font-mono)\"\n              >\n                {p.value}\n              </text>\n            ))}\n          </g>\n\n          {/* Axis labels */}\n          {showLabels && points.map((p, i) => {\n            const lx = cx + (r + 8) * Math.cos(p.a)\n            const ly = cy + (r + 8) * Math.sin(p.a)\n            return (\n              <text\n                key={i}\n                x={lx.toFixed(2)}\n                y={ly.toFixed(2)}\n                textAnchor={labelAnchor(p.a)}\n                dominantBaseline={labelBaseline(p.a)}\n                fontSize={9}\n                fill=\"var(--text-muted)\"\n                fontFamily=\"var(--font-mono)\"\n              >\n                {p.label.toUpperCase()}\n              </text>\n            )\n          })}\n        </svg>\n      </div>\n    )\n  }\n)\nRadarChart.displayName = 'RadarChart'\n\nexport { RadarChart }\n"
    }
  ]
}