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.
80 lines (79 loc) • 3.32 kB
JavaScript
// @ts-nocheck
"use client";
import { jsx as _jsx } from "react/jsx-runtime";
import { useGSAP } from "@gsap/react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { useRef } from "react";
import { cn } from "../../lib/utils";
export function ScrollPara({ paragraphs, direction = "bottom", startBlur = 10, offset = 50, className, containerClassName, textClassName, startOpacity = 0.1, stagger = 0.5, }) {
const container = useRef(null);
const textRefs = useRef([]);
useGSAP(() => {
gsap.registerPlugin(ScrollTrigger);
const elements = textRefs.current.filter(Boolean);
const totalElements = elements.length;
if (totalElements === 0)
return;
const getInitialTransform = () => {
switch (direction) {
case "top":
return { y: -offset, x: 0 };
case "left":
return { x: -offset, y: 0 };
case "right":
return { x: offset, y: 0 };
case "bottom":
return { y: offset, x: 0 };
case "none":
default:
return { x: 0, y: 0 };
}
};
// Set initial state
elements.forEach((el) => {
gsap.set(el, {
...getInitialTransform(),
opacity: startOpacity,
filter: `blur(${startBlur}px)`,
});
});
const scrollTimeline = gsap.timeline({
scrollTrigger: {
trigger: container.current,
start: "top top",
end: `+=${window.innerHeight * totalElements * 0.8}`, // Extended scroll duration based on items
pin: true,
scrub: 1,
pinSpacing: true,
anticipatePin: 1,
},
});
elements.forEach((el, index) => {
scrollTimeline.to(el, {
x: 0,
y: 0,
opacity: 1,
filter: "blur(0px)",
duration: 1,
ease: "power2.out",
}, index * stagger);
});
const resizeObserver = new ResizeObserver(() => {
ScrollTrigger.refresh();
});
if (container.current) {
resizeObserver.observe(container.current);
}
return () => {
resizeObserver.disconnect();
scrollTimeline.kill();
};
}, {
scope: container,
dependencies: [direction, paragraphs.length, startOpacity, startBlur, offset, stagger],
});
return (_jsx("div", { className: cn("relative w-full min-h-[100vh]", className), ref: container, children: _jsx("div", { className: "relative flex h-[100vh] w-full items-center justify-center overflow-hidden p-6 md:p-12", children: _jsx("div", { className: cn("relative w-full max-w-5xl flex flex-col gap-6 md:gap-10", containerClassName), children: paragraphs.map((text, i) => (_jsx("p", { className: cn("text-2xl md:text-5xl lg:text-6xl font-medium leading-tight tracking-tight text-white will-change-transform", textClassName), ref: (el) => {
textRefs.current[i] = el;
}, children: text }, i))) }) }) }));
}