{
  "$schema": "https://ethereal-ui.saefulrohman.dev/schema/registry-item.json",
  "name": "progress",
  "title": "Progress",
  "type": "registry:primitives",
  "description": "Linear and circular progress bars for quota consumption, onboarding completion, and file uploads.",
  "dependencies": [],
  "usage": "import { Progress, CircularProgress } from \"@etherealui/react\"\n\nexport function ProgressDemo() {\n  return (\n    <div className=\"flex items-center gap-6 w-80\">\n      <CircularProgress value={72} variant=\"blue\" />\n      <Progress value={72} label=\"Storage used\" showValue className=\"flex-1\" />\n    </div>\n  )\n}",
  "files": [
    {
      "path": "packages/ui/src/primitives/progress.tsx",
      "target": "components/ui/progress.tsx",
      "type": "registry:primitives",
      "content": "import * as React from \"react\"\nimport { cn } from \"../utils/cn\"\n\nexport interface ProgressProps extends React.HTMLAttributes<HTMLDivElement> {\n  value: number\n  max?: number\n  variant?: \"blue\" | \"indigo\" | \"emerald\" | \"amber\" | \"rose\" | \"white\"\n  size?: \"sm\" | \"default\" | \"lg\"\n  showValue?: boolean\n  label?: string\n}\n\nconst barColorMap: Record<NonNullable<ProgressProps[\"variant\"]>, string> = {\n  blue: \"bg-blue-600 dark:bg-blue-500\",\n  indigo: \"bg-blue-600 dark:bg-blue-500\",\n  emerald: \"bg-emerald-600 dark:bg-emerald-500\",\n  amber: \"bg-amber-500\",\n  rose: \"bg-rose-600 dark:bg-rose-500\",\n  white: \"bg-zinc-900 dark:bg-zinc-100\",\n}\n\nconst Progress = React.forwardRef<HTMLDivElement, ProgressProps>(\n  (\n    {\n      className,\n      value,\n      max = 100,\n      variant = \"blue\",\n      size = \"default\",\n      showValue = false,\n      label,\n      ...props\n    },\n    ref\n  ) => {\n    const percentage = Math.min(100, Math.max(0, (value / max) * 100))\n\n    return (\n      <div className={cn(\"w-full space-y-1.5\", className)} ref={ref} {...props}>\n        {(label || showValue) && (\n          <div className=\"flex items-center justify-between text-xs\">\n            {label && (\n              <span className=\"text-zinc-700 dark:text-zinc-300 font-medium\">\n                {label}\n              </span>\n            )}\n            {showValue && (\n              <span className=\"font-mono text-zinc-500 dark:text-zinc-400\">\n                {Math.round(percentage)}%\n              </span>\n            )}\n          </div>\n        )}\n        <div\n          role=\"progressbar\"\n          aria-valuenow={value}\n          aria-valuemin={0}\n          aria-valuemax={max}\n          className={cn(\n            \"w-full overflow-hidden rounded-full bg-zinc-200/80 dark:bg-zinc-800\",\n            size === \"sm\" && \"h-1.5\",\n            size === \"default\" && \"h-2\",\n            size === \"lg\" && \"h-3\"\n          )}\n        >\n          <div\n            className={cn(\n              \"h-full rounded-full transition-all duration-300\",\n              barColorMap[variant]\n            )}\n            style={{ width: `${percentage}%` }}\n          />\n        </div>\n      </div>\n    )\n  }\n)\nProgress.displayName = \"Progress\"\n\nexport interface CircularProgressProps extends React.HTMLAttributes<HTMLDivElement> {\n  value: number\n  size?: number\n  strokeWidth?: number\n  variant?: \"blue\" | \"indigo\" | \"emerald\" | \"amber\" | \"rose\"\n}\n\nconst strokeColorMap: Record<NonNullable<CircularProgressProps[\"variant\"]>, string> = {\n  blue: \"text-blue-600 dark:text-blue-500\",\n  indigo: \"text-blue-600 dark:text-blue-500\",\n  emerald: \"text-emerald-600 dark:text-emerald-500\",\n  amber: \"text-amber-500\",\n  rose: \"text-rose-600 dark:text-rose-500\",\n}\n\nconst CircularProgress: React.FC<CircularProgressProps> = ({\n  value,\n  size = 48,\n  strokeWidth = 4,\n  variant = \"blue\",\n  className,\n  ...props\n}) => {\n  const clamped = Math.min(100, Math.max(0, value))\n  const radius = (size - strokeWidth) / 2\n  const circumference = 2 * Math.PI * radius\n  const offset = circumference - (clamped / 100) * circumference\n\n  return (\n    <div\n      className={cn(\"relative inline-flex items-center justify-center\", className)}\n      style={{ width: size, height: size }}\n      {...props}\n    >\n      <svg width={size} height={size} className=\"-rotate-90 transform\">\n        <circle\n          cx={size / 2}\n          cy={size / 2}\n          r={radius}\n          fill=\"transparent\"\n          stroke=\"currentColor\"\n          strokeWidth={strokeWidth}\n          className=\"text-zinc-200 dark:text-zinc-800\"\n        />\n        <circle\n          cx={size / 2}\n          cy={size / 2}\n          r={radius}\n          fill=\"transparent\"\n          stroke=\"currentColor\"\n          strokeWidth={strokeWidth}\n          strokeDasharray={circumference}\n          strokeDashoffset={offset}\n          strokeLinecap=\"round\"\n          className={cn(\"transition-all duration-300\", strokeColorMap[variant])}\n        />\n      </svg>\n      <span className=\"absolute font-mono text-[11px] font-medium text-zinc-800 dark:text-zinc-200\">\n        {Math.round(clamped)}%\n      </span>\n    </div>\n  )\n}\nCircularProgress.displayName = \"CircularProgress\"\n\nexport { Progress, CircularProgress }\n"
    }
  ]
}