{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "text-animate", "title": "Text Animate", "description": "A text animation component that animates text using a variety of different animations.", "dependencies": [ "motion" ], "files": [ { "path": "registry/magicui/text-animate.tsx", "content": "\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport { AnimatePresence, motion, MotionProps, Variants } from \"motion/react\";\nimport { ElementType } from \"react\";\n\ntype AnimationType = \"text\" | \"word\" | \"character\" | \"line\";\ntype AnimationVariant =\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 content to animate\n */\n children: string;\n /**\n * The class name to be applied to the component\n */\n className?: string;\n /**\n * The class name to be applied to each segment\n */\n segmentClassName?: string;\n /**\n * The delay before the animation starts\n */\n delay?: number;\n /**\n * The duration of the animation\n */\n duration?: number;\n /**\n * Custom motion variants for the animation\n */\n variants?: Variants;\n /**\n * The element type to render\n */\n as?: ElementType;\n /**\n * How to split the text (\"text\", \"word\", \"character\")\n */\n by?: AnimationType;\n /**\n * Whether to start animation when component enters viewport\n */\n startOnView?: boolean;\n /**\n * Whether to animate only once\n */\n once?: boolean;\n /**\n * The animation preset to use\n */\n animation?: AnimationVariant;\n}\n\nconst staggerTimings: Record = {\n text: 0.06,\n word: 0.05,\n character: 0.03,\n line: 0.06,\n};\n\nconst defaultContainerVariants = {\n hidden: { opacity: 1 },\n show: {\n opacity: 1,\n transition: {\n staggerChildren: 0.05,\n },\n },\n exit: {\n opacity: 0,\n transition: {\n staggerChildren: 0.05,\n staggerDirection: -1,\n },\n },\n};\n\nconst defaultItemVariants: Variants = {\n hidden: { opacity: 0 },\n show: {\n opacity: 1,\n },\n exit: {\n opacity: 0,\n },\n};\n\nconst defaultItemAnimationVariants: Record<\n AnimationVariant,\n { container: Variants; item: Variants }\n> = {\n fadeIn: {\n container: defaultContainerVariants,\n item: {\n hidden: { opacity: 0, y: 20 },\n show: (delay: number) => ({\n opacity: 1,\n y: 0,\n transition: {\n delay,\n duration: 0.3,\n },\n }),\n exit: {\n opacity: 0,\n y: 20,\n transition: { duration: 0.3 },\n },\n },\n },\n blurIn: {\n container: defaultContainerVariants,\n item: {\n hidden: { opacity: 0, filter: \"blur(10px)\" },\n show: (i: number) => ({\n opacity: 1,\n filter: \"blur(0px)\",\n transition: {\n delay: i * 0.1,\n duration: 0.3,\n },\n }),\n exit: {\n opacity: 0,\n filter: \"blur(10px)\",\n transition: { duration: 0.3 },\n },\n },\n },\n blurInUp: {\n container: defaultContainerVariants,\n item: {\n hidden: { opacity: 0, filter: \"blur(10px)\", y: 20 },\n show: (delay: number) => ({\n opacity: 1,\n filter: \"blur(0px)\",\n y: 0,\n transition: {\n y: { duration: 0.3 },\n opacity: { duration: 0.4 },\n filter: { duration: 0.3 },\n },\n }),\n exit: {\n opacity: 0,\n filter: \"blur(10px)\",\n y: 20,\n transition: {\n y: { duration: 0.3 },\n opacity: { duration: 0.4 },\n filter: { duration: 0.3 },\n },\n },\n },\n },\n blurInDown: {\n container: defaultContainerVariants,\n item: {\n hidden: { opacity: 0, filter: \"blur(10px)\", y: -20 },\n show: (delay: number) => ({\n opacity: 1,\n filter: \"blur(0px)\",\n y: 0,\n transition: {\n y: { duration: 0.3 },\n opacity: { duration: 0.4 },\n filter: { duration: 0.3 },\n },\n }),\n },\n },\n slideUp: {\n container: defaultContainerVariants,\n item: {\n hidden: { y: 20, opacity: 0 },\n show: (delay: number) => ({\n y: 0,\n opacity: 1,\n transition: {\n delay,\n duration: 0.3,\n },\n }),\n exit: {\n y: -20,\n opacity: 0,\n transition: {\n duration: 0.3,\n },\n },\n },\n },\n slideDown: {\n container: defaultContainerVariants,\n item: {\n hidden: { y: -20, opacity: 0 },\n show: {\n y: 0,\n opacity: 1,\n transition: { duration: 0.3 },\n },\n exit: {\n y: 20,\n opacity: 0,\n transition: { duration: 0.3 },\n },\n },\n },\n slideLeft: {\n container: defaultContainerVariants,\n item: {\n hidden: { x: 20, opacity: 0 },\n show: {\n x: 0,\n opacity: 1,\n transition: { duration: 0.3 },\n },\n exit: {\n x: -20,\n opacity: 0,\n transition: { duration: 0.3 },\n },\n },\n },\n slideRight: {\n container: defaultContainerVariants,\n item: {\n hidden: { x: -20, opacity: 0 },\n show: {\n x: 0,\n opacity: 1,\n transition: { duration: 0.3 },\n },\n exit: {\n x: 20,\n opacity: 0,\n transition: { duration: 0.3 },\n },\n },\n },\n scaleUp: {\n container: defaultContainerVariants,\n item: {\n hidden: { scale: 0.5, opacity: 0 },\n show: {\n scale: 1,\n opacity: 1,\n transition: {\n duration: 0.3,\n scale: {\n type: \"spring\",\n damping: 15,\n stiffness: 300,\n },\n },\n },\n exit: {\n scale: 0.5,\n opacity: 0,\n transition: { duration: 0.3 },\n },\n },\n },\n scaleDown: {\n container: defaultContainerVariants,\n item: {\n hidden: { scale: 1.5, opacity: 0 },\n show: (delay: number) => ({\n scale: 1,\n opacity: 1,\n transition: {\n delay,\n duration: 0.3,\n scale: {\n type: \"spring\",\n damping: 15,\n stiffness: 300,\n },\n },\n }),\n exit: {\n scale: 1.5,\n opacity: 0,\n transition: { duration: 0.3 },\n },\n },\n },\n};\n\nexport function TextAnimate({\n children,\n delay = 0,\n duration = 0.3,\n variants,\n className,\n segmentClassName,\n as: Component = \"p\",\n startOnView = true,\n once = false,\n by = \"word\",\n animation = \"fadeIn\",\n ...props\n}: TextAnimateProps) {\n const MotionComponent = motion.create(Component);\n\n // Use provided variants or default variants based on animation type\n const finalVariants = animation\n ? {\n container: {\n ...defaultItemAnimationVariants[animation].container,\n show: {\n ...defaultItemAnimationVariants[animation].container.show,\n transition: {\n staggerChildren: staggerTimings[by],\n },\n },\n exit: {\n ...defaultItemAnimationVariants[animation].container.exit,\n transition: {\n staggerChildren: staggerTimings[by],\n staggerDirection: -1,\n },\n },\n },\n item: defaultItemAnimationVariants[animation].item,\n }\n : { container: defaultContainerVariants, item: defaultItemVariants };\n\n let segments: string[] = [];\n switch (by) {\n case \"word\":\n segments = children.split(/(\\s+)/);\n break;\n case \"character\":\n segments = children.split(\"\");\n break;\n case \"line\":\n segments = children.split(\"\\n\");\n break;\n case \"text\":\n default:\n segments = [children];\n break;\n }\n\n return (\n \n \n {segments.map((segment, i) => (\n \n {segment}\n \n ))}\n \n \n );\n}\n", "type": "registry:ui", "target": "components/magicui/text-animate.tsx" } ], "type": "registry:ui" }