{
	"$schema": "https://ui.shadcn.com/schema/registry-item.json",
	"name": "CircularText-JS-TW",
	"title": "CircularText",
	"description": "Layouts characters around a circle with optional rotation animation.",
	"type": "registry:component",
	"files": [
		{
			"type": "registry:component",
			"path": "CircularText/CircularText.jsx",
			"content": "import { useEffect } from 'react';\nimport { motion, useAnimation, useMotionValue } from 'motion/react';\n\nconst getRotationTransition = (duration, from, loop = true) => ({\n  from,\n  to: from + 360,\n  ease: 'linear',\n  duration,\n  type: 'tween',\n  repeat: loop ? Infinity : 0\n});\n\nconst getTransition = (duration, from) => ({\n  rotate: getRotationTransition(duration, from),\n  scale: {\n    type: 'spring',\n    damping: 20,\n    stiffness: 300\n  }\n});\n\nconst CircularText = ({ text, spinDuration = 20, onHover = 'speedUp', className = '' }) => {\n  const letters = Array.from(text);\n  const controls = useAnimation();\n  const rotation = useMotionValue(0);\n\n  useEffect(() => {\n    const start = rotation.get();\n    controls.start({\n      rotate: start + 360,\n      scale: 1,\n      transition: getTransition(spinDuration, start)\n    });\n  }, [spinDuration, text, onHover, controls, rotation]);\n\n  const handleHoverStart = () => {\n    const start = rotation.get();\n    if (!onHover) return;\n\n    let transitionConfig;\n    let scaleVal = 1;\n\n    switch (onHover) {\n      case 'slowDown':\n        transitionConfig = getTransition(spinDuration * 2, start);\n        break;\n      case 'speedUp':\n        transitionConfig = getTransition(spinDuration / 4, start);\n        break;\n      case 'pause':\n        transitionConfig = {\n          rotate: { type: 'spring', damping: 20, stiffness: 300 },\n          scale: { type: 'spring', damping: 20, stiffness: 300 }\n        };\n        scaleVal = 1;\n        break;\n      case 'goBonkers':\n        transitionConfig = getTransition(spinDuration / 20, start);\n        scaleVal = 0.8;\n        break;\n      default:\n        transitionConfig = getTransition(spinDuration, start);\n    }\n\n    controls.start({\n      rotate: start + 360,\n      scale: scaleVal,\n      transition: transitionConfig\n    });\n  };\n\n  const handleHoverEnd = () => {\n    const start = rotation.get();\n    controls.start({\n      rotate: start + 360,\n      scale: 1,\n      transition: getTransition(spinDuration, start)\n    });\n  };\n\n  return (\n    <motion.div\n      className={`m-0 mx-auto rounded-full w-[200px] h-[200px] relative text-white font-black text-center cursor-pointer origin-center ${className}`}\n      style={{ rotate: rotation }}\n      initial={{ rotate: 0 }}\n      animate={controls}\n      onMouseEnter={handleHoverStart}\n      onMouseLeave={handleHoverEnd}\n    >\n      {letters.map((letter, i) => {\n        const rotationDeg = (360 / letters.length) * i;\n        const factor = Math.PI / letters.length;\n        const x = factor * i;\n        const y = factor * i;\n        const transform = `rotateZ(${rotationDeg}deg) translate3d(${x}px, ${y}px, 0)`;\n\n        return (\n          <span\n            key={i}\n            className=\"absolute inline-block inset-0 text-2xl transition-all duration-500 ease-[cubic-bezier(0,0,0,1)]\"\n            style={{ transform, WebkitTransform: transform }}\n          >\n            {letter}\n          </span>\n        );\n      })}\n    </motion.div>\n  );\n};\n\nexport default CircularText;\n"
		}
	],
	"registryDependencies": [],
	"dependencies": [
		"motion@^12.23.12"
	]
}