{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "halo-progress",
  "type": "registry:ui",
  "description": "Progress bar with spring-driven determinate fill and indeterminate gradient strip",
  "dependencies": [
    "@base-ui/react",
    "motion"
  ],
  "files": [
    {
      "path": "registry/default/ui/halo-progress.tsx",
      "content": "\"use client\"\n\n/**\n * Progress bar for async flows and inline status (pairs with polished toast / notification).\n * Determinate fill uses `scaleX` (transform) — not animated `width`. Indeterminate uses a\n * sliding gradient strip. Styling aligns with {@link HaloSegmented} frosted + rim chrome.\n */\nimport { useMemo, type ComponentProps, type ReactNode } from \"react\"\nimport { Progress as ProgressPrimitive } from \"@base-ui/react/progress\"\nimport { motion, useReducedMotion } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/** Matches `layoutSpring` in `halo-button.tsx` / `halo-segmented.tsx`. */\nconst layoutSpring = {\n  type: \"spring\" as const,\n  bounce: 0.12,\n  damping: 34,\n  stiffness: 420,\n}\n\nfunction IndeterminateBar({\n  className,\n  reduceMotion,\n}: {\n  className?: string\n  reduceMotion: boolean\n}) {\n  return (\n    <div\n      className={cn(\n        \"pointer-events-none absolute inset-0 overflow-hidden rounded-[inherit]\",\n        className\n      )}\n    >\n      <motion.div\n        animate={\n          reduceMotion\n            ? { x: \"0%\" }\n            : {\n                x: [\"-45%\", \"145%\"],\n              }\n        }\n        aria-hidden\n        className=\"absolute inset-y-0 left-0 h-full w-2/5 rounded-[inherit] bg-gradient-to-r from-primary/25 via-primary to-primary/25\"\n        style={{ willChange: reduceMotion ? undefined : \"transform\" }}\n        transition={{\n          duration: reduceMotion ? 0.01 : 1.15,\n          ease: \"easeInOut\",\n          repeat: reduceMotion ? 0 : Number.POSITIVE_INFINITY,\n        }}\n      />\n    </div>\n  )\n}\n\nexport interface HaloProgressProps\n  extends Omit<ProgressPrimitive.Root.Props, \"children\"> {\n  /** Optional label wired to Base UI progress label + `aria-labelledby`. */\n  label?: ReactNode\n  /** Show formatted percentage from Base UI (`tabular-nums`). */\n  showValue?: boolean\n  /** Frosted track + gradient rim (matches segmented / button polish). */\n  translucent?: boolean\n  trackClassName?: string\n  indicatorClassName?: string\n}\n\nexport function HaloProgress({\n  className,\n  label,\n  showValue,\n  translucent = true,\n  trackClassName,\n  indicatorClassName,\n  value,\n  min = 0,\n  max = 100,\n  ...rootProps\n}: HaloProgressProps) {\n  const reduceMotion = useReducedMotion() ?? false\n  const isIndeterminate = value === null\n\n  const pct = useMemo(() => {\n    if (value === null || !Number.isFinite(value)) {\n      return 0\n    }\n    const span = max - min\n    if (span <= 0) {\n      return 0\n    }\n    return Math.min(1, Math.max(0, (value - min) / span))\n  }, [value, min, max])\n\n  return (\n    <ProgressPrimitive.Root\n      className={cn(\"flex w-full min-w-[8rem] flex-wrap gap-2\", className)}\n      max={max}\n      min={min}\n      value={value}\n      {...rootProps}\n    >\n      {(label != null || showValue) && (\n        <div className=\"flex w-full items-baseline justify-between gap-3\">\n          {label == null ? (\n            <span className=\"sr-only\">Progress</span>\n          ) : (\n            <ProgressPrimitive.Label className=\"font-medium text-foreground text-xs/relaxed\">\n              {label}\n            </ProgressPrimitive.Label>\n          )}\n          {showValue ? (\n            <ProgressPrimitive.Value className=\"text-muted-foreground text-xs/relaxed tabular-nums\" />\n          ) : null}\n        </div>\n      )}\n\n      <div\n        className={cn(\n          \"relative w-full rounded-full p-px\",\n          !(label || showValue) && \"min-w-[8rem]\"\n        )}\n      >\n        <div className=\"pointer-events-none absolute inset-0 overflow-hidden rounded-full\">\n          <motion.div\n            animate={{\n              opacity: translucent ? 0.55 : 0.4,\n            }}\n            className=\"absolute inset-x-0 bottom-0 h-1/2\"\n            transition={{ duration: 0.22, ease: \"easeOut\" }}\n          >\n            <motion.div\n              animate={{ left: [\"-8%\", \"72%\", \"-8%\"] }}\n              className=\"-bottom-3 absolute h-10 w-32 blur-xl\"\n              style={{\n                background:\n                  \"linear-gradient(90deg, #0070f3, #7928ca, #00d4ff, #ff0080)\",\n              }}\n              transition={{\n                duration: reduceMotion ? 0.01 : 5.5,\n                ease: \"easeInOut\",\n                repeat: reduceMotion ? 0 : Number.POSITIVE_INFINITY,\n              }}\n            />\n          </motion.div>\n        </div>\n\n        <ProgressPrimitive.Track\n          className={cn(\n            \"relative h-2 w-full overflow-hidden rounded-full border border-border/80\",\n            \"shadow-[0_1px_0_rgba(255,255,255,0.08)_inset,0_1px_2px_rgba(0,0,0,0.05)]\",\n            \"dark:border-border dark:shadow-[0_1px_0_rgba(255,255,255,0.05)_inset,0_2px_10px_rgba(0,0,0,0.35)]\",\n            translucent && \"backdrop-blur-md backdrop-saturate-150\",\n            trackClassName\n          )}\n          style={{\n            background: translucent\n              ? \"linear-gradient(to bottom, color-mix(in oklch, var(--muted) 55%, transparent) 0%, color-mix(in oklch, var(--muted) 40%, transparent) 100%)\"\n              : \"var(--muted)\",\n          }}\n        >\n          {isIndeterminate ? (\n            <IndeterminateBar reduceMotion={reduceMotion} />\n          ) : (\n            <motion.div\n              animate={{ scaleX: pct }}\n              aria-hidden\n              className={cn(\n                \"absolute inset-y-0 left-0 h-full w-full origin-left rounded-[inherit]\",\n                \"bg-gradient-to-b from-primary to-primary/85\",\n                \"shadow-[0_1px_0_rgba(255,255,255,0.2)_inset]\",\n                indicatorClassName\n              )}\n              initial={false}\n              style={{ willChange: reduceMotion ? undefined : \"transform\" }}\n              transition={reduceMotion ? { duration: 0 } : { ...layoutSpring }}\n            />\n          )}\n        </ProgressPrimitive.Track>\n      </div>\n    </ProgressPrimitive.Root>\n  )\n}\n\nexport type HaloProgressLabelProps = ComponentProps<\n  typeof ProgressPrimitive.Label\n>\nexport type HaloProgressValueProps = ComponentProps<\n  typeof ProgressPrimitive.Value\n>\n",
      "type": "registry:ui"
    }
  ]
}