import React, { forwardRef, useImperativeHandle, useRef, ReactElement, ComponentType, JSXElementConstructor, ReactNode } from 'react'; import { SheetSize, SizeInfo, TrueSheet, TrueSheetProps } from '@lodev09/react-native-true-sheet'; import { Keyboard, StyleSheet, View, TouchableOpacity, Platform, Image } from 'react-native'; interface BottomModalProps extends TrueSheetProps { children?: React.ReactNode; onClose?: () => void; isGrabberVisible?: boolean; sizes?: SheetSize[] | undefined; footer?: ReactElement | ComponentType | null; footerDefaultMargins?: boolean | number; onPresent?: () => void; onSizeChange?: (size: SizeInfo) => void; showCloseButton?: boolean; } export interface BottomModalHandle { present: () => Promise; dismiss: () => Promise; } const styles = StyleSheet.create({ footerContainer: { alignItems: 'center', justifyContent: 'center', }, buttonContainer: { position: 'absolute', backgroundColor: 'lightgray', justifyContent: 'center', alignItems: 'center', width: 30, height: 30, borderRadius: 15, top: 20, right: 20, zIndex: 10, }, }); const BottomModal = forwardRef( ( { onClose, onPresent, onSizeChange, showCloseButton = true, isGrabberVisible = true, sizes = ['auto'], footer, footerDefaultMargins, children, ...props }, ref, ) => { const trueSheetRef = useRef(null); useImperativeHandle(ref, () => ({ present: async () => { Keyboard.dismiss(); if (trueSheetRef.current?.present) { await trueSheetRef.current.present(); } else { return Promise.resolve(); } }, dismiss: async () => { Keyboard.dismiss(); if (trueSheetRef.current?.dismiss) { await trueSheetRef.current.dismiss(); } else { return Promise.resolve(); } }, })); const dismiss = () => { trueSheetRef.current?.dismiss(); }; const renderTopRightButton = () => showCloseButton ? ( ) : null; const renderFooter = (): ReactElement> | ComponentType | undefined => { // Footer is not working correctly on Android yet. if (!footer) return undefined; if (React.isValidElement(footer)) { return footerDefaultMargins ? {footer} : footer; } else if (typeof footer === 'function') { // Render the footer component dynamically const FooterComponent = footer as ComponentType; return ; } return undefined; }; const FooterComponent = Platform.OS !== 'android' && renderFooter(); return ( {children} {renderTopRightButton()} {Platform.OS === 'android' && (renderFooter() as ReactNode)} ); }, ); export default BottomModal;