{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "math-curve-progress",
  "title": "Math Curve Progress",
  "description": "Progress indicator that traces a mathematical curve — value-driven head moves along the curve path from 0 to 100%",
  "dependencies": [
    "class-variance-authority"
  ],
  "registryDependencies": [
    "@boldkit/utils",
    "@boldkit/math-curves",
    "@boldkit/error-boundary"
  ],
  "files": [
    {
      "path": "registry/default/ui/math-curve-progress.tsx",
      "content": "/* eslint-disable react-refresh/only-export-components */\nimport * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/lib/utils'\nimport { ErrorBoundary } from '@/components/ErrorBoundary'\nimport {\n  buildPath,\n  getPoint,\n  getAngle,\n  type ProgressCurveKey,\n} from '@/lib/math-curves'\n\nconst mathCurveProgressVariants = cva('', {\n  variants: {\n    size: {\n      sm: 'w-12 h-12',\n      md: 'w-16 h-16',\n      lg: 'w-24 h-24',\n    },\n  },\n  defaultVariants: {\n    size: 'md',\n  },\n})\n\nexport interface MathCurveProgressProps\n  extends React.SVGAttributes<SVGSVGElement>,\n    VariantProps<typeof mathCurveProgressVariants> {\n  value: number\n  curve?: ProgressCurveKey\n  showValue?: boolean\n  trackColor?: string\n  fillColor?: string\n  strokeWidth?: number\n}\n\nconst MathCurveProgress = React.forwardRef<SVGSVGElement, MathCurveProgressProps>(\n  (\n    {\n      className,\n      size,\n      value,\n      curve = 'spiral',\n      showValue = false,\n      trackColor,\n      fillColor,\n      strokeWidth = 4,\n      ...props\n    },\n    ref\n  ) => {\n    const clampedValue = Math.min(100, Math.max(0, value))\n    const progress = clampedValue / 100\n\n    const trackPath = React.useMemo(() => buildPath(curve, 1.0), [curve])\n    const headPoint = React.useMemo(() => getPoint(curve, progress), [curve, progress])\n    const headAngle = React.useMemo(() => getAngle(curve, progress), [curve, progress])\n    const HEAD_SIZE = 8\n\n    const resolvedTrackStroke = trackColor ?? 'currentColor'\n    const resolvedFillColor = fillColor ?? 'hsl(var(--primary))'\n\n    return (\n      <ErrorBoundary>\n        <svg\n          ref={ref}\n          viewBox=\"0 0 100 100\"\n          xmlns=\"http://www.w3.org/2000/svg\"\n          role=\"progressbar\"\n          aria-valuenow={clampedValue}\n          aria-valuemin={0}\n          aria-valuemax={100}\n          aria-label={`${Math.round(clampedValue)}% progress`}\n          className={cn(mathCurveProgressVariants({ size }), className)}\n          {...props}\n        >\n          {/* Track layer */}\n          <path\n            d={trackPath}\n            fill=\"none\"\n            stroke={resolvedTrackStroke}\n            strokeWidth={strokeWidth}\n            strokeOpacity={0.2}\n            strokeLinecap=\"square\"\n            strokeLinejoin=\"miter\"\n          />\n          {/* Head square — CSS transition for smooth value-driven movement */}\n          <rect\n            width={HEAD_SIZE}\n            height={HEAD_SIZE}\n            x={headPoint.x - HEAD_SIZE / 2}\n            y={headPoint.y - HEAD_SIZE / 2}\n            fill={resolvedFillColor}\n            stroke=\"currentColor\"\n            strokeWidth={1.5}\n            style={{\n              transformBox: 'fill-box',\n              transformOrigin: 'center',\n              transform: `rotate(${headAngle}deg)`,\n              transition: 'transform 300ms ease',\n            }}\n          />\n          {/* Optional numeric label */}\n          {showValue && (\n            <text\n              x={50}\n              y={50}\n              textAnchor=\"middle\"\n              dominantBaseline=\"central\"\n              fontSize={12}\n              fontWeight={700}\n              fill=\"currentColor\"\n              letterSpacing=\"0.05em\"\n              style={{ userSelect: 'none', fontFamily: 'inherit' }}\n            >\n              {Math.round(clampedValue)}%\n            </text>\n          )}\n        </svg>\n      </ErrorBoundary>\n    )\n  }\n)\nMathCurveProgress.displayName = 'MathCurveProgress'\n\nexport { MathCurveProgress, mathCurveProgressVariants }\n",
      "type": "registry:ui",
      "target": "components/ui/math-curve-progress.tsx"
    }
  ],
  "type": "registry:ui"
}