{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "progress-circle",
  "title": "Progress Circle",
  "description": "The nx-ui Progress Circle component.",
  "registryDependencies": [
    "@nx-ui/utils"
  ],
  "files": [
    {
      "path": "components/ui/progress-circle.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/**\n * ProgressCircle — a circular (or half-circle) progress ring with an optional\n * centre value and label.\n *\n * Pure SVG: a track circle plus a foreground arc driven by\n * `stroke-dasharray`/`stroke-dashoffset` from the percentage. The `half` variant\n * draws a bottom-open semicircle with bottom-anchored text. Ported from the UUI\n * `ProgressBarCircle` / `ProgressBarHalfCircle` gauges.\n */\n\nconst sizeMap = {\n  xs: { box: 48, stroke: 6, value: \"text-sm\", label: \"text-xs\" },\n  sm: { box: 80, stroke: 8, value: \"text-lg\", label: \"text-xs\" },\n  md: { box: 120, stroke: 10, value: \"text-display-xs\", label: \"text-sm\" },\n  lg: { box: 160, stroke: 12, value: \"text-display-sm\", label: \"text-sm\" },\n} as const\n\nfunction ProgressCircle({\n  value = 0,\n  max = 100,\n  size = \"md\",\n  variant = \"circle\",\n  label,\n  showValue = true,\n  className,\n  children,\n  ...props\n}: Omit<React.ComponentProps<\"div\">, \"children\"> & {\n  value?: number\n  max?: number\n  size?: keyof typeof sizeMap\n  variant?: \"circle\" | \"half\"\n  label?: React.ReactNode\n  /** Show the percentage in the centre (default true). */\n  showValue?: boolean\n  children?: React.ReactNode\n}) {\n  const { box, stroke, value: valueClass, label: labelClass } = sizeMap[size]\n  const pct = Math.min(100, Math.max(0, (value / max) * 100))\n\n  const radius = (box - stroke) / 2\n  const cx = box / 2\n  const cy = box / 2\n\n  const half = variant === \"half\"\n  const circumference = 2 * Math.PI * radius\n  // The half gauge uses the bottom-open semicircle (half the circumference).\n  const arcLength = half ? circumference / 2 : circumference\n  const dashoffset = arcLength - (pct / 100) * arcLength\n\n  const height = half ? box / 2 + stroke : box\n\n  return (\n    <div\n      data-slot=\"progress-circle\"\n      role=\"progressbar\"\n      aria-valuenow={Math.round(pct)}\n      aria-valuemin={0}\n      aria-valuemax={100}\n      className={cn(\"relative inline-flex items-center justify-center\", className)}\n      style={{ width: box, height }}\n      {...props}\n    >\n      <svg\n        width={box}\n        height={height}\n        viewBox={`0 0 ${box} ${height}`}\n        fill=\"none\"\n        className=\"shrink-0\"\n      >\n        {half ? (\n          <>\n            <path\n              d={describeArc(cx, cy, radius)}\n              className=\"stroke-bg-quaternary\"\n              strokeWidth={stroke}\n              strokeLinecap=\"round\"\n            />\n            <path\n              d={describeArc(cx, cy, radius)}\n              className=\"stroke-primary transition-[stroke-dashoffset] duration-300 ease-out\"\n              strokeWidth={stroke}\n              strokeLinecap=\"round\"\n              strokeDasharray={arcLength}\n              strokeDashoffset={dashoffset}\n            />\n          </>\n        ) : (\n          <>\n            <circle\n              cx={cx}\n              cy={cy}\n              r={radius}\n              className=\"stroke-bg-quaternary\"\n              strokeWidth={stroke}\n            />\n            <circle\n              cx={cx}\n              cy={cy}\n              r={radius}\n              className=\"stroke-primary transition-[stroke-dashoffset] duration-300 ease-out\"\n              strokeWidth={stroke}\n              strokeLinecap=\"round\"\n              strokeDasharray={circumference}\n              strokeDashoffset={dashoffset}\n              transform={`rotate(-90 ${cx} ${cy})`}\n            />\n          </>\n        )}\n      </svg>\n\n      <div\n        className={cn(\n          \"absolute inset-x-0 flex flex-col items-center\",\n          half ? \"bottom-0\" : \"top-1/2 -translate-y-1/2\"\n        )}\n      >\n        {children ??\n          (showValue ? (\n            <span\n              className={cn(\n                \"font-semibold text-foreground tabular-nums\",\n                valueClass\n              )}\n            >\n              {Math.round(pct)}%\n            </span>\n          ) : null)}\n        {label ? (\n          <span className={cn(\"text-text-tertiary\", labelClass)}>{label}</span>\n        ) : null}\n      </div>\n    </div>\n  )\n}\n\n/** SVG path for a bottom-open semicircle from left to right through the top. */\nfunction describeArc(cx: number, cy: number, r: number) {\n  const startX = cx - r\n  const endX = cx + r\n  return `M ${startX} ${cy} A ${r} ${r} 0 0 1 ${endX} ${cy}`\n}\n\nexport { ProgressCircle }\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}