import { useState, useRef, ReactNode } from "react"; import { View, Text, StyleSheet, TouchableOpacity, Animated, ViewStyle, TextStyle, } from "react-native"; import { ChevronDown, LucideIcon } from "../../icons"; import { gameUIColors } from "../gameUI"; interface CollapsibleSectionProps { title: string; children: ReactNode; icon?: LucideIcon; badge?: string | number | ReactNode; defaultOpen?: boolean; variant?: "bordered" | "plain" | "card"; style?: ViewStyle; headerStyle?: ViewStyle; titleStyle?: TextStyle; contentStyle?: ViewStyle; onToggle?: (isOpen: boolean) => void; } export function CollapsibleSection({ title, children, icon: Icon, badge, defaultOpen = false, variant = "bordered", style, headerStyle, titleStyle, contentStyle, onToggle, }: CollapsibleSectionProps) { const [isOpen, setIsOpen] = useState(defaultOpen); const rotateAnim = useRef(new Animated.Value(defaultOpen ? 1 : 0)).current; const toggle = () => { const newState = !isOpen; setIsOpen(newState); onToggle?.(newState); Animated.timing(rotateAnim, { toValue: newState ? 1 : 0, duration: 200, useNativeDriver: true, }).start(); }; const rotation = rotateAnim.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "180deg"], }); const containerStyles = [ styles.container, variant === "bordered" && styles.borderedVariant, variant === "card" && styles.cardVariant, style, ]; return ( {Icon && ( )} {title} {badge !== undefined && ( {typeof badge === "string" || typeof badge === "number" ? ( {badge} ) : ( badge )} )} {isOpen && {children}} ); } interface SimpleProps { title: string; children: ReactNode; defaultOpen?: boolean; } CollapsibleSection.Simple = function Simple({ title, children, defaultOpen, }: SimpleProps) { return ( {children} ); }; interface WithIconProps { title: string; icon: LucideIcon; children: ReactNode; defaultOpen?: boolean; badge?: string | number; } CollapsibleSection.WithIcon = function WithIcon({ title, icon, children, defaultOpen, badge, }: WithIconProps) { return ( {children} ); }; const styles = StyleSheet.create({ container: { marginBottom: 8, }, borderedVariant: { borderWidth: 1, borderColor: gameUIColors.border + "30", borderRadius: 8, overflow: "hidden", }, cardVariant: { backgroundColor: gameUIColors.panel, borderRadius: 8, overflow: "hidden", }, header: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", padding: 12, }, headerLeft: { flexDirection: "row", alignItems: "center", flex: 1, gap: 8, }, headerRight: { flexDirection: "row", alignItems: "center", gap: 8, }, title: { fontSize: 14, fontWeight: "600", color: gameUIColors.text, flex: 1, }, badgeContainer: { marginRight: 4, }, badge: { backgroundColor: gameUIColors.primary + "20", paddingHorizontal: 8, paddingVertical: 2, borderRadius: 4, }, badgeText: { fontSize: 11, fontWeight: "600", color: gameUIColors.primary, }, content: { paddingHorizontal: 12, paddingBottom: 12, }, });