"use client"; import { ChevronLeft, ChevronRight } from "lucide-react"; import { AnimatePresence, motion } from "motion/react"; import { useCallback, useEffect, useRef, useState } from "react"; import { ExpandedGifOverlay, useExpandedGif } from "@/components/ui/expanded-gif-overlay"; const carouselItems = [ { title: "Connect & Sync", description: "Connect data sources like Notion, Drive and Gmail. Automatically sync to keep them updated.", src: "/homepage/hero_tutorial/ConnectorFlowGif.mp4", }, { title: "Upload Documents", description: "Upload documents directly, from images to massive PDFs.", src: "/homepage/hero_tutorial/DocUploadGif.mp4", }, { title: "Video Generation", description: "Create short videos with AI-generated visuals and narration from your sources.", src: "/homepage/hero_tutorial/video_gen_surf.mp4", }, { title: "Search & Citation", description: "Ask questions and get cited responses from your knowledge base.", src: "/homepage/hero_tutorial/BSNCGif.mp4", }, { title: "Targeted Document Q&A", description: "Mention specific documents in chat for targeted answers.", src: "/homepage/hero_tutorial/BQnaGif_compressed.mp4", }, { title: "Produce Reports Instantly", description: "Generate reports from your sources in many formats.", src: "/homepage/hero_tutorial/ReportGenGif_compressed.mp4", }, { title: "Create Podcasts", description: "Turn anything into a podcast in under 20 seconds.", src: "/homepage/hero_tutorial/PodcastGenGif.mp4", }, { title: "Image Generation", description: "Generate high-quality images easily from your conversations.", src: "/homepage/hero_tutorial/ImageGenGif.mp4", }, { title: "Collaborative AI Chat", description: "Collaborate on AI-powered conversations in realtime with your team.", src: "/homepage/hero_realtime/RealTimeChatGif.mp4", }, { title: "Realtime Comments", description: "Add comments and tag teammates on any message.", src: "/homepage/hero_realtime/RealTimeCommentsFlow.mp4", }, ]; function HeroCarouselCard({ title, description, src, onExpandedChange, }: { title: string; description: string; src: string; onExpandedChange?: (expanded: boolean) => void; }) { const { expanded, open, close } = useExpandedGif(); const videoRef = useRef(null); const [hasLoaded, setHasLoaded] = useState(false); useEffect(() => { onExpandedChange?.(expanded); }, [expanded, onExpandedChange]); useEffect(() => { const video = videoRef.current; if (!video) return; setHasLoaded(false); video.currentTime = 0; const observer = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting) { video.play().catch(() => {}); observer.disconnect(); } }, { threshold: 0.1 } ); observer.observe(video); return () => observer.disconnect(); }, [src]); const handleCanPlay = useCallback(() => { setHasLoaded(true); }, []); return ( <>

{title}

{description}

{expanded && } ); } function HeroCarousel() { const [activeIndex, setActiveIndex] = useState(0); const [isGifExpanded, setIsGifExpanded] = useState(false); const directionRef = useRef<"forward" | "backward">("forward"); const goTo = useCallback( (newIndex: number) => { directionRef.current = newIndex >= activeIndex ? "forward" : "backward"; setActiveIndex(newIndex); }, [activeIndex] ); const goToPrev = useCallback(() => { goTo(activeIndex <= 0 ? carouselItems.length - 1 : activeIndex - 1); }, [activeIndex, goTo]); const goToNext = useCallback(() => { goTo(activeIndex >= carouselItems.length - 1 ? 0 : activeIndex + 1); }, [activeIndex, goTo]); const item = carouselItems[activeIndex]; const isForward = directionRef.current === "forward"; return (
{carouselItems.map((_, i) => ( ))}
); } export { HeroCarousel, HeroCarouselCard };