{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "reading-progress",
  "title": "Reading Progress",
  "description": "A drawn-line progress indicator with spring-smoothed scroll tracking and a fading percentage.",
  "dependencies": [
    "framer-motion"
  ],
  "files": [
    {
      "path": "components/content/ReadingProgress.tsx",
      "content": "'use client';\n\nimport { motion, useScroll, useSpring, useMotionValueEvent } from 'framer-motion';\nimport { useEffect, useState, type RefObject } from 'react';\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n//\n// target           Optional element ref to track (defaults to document)\n// position         Where the bar lives: top | bottom | inline\n// thickness        Bar height in px\n// color            CSS color for the filled track\n// showPercentage   Fade in a tiny % label while scrolling\n// progress         Controlled 0–1 value — skips scroll tracking when set\n// className        Styles for the outer shell\n//\ntype ReadingProgressProps = {\n  target?: RefObject<HTMLElement | null>;\n  position?: 'top' | 'bottom' | 'inline';\n  thickness?: number;\n  color?: string;\n  showPercentage?: boolean;\n  progress?: number;\n  className?: string;\n};\n\nexport default function ReadingProgress({\n  target,\n  position = 'inline',\n  thickness = 2,\n  color = 'var(--color-primary, #111827)',\n  showPercentage = true,\n  progress,\n  className = '',\n}: ReadingProgressProps) {\n  const controlled = typeof progress === 'number';\n  const { scrollYProgress } = useScroll(\n    target ? { target, offset: ['start start', 'end end'] } : undefined\n  );\n  const smooth = useSpring(scrollYProgress, {\n    stiffness: 120,\n    damping: 28,\n    mass: 0.35,\n  });\n\n  const [pct, setPct] = useState(\n    controlled ? Math.round(Math.max(0, Math.min(1, progress)) * 100) : 0\n  );\n  const [active, setActive] = useState(controlled ? progress > 0.02 : false);\n\n  useMotionValueEvent(smooth, 'change', (v) => {\n    if (controlled) return;\n    const next = Math.round(v * 100);\n    setPct(next);\n    setActive(v > 0.02 && v < 0.98);\n  });\n\n  useEffect(() => {\n    if (!controlled) return;\n    const clamped = Math.max(0, Math.min(1, progress));\n    setPct(Math.round(clamped * 100));\n    setActive(clamped > 0.02);\n  }, [controlled, progress]);\n\n  const fixed =\n    position === 'top'\n      ? 'fixed left-0 right-0 top-0 z-50'\n      : position === 'bottom'\n        ? 'fixed bottom-0 left-0 right-0 z-50'\n        : 'relative w-full';\n\n  return (\n    <div\n      className={[fixed, 'pointer-events-none', className]\n        .filter(Boolean)\n        .join(' ')}\n      role='progressbar'\n      aria-valuemin={0}\n      aria-valuemax={100}\n      aria-valuenow={pct}\n      aria-label='Reading progress'\n    >\n      <div\n        className='relative w-full overflow-hidden bg-[var(--color-muted,#e5e7eb)]'\n        style={{ height: thickness }}\n      >\n        {controlled ? (\n          <motion.div\n            className='absolute inset-y-0 left-0'\n            style={{ backgroundColor: color }}\n            initial={{ width: 0 }}\n            animate={{ width: `${pct}%` }}\n            transition={{ duration: 0.8, ease: [0.22, 1, 0.36, 1] }}\n          />\n        ) : (\n          <motion.div\n            className='absolute inset-y-0 left-0 w-full origin-left'\n            style={{ backgroundColor: color, scaleX: smooth }}\n          />\n        )}\n      </div>\n\n      {showPercentage ? (\n        <motion.span\n          className={[\n            'absolute right-3 font-mono text-[10px] tracking-wider text-[color:var(--color-muted-foreground,#6b7280)]',\n            position === 'bottom' ? '-top-5' : 'top-2',\n          ].join(' ')}\n          animate={{ opacity: active ? 1 : 0, y: active ? 0 : -4 }}\n          transition={{ duration: 0.25 }}\n        >\n          {pct}%\n        </motion.span>\n      ) : null}\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "@components/content/ReadingProgress.tsx"
    }
  ],
  "categories": [
    "content"
  ],
  "type": "registry:component"
}