{ "name": "text-animate", "type": "registry:ui", "dependencies": ["framer-motion"], "files": [ { "path": "components/ui/text-animate.tsx", "content": "\"use client\"\n\nimport { cn } from \"@/lib/utils\"\nimport { AnimatePresence, motion, useInView, MotionProps, Variants } from \"framer-motion\"\nimport { ElementType, useRef } from \"react\"\n\ntype AnimationType =\n | \"fadeIn\"\n | \"blurIn\"\n | \"blurInUp\"\n | \"blurInDown\"\n | \"slideUp\"\n | \"slideDown\"\n | \"slideLeft\"\n | \"slideRight\"\n | \"scaleUp\"\n | \"scaleDown\"\n\ninterface TextAnimateProps extends MotionProps {\n /**\n * The text to animate\n */\n children: string\n /**\n * The class name for the wrapper element\n */\n className?: string\n /**\n * The class name for the segmented elements (words or characters)\n */\n segmentClassName?: string\n /**\n * The base component to use for the wrapper\n */\n as?: ElementType\n /**\n * The base delay for the animation\n */\n delay?: number\n /**\n * The duration of the animation per item\n */\n duration?: number\n /**\n * The type of animation to perform\n */\n animation?: AnimationType\n /**\n * How to split the text\n */\n by?: \"text\" | \"word\" | \"character\"\n /**\n * Whether to start the animation when the element comes into view\n */\n startOnView?: boolean\n /**\n * Whether to run the animation only once\n */\n once?: boolean\n}\n\nexport function TextAnimate({\n children,\n delay = 0,\n duration = 0.3,\n className,\n segmentClassName,\n as: Component = \"p\",\n startOnView = true,\n once = true,\n by = \"word\",\n animation = \"fadeIn\",\n ...props\n}: TextAnimateProps) {\n const ref = useRef(null)\n const isInView = useInView(ref, { once })\n\n const segments =\n by === \"character\"\n ? children.split(\"\")\n : by === \"word\"\n ? children.split(\" \")\n : [children]\n\n const containerVariants: Variants = {\n hidden: { opacity: 0 },\n show: {\n opacity: 1,\n transition: {\n staggerChildren: 0.1,\n delayChildren: delay,\n },\n },\n exit: {\n opacity: 0,\n transition: {\n staggerChildren: 0.05,\n staggerDirection: -1,\n },\n },\n }\n\n const itemVariants: Record<\n AnimationType,\n Variants\n > = {\n fadeIn: {\n hidden: { opacity: 0 },\n show: {\n opacity: 1,\n transition: { duration },\n },\n },\n blurIn: {\n hidden: { opacity: 0, filter: \"blur(10px)\" },\n show: {\n opacity: 1,\n filter: \"blur(0px)\",\n transition: { duration },\n },\n },\n blurInUp: {\n hidden: { opacity: 0, filter: \"blur(10px)\", y: 20 },\n show: {\n opacity: 1,\n filter: \"blur(0px)\",\n y: 0,\n transition: { duration },\n },\n },\n blurInDown: {\n hidden: { opacity: 0, filter: \"blur(10px)\", y: -20 },\n show: {\n opacity: 1,\n filter: \"blur(0px)\",\n y: 0,\n transition: { duration },\n },\n },\n slideUp: {\n hidden: { y: 20, opacity: 0 },\n show: {\n y: 0,\n opacity: 1,\n transition: { duration },\n },\n },\n slideDown: {\n hidden: { y: -20, opacity: 0 },\n show: {\n y: 0,\n opacity: 1,\n transition: { duration },\n },\n },\n slideLeft: {\n hidden: { x: 20, opacity: 0 },\n show: {\n x: 0,\n opacity: 1,\n transition: { duration },\n },\n },\n slideRight: {\n hidden: { x: -20, opacity: 0 },\n show: {\n x: 0,\n opacity: 1,\n transition: { duration },\n },\n },\n scaleUp: {\n hidden: { scale: 0.5, opacity: 0 },\n show: {\n scale: 1,\n opacity: 1,\n transition: { duration },\n },\n },\n scaleDown: {\n hidden: { scale: 1.5, opacity: 0 },\n show: {\n scale: 1,\n opacity: 1,\n transition: { duration },\n },\n },\n }\n\n const finalVariants = itemVariants[animation]\n\n // Use the 'as' prop to dynmically render the motion component\n const MotionComponent = motion.create(Component)\n\n return (\n \n \n {segments.map((segment, i) => (\n \n {segment}\n {by === \"word\" && i < segments.length - 1 && (\n  \n )}\n \n ))}\n \n \n )\n}\n", "type": "registry:ui" } ] }