lightswind
Version:
A collection of beautifully crafted React Components, Blocks & Templates for Modern Developers. Create stunning web applications effortlessly by using our 160+ professional and animated react components.
47 lines • 3.61 kB
JavaScript
;
"use client";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LoopingWords = LoopingWords;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const framer_motion_1 = require("framer-motion");
const utils_1 = require("@/components/lib/utils");
function LoopingWords({ words, className }) {
const controls = (0, framer_motion_1.useAnimationControls)();
const wordsRef = (0, react_1.useRef)([]);
const [selectorWidth, setSelectorWidth] = (0, react_1.useState)(0);
// Duplicate the words array to create a seamless infinite loop
const duplicatedWords = [...words, ...words];
const totalOriginal = words.length;
(0, react_1.useEffect)(() => {
// Initial width setup
updateWidth(1);
let index = 0;
const interval = setInterval(async () => {
index++;
updateWidth((index % totalOriginal) + 1);
await controls.start({
y: `-${(index * 100) / duplicatedWords.length}%`,
transition: { duration: 1.2, ease: [0.175, 0.885, 0.32, 1.15] },
});
// If we've scrolled past the first full set, snap back to the start seamlessly
if (index === totalOriginal) {
index = 0;
controls.set({ y: "0%" });
}
}, 2200);
return () => clearInterval(interval);
}, [controls, totalOriginal, duplicatedWords.length]);
const updateWidth = (index) => {
const el = wordsRef.current[index];
if (el) {
setSelectorWidth(el.offsetWidth);
}
};
return ((0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)("flex items-center justify-center", className), children: (0, jsx_runtime_1.jsxs)("div", { className: "relative h-[2.7em] px-[0.2em] text-[11vw] md:text-[6vw] leading-[0.9] font-bold uppercase whitespace-nowrap overflow-hidden", children: [(0, jsx_runtime_1.jsx)(framer_motion_1.motion.ul, { className: "flex flex-col items-center m-0 p-0 list-none", animate: controls, initial: { y: "0%" }, children: duplicatedWords.map((word, i) => ((0, jsx_runtime_1.jsx)("li", { ref: (el) => {
wordsRef.current[i] = el;
}, className: "text-foreground tracking-tight", children: (0, jsx_runtime_1.jsx)("p", { className: "m-0", children: word }) }, i))) }), (0, jsx_runtime_1.jsx)("div", { className: "pointer-events-none absolute inset-0 z-10", style: {
backgroundImage: "linear-gradient(180deg, hsl(var(--background)) 5%, transparent 40%, transparent 60%, hsl(var(--background)) 95%)",
} }), (0, jsx_runtime_1.jsxs)(framer_motion_1.motion.div, { className: "absolute left-1/2 top-1/2 h-[0.9em] -translate-x-1/2 -translate-y-1/2 pointer-events-none z-20", animate: { width: selectorWidth }, transition: { duration: 0.5, ease: "easeOut" }, children: [(0, jsx_runtime_1.jsx)("div", { className: "absolute top-0 left-0 w-[0.125em] h-[0.125em] border-t-[0.035em] border-l-[0.035em] border-primarylw" }), (0, jsx_runtime_1.jsx)("div", { className: "absolute top-0 right-0 w-[0.125em] h-[0.125em] border-t-[0.035em] border-r-[0.035em] border-primarylw" }), (0, jsx_runtime_1.jsx)("div", { className: "absolute bottom-0 left-0 w-[0.125em] h-[0.125em] border-b-[0.035em] border-l-[0.035em] border-primarylw" }), (0, jsx_runtime_1.jsx)("div", { className: "absolute bottom-0 right-0 w-[0.125em] h-[0.125em] border-b-[0.035em] border-r-[0.035em] border-primarylw" })] })] }) }));
}
//# sourceMappingURL=looping-words.js.map