199 lines
6.2 KiB
TypeScript
199 lines
6.2 KiB
TypeScript
"use client";
|
|
|
|
import { motion } from "framer-motion";
|
|
import {
|
|
AudioLines,
|
|
Globe,
|
|
Heart,
|
|
TrophyIcon,
|
|
type LucideIcon,
|
|
} from "lucide-react";
|
|
import React, { useState } from "react";
|
|
|
|
import { cn } from "@/lib/utils";
|
|
|
|
interface FeatureChip {
|
|
icon: LucideIcon;
|
|
value: string;
|
|
label: string;
|
|
}
|
|
|
|
interface FeatureData {
|
|
id: number;
|
|
img: string;
|
|
link: string;
|
|
title: string;
|
|
description: string;
|
|
chips: FeatureChip[];
|
|
}
|
|
|
|
interface Gallery34Props {
|
|
featureData?: FeatureData[];
|
|
className?: string;
|
|
}
|
|
|
|
const formatCount = (value: string) => {
|
|
const match = value.match(/^(\d+)(.*)$/);
|
|
if (!match) return value;
|
|
return `${new Intl.NumberFormat("fa-IR").format(Number(match[1]))}${match[2]}`;
|
|
};
|
|
|
|
const defaultFeatureData: FeatureData[] = [
|
|
{
|
|
id: 1,
|
|
img: "/block-media/shadcnblocks/block/guri3/img7.jpeg",
|
|
link: "#",
|
|
title: "مجموعه گرید چیدمان تیر نسخه ۲",
|
|
description: "#مجموعه-بلاک-تیر",
|
|
chips: [
|
|
{ icon: TrophyIcon, value: "50+", label: "جایزه" },
|
|
{ icon: Globe, value: "50+", label: "بازار جهانی" },
|
|
{ icon: AudioLines, value: "50+", label: "محتوای صوتی" },
|
|
],
|
|
},
|
|
{
|
|
id: 2,
|
|
img: "/block-media/shadcnblocks/block/guri3/img6.jpeg",
|
|
link: "#",
|
|
title: "بسته کامپوننتهای رابط مدرن",
|
|
description: "#کامپوننت-مدرن",
|
|
chips: [
|
|
{ icon: TrophyIcon, value: "75+", label: "جایزه" },
|
|
{ icon: Globe, value: "60+", label: "بازار جهانی" },
|
|
{ icon: AudioLines, value: "45+", label: "محتوای صوتی" },
|
|
],
|
|
},
|
|
{
|
|
id: 3,
|
|
img: "/block-media/shadcnblocks/block/guri3/img14.jpeg",
|
|
link: "#",
|
|
title: "سیستم طراحی واکنشگرا",
|
|
description: "#طراحی-واکنشگرا",
|
|
chips: [
|
|
{ icon: TrophyIcon, value: "90+", label: "جایزه" },
|
|
{ icon: Globe, value: "80+", label: "بازار جهانی" },
|
|
{ icon: AudioLines, value: "65+", label: "محتوای صوتی" },
|
|
],
|
|
},
|
|
{
|
|
id: 4,
|
|
img: "/block-media/shadcnblocks/block/guri3/img25.jpeg",
|
|
link: "#",
|
|
title: "کیت انیمیشن تعاملی",
|
|
description: "#انیمیشن",
|
|
chips: [
|
|
{ icon: TrophyIcon, value: "40+", label: "جایزه" },
|
|
{ icon: Globe, value: "35+", label: "بازار جهانی" },
|
|
{ icon: AudioLines, value: "55+", label: "محتوای صوتی" },
|
|
],
|
|
},
|
|
{
|
|
id: 5,
|
|
img: "/block-media/shadcnblocks/block/guri3/img11.jpeg",
|
|
link: "#",
|
|
title: "کامپوننتهای حالت تیره",
|
|
description: "#حالت-تیره",
|
|
chips: [
|
|
{ icon: TrophyIcon, value: "65+", label: "جایزه" },
|
|
{ icon: Globe, value: "70+", label: "بازار جهانی" },
|
|
{ icon: AudioLines, value: "50+", label: "محتوای صوتی" },
|
|
],
|
|
},
|
|
{
|
|
id: 6,
|
|
img: "/block-media/shadcnblocks/block/guri3/img12.jpeg",
|
|
link: "#",
|
|
title: "بسته قالب فروشگاه آنلاین",
|
|
description: "#فروشگاه-آنلاین",
|
|
chips: [
|
|
{ icon: TrophyIcon, value: "85+", label: "جایزه" },
|
|
{ icon: Globe, value: "90+", label: "بازار جهانی" },
|
|
{ icon: AudioLines, value: "75+", label: "محتوای صوتی" },
|
|
],
|
|
},
|
|
];
|
|
|
|
const Gallery34 = ({
|
|
featureData = defaultFeatureData,
|
|
className,
|
|
}: Gallery34Props) => {
|
|
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);
|
|
|
|
return (
|
|
<section
|
|
dir="rtl"
|
|
lang="fa"
|
|
className={cn("h-full overflow-hidden py-32", className)}
|
|
>
|
|
<div className="container">
|
|
<div className="mx-auto grid w-full max-w-6xl grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
|
|
{featureData.map((item, index) => (
|
|
<a
|
|
key={item.id}
|
|
href={item.link}
|
|
onMouseEnter={() => setHoveredIndex(index)}
|
|
onMouseLeave={() => setHoveredIndex(null)}
|
|
className="relative block overflow-hidden rounded-3xl bg-muted p-2 transition-colors hover:bg-muted/80"
|
|
aria-label={item.title}
|
|
>
|
|
<motion.img
|
|
transition={{
|
|
duration: 0.2,
|
|
ease: "easeOut",
|
|
delay: index * 0.1 + 0.5,
|
|
}}
|
|
animate={{
|
|
filter:
|
|
hoveredIndex !== null && hoveredIndex !== index
|
|
? "blur(10px)"
|
|
: "blur(0px)",
|
|
transition: {
|
|
duration: 0.3,
|
|
ease: "easeOut",
|
|
delay: 0,
|
|
},
|
|
scale: hoveredIndex === index ? 1.02 : 1,
|
|
}}
|
|
src={item.img}
|
|
className="pointer-events-none h-72 w-full rounded-2xl object-cover"
|
|
alt={item.title}
|
|
/>
|
|
<div className="absolute top-4 inset-e-4 z-10">
|
|
<Heart
|
|
className="size-6 fill-background/20 text-background"
|
|
aria-hidden
|
|
/>
|
|
</div>
|
|
<div className="mt-2 p-2 text-right">
|
|
<h2 className="text-xl font-semibold tracking-tight">
|
|
{item.title}
|
|
</h2>
|
|
<p className="mt-2 text-sm text-muted-foreground" dir="rtl">
|
|
{item.description}
|
|
</p>
|
|
<div className="mt-4 flex flex-wrap items-center justify-end gap-2">
|
|
{item.chips.map((chip, chipIndex) => {
|
|
const IconComponent = chip.icon;
|
|
return (
|
|
<span
|
|
key={chipIndex}
|
|
aria-label={`${chip.label}: ${formatCount(chip.value)}`}
|
|
className="inline-flex items-center justify-center gap-2 rounded-full bg-background px-2 py-1 text-sm"
|
|
>
|
|
<IconComponent className="size-4 shrink-0" />
|
|
<span dir="rtl">{formatCount(chip.value)}</span>
|
|
</span>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
</a>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|
|
|
|
export { Gallery34 };
|