import { useEffect, useRef } from "react"; import { gsap } from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; import Button from "@/components/ui/Button"; import TextAnimation from "@/components/ui/TextAnimation"; import ImageOrVideo from "@/components/ui/ImageOrVideo"; import { cls } from "@/lib/utils"; gsap.registerPlugin(ScrollTrigger); type FeatureItem = { title: string; description: string; primaryButton?: { text: string; href: string }; secondaryButton?: { text: string; href: string }; } & ({ imageSrc: string; videoSrc?: never } | { videoSrc: string; imageSrc?: never }); interface FeaturesAlternatingSplitProps { tag: string; title: string; description: string; primaryButton?: { text: string; href: string }; secondaryButton?: { text: string; href: string }; items: FeatureItem[]; } const FeaturesAlternatingSplit = ({ tag, title, description, primaryButton, secondaryButton, items, }: FeaturesAlternatingSplitProps) => { const itemRefs = useRef<(HTMLDivElement | null)[]>([]); useEffect(() => { const ctx = gsap.context(() => { itemRefs.current.forEach((ref, position) => { if (!ref) return; const isLast = position === itemRefs.current.length - 1; gsap.timeline({ scrollTrigger: { trigger: ref, start: "center center", end: "+=100%", scrub: true, }, }) .set(ref, { willChange: "opacity" }) .to(ref, { ease: "none", opacity: isLast ? 1 : 0, }); }); }); return () => ctx.revert(); }, [items.length]); return (

{tag}

{(primaryButton || secondaryButton) && (
{primaryButton &&
)}
{items.map((item, index) => (
{ itemRefs.current[index] = el; }} className={cls("sticky top-[25vw] md:top-[12.5vh] h-[140vw] md:h-[75vh] flex flex-col gap-6 md:gap-10 p-6 md:p-10 card rounded", index % 2 === 0 ? "md:flex-row" : "md:flex-row-reverse")} >

{index + 1}

{item.title}

{item.description}

{(item.primaryButton || item.secondaryButton) && (
{item.primaryButton &&
)}
))}
); }; export default FeaturesAlternatingSplit;