185 lines
5.5 KiB
TypeScript
185 lines
5.5 KiB
TypeScript
"use client";
|
|
|
|
import "swiper/css/effect-coverflow";
|
|
import "swiper/css/pagination";
|
|
import "swiper/css/navigation";
|
|
import "swiper/css";
|
|
import "swiper/css/effect-cards";
|
|
|
|
import { motion } from "framer-motion";
|
|
import { ArrowRight } from "lucide-react";
|
|
import { useEffect, useRef, useState } from "react";
|
|
import type { Swiper as SwiperType } from "swiper";
|
|
import { Autoplay, EffectCoverflow } from "swiper/modules";
|
|
import { Swiper, SwiperSlide } from "swiper/react";
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
const IMAGES = [
|
|
{
|
|
src: "/block-media/shadcnblocks/block/lummi/random11.jpeg",
|
|
alt: "اجرای زنده موسیقی در فضای شهری",
|
|
},
|
|
{
|
|
src: "/block-media/shadcnblocks/block/lummi/random1.jpeg",
|
|
alt: "نوازنده در استودیو ضبط",
|
|
},
|
|
{
|
|
src: "/block-media/shadcnblocks/block/lummi/random2.jpeg",
|
|
alt: "جمعیت در کنسرت روباز",
|
|
},
|
|
{
|
|
src: "/block-media/shadcnblocks/block/lummi/random11.jpeg",
|
|
alt: "صحنه اجرای موسیقی الکترونیک",
|
|
},
|
|
{
|
|
src: "/block-media/shadcnblocks/block/lummi/random1.jpeg",
|
|
alt: "تمرین گروه موسیقی",
|
|
},
|
|
{
|
|
src: "/block-media/shadcnblocks/block/lummi/random2.jpeg",
|
|
alt: "جشن موسیقی در فضای باز",
|
|
},
|
|
];
|
|
|
|
const css = `
|
|
.mySwiper21 {
|
|
width: 100%;
|
|
height: 420px;
|
|
padding-bottom: 50px;
|
|
}
|
|
|
|
.mySwiper21 .swiper-slide {
|
|
background-position: center;
|
|
background-size: cover;
|
|
width: 300px;
|
|
}
|
|
|
|
.mySwiper21 .swiper-slide img {
|
|
display: block;
|
|
width: 100%;
|
|
}
|
|
|
|
.swiper-3d .swiper-slide-shadow-left {
|
|
background-image: none;
|
|
}
|
|
.swiper-3d .swiper-slide-shadow-right {
|
|
background: none;
|
|
}
|
|
`;
|
|
|
|
interface Gallery21Props {
|
|
className?: string;
|
|
}
|
|
|
|
const Gallery21 = ({ className }: Gallery21Props) => {
|
|
const swiperRef = useRef<SwiperType | null>(null);
|
|
const swiperContainerRef = useRef<HTMLDivElement>(null);
|
|
const [swiperReady, setSwiperReady] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const swiper = swiperRef.current;
|
|
if (!swiper || !swiperReady) {
|
|
return;
|
|
}
|
|
|
|
const updateSwiper = () => {
|
|
swiper.update();
|
|
swiper.slideToLoop(swiper.realIndex, 0);
|
|
};
|
|
|
|
updateSwiper();
|
|
|
|
const container = swiperContainerRef.current;
|
|
if (!container) {
|
|
return;
|
|
}
|
|
|
|
const resizeObserver = new ResizeObserver(updateSwiper);
|
|
resizeObserver.observe(container);
|
|
|
|
return () => {
|
|
resizeObserver.disconnect();
|
|
};
|
|
}, [swiperReady]);
|
|
|
|
return (
|
|
<section dir="rtl" lang="fa" className={cn("py-32", className)}>
|
|
<style>{css}</style>
|
|
<div className="container">
|
|
<div className="relative mx-auto flex w-full max-w-4xl flex-col items-center gap-10">
|
|
<div
|
|
ref={swiperContainerRef}
|
|
dir="rtl"
|
|
className="relative h-[420px] w-full overflow-hidden"
|
|
>
|
|
<div className="pointer-events-none absolute inset-y-0 start-0 z-10 w-16 bg-gradient-to-r from-background to-transparent sm:w-24 lg:w-32" />
|
|
<div className="pointer-events-none absolute inset-y-0 end-0 z-10 w-16 bg-gradient-to-l from-background to-transparent sm:w-24 lg:w-32" />
|
|
|
|
<motion.div
|
|
className="relative mx-auto flex h-full w-full items-center justify-center"
|
|
initial={{ opacity: 0, translateY: 20 }}
|
|
animate={{ opacity: 1, translateY: 0 }}
|
|
transition={{
|
|
duration: 0.3,
|
|
delay: 0.5,
|
|
}}
|
|
>
|
|
<Swiper
|
|
spaceBetween={50}
|
|
autoplay={{
|
|
delay: 1500,
|
|
disableOnInteraction: false,
|
|
}}
|
|
effect="coverflow"
|
|
grabCursor={true}
|
|
centeredSlides={true}
|
|
centeredSlidesBounds={true}
|
|
loop={true}
|
|
slidesPerView={2.447}
|
|
coverflowEffect={{
|
|
rotate: 0,
|
|
stretch: 0,
|
|
depth: 100,
|
|
modifier: 2.5,
|
|
}}
|
|
className="mySwiper21"
|
|
modules={[EffectCoverflow, Autoplay]}
|
|
onSwiper={(swiper) => {
|
|
swiperRef.current = swiper;
|
|
setSwiperReady(true);
|
|
}}
|
|
>
|
|
{IMAGES.map((image, index) => (
|
|
<SwiperSlide key={`${image.alt}-${index}`}>
|
|
<img
|
|
className="h-full w-full overflow-hidden rounded-3xl object-cover shadow-lg"
|
|
src={image.src}
|
|
alt={image.alt}
|
|
/>
|
|
</SwiperSlide>
|
|
))}
|
|
</Swiper>
|
|
</motion.div>
|
|
</div>
|
|
<div className="flex flex-col items-center justify-center text-center">
|
|
<h3 className="max-w-sm px-2 text-xl font-medium tracking-tight">
|
|
موسیقی را بشنوید: تجربهای بیسابقه
|
|
</h3>
|
|
<Button
|
|
variant="secondary"
|
|
className="group mt-10 flex items-center justify-center gap-2 rounded-full tracking-tight"
|
|
>
|
|
کشف موسیقی
|
|
<ArrowRight className="size-4 -rotate-45 transition-all ease-out group-hover:rotate-0 rtl:rotate-[135deg] rtl:group-hover:rotate-0" />
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|
|
|
|
export { Gallery21 };
|