/** * Modal * Dependencies: * - @gorhom/bottom-sheet. * * Props: * - All `BottomSheetModalProps` props. * - `title` (string | undefined): Optional title for the modal header. * * Usage Example: * import { Modal, useModal } from '@gorhom/bottom-sheet'; * * function DisplayModal() { * const { ref, present, dismiss } = useModal(); * * return ( * * * Modal Content * * * ); * } * */ import type { BottomSheetBackdropProps, BottomSheetModalProps, } from '@gorhom/bottom-sheet'; import { BottomSheetModal, useBottomSheet } from '@gorhom/bottom-sheet'; import * as React from 'react'; import { Pressable, View } from 'react-native'; import Animated, { FadeIn, FadeOut } from 'react-native-reanimated'; import { Path, Svg } from 'react-native-svg'; import { Text } from './text'; type ModalProps = BottomSheetModalProps & { title?: string; }; type ModalRef = React.ForwardedRef; type ModalHeaderProps = { title?: string; dismiss: () => void; }; export const useModal = () => { const ref = React.useRef(null); const present = React.useCallback((data?: any) => { ref.current?.present(data); }, []); const dismiss = React.useCallback(() => { ref.current?.dismiss(); }, []); return { ref, present, dismiss }; }; export const Modal = React.forwardRef( ( { snapPoints: _snapPoints = ['60%'], title, detached = false, ...props }: ModalProps, ref: ModalRef, ) => { const detachedProps = React.useMemo( () => getDetachedProps(detached), [detached], ); const modal = useModal(); const snapPoints = React.useMemo(() => _snapPoints, [_snapPoints]); React.useImperativeHandle( ref, () => (modal.ref.current as BottomSheetModal) || null, ); const renderHandleComponent = React.useCallback( () => ( <> ), [title, modal.dismiss], ); return ( ); }, ); /** * Custom Backdrop */ const AnimatedPressable = Animated.createAnimatedComponent(Pressable); const CustomBackdrop = ({ style }: BottomSheetBackdropProps) => { const { close } = useBottomSheet(); return ( close()} entering={FadeIn.duration(50)} exiting={FadeOut.duration(20)} style={[style, { backgroundColor: 'rgba(0, 0, 0, 0.4)' }]} /> ); }; export const renderBackdrop = (props: BottomSheetBackdropProps) => ( ); /** * * @param detached * @returns * * @description * In case the modal is detached, we need to add some extra props to the modal to make it look like a detached modal. */ const getDetachedProps = (detached: boolean) => { if (detached) { return { detached: true, bottomInset: 46, style: { marginHorizontal: 16, overflow: 'hidden' }, } as Partial; } return {} as Partial; }; /** * ModalHeader */ const ModalHeader = React.memo(({ title, dismiss }: ModalHeaderProps) => { return ( <> {title && ( {title} )} ); }); const CloseButton = ({ close }: { close: () => void }) => { return ( ); };