{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "flip-fade-text",
  "type": "registry:ui",
  "dependencies": [
    "framer-motion"
  ],
  "files": [
    {
      "path": "components/ui/flip-fade-text.tsx",
      "content": "\"use client\"\n\nimport { useEffect, useState, useMemo, useCallback, memo } from \"react\"\nimport { motion, AnimatePresence } from \"framer-motion\"\nimport { cn } from \"@/lib/utils\"\n\ninterface FlipFadeTextProps {\n    /**\n     * Array of words to cycle through\n     * @default [\"LOADING\", \"COMPUTING\", \"SEARCHING\", \"RETRIEVING\", \"ASSEMBLING\"]\n     */\n    words?: string[]\n    /**\n     * Interval between word changes in milliseconds\n     * @default 2500\n     */\n    interval?: number\n    /**\n     * Additional CSS classes for the container\n     */\n    className?: string\n    /**\n     * Additional CSS classes for the text\n     */\n    textClassName?: string\n    /**\n     * Animation duration for each letter in seconds\n     * @default 0.6\n     */\n    letterDuration?: number\n    /**\n     * Stagger delay between letters on enter in seconds\n     * @default 0.1\n     */\n    staggerDelay?: number\n    /**\n     * Stagger delay between letters on exit in seconds\n     * @default 0.05\n     */\n    exitStaggerDelay?: number\n}\n\nconst defaultWords = [\"LOADING\", \"COMPUTING\", \"SEARCHING\", \"RETRIEVING\", \"ASSEMBLING\"]\n\n// Memoized Letter component for performance\nconst Letter = memo(function Letter({\n    char,\n    letterDuration\n}: {\n    char: string\n    letterDuration: number\n}) {\n    return (\n        <motion.span\n            style={{ transformStyle: \"preserve-3d\" }}\n            variants={{\n                initial: {\n                    rotateX: 90,\n                    y: 20,\n                    opacity: 0,\n                    filter: \"blur(8px)\",\n                },\n                animate: {\n                    rotateX: 0,\n                    y: 0,\n                    opacity: 1,\n                    filter: \"blur(0px)\",\n                    transition: {\n                        duration: letterDuration,\n                        ease: [0.2, 0.65, 0.3, 0.9],\n                    },\n                },\n                exit: {\n                    rotateX: -90,\n                    y: -20,\n                    opacity: 0,\n                    filter: \"blur(8px)\",\n                    transition: {\n                        duration: letterDuration * 0.67,\n                        ease: \"easeIn\",\n                    },\n                },\n            }}\n            className=\"inline-block\"\n        >\n            {char}\n        </motion.span>\n    )\n})\n\n// Memoized Word component for performance\nconst Word = memo(function Word({\n    text,\n    staggerDelay,\n    exitStaggerDelay,\n    letterDuration,\n    textClassName\n}: {\n    text: string\n    staggerDelay: number\n    exitStaggerDelay: number\n    letterDuration: number\n    textClassName?: string\n}) {\n    const letters = useMemo(() => text.split(\"\"), [text])\n\n    return (\n        <motion.div\n            className={cn(\n                \"flex gap-[0.1em] text-4xl md:text-6xl font-bold uppercase tracking-wider text-neutral-800 dark:text-neutral-100\",\n                textClassName\n            )}\n            initial=\"initial\"\n            animate=\"animate\"\n            exit=\"exit\"\n            variants={{\n                initial: { opacity: 1 },\n                animate: {\n                    opacity: 1,\n                    transition: {\n                        staggerChildren: staggerDelay,\n                    },\n                },\n                exit: {\n                    opacity: 1,\n                    transition: {\n                        staggerChildren: exitStaggerDelay,\n                    },\n                },\n            }}\n        >\n            {letters.map((char, i) => (\n                <Letter\n                    key={`${char}-${i}`}\n                    char={char}\n                    letterDuration={letterDuration}\n                />\n            ))}\n        </motion.div>\n    )\n})\n\nexport function FlipFadeText({\n    words = defaultWords,\n    interval = 2500,\n    className,\n    textClassName,\n    letterDuration = 0.6,\n    staggerDelay = 0.1,\n    exitStaggerDelay = 0.05,\n}: FlipFadeTextProps) {\n    const [index, setIndex] = useState(0)\n\n    // Memoize the interval callback\n    const updateIndex = useCallback(() => {\n        setIndex((prev) => (prev + 1) % words.length)\n    }, [words.length])\n\n    useEffect(() => {\n        const timer = setInterval(updateIndex, interval)\n        return () => clearInterval(timer)\n    }, [updateIndex, interval])\n\n    // Memoize the current word\n    const currentWord = useMemo(() => words[index], [words, index])\n\n    return (\n        <div className={cn(\"flex items-center justify-center min-h-[200px]\", className)}>\n            <div className=\"relative flex items-center justify-center\" style={{ perspective: \"1000px\" }}>\n                <AnimatePresence mode=\"wait\">\n                    <Word\n                        key={currentWord}\n                        text={currentWord}\n                        staggerDelay={staggerDelay}\n                        exitStaggerDelay={exitStaggerDelay}\n                        letterDuration={letterDuration}\n                        textClassName={textClassName}\n                    />\n                </AnimatePresence>\n            </div>\n        </div>\n    )\n}\n\nexport default FlipFadeText\n",
      "type": "registry:ui",
      "target": "components/ui/flip-fade-text.tsx"
    }
  ]
}