{
	"$schema": "https://ui.shadcn.com/schema/registry-item.json",
	"name": "TrueFocus-JS-TW",
	"title": "TrueFocus",
	"description": "Applies dynamic blur / clarity based over a series of words in order.",
	"type": "registry:component",
	"files": [
		{
			"type": "registry:component",
			"path": "TrueFocus/TrueFocus.jsx",
			"content": "import { useEffect, useRef, useState } from 'react';\nimport { motion } from 'motion/react';\n\nconst TrueFocus = ({\n  sentence = 'True Focus',\n  separator = ' ',\n  manualMode = false,\n  blurAmount = 5,\n  borderColor = 'green',\n  glowColor = 'rgba(0, 255, 0, 0.6)',\n  animationDuration = 0.5,\n  pauseBetweenAnimations = 1\n}) => {\n  const words = sentence.split(separator);\n  const [currentIndex, setCurrentIndex] = useState(0);\n  const [lastActiveIndex, setLastActiveIndex] = useState(null);\n  const containerRef = useRef(null);\n  const wordRefs = useRef([]);\n  const [focusRect, setFocusRect] = useState({ x: 0, y: 0, width: 0, height: 0 });\n\n  useEffect(() => {\n    if (!manualMode) {\n      const interval = setInterval(\n        () => {\n          setCurrentIndex(prev => (prev + 1) % words.length);\n        },\n        (animationDuration + pauseBetweenAnimations) * 1000\n      );\n\n      return () => clearInterval(interval);\n    }\n  }, [manualMode, animationDuration, pauseBetweenAnimations, words.length]);\n\n  useEffect(() => {\n    if (currentIndex === null || currentIndex === -1) return;\n    if (!wordRefs.current[currentIndex] || !containerRef.current) return;\n\n    const parentRect = containerRef.current.getBoundingClientRect();\n    const activeRect = wordRefs.current[currentIndex].getBoundingClientRect();\n\n    setFocusRect({\n      x: activeRect.left - parentRect.left,\n      y: activeRect.top - parentRect.top,\n      width: activeRect.width,\n      height: activeRect.height\n    });\n  }, [currentIndex, words.length]);\n\n  const handleMouseEnter = index => {\n    if (manualMode) {\n      setLastActiveIndex(index);\n      setCurrentIndex(index);\n    }\n  };\n\n  const handleMouseLeave = () => {\n    if (manualMode) {\n      setCurrentIndex(lastActiveIndex);\n    }\n  };\n\n  return (\n    <div\n      className=\"relative flex gap-4 justify-center items-center flex-wrap\"\n      ref={containerRef}\n      style={{ outline: 'none', userSelect: 'none' }}\n    >\n      {words.map((word, index) => {\n        const isActive = index === currentIndex;\n        return (\n          <span\n            key={index}\n            ref={el => {\n              wordRefs.current[index] = el;\n            }}\n            className=\"relative text-[3rem] font-black cursor-pointer\"\n            style={{\n              filter: manualMode\n                ? isActive\n                  ? `blur(0px)`\n                  : `blur(${blurAmount}px)`\n                : isActive\n                  ? `blur(0px)`\n                  : `blur(${blurAmount}px)`,\n              '--border-color': borderColor,\n              '--glow-color': glowColor,\n              transition: `filter ${animationDuration}s ease`,\n              outline: 'none',\n              userSelect: 'none'\n            }}\n            onMouseEnter={() => handleMouseEnter(index)}\n            onMouseLeave={handleMouseLeave}\n          >\n            {word}\n          </span>\n        );\n      })}\n\n      <motion.div\n        className=\"absolute top-0 left-0 pointer-events-none box-border border-0\"\n        animate={{\n          x: focusRect.x,\n          y: focusRect.y,\n          width: focusRect.width,\n          height: focusRect.height,\n          opacity: currentIndex >= 0 ? 1 : 0\n        }}\n        transition={{\n          duration: animationDuration\n        }}\n        style={{\n          '--border-color': borderColor,\n          '--glow-color': glowColor\n        }}\n      >\n        <span\n          className=\"absolute w-4 h-4 border-[3px] rounded-[3px] top-[-10px] left-[-10px] border-r-0 border-b-0\"\n          style={{\n            borderColor: 'var(--border-color)',\n            filter: 'drop-shadow(0 0 4px var(--border-color))'\n          }}\n        ></span>\n        <span\n          className=\"absolute w-4 h-4 border-[3px] rounded-[3px] top-[-10px] right-[-10px] border-l-0 border-b-0\"\n          style={{\n            borderColor: 'var(--border-color)',\n            filter: 'drop-shadow(0 0 4px var(--border-color))'\n          }}\n        ></span>\n        <span\n          className=\"absolute w-4 h-4 border-[3px] rounded-[3px] bottom-[-10px] left-[-10px] border-r-0 border-t-0\"\n          style={{\n            borderColor: 'var(--border-color)',\n            filter: 'drop-shadow(0 0 4px var(--border-color))'\n          }}\n        ></span>\n        <span\n          className=\"absolute w-4 h-4 border-[3px] rounded-[3px] bottom-[-10px] right-[-10px] border-l-0 border-t-0\"\n          style={{\n            borderColor: 'var(--border-color)',\n            filter: 'drop-shadow(0 0 4px var(--border-color))'\n          }}\n        ></span>\n      </motion.div>\n    </div>\n  );\n};\n\nexport default TrueFocus;\n"
		}
	],
	"registryDependencies": [],
	"dependencies": [
		"motion@^12.23.12"
	]
}