Files
reui-blocks/blocks/feature242.tsx
T
2026-08-13 20:38:45 +03:30

187 lines
7.0 KiB
TypeScript

"use client";
import { ChevronRight, Plus } from "lucide-react";
import React from "react";
import { Button } from "@/components/ui/button";
import type { CarouselApi } from "@/components/ui/carousel";
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@/components/ui/carousel";
import { cn } from "@/lib/utils";
const TESTIMONIALS = [
{
id: "copy-paste",
title: "طبقه‌بندی خودکار",
imageAlt: "دستیار هوش مصنوعی",
imgSrc:
"/block-media/shadcnblocks/block/illustrations/tokyo-exchange-between-the-user-and-the-global-network.svg",
href: "#",
},
{
id: "modern-ui",
title: "پیش‌بینی ریزش",
imageAlt: "پیشنهادهای هوشمند",
imgSrc:
"/block-media/shadcnblocks/block/illustrations/tokyo-letters-and-arrows-flying-out-of-a-black-hole.svg",
href: "#",
},
{
id: "workflow",
title: "جستجوی معنایی",
imageAlt: "تحلیل با AI",
imgSrc:
"/block-media/shadcnblocks/block/illustrations/tokyo-loading-the-next-page.svg",
href: "#",
},
{
id: "collaborate",
title: "تولید محتوا",
imageAlt: "دستیار هوش مصنوعی",
imgSrc:
"/block-media/shadcnblocks/block/illustrations/tokyo-many-browser-windows-with-different-information.svg",
href: "#",
},
] as const;
interface Feature242Props {
className?: string;
}
const Feature242 = ({ className }: Feature242Props) => {
const [api, setApi] = React.useState<CarouselApi>();
const [current, setCurrent] = React.useState(0);
const [count, setCount] = React.useState(0);
React.useEffect(() => {
if (!api) {
return;
}
setCount(TESTIMONIALS.length);
setCurrent(api.selectedScrollSnap() + 1);
api.on("select", () => {
setCurrent(api.selectedScrollSnap() + 1);
});
}, [api]);
const formatSlideNumber = (value: number) =>
value.toLocaleString("fa-IR", { minimumIntegerDigits: 2 });
return (
<section
dir="rtl"
lang="fa"
className={cn("relative w-full overflow-hidden py-32", className)}
>
<div className="relative container flex min-w-0 flex-col items-center md:px-0 lg:pt-8">
<div className="relative z-10 w-full min-w-0 items-center justify-between text-start lg:flex">
<h1 className="max-w-2xl text-2xll font-semibold tracking-tighter text-balance md:text-2xll">
با هوش مصنوعی سریع‌تر تصمیم بگیرید
</h1>
<p className="mt-8 max-w-lg tracking-tight text-pretty text-muted-foreground/80 md:text-xl lg:mt-0">
مدل‌های هوشمند الگوهای پنهان در داده فروش و پشتیبانی را پیدا می‌کنند.
تیم‌ها با پیشنهادهای عملی، سریع‌تر اقدام می‌کنند.{" "}
<span className="group inline-flex cursor-pointer items-center font-medium text-foreground transition-all ease-in-out">
اتوماسیون AI
<ChevronRight
size={17}
className="mt-px ms-1 transition-all ease-in-out group-hover:ms-2 rtl:rotate-180"
/>
</span>
</p>
</div>
<DottedDiv className="mt-8 flex w-full min-w-0 items-center justify-center px-2 py-10">
<Carousel
opts={{
align: "center",
loop: true,
direction: "rtl",
}}
className="w-full min-w-0"
setApi={setApi}
>
{/* Override -ml-4 — breaks RTL track sizing */}
<CarouselContent className="-ml-0! m-0 flex w-full">
{TESTIMONIALS.map((item) => (
<CarouselItem
key={item.id}
className="min-w-0 pl-0! px-2 md:basis-1/2 lg:basis-1/3"
>
<div className="group relative flex h-full max-h-96 w-full min-w-0 flex-col items-start justify-between rounded-3xl bg-muted p-5 text-ellipsis">
<img
className="max-h-72 w-full max-w-full opacity-100 transition-all ease-in-out group-hover:scale-90 group-hover:opacity-60"
src={item.imgSrc}
alt={item.imageAlt}
/>
<div className="flex w-full min-w-0 items-center justify-between gap-4">
<h5 className="min-w-0 text-xl leading-7 font-medium tracking-tighter text-balance transition-all ease-in-out group-hover:translate-x-4 rtl:group-hover:-translate-x-4">
{item.title}
</h5>
<a
href={item.href}
className="relative z-10 shrink-0 cursor-pointer"
aria-label={`بیشتر درباره ${item.title}`}
>
<Button
variant="outline"
className="size-12 rounded-full bg-transparent transition-all ease-in-out hover:bg-muted"
>
<Plus className="scale-150" />
</Button>
</a>
</div>
</div>
</CarouselItem>
))}
</CarouselContent>
<div className="mt-8 flex w-full items-center justify-between px-4">
<div className="flex items-center gap-2 font-medium">
<span className="text-lg">{formatSlideNumber(current)}</span>
<span className="text-muted-foreground">/</span>
<span className="text-muted-foreground">
{formatSlideNumber(count)}
</span>
</div>
<div className="relative z-10 flex gap-2">
<CarouselPrevious className="static size-10 translate-y-0 rtl:rotate-180" />
<CarouselNext className="static size-10 translate-y-0 rtl:rotate-180" />
</div>
</div>
</Carousel>
</DottedDiv>
</div>
</section>
);
};
export { Feature242 };
const DottedDiv = ({
children,
className,
}: {
children: React.ReactNode;
className?: string;
}) => (
<div className={cn("relative min-w-0 overflow-hidden", className)}>
<div className="absolute top-4 -start-[12.5px] h-px w-[110%] bg-muted md:-start-20" />
<div className="absolute bottom-4 -start-[12.5px] h-px w-[110%] bg-muted md:-start-20" />
<div className="absolute -top-4 start-0 h-[110%] w-px bg-muted" />
<div className="absolute -top-4 end-0 h-[110%] w-px bg-muted" />
<div className="absolute start-[-3px] top-[12.5px] z-10 size-2 rounded-full bg-foreground" />
<div className="absolute end-[-3px] top-[12.5px] z-10 size-2 rounded-full bg-foreground" />
<div className="absolute start-[-3px] bottom-[12.5px] z-10 size-2 rounded-full bg-foreground" />
<div className="absolute end-[-3px] bottom-[12.5px] z-10 size-2 rounded-full bg-foreground" />
{children}
</div>
);