{
	"$schema": "https://ui.shadcn.com/schema/registry-item.json",
	"name": "ShinyText-JS-CSS",
	"title": "ShinyText",
	"description": "Metallic sheen sweeps across text producing a reflective highlight.",
	"type": "registry:component",
	"files": [
		{
			"type": "registry:file",
			"path": "ShinyText.css",
			"target": "@components/ShinyText.css",
			"content": ".shiny-text {\n  display: inline-block;\n}\n"
		},
		{
			"type": "registry:component",
			"path": "ShinyText.jsx",
			"content": "import { useState, useCallback, useEffect, useRef } from 'react';\nimport { motion, useMotionValue, useAnimationFrame, useTransform } from 'motion/react';\nimport './ShinyText.css';\n\nconst ShinyText = ({\n  text,\n  disabled = false,\n  speed = 2,\n  className = '',\n  color = '#b5b5b5',\n  shineColor = '#ffffff',\n  spread = 120,\n  yoyo = false,\n  pauseOnHover = false,\n  direction = 'left',\n  delay = 0\n}) => {\n  const [isPaused, setIsPaused] = useState(false);\n  const progress = useMotionValue(0);\n  const elapsedRef = useRef(0);\n  const lastTimeRef = useRef(null);\n  const directionRef = useRef(direction === 'left' ? 1 : -1);\n\n  const animationDuration = speed * 1000;\n  const delayDuration = delay * 1000;\n\n  useAnimationFrame(time => {\n    if (disabled || isPaused) {\n      lastTimeRef.current = null;\n      return;\n    }\n\n    if (lastTimeRef.current === null) {\n      lastTimeRef.current = time;\n      return;\n    }\n\n    const deltaTime = time - lastTimeRef.current;\n    lastTimeRef.current = time;\n\n    elapsedRef.current += deltaTime;\n\n    if (yoyo) {\n      const cycleDuration = animationDuration + delayDuration;\n      const fullCycle = cycleDuration * 2;\n      const cycleTime = elapsedRef.current % fullCycle;\n\n      if (cycleTime < animationDuration) {\n        // Forward animation: 0 -> 100\n        const p = (cycleTime / animationDuration) * 100;\n        progress.set(directionRef.current === 1 ? p : 100 - p);\n      } else if (cycleTime < cycleDuration) {\n        // Delay at end\n        progress.set(directionRef.current === 1 ? 100 : 0);\n      } else if (cycleTime < cycleDuration + animationDuration) {\n        // Reverse animation: 100 -> 0\n        const reverseTime = cycleTime - cycleDuration;\n        const p = 100 - (reverseTime / animationDuration) * 100;\n        progress.set(directionRef.current === 1 ? p : 100 - p);\n      } else {\n        // Delay at start\n        progress.set(directionRef.current === 1 ? 0 : 100);\n      }\n    } else {\n      const cycleDuration = animationDuration + delayDuration;\n      const cycleTime = elapsedRef.current % cycleDuration;\n\n      if (cycleTime < animationDuration) {\n        // Animation phase: 0 -> 100\n        const p = (cycleTime / animationDuration) * 100;\n        progress.set(directionRef.current === 1 ? p : 100 - p);\n      } else {\n        // Delay phase - hold at end (shine off-screen)\n        progress.set(directionRef.current === 1 ? 100 : 0);\n      }\n    }\n  });\n\n  useEffect(() => {\n    directionRef.current = direction === 'left' ? 1 : -1;\n    elapsedRef.current = 0;\n    progress.set(0);\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [direction]);\n\n  // Transform: p=0 -> 150% (shine off right), p=100 -> -50% (shine off left)\n  const backgroundPosition = useTransform(progress, p => `${150 - p * 2}% center`);\n\n  const handleMouseEnter = useCallback(() => {\n    if (pauseOnHover) setIsPaused(true);\n  }, [pauseOnHover]);\n\n  const handleMouseLeave = useCallback(() => {\n    if (pauseOnHover) setIsPaused(false);\n  }, [pauseOnHover]);\n\n  const gradientStyle = {\n    backgroundImage: `linear-gradient(${spread}deg, ${color} 0%, ${color} 35%, ${shineColor} 50%, ${color} 65%, ${color} 100%)`,\n    backgroundSize: '200% auto',\n    WebkitBackgroundClip: 'text',\n    backgroundClip: 'text',\n    WebkitTextFillColor: 'transparent'\n  };\n\n  return (\n    <motion.span\n      className={`shiny-text ${className}`}\n      style={{ ...gradientStyle, backgroundPosition }}\n      onMouseEnter={handleMouseEnter}\n      onMouseLeave={handleMouseLeave}\n    >\n      {text}\n    </motion.span>\n  );\n};\n\nexport default ShinyText;\n"
		}
	],
	"registryDependencies": [],
	"dependencies": [
		"motion@^12.23.12"
	]
}