import React, { useRef } from 'react'; import { Animated, TouchableWithoutFeedback, Text, StyleSheet, ActivityIndicator, ViewStyle, TextStyle, View, } from 'react-native'; import { COLORS, RADIUS, SPACING, FONT_SIZE, FONT, SHADOWS } from '../../theme'; import { useTheme } from '../../theme'; type Variant = 'primary' | 'secondary' | 'outline' | 'ghost' | 'danger'; type Size = 'sm' | 'md' | 'lg'; interface ButtonProps { title: string; onPress: () => void; variant?: Variant; size?: Size; loading?: boolean; disabled?: boolean; style?: ViewStyle; textStyle?: TextStyle; fullWidth?: boolean; } export function Button({ title, onPress, variant = 'primary', size = 'md', loading = false, disabled = false, style, textStyle, fullWidth = false, }: ButtonProps) { const { theme, isDark } = useTheme(); const scale = useRef(new Animated.Value(1)).current; const onPressIn = () => Animated.spring(scale, { toValue: 0.96, useNativeDriver: true, speed: 50, bounciness: 0 }).start(); const onPressOut = () => Animated.spring(scale, { toValue: 1, useNativeDriver: true, speed: 30, bounciness: 4 }).start(); const containerBg = getContainerBg(variant, theme, isDark); const labelColor = getLabelColor(variant); const shadow = variant === 'primary' ? SHADOWS.primary : variant === 'danger' ? SHADOWS.sm : {}; return ( {loading ? ( ) : ( {title} )} ); } function getContainerBg(variant: Variant, theme: any, isDark: boolean): ViewStyle { switch (variant) { case 'primary': return { backgroundColor: COLORS.primary }; case 'secondary': return { backgroundColor: isDark ? theme.surfaceHover : theme.bgSecondary }; case 'outline': return { backgroundColor: 'transparent', borderWidth: 1.5, borderColor: COLORS.primary }; case 'ghost': return { backgroundColor: 'transparent' }; case 'danger': return { backgroundColor: COLORS.error }; } } function getLabelColor(variant: Variant): string { switch (variant) { case 'primary': case 'danger': return COLORS.white; case 'secondary': return COLORS.primary; case 'outline': case 'ghost': return COLORS.primary; } } const styles = StyleSheet.create({ base: { borderRadius: RADIUS.md, alignItems: 'center', justifyContent: 'center', flexDirection: 'row', }, fullWidth: { width: '100%' }, disabled: { opacity: 0.55 }, size_sm: { paddingVertical: SPACING.xs + 2, paddingHorizontal: SPACING.md, borderRadius: RADIUS.sm }, size_md: { paddingVertical: SPACING.md - 1, paddingHorizontal: SPACING.xl, borderRadius: RADIUS.md }, size_lg: { paddingVertical: SPACING.md + 1, paddingHorizontal: SPACING.xxl, borderRadius: RADIUS.lg, minHeight: 52 }, label: { fontWeight: FONT.semibold as any, letterSpacing: 0.1 }, label_sm: { fontSize: FONT_SIZE.sm }, label_md: { fontSize: FONT_SIZE.md }, label_lg: { fontSize: FONT_SIZE.md }, });