{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "circular-progress",
  "title": "Circular Progress",
  "description": "A circular progress component for loading states.",
  "registryDependencies": [
    "https://blok.sitecore.com/r/theme.json"
  ],
  "files": [
    {
      "path": "src/components/ui/circular-progress.tsx",
      "content": "\"use client\";\n\nimport type React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst CIRCLE_CX = 50;\nconst CIRCLE_CY = 50;\nconst CIRCLE_R = 42;\nconst CIRCUMFERENCE = 2 * Math.PI * CIRCLE_R;\n\n/** Keyframes injected by component (no global CSS) - same pattern as Progress. */\nconst CIRCULAR_PROGRESS_KEYFRAMES = `\n@keyframes circular-progress-rotate {\n  0% { transform: rotate(0deg); }\n  100% { transform: rotate(360deg); }\n}\n@keyframes circular-progress-spin {\n  0% { stroke-dasharray: 1, 400; stroke-dashoffset: 0; }\n  50% { stroke-dasharray: 400, 400; stroke-dashoffset: -100; }\n  100% { stroke-dasharray: 400, 400; stroke-dashoffset: -260; }\n}\n`;\n\nconst sizePresets: Record<string, string> = {\n  xs: \"16px\",\n  sm: \"24px\",\n  md: \"48px\",\n  lg: \"64px\",\n  xl: \"96px\",\n};\n\nexport interface CircularProgressProps\n  extends React.HTMLAttributes<HTMLDivElement> {\n  /** Progress value 0–100 (default variant only). */\n  value?: number;\n  min?: number;\n  max?: number;\n  /** When true, uses indeterminate variant (spinning). */\n  isIndeterminate?: boolean;\n  /** Rounded line cap on the progress arc. */\n  capIsRound?: boolean;\n  /** Overall size: preset (xs/sm/md/lg/xl) or CSS length (e.g. 48px). Default: 48px. */\n  size?: \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\" | string | number;\n  /** Stroke width of track and indicator. Default: 10px. */\n  thickness?: string | number;\n  /** Variant: default (determinate) or indeterminate. */\n  variant?: \"default\" | \"indeterminate\";\n}\n\n/** Default stroke colors: indicator = primary, track = gray-200. Override via className, e.g. [&_[data-slot=circular-progress-indicator]]:stroke-blue-500 */\nconst DEFAULT_TRACK_CLASS = \"stroke-gray-200\";\nconst DEFAULT_INDICATOR_CLASS = \"stroke-primary\";\n\nfunction CircularProgress({\n  value = 0,\n  min = 0,\n  max = 100,\n  isIndeterminate,\n  capIsRound = false,\n  size = \"48px\",\n  thickness = \"10px\",\n  variant = \"default\",\n  className,\n  ...props\n}: CircularProgressProps) {\n  const indeterminate = isIndeterminate ?? variant === \"indeterminate\";\n  const sizeCss =\n    typeof size === \"number\"\n      ? `${size}px`\n      : (sizePresets[size as string] ?? size);\n  const thicknessCss =\n    typeof thickness === \"number\" ? `${thickness}px` : thickness;\n\n  const percent = Math.min(\n    100,\n    Math.max(0, ((value - min) / (max - min)) * 100),\n  );\n  const strokeDashoffset = CIRCUMFERENCE * (1 - percent / 100);\n\n  return (\n    <div\n      role=\"progressbar\"\n      aria-valuemin={min}\n      aria-valuemax={max}\n      aria-valuenow={indeterminate ? undefined : value}\n      aria-label={\n        indeterminate ? undefined : `Progress: ${Math.round(percent)}%`\n      }\n      data-slot=\"circular-progress\"\n      data-variant={indeterminate ? \"indeterminate\" : \"default\"}\n      className={cn(\"inline-block\", className)}\n      style={{ fontSize: sizeCss }}\n      {...props}\n    >\n      <style\n        dangerouslySetInnerHTML={{ __html: CIRCULAR_PROGRESS_KEYFRAMES }}\n      />\n      <svg\n        width={sizeCss}\n        height={sizeCss}\n        viewBox=\"0 0 100 100\"\n        style={\n          indeterminate\n            ? { animation: \"circular-progress-rotate 2s linear infinite\" }\n            : undefined\n        }\n      >\n        <circle\n          data-slot=\"circular-progress-track\"\n          cx={CIRCLE_CX}\n          cy={CIRCLE_CY}\n          r={CIRCLE_R}\n          fill=\"none\"\n          strokeWidth={thicknessCss}\n          className={DEFAULT_TRACK_CLASS}\n        />\n        <circle\n          data-slot=\"circular-progress-indicator\"\n          cx={CIRCLE_CX}\n          cy={CIRCLE_CY}\n          r={CIRCLE_R}\n          fill=\"none\"\n          strokeWidth={thicknessCss}\n          strokeLinecap={capIsRound ? \"round\" : \"butt\"}\n          strokeDasharray={\n            indeterminate ? undefined : `${CIRCUMFERENCE} ${CIRCUMFERENCE}`\n          }\n          strokeDashoffset={indeterminate ? undefined : strokeDashoffset}\n          transform=\"rotate(-90 50 50)\"\n          className={cn(\n            DEFAULT_INDICATOR_CLASS,\n            !indeterminate &&\n              \"transition-[stroke-dasharray,stroke-dashoffset] duration-300\",\n          )}\n          style={\n            indeterminate\n              ? {\n                  animation: \"circular-progress-spin 1.5s linear infinite\",\n                }\n              : undefined\n          }\n        />\n      </svg>\n    </div>\n  );\n}\n\nexport { CircularProgress };\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}