import * as React from "react" import { View, Swiper, SwiperItem } from "@tarojs/components" import { ArrowLeft, ArrowRight } from "lucide-react-taro" import { cn } from "@/lib/utils" import { Button } from "@/components/ui/button" type CarouselProps = { opts?: { loop?: boolean autoplay?: boolean interval?: number duration?: number displayMultipleItems?: number } orientation?: "horizontal" | "vertical" setApi?: (api: CarouselApi) => void className?: string children?: React.ReactNode } export type CarouselApi = { scrollPrev: () => void scrollNext: () => void canScrollPrev: boolean canScrollNext: boolean scrollTo: (index: number) => void selectedScrollSnap: () => number } type CarouselContextProps = { orientation: "horizontal" | "vertical" current: number setCurrent: (index: number) => void count: number setCount: (count: number) => void scrollPrev: () => void scrollNext: () => void canScrollPrev: boolean canScrollNext: boolean opts?: CarouselProps["opts"] } const CarouselContext = React.createContext(null) function useCarousel() { const context = React.useContext(CarouselContext) if (!context) { throw new Error("useCarousel must be used within a ") } return context } const Carousel = React.forwardRef< React.ElementRef, CarouselProps >(({ opts, orientation = "horizontal", setApi, className, children, ...props }, ref) => { const [current, setCurrent] = React.useState(0) const [count, setCount] = React.useState(0) const scrollPrev = React.useCallback(() => { setCurrent((prev) => Math.max(0, prev - 1)) }, []) const scrollNext = React.useCallback(() => { setCurrent((prev) => Math.min(count - 1, prev + 1)) }, [count]) const canScrollPrev = current > 0 const canScrollNext = current < count - 1 const scrollTo = React.useCallback((index: number) => { setCurrent(index) }, []) const selectedScrollSnap = React.useCallback(() => current, [current]) React.useEffect(() => { if (setApi) { setApi({ scrollPrev, scrollNext, canScrollPrev, canScrollNext, scrollTo, selectedScrollSnap, }) } }, [setApi, scrollPrev, scrollNext, canScrollPrev, canScrollNext, scrollTo, selectedScrollSnap]) return ( {children} ) }) Carousel.displayName = "Carousel" const CarouselContent = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, children, ...props }, ref) => { const { orientation, current, setCurrent, setCount, opts } = useCarousel() React.useEffect(() => { const childCount = React.Children.count(children) setCount(childCount) }, [children, setCount]) return ( setCurrent(e.detail.current)} circular={opts?.loop} autoplay={opts?.autoplay} interval={opts?.interval || 5000} duration={opts?.duration || 500} displayMultipleItems={opts?.displayMultipleItems || 1} {...props} > {React.Children.map(children, (child) => { if (React.isValidElement(child)) { return {child} } return null })} ) }) CarouselContent.displayName = "CarouselContent" const CarouselItem = ({ className, children, ...props }: React.ComponentProps) => { return ( {children} ) } CarouselItem.displayName = "CarouselItem" const CarouselPrevious = React.forwardRef< React.ElementRef, React.ComponentProps >(({ className, variant = "outline", size = "icon", ...props }, ref) => { const { orientation, scrollPrev, canScrollPrev } = useCarousel() return ( ) }) CarouselPrevious.displayName = "CarouselPrevious" const CarouselNext = React.forwardRef< React.ElementRef, React.ComponentProps >(({ className, variant = "outline", size = "icon", ...props }, ref) => { const { orientation, scrollNext, canScrollNext } = useCarousel() return ( ) }) CarouselNext.displayName = "CarouselNext" export { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext, }