mirror of
https://github.com/inaturalist/iNaturalistReactNative.git
synced 2025-12-23 14:08:56 -05:00
165 lines
4.0 KiB
TypeScript
165 lines
4.0 KiB
TypeScript
import BottomSheet, {
|
|
BottomSheetModal, BottomSheetScrollView,
|
|
} from "@gorhom/bottom-sheet";
|
|
import classnames from "classnames";
|
|
import { BottomSheetStandardBackdrop, Heading4, INatIconButton } from "components/SharedComponents";
|
|
import { View } from "components/styledComponents";
|
|
import type { Node } from "react";
|
|
import React, {
|
|
useCallback,
|
|
useEffect,
|
|
useRef,
|
|
} from "react";
|
|
import { Dimensions } from "react-native";
|
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
import { useTranslation } from "sharedHooks";
|
|
|
|
const { width } = Dimensions.get( "window" );
|
|
const marginOnWide = {
|
|
marginHorizontal: width > 500
|
|
? ( width - 500 ) / 2
|
|
: 0,
|
|
borderTopLeftRadius: 24,
|
|
borderTopRightRadius: 24,
|
|
overflow: "hidden",
|
|
};
|
|
|
|
// eslint-disable-next-line
|
|
const noHandle = ( ) => <></>;
|
|
|
|
interface Props {
|
|
children: React.JSX.Element;
|
|
hidden?: boolean;
|
|
hideCloseButton?: boolean;
|
|
headerText?: string;
|
|
onLayout?: ( event: object ) => void;
|
|
// Callback when the user presses the close button or backdrop, not whenever the sheet
|
|
// closes
|
|
onPressClose?: ( ) => void;
|
|
snapPoints?: string[];
|
|
insideModal?: boolean;
|
|
keyboardShouldPersistTaps?: string;
|
|
testID?: string;
|
|
containerClass?: string;
|
|
scrollEnabled?: boolean;
|
|
}
|
|
|
|
const StandardBottomSheet = ( {
|
|
children,
|
|
hidden,
|
|
hideCloseButton = false,
|
|
headerText,
|
|
onLayout,
|
|
onPressClose,
|
|
snapPoints,
|
|
insideModal,
|
|
keyboardShouldPersistTaps = "never",
|
|
containerClass,
|
|
testID,
|
|
scrollEnabled = true,
|
|
}: Props ): Node => {
|
|
if ( snapPoints ) {
|
|
throw new Error( "BottomSheet does not accept snapPoints as a prop." );
|
|
}
|
|
|
|
const { t } = useTranslation( );
|
|
const sheetRef = useRef<BottomSheet>( null );
|
|
const insets = useSafeAreaInsets( );
|
|
|
|
const handleClose = useCallback( ( ) => {
|
|
if ( onPressClose ) onPressClose( );
|
|
|
|
if ( insideModal ) {
|
|
sheetRef.current?.collapse( );
|
|
} else {
|
|
sheetRef.current?.dismiss( );
|
|
}
|
|
}, [insideModal, onPressClose] );
|
|
|
|
const renderBackdrop = props => (
|
|
<BottomSheetStandardBackdrop
|
|
props={props}
|
|
onPress={onPressClose}
|
|
/>
|
|
);
|
|
|
|
const handleSnapPress = useCallback( ( ) => {
|
|
if ( insideModal ) {
|
|
sheetRef.current?.expand( );
|
|
} else {
|
|
sheetRef.current?.present( );
|
|
}
|
|
}, [insideModal] );
|
|
|
|
useEffect( ( ) => {
|
|
if ( hidden ) { return; }
|
|
handleSnapPress( );
|
|
}, [hidden, handleSnapPress] );
|
|
|
|
const BottomSheetComponent = insideModal
|
|
? BottomSheet
|
|
: BottomSheetModal;
|
|
|
|
if ( hidden ) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<BottomSheetComponent
|
|
backdropComponent={renderBackdrop}
|
|
enableDynamicSizing
|
|
handleComponent={noHandle}
|
|
index={0}
|
|
ref={sheetRef}
|
|
style={marginOnWide}
|
|
accessible={false}
|
|
onDismiss={handleClose}
|
|
>
|
|
<BottomSheetScrollView
|
|
keyboardShouldPersistTaps={keyboardShouldPersistTaps}
|
|
scrollEnabled={scrollEnabled}
|
|
>
|
|
<View
|
|
className={classnames(
|
|
"pt-7",
|
|
insets.bottom > 0
|
|
? "pb-7"
|
|
: null,
|
|
containerClass,
|
|
)}
|
|
onLayout={onLayout}
|
|
// Not ideal, but @gorhom/bottom-sheet components don't support
|
|
// testID
|
|
testID={testID}
|
|
>
|
|
{!headerText
|
|
? null
|
|
: (
|
|
<View className="mx-12 flex">
|
|
<Heading4
|
|
testID="bottom-sheet-header"
|
|
className="w-full text-center"
|
|
>
|
|
{headerText}
|
|
</Heading4>
|
|
</View>
|
|
)}
|
|
{children}
|
|
{!hideCloseButton && (
|
|
<INatIconButton
|
|
icon="close"
|
|
onPress={handleClose}
|
|
size={19}
|
|
className="absolute top-3.5 right-3"
|
|
accessibilityState={{ disabled: hidden }}
|
|
accessibilityLabel={t( "Close" )}
|
|
/>
|
|
)}
|
|
</View>
|
|
</BottomSheetScrollView>
|
|
</BottomSheetComponent>
|
|
);
|
|
};
|
|
|
|
export default StandardBottomSheet;
|