"use client"; import { Children, useRef, useState } from "react"; import { Swiper, SwiperSlide } from "swiper/react"; import { FreeMode } from "swiper/modules"; import type { Swiper as SwiperClass } from "swiper"; import "swiper/css"; import "swiper/css/free-mode"; type CarouselProps = { children: React.ReactNode; ariaLabel: string; slideClassName?: string; }; function ChevronLeftIcon() { return ( ); } function ChevronRightIcon() { return ( ); } export function Carousel({ children, ariaLabel, slideClassName }: CarouselProps) { const swiperRef = useRef(null); const [isLocked, setIsLocked] = useState(false); const btnClass = "absolute top-1/2 z-10 flex h-10 w-10 -translate-y-1/2 items-center justify-center rounded-full border border-white/40 bg-white/40 text-red shadow-sm backdrop-blur-md transition-colors hover:border-red/40 hover:bg-white/60 hover:text-red-dark disabled:pointer-events-none disabled:opacity-0"; return (
{ swiperRef.current = swiper; setIsLocked(swiper.isLocked); }} onLock={(swiper) => { swiper.slideTo(0, 0); setIsLocked(true); }} onUnlock={() => setIsLocked(false)} dir="rtl" slidesPerView="auto" spaceBetween={16} watchOverflow freeMode={{ enabled: true, momentum: true, sticky: true }} grabCursor role="region" aria-label={ariaLabel} className="!px-1 !py-2" > {Children.map(children, (child) => ( // Swiper's own CSS pins slide height to 100%, which — with no definite // wrapper height — resolves per-slide instead of stretching to match // the tallest sibling. height:auto (inline, so it wins) lets normal // flex stretch equalize card heights across a row. {child} ))}
); }