xlibs-components
Version:
Modern React component library with Aceternity, MagicUI, and ShadCN components for building beautiful web applications
42 lines (41 loc) • 2.62 kB
JavaScript
"use client";
import { jsx as _jsx } from "react/jsx-runtime";
import React, { useState, useEffect, useId } from "react";
import { motion } from "framer-motion";
import { cn } from '../../lib/utils.js';
export function ContainerTextFlip({ words = ["better", "modern", "beautiful", "awesome"], interval = 3000, className, textClassName, animationDuration = 700, }) {
const id = useId();
const [currentWordIndex, setCurrentWordIndex] = useState(0);
const [width, setWidth] = useState(100);
const textRef = React.useRef(null);
const updateWidthForWord = () => {
if (textRef.current) {
// Add some padding to the text width (30px on each side)
const textWidth = textRef.current.scrollWidth + 30;
setWidth(textWidth);
}
};
useEffect(() => {
// Update width whenever the word changes
updateWidthForWord();
}, [currentWordIndex]);
useEffect(() => {
const intervalId = setInterval(() => {
setCurrentWordIndex((prevIndex) => (prevIndex + 1) % words.length);
// Width will be updated in the effect that depends on currentWordIndex
}, interval);
return () => clearInterval(intervalId);
}, [words, interval]);
return (_jsx(motion.p, { layout: true, layoutId: `words-here-${id}`, animate: { width }, transition: { duration: animationDuration / 2000 }, className: cn("relative inline-block rounded-lg pt-2 pb-3 text-center text-4xl font-bold text-black md:text-7xl dark:text-white", "[background:linear-gradient(to_bottom,#f3f4f6,#e5e7eb)]", "shadow-[inset_0_-1px_#d1d5db,inset_0_0_0_1px_#d1d5db,_0_4px_8px_#d1d5db]", "dark:[background:linear-gradient(to_bottom,#374151,#1f2937)]", "dark:shadow-[inset_0_-1px_#10171e,inset_0_0_0_1px_hsla(205,89%,46%,.24),_0_4px_8px_#00000052]", className), children: _jsx(motion.div, { transition: {
duration: animationDuration / 1000,
ease: "easeInOut",
}, className: cn("inline-block", textClassName), ref: textRef, layoutId: `word-div-${words[currentWordIndex]}-${id}`, children: _jsx(motion.div, { className: "inline-block", children: words[currentWordIndex].split("").map((letter, index) => (_jsx(motion.span, { initial: {
opacity: 0,
filter: "blur(10px)",
}, animate: {
opacity: 1,
filter: "blur(0px)",
}, transition: {
delay: index * 0.02,
}, children: letter }, index))) }) }) }, words[currentWordIndex]));
}