import React, { useEffect, useRef } from "react"; import { View, StyleSheet, Animated } from "react-native"; import { CheckCircle2, AlertCircle, AlertTriangle, Lightbulb, } from "@/lib/icons"; import { Text } from "@/components/ui/text"; import { useToast, ToastType } from "@/lib/toast-store"; import { useColorScheme } from "nativewind"; const VARIANT_CONFIG: Record< ToastType, { iconColor: string; icon: typeof CheckCircle2 } > = { success: { iconColor: "#4ADE80", icon: CheckCircle2, }, error: { iconColor: "#F87171", icon: AlertCircle, }, warning: { iconColor: "#FBBF24", icon: AlertTriangle, }, info: { iconColor: "#60A5FA", icon: Lightbulb, }, }; export function ModalToast() { const { visible, type, title, message, hide, duration } = useToast(); const isDark = useColorScheme() === "dark"; const translateY = useRef(new Animated.Value(-20)).current; const opacity = useRef(new Animated.Value(0)).current; const hideRef = useRef(hide); hideRef.current = hide; useEffect(() => { if (visible) { translateY.setValue(-20); opacity.setValue(0); Animated.parallel([ Animated.spring(translateY, { toValue: 0, useNativeDriver: true, speed: 20, bounciness: 6, }), Animated.timing(opacity, { toValue: 1, duration: 180, useNativeDriver: true, }), ]).start(); const timer = setTimeout(() => { Animated.timing(opacity, { toValue: 0, duration: 180, useNativeDriver: true, }).start(() => hideRef.current()); }, duration); return () => clearTimeout(timer); } }, [visible, duration]); if (!visible) return null; const config = VARIANT_CONFIG[type]; const Icon = config.icon; return ( {title} ); } const styles = StyleSheet.create({ absoluteOverlay: { zIndex: 9999, elevation: 50, }, wrapper: { position: "absolute", top: 60, left: 0, right: 0, alignItems: "center", paddingHorizontal: 20, }, toast: { width: "100%", maxWidth: 400, borderRadius: 14, paddingHorizontal: 18, paddingVertical: 16, flexDirection: "row", alignItems: "center", borderWidth: 1, gap: 12, }, textContainer: { flex: 1, }, });