{
  "name": "container-text-flip",
  "type": "registry:ui",
  "files": [
    {
      "path": "components/ui/container-text-flip.tsx",
      "content": "\"use client\";\n\nimport React, { useState, useEffect, useId } from \"react\";\n\nimport { motion } from \"motion/react\";\nimport { cn } from \"@/utils/cn\";\n\nexport interface ContainerTextFlipProps {\n  /** Array of words to cycle through in the animation */\n  words?: string[];\n  /** Time in milliseconds between word transitions */\n  interval?: number;\n  /** Additional CSS classes to apply to the container */\n  className?: string;\n  /** Additional CSS classes to apply to the text */\n  textClassName?: string;\n  /** Duration of the transition animation in milliseconds */\n  animationDuration?: number;\n}\n\nexport function ContainerTextFlip({\n  words = [\"better\", \"modern\", \"beautiful\", \"awesome\"],\n  interval = 3000,\n  className,\n  textClassName,\n  animationDuration = 700,\n}: ContainerTextFlipProps) {\n  const id = useId();\n  const [currentWordIndex, setCurrentWordIndex] = useState(0);\n  const [width, setWidth] = useState(100);\n  const textRef = React.useRef(null);\n\n  const updateWidthForWord = () => {\n    if (textRef.current) {\n      // Add some padding to the text width (30px on each side)\n      // @ts-ignore\n      const textWidth = textRef.current.scrollWidth + 30;\n      setWidth(textWidth);\n    }\n  };\n\n  useEffect(() => {\n    // Update width whenever the word changes\n    updateWidthForWord();\n  }, [currentWordIndex]);\n\n  useEffect(() => {\n    const intervalId = setInterval(() => {\n      setCurrentWordIndex((prevIndex) => (prevIndex + 1) % words.length);\n      // Width will be updated in the effect that depends on currentWordIndex\n    }, interval);\n\n    return () => clearInterval(intervalId);\n  }, [words, interval]);\n\n  return (\n    <motion.p\n      layout\n      layoutId={`words-here-${id}`}\n      animate={{ width }}\n      transition={{ duration: animationDuration / 2000 }}\n      className={cn(\n        \"relative inline-block rounded-lg pt-2 pb-3 text-center text-4xl font-bold text-black md:text-7xl dark:text-white\",\n        \"[background:linear-gradient(to_bottom,#f3f4f6,#e5e7eb)]\",\n        \"shadow-[inset_0_-1px_#d1d5db,inset_0_0_0_1px_#d1d5db,_0_4px_8px_#d1d5db]\",\n        \"dark:[background:linear-gradient(to_bottom,#374151,#1f2937)]\",\n        \"dark:shadow-[inset_0_-1px_#10171e,inset_0_0_0_1px_hsla(205,89%,46%,.24),_0_4px_8px_#00000052]\",\n        className,\n      )}\n      key={words[currentWordIndex]}\n    >\n      <motion.div\n        transition={{\n          duration: animationDuration / 1000,\n          ease: \"easeInOut\",\n        }}\n        className={cn(\"inline-block\", textClassName)}\n        ref={textRef}\n        layoutId={`word-div-${words[currentWordIndex]}-${id}`}\n      >\n        <motion.div className=\"inline-block\">\n          {words[currentWordIndex].split(\"\").map((letter, index) => (\n            <motion.span\n              key={index}\n              initial={{\n                opacity: 0,\n                filter: \"blur(10px)\",\n              }}\n              animate={{\n                opacity: 1,\n                filter: \"blur(0px)\",\n              }}\n              transition={{\n                delay: index * 0.02,\n              }}\n            >\n              {letter}\n            </motion.span>\n          ))}\n        </motion.div>\n      </motion.div>\n    </motion.p>\n  );\n}\n",
      "type": "registry:ui",
      "target": "components/ui/container-text-flip.tsx"
    }
  ],
  "author": "Manu Arora <hi@manuarora.in>",
  "title": "Container Text Flip"
}