import { useEffect, useState, type FC, useRef } from "react"; import { TouchableWithoutFeedback, Animated, Easing, View } from "react-native"; import type ISnackBarProps from "./type"; import stylesheet, { getSnackBarType, useStyles } from "./stylesheet"; import { NCoreUIKitTheme } from "../../core/hooks"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { X as XIcon } from "lucide-react-native"; import { Portal } from "../../helpers/portalize"; import Button from "../button"; import Text from "../text"; import { windowHeight } from "../../utils"; const SnackBar: FC = ({ isCloseOnPressActionButton = true, closeAnimationDelay = 350, openAnimationDelay = 200, contentContainerStyle, autoCloseDelay = 5000, isCloseOnPress = true, isShowAction = true, isFullWidth = false, isInlineSafeArea, icon: CustomIcon, type = "neutral", customTheme, onClosed, subTitle, children, onPress, action, style, title, id }) => { const { radiuses, colors, spaces } = NCoreUIKitTheme.useContext(customTheme); const { top } = useSafeAreaInsets(); const [ isMeasured, setIsMeasured ] = useState(false); const contentHeight = useRef(windowHeight); const transformAnim = useRef(new Animated.Value(-contentHeight.current + -top + -spaces.spacingSm)).current; const opacityAnim = useRef(new Animated.Value(0)).current; const currentType = getSnackBarType({ type }); const { contentContainer: contentContainerDynamicStyle, containerObject: containerObjectDynamicStyle, iconContainer: iconContainerDynamicStyle, container: containerDynamicStyle, subTitle: subTitleDynamicStyle, action: actionDynamicStyle, title: titleDynamicStyle } = useStyles({ isInlineSafeArea, safeAreaTop: top, isFullWidth, currentType, radiuses, spaces, colors, type }); useEffect(() => { if(isMeasured) { transformAnim.setValue(-contentHeight.current + -top + -spaces.spacingSm); Animated.parallel([ Animated.timing(opacityAnim, { duration: openAnimationDelay, useNativeDriver: true, easing: Easing.linear, toValue: 1 }), Animated.timing(transformAnim, { duration: openAnimationDelay, useNativeDriver: true, easing: Easing.linear, toValue: 0 }) ]).start(); setTimeout(() => { closeAnimation(); }, autoCloseDelay); } }, [isMeasured]); const closeAnimation = (_onClosed?: (props: { id: string; }) => void) => { Animated.parallel([ Animated.timing(transformAnim, { toValue: -contentHeight.current + -top + -spaces.spacingSm, duration: closeAnimationDelay, useNativeDriver: true, easing: Easing.linear }), Animated.timing(opacityAnim, { duration: closeAnimationDelay, useNativeDriver: true, easing: Easing.linear, toValue: 0 }) ]).start(({ finished }) => { if(finished) { if(onClosed) onClosed({ id }); if(_onClosed) _onClosed({ id }); } }); }; const renderIcon = () => { if(!CustomIcon) { return null; } return ; }; const renderContent = () => { return {title} { subTitle ? {subTitle} : null } ; }; const renderAction = () => { if(!isShowAction) { return null; } return