import React, { forwardRef, ForwardRefRenderFunction, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, } from 'react'; import { Animated, Modal, StyleSheet, TouchableOpacity, View, } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { NotificationProps, NotificationRef, NotificationStatus, } from './interface'; import { IconXRemind2, IconXSuccess2, IconXWarn2, IconXError2, IconXClosesmall1, } from '../../icons'; import { ShouldRender } from '@xrnjs/ui'; import { renderTextLikeJSX } from '../../core/helpers'; import createStyle from './styles/notification.style'; import { useTheme } from '../Theme'; const TypeIconMap: Record = { success: IconXSuccess2, error: IconXError2, warning: IconXWarn2, info: IconXRemind2, }; const Notification: ForwardRefRenderFunction< NotificationRef, NotificationProps > = (props, ref) => { const { showIcon = true, duration = 5000, title, titleStyle, titleProps, description, descriptionStyle, descriptionProps, btn, offset, icon, closeable = true, onSolidPress, onWeakPress, onRequestClose, onClose, onClosed, onVisibleAnimateEnd, } = props; const { top } = useSafeAreaInsets(); const _top = useMemo(() => (top || 10) + (offset || 0), [top, offset]); const token = useTheme(); const styles = createStyle(token); const IconComponent = TypeIconMap[props.status]; const timer = useRef(); const fadeAnim = useRef(new Animated.Value(0)).current; const [visible, setVisible] = useState(); const onInnerClose = useCallback( (finishedCallback?: () => void) => { clearTimeout(timer.current); onClose?.(); Animated.timing(fadeAnim, { toValue: 0, duration: 200, useNativeDriver: false, }).start(({ finished }) => { if (finished) { setVisible(false); onClosed?.(); finishedCallback?.(); } }); }, [timer.current, setVisible] ); const onCancel = useCallback(async () => { await onWeakPress?.(); onInnerClose(); }, [onInnerClose, onSolidPress]); useEffect(() => { setVisible(props.visible); if (props.visible) { Animated.spring(fadeAnim, { toValue: _top, useNativeDriver: false, }).start(onVisibleAnimateEnd); if (duration > 0) { timer.current = setTimeout(onCancel, duration); } } }, [props.visible, duration, top]); useImperativeHandle(ref, () => ({ close: onInnerClose, })); return ( {icon ? icon : } {renderTextLikeJSX( title, [StyleSheet.flatten([styles.title, titleStyle])], { numberOfLines: 2, ellipsizeMode: 'tail', ...titleProps } )} {renderTextLikeJSX( description, [StyleSheet.flatten([styles.description, descriptionStyle])], { numberOfLines: 3, ellipsizeMode: 'tail', ...descriptionProps } )} {btn} ); }; export default forwardRef(Notification);