{
	"$schema": "https://ui.shadcn.com/schema/registry-item.json",
	"name": "ScrollVelocity-JS-TW",
	"title": "ScrollVelocity",
	"description": "Text marquee animatio - speed and distortion scale with user's scroll velocity.",
	"type": "registry:component",
	"files": [
		{
			"type": "registry:component",
			"path": "ScrollVelocity/ScrollVelocity.jsx",
			"content": "import { useRef, useLayoutEffect, useState } from 'react';\nimport {\n  motion,\n  useScroll,\n  useSpring,\n  useTransform,\n  useMotionValue,\n  useVelocity,\n  useAnimationFrame\n} from 'motion/react';\n\nfunction useElementWidth(ref) {\n  const [width, setWidth] = useState(0);\n\n  useLayoutEffect(() => {\n    function updateWidth() {\n      if (ref.current) {\n        setWidth(ref.current.offsetWidth);\n      }\n    }\n    updateWidth();\n    window.addEventListener('resize', updateWidth);\n    return () => window.removeEventListener('resize', updateWidth);\n  }, [ref]);\n\n  return width;\n}\n\nexport const ScrollVelocity = ({\n  scrollContainerRef,\n  texts = [],\n  velocity = 100,\n  className = '',\n  damping = 50,\n  stiffness = 400,\n  numCopies = 6,\n  velocityMapping = { input: [0, 1000], output: [0, 5] },\n  parallaxClassName,\n  scrollerClassName,\n  parallaxStyle,\n  scrollerStyle\n}) => {\n  function VelocityText({\n    children,\n    baseVelocity = velocity,\n    scrollContainerRef,\n    className = '',\n    damping,\n    stiffness,\n    numCopies,\n    velocityMapping,\n    parallaxClassName,\n    scrollerClassName,\n    parallaxStyle,\n    scrollerStyle\n  }) {\n    const baseX = useMotionValue(0);\n    const scrollOptions = scrollContainerRef ? { container: scrollContainerRef } : {};\n    const { scrollY } = useScroll(scrollOptions);\n    const scrollVelocity = useVelocity(scrollY);\n    const smoothVelocity = useSpring(scrollVelocity, {\n      damping: damping ?? 50,\n      stiffness: stiffness ?? 400\n    });\n    const velocityFactor = useTransform(\n      smoothVelocity,\n      velocityMapping?.input || [0, 1000],\n      velocityMapping?.output || [0, 5],\n      { clamp: false }\n    );\n\n    const copyRef = useRef(null);\n    const copyWidth = useElementWidth(copyRef);\n\n    function wrap(min, max, v) {\n      const range = max - min;\n      const mod = (((v - min) % range) + range) % range;\n      return mod + min;\n    }\n\n    const x = useTransform(baseX, v => {\n      if (copyWidth === 0) return '0px';\n      return `${wrap(-copyWidth, 0, v)}px`;\n    });\n\n    const directionFactor = useRef(1);\n    useAnimationFrame((t, delta) => {\n      let moveBy = directionFactor.current * baseVelocity * (delta / 1000);\n\n      if (velocityFactor.get() < 0) {\n        directionFactor.current = -1;\n      } else if (velocityFactor.get() > 0) {\n        directionFactor.current = 1;\n      }\n\n      moveBy += directionFactor.current * moveBy * velocityFactor.get();\n      baseX.set(baseX.get() + moveBy);\n    });\n\n    const spans = [];\n    for (let i = 0; i < (numCopies ?? 1); i++) {\n      spans.push(\n        <span className={`flex-shrink-0 ${className}`} key={i} ref={i === 0 ? copyRef : null}>\n          {children}&nbsp;\n        </span>\n      );\n    }\n\n    return (\n      <div className={`${parallaxClassName} relative overflow-hidden`} style={parallaxStyle}>\n        <motion.div\n          className={`${scrollerClassName} flex whitespace-nowrap text-center font-sans text-4xl font-bold tracking-[-0.02em] drop-shadow md:text-[5rem] md:leading-[5rem]`}\n          style={{ x, ...scrollerStyle }}\n        >\n          {spans}\n        </motion.div>\n      </div>\n    );\n  }\n\n  return (\n    <section>\n      {texts.map((text, index) => (\n        <VelocityText\n          key={index}\n          className={className}\n          baseVelocity={index % 2 !== 0 ? -velocity : velocity}\n          scrollContainerRef={scrollContainerRef}\n          damping={damping}\n          stiffness={stiffness}\n          numCopies={numCopies}\n          velocityMapping={velocityMapping}\n          parallaxClassName={parallaxClassName}\n          scrollerClassName={scrollerClassName}\n          parallaxStyle={parallaxStyle}\n          scrollerStyle={scrollerStyle}\n        >\n          {text}\n        </VelocityText>\n      ))}\n    </section>\n  );\n};\n\nexport default ScrollVelocity;\n"
		}
	],
	"registryDependencies": [],
	"dependencies": [
		"motion@^12.23.12"
	]
}