import React, { useState, useRef } from "react"; import { View as RNView, Dimensions, type ViewProps, type StyleProp, type ViewStyle } from "react-native"; import RNCarousel, { ICarouselInstance } from "react-native-reanimated-carousel"; import { cn } from "../../lib/utils"; // 扩展 View 以支持 className(NativeWind) const View = RNView as React.ComponentType; const { width: screenWidth } = Dimensions.get("window"); export type CarouselApi = ICarouselInstance; type CarouselProps = { orientation?: "horizontal" | "vertical"; setApi?: (api: CarouselApi) => void; className?: string; children: React.ReactNode; width?: number; height?: number; autoPlay?: boolean; autoPlayInterval?: number; loop?: boolean; }; type CarouselContextProps = { api: CarouselApi | null; orientation: "horizontal" | "vertical"; width: number; height: number; autoPlay: boolean; autoPlayInterval: number; loop: boolean; }; 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; } function Carousel({ orientation = "horizontal", setApi, className, children, width = screenWidth, height = 410, autoPlay = false, autoPlayInterval = 3000, loop = true, onIndexChange, }: CarouselProps & { onIndexChange?: (index: number) => void }) { const [api, setInternalApi] = useState(null); const carouselRef = useRef(null); React.useEffect(() => { if (carouselRef.current) { const instance = carouselRef.current; setInternalApi(instance); setApi?.(instance); } }, [setApi]); // 提取子元素到数组,过滤掉非 ReactElement 的内容 // 如果子元素是 CarouselContent,需要提取其内部的子元素 const childrenArray = React.Children.toArray(children); const items = childrenArray.reduce((acc, child) => { if (React.isValidElement(child)) { const props = child.props as { children?: React.ReactNode }; if (props.children) { const innerChildren = React.Children.toArray(props.children).filter( (innerChild): innerChild is React.ReactElement => React.isValidElement(innerChild) ); return [...acc, ...innerChildren]; } return [...acc, child]; } return acc; }, []); return ( item as React.ReactElement} onSnapToItem={onIndexChange} /> ); } function CarouselContent({ children, ...props }: { className?: string; children: React.ReactNode; style?: StyleProp; }) { // CarouselContent 在新架构中主要用于包裹 CarouselItem // 实际渲染由 Carousel 的 renderItem 处理 return <>{children}; } function CarouselItem({ className, children, ...props }: { className?: string; children: React.ReactNode; style?: StyleProp; }) { const { width, height } = useCarousel(); return ( {children} ); } export { Carousel, CarouselContent, CarouselItem, useCarousel };