{
	"$schema": "https://ui.shadcn.com/schema/registry-item.json",
	"name": "TrueFocus-JS-CSS",
	"title": "TrueFocus",
	"description": "Applies dynamic blur / clarity based over a series of words in order.",
	"type": "registry:component",
	"files": [
		{
			"type": "registry:file",
			"path": "TrueFocus.css",
			"target": "@components/TrueFocus.css",
			"content": ".focus-container {\n  position: relative;\n  display: flex;\n  gap: 1em;\n  justify-content: center;\n  align-items: center;\n  flex-wrap: wrap;\n  outline: none;\n  user-select: none;\n}\n\n.focus-word {\n  position: relative;\n  font-size: 3rem;\n  font-weight: 900;\n  cursor: pointer;\n  transition:\n    filter 0.3s ease,\n    color 0.3s ease;\n  outline: none;\n  user-select: none;\n}\n\n.focus-word.active {\n  filter: blur(0);\n}\n\n.focus-frame {\n  position: absolute;\n  top: 0;\n  left: 0;\n  pointer-events: none;\n  box-sizing: content-box;\n  border: none;\n}\n\n.corner {\n  position: absolute;\n  width: 1rem;\n  height: 1rem;\n  border: 3px solid var(--border-color, #fff);\n  filter: drop-shadow(0px 0px 4px var(--border-color, #fff));\n  border-radius: 3px;\n  transition: none;\n}\n\n.top-left {\n  top: -10px;\n  left: -10px;\n  border-right: none;\n  border-bottom: none;\n}\n\n.top-right {\n  top: -10px;\n  right: -10px;\n  border-left: none;\n  border-bottom: none;\n}\n\n.bottom-left {\n  bottom: -10px;\n  left: -10px;\n  border-right: none;\n  border-top: none;\n}\n\n.bottom-right {\n  bottom: -10px;\n  right: -10px;\n  border-left: none;\n  border-top: none;\n}\n"
		},
		{
			"type": "registry:component",
			"path": "TrueFocus.jsx",
			"content": "import { useEffect, useRef, useState } from 'react';\nimport { motion } from 'motion/react';\nimport './TrueFocus.css';\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\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 className=\"focus-container\" ref={containerRef}>\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={`focus-word ${manualMode ? 'manual' : ''} ${isActive && !manualMode ? 'active' : ''}`}\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            }}\n            onMouseEnter={() => handleMouseEnter(index)}\n            onMouseLeave={handleMouseLeave}\n          >\n            {word}\n          </span>\n        );\n      })}\n\n      <motion.div\n        className=\"focus-frame\"\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 className=\"corner top-left\"></span>\n        <span className=\"corner top-right\"></span>\n        <span className=\"corner bottom-left\"></span>\n        <span className=\"corner bottom-right\"></span>\n      </motion.div>\n    </div>\n  );\n};\n\nexport default TrueFocus;\n"
		}
	],
	"registryDependencies": [],
	"dependencies": [
		"motion@^12.23.12"
	]
}