{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "gravity-text-swap",
  "type": "registry:ui",
  "title": "Gravity Text Swap",
  "description": "The GravityTextSwap component drops characters into place under a gravity-like fall, so one word gives way to the next instead of simply being replaced.",
  "author": "Michael (https://github.com/lappemic)",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "components/demo/text/gravity-text-swap.tsx",
      "content": "\"use client\";\nimport React, { useState, useEffect } from \"react\";\nimport { motion, AnimatePresence } from \"motion/react\";\nimport { cn } from \"@/lib/utils\";\n\ninterface GravityTextSwapProps {\n  textArray: string[];\n  duration?: number;\n  pauseDuration?: number;\n  className?: string;\n}\n\nconst GravityTextSwap: React.FC<GravityTextSwapProps> = ({\n  textArray,\n  duration = 0.5,\n  pauseDuration = 2,\n  className = \"\",\n}) => {\n  const [, setCurrentIndex] = useState(0);\n  const [currentText, setCurrentText] = useState(textArray[0]);\n\n  useEffect(() => {\n    if (textArray.length <= 1) return;\n\n    const intervalId = setInterval(\n      () => {\n        setCurrentIndex((prevIndex) => {\n          const nextIndex = (prevIndex + 1) % textArray.length;\n          setCurrentText(textArray[nextIndex] ?? \"\");\n          return nextIndex;\n        });\n      },\n      (duration + pauseDuration) * 1000,\n    );\n\n    return () => clearInterval(intervalId);\n  }, [textArray, duration, pauseDuration]);\n\n  return (\n    <div className={cn(\"inline-block overflow-hidden\", className)}>\n      <AnimatePresence mode=\"wait\">\n        <motion.span\n          key={currentText}\n          className=\"inline-block\"\n          initial={{ opacity: 0 }}\n          animate={{ opacity: 1 }}\n          exit={{ opacity: 0 }}\n          transition={{ duration: duration / 2 }}\n        >\n          {(currentText ?? \"\").split(\"\").map((char, index) => (\n            <motion.span\n              key={index}\n              className=\"inline-block\"\n              initial={{ y: -20, opacity: 0 }}\n              animate={{\n                y: 0,\n                opacity: 1,\n                transition: {\n                  type: \"spring\",\n                  damping: 12,\n                  stiffness: 200,\n                  delay: index * 0.03,\n                },\n              }}\n              exit={{\n                y: 20,\n                opacity: 0,\n                transition: {\n                  duration: duration / 2,\n                  delay: index * 0.02,\n                },\n              }}\n            >\n              {char}\n            </motion.span>\n          ))}\n        </motion.span>\n      </AnimatePresence>\n    </div>\n  );\n};\n\nexport default GravityTextSwap;\n",
      "type": "registry:ui",
      "target": "components/ui/gravity-text-swap.tsx"
    }
  ]
}
