UNPKG

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
"use strict"; "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