import React, { type ReactNode, useEffect, useRef, useMemo } from "react"; import { Modal as RNModal, View, ScrollView, TouchableOpacity, Text, StyleSheet, Animated, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { spacing, borderRadius, fontSize } from "../../theme"; import { useTheme } from "../../context/ThemeContext"; interface ModalProps { visible: boolean; onClose: () => void; title?: string; children: ReactNode; icon?: keyof typeof Ionicons.glyphMap; iconColor?: string; } export default function Modal({ visible, onClose, title, children, icon, iconColor, }: ModalProps) { const { colors } = useTheme(); const scale = useRef(new Animated.Value(0.85)).current; const opacity = useRef(new Animated.Value(0)).current; useEffect(() => { if (visible) { Animated.parallel([ Animated.spring(scale, { toValue: 1, useNativeDriver: true, tension: 65, friction: 8, }), Animated.timing(opacity, { toValue: 1, duration: 200, useNativeDriver: true, }), ]).start(); } else { scale.setValue(0.85); opacity.setValue(0); } }, [visible]); const styles = useMemo( () => StyleSheet.create({ overlay: { flex: 1, backgroundColor: "rgba(0,0,0,0.85)", justifyContent: "center", alignItems: "center", padding: spacing.xl, }, content: { backgroundColor: colors.bgSecondary, borderRadius: 20, width: "100%", maxHeight: "80%", borderWidth: 1, borderColor: "rgba(255,255,255,0.08)", overflow: "hidden", shadowColor: colors.accent, shadowOffset: { width: 0, height: 0 }, shadowOpacity: 0.15, shadowRadius: 30, elevation: 20, }, accentBar: { height: 3, backgroundColor: colors.accent, width: "100%", }, header: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", paddingHorizontal: spacing.xl, paddingTop: spacing.l, paddingBottom: spacing.m, }, titleRow: { flexDirection: "row", alignItems: "center", gap: 10, flex: 1, }, iconCircle: { width: 36, height: 36, borderRadius: 18, backgroundColor: colors.accent + "20", justifyContent: "center", alignItems: "center", }, title: { color: colors.textWhite, fontSize: fontSize.lg, fontWeight: "700", flex: 1, }, closeBtn: { width: 32, height: 32, borderRadius: 16, backgroundColor: "rgba(255,255,255,0.06)", justifyContent: "center", alignItems: "center", }, body: { paddingHorizontal: spacing.xl, }, }), [colors], ); return ( {icon && ( )} {title && {title}} {children} ); }