"use client"; import Headline from "@/components/ui/headline"; import Image from "next/image"; import gsap from "gsap"; import { useEffect, useRef, useState } from "react"; import Button from "@/components/shared/Button"; import { useSplitHeading } from "@/lib/useTextRevealHeading"; const ProductPreview = () => { const headingRef = useRef(null); const headingRef2 = useRef(null); const paraRef = useRef(null); const paraRef2 = useRef(null); const containerRef = useRef(null); const [activeIndex, setActiveIndex] = useState(0); const imageRef = useRef(null); const intervalRef = useRef(null); const listItemsRef = useRef<(HTMLLIElement | null)[]>([]); useSplitHeading(headingRef, paraRef); useSplitHeading(headingRef2, paraRef2); const features = [ { feature: "Tree Health View with Vitality Gauge", Image: "/images/png/hero-bg.png", }, { feature: "Sensor Management System", Image: "/images/png/hero-bg.png", }, { feature: "Data Export & Analytics Tools", Image: "/images/png/hero-bg.png", }, { feature: "Multi-user Access and Permissions", Image: "/images/png/hero-bg.png", }, ]; useEffect(() => { if (!imageRef.current) return; gsap.fromTo( imageRef.current, { opacity: 0, scale: 0.97 }, { opacity: 1, scale: 1, duration: 0.8, ease: "power2.out" } ); }, [activeIndex]); useEffect(() => { intervalRef.current = setInterval(() => { setActiveIndex((prev) => (prev + 1) % features.length); }, 4000); return () => { if (intervalRef.current) clearInterval(intervalRef.current); }; }, []); /* --------------------------------------------------------------- */ /* 3. Scroll-triggered: Image clip-path + List stagger */ /* --------------------------------------------------------------- */ useEffect(() => { const ctx = gsap.context(() => { const tl = gsap.timeline({ scrollTrigger: { trigger: ".report-wrapper", start: "top 85%", toggleActions: "play none none none", }, }); /* ---- Image: bottom → top clip-path ---- */ if (imageRef.current) { gsap.set(imageRef.current, { clipPath: "inset(100% 0% 0% 0%)", opacity: 0, }); tl.to(imageRef.current, { clipPath: "inset(0% 0% 0% 0%)", opacity: 1, duration: 1.2, ease: "power3.out", }); } const items = listItemsRef.current.filter(Boolean); gsap.set(items, { y: 60 }); tl.to( items, { y: 0, duration: 0.8, ease: "power2.out", stagger: 0.15, }, "-=0.8" ); // overlap slightly with image reveal }, containerRef); return () => ctx.revert(); }, []); return (

Manage Every Tree with{" "} Clarity. and{" "} Confidence.{" "}

A powerful all-in-one dashboard to monitor tree health, sensors, and data insights — built for precision forestry and sustainability.

Export for{" "} Reports

Generate ready-to-share reports with insights for management, research, or community updates.

    {features.map((item, idx) => (
  • { listItemsRef.current[idx] = el; }} className={`flex items-center gap-3 transition-all duration-500 ${ activeIndex === idx ? "scale-[1.02] opacity-100" : "scale-100 opacity-30" }`} >
    Leaf icon

    {item.feature}

  • ))}
{/* RIGHT SIDE: Changing Image */}
{features[activeIndex].feature}
); }; export default ProductPreview;