"use client"; import type { MotionValue } from "framer-motion"; import { AnimatePresence, motion, useScroll, useTransform, } from "framer-motion"; import React, { useEffect, useRef, useState } from "react"; import { cn } from "@/lib/utils"; const getAnimationRange = (index: number, totalFeatures: number) => { const cardPosition = index / totalFeatures; const range = [0, cardPosition, 1]; return range; }; interface Statistics { value: string; label: string; } interface Feature { id: string; title: string; subtitle: string; statistics: Statistics; visual: string; } interface Testimonial { quote: string; companyLogo: string; author: string; designation: string; } interface AnimationWrapperProps { children: React.ReactNode; delay?: number; className?: string; duration?: number; } const AnimationWrapper = ({ children, delay = 0, className, duration = 0.3, }: AnimationWrapperProps) => { return ( {children} ); }; interface TestimonialCardProps { testimonial: Testimonial; } const TestimonialCard = ({ testimonial }: TestimonialCardProps) => { return (
{testimonial.author}

«{testimonial.quote}»

{testimonial.author}{" "} {testimonial.designation}

); }; interface ScrollProgressIndicatorProps { totalFeatures: number; activeIndex: number; scrollYProgress: MotionValue; } const ScrollProgressIndicator = ({ totalFeatures, activeIndex, scrollYProgress, }: ScrollProgressIndicatorProps) => { const range = getAnimationRange( Math.max(0, activeIndex - 0.5), totalFeatures, ); const nextRange = getAnimationRange( Math.min(totalFeatures, activeIndex + 0.5), totalFeatures, ); const currentRange = [range[1], nextRange[1]]; const width = useTransform(scrollYProgress, currentRange, ["0%", "100%"]); return (
{Array.from({ length: totalFeatures }).map((_, index) => { return (
index && "bg-foreground", )} > {activeIndex === index && ( )}
); })}
); }; interface FeatureCardProps { feature: Feature; index: number; testimonial: Testimonial; totalFeatures: number; scrollYProgress: MotionValue; } const FeatureCard = ({ feature, index, testimonial, totalFeatures, scrollYProgress, }: FeatureCardProps) => { return (

{feature.title}

{feature.subtitle}

{feature.statistics.value}

{feature.statistics.label}

{feature.title} {index === 0 && }
); }; interface Feature322Props { features?: Feature[]; testimonial?: Testimonial; className?: string; } const DEFAULT_FEATURES: Feature[] = [ { id: "performance", title: "طبقه‌بندی خودکار", subtitle: "درخواست‌ها را خودکار دسته‌بندی کنید و به تیم مناسب بفرستید.", statistics: { value: "اتوماسیون AI", label: "دستیار کسب‌وکار", }, visual: "/block-media/shadcnblocks/block/photos/christopher-gower-vjMgqUkS8q8-unsplash.jpg", }, { id: "security", title: "پیش‌بینی ریزش", subtitle: "مشتریان در معرض ریزش را زودتر شناسایی کنید.", statistics: { value: "هوش مصنوعی", label: "پیشنهاد هوشمند", }, visual: "/block-media/shadcnblocks/block/photos/daniel-leone-g30P1zcOzXo-unsplash.jpg", }, { id: "analytics", title: "جستجوی معنایی", subtitle: "متن‌های طولانی را در چند ثانیه به نکات کلیدی تبدیل کنید.", statistics: { value: "اتوماسیون AI", label: "دستیار کسب‌وکار", }, visual: "/block-media/shadcnblocks/block/photos/jason-leung-6uoj7DL6BFk-unsplash.jpg", }, { id: "integration", title: "تولید محتوا", subtitle: "بهترین پاسخ را بر اساس زمینه مکالمه پیشنهاد دهید.", statistics: { value: "هوش مصنوعی", label: "پیشنهاد هوشمند", }, visual: "/block-media/shadcnblocks/block/photos/ivan-bandura-Kj2tYAl4HZg-unsplash.jpg", }, ]; const DEFAULT_TESTIMONIAL: Testimonial = { quote: "مدل‌های هوشمند الگوهای پنهان در داده فروش و پشتیبانی را پیدا می‌کنند. تیم‌ها با پیشنهادهای عملی، سریع‌تر اقدام می‌کنند.", companyLogo: "/block-media/shadcnblocks/block/logos/company/fictional-company-logo-4.svg", author: "اتوماسیون AI", designation: "با هوش مصنوعی سریع‌تر تصمیم بگیرید", }; const Feature322 = ({ className, features = DEFAULT_FEATURES, testimonial = DEFAULT_TESTIMONIAL, }: Feature322Props) => { const ref = useRef(null); const { scrollYProgress } = useScroll({ container: ref, }); const [activeIndex, setActiveIndex] = useState(0); useEffect(() => { const unsubscribe = scrollYProgress.on("change", (latest) => { let minDistance = Infinity; let temp = 0; features.forEach((_, index) => { const range = getAnimationRange(index, features.length); const position = range[1]; const distance = Math.abs(latest - position); if (distance < minDistance) { minDistance = distance; temp = index; } }); setActiveIndex(temp); }); return () => unsubscribe(); }, [features, scrollYProgress]); return (
{features.map((feature, index) => { return ( ); })}
); }; export { Feature322 };