import { Pressable, Text, ActivityIndicator, View, type ViewStyle } from "react-native"; import { useTheme } from "../theme"; type Variant = "primary" | "secondary" | "outline" | "ghost" | "destructive" | "success"; type Size = "xs" | "sm" | "md" | "lg"; interface ButtonProps { variant?: Variant; loading?: boolean; size?: Size; disabled?: boolean; fullWidth?: boolean; onPress?: () => void; children: React.ReactNode; style?: ViewStyle; accessibilityLabel?: string; } function renderChildren(children: React.ReactNode, textColor: string, size: Size) { const fontSize = size === "xs" ? 12 : size === "sm" ? 13 : size === "md" ? 14 : 16; if (typeof children === "string") { return ( {children} ); } if (Array.isArray(children)) { return ( {children.map((child, i) => typeof child === "string" ? ( {child} ) : ( child ) )} ); } return children; } export function Button({ variant = "primary", loading = false, size = "md", disabled = false, fullWidth = false, children, style, onPress, accessibilityLabel, }: ButtonProps) { const theme = useTheme(); const sizeStyles: Record = { xs: { paddingVertical: 6, paddingHorizontal: 12, borderRadius: theme.radius.sm }, sm: { paddingVertical: 8, paddingHorizontal: 16, borderRadius: theme.radius.md }, md: { paddingVertical: 12, paddingHorizontal: 22, borderRadius: theme.radius.md }, lg: { paddingVertical: 16, paddingHorizontal: 28, borderRadius: theme.radius.lg }, }; const variantStyles: Record = { primary: { backgroundColor: theme.colors.primary }, secondary: { backgroundColor: theme.colors.surfaceAlt, borderWidth: 1, borderColor: theme.colors.border }, outline: { backgroundColor: "transparent", borderWidth: 1.5, borderColor: theme.colors.primary }, ghost: { backgroundColor: "transparent" }, destructive: { backgroundColor: theme.colors.error }, success: { backgroundColor: theme.colors.success }, }; const textColors: Record = { primary: theme.colors.textInverse, secondary: theme.colors.text, outline: theme.colors.primary, ghost: theme.colors.primary, destructive: theme.colors.textInverse, success: theme.colors.textInverse, }; const label = typeof children === "string" ? children : accessibilityLabel; return ( [ { alignItems: "center", justifyContent: "center", flexDirection: "row", }, sizeStyles[size], variantStyles[variant], variant === "primary" && theme.shadows.sm, fullWidth && { width: "100%" }, disabled && { opacity: 0.45 }, pressed && { opacity: 0.82, transform: [{ scale: 0.98 }] }, style, ]} > {loading ? ( ) : ( renderChildren(children, textColors[variant], size) )} ); }