UNPKG

@cometchat/chat-uikit-react-native

Version:

Ready-to-use Chat UI Components for React Native

109 lines (108 loc) 4.3 kB
import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState, } from "react"; import { Animated, BackHandler, Dimensions, Modal, View, Easing, KeyboardAvoidingView, Platform, ScrollView, } from "react-native"; import { useTheme } from "../../../theme"; /** * CometChatBottomSheet is a component that renders a modal bottom sheet. * It provides a customizable bottom sheet with overlay fade effect and keyboard handling. * * @param {CometChatBottomSheetInterface} props - Props for the bottom sheet component. * @param {React.Ref<any>} ref - Reference object to expose component methods. * @returns {JSX.Element} The rendered modal bottom sheet. */ const CometChatBottomSheet = forwardRef((props, ref) => { const theme = useTheme(); const { style = { maxHeight: Dimensions.get("screen").height * 0.9, minHeight: 50, }, children = <View />, isOpen = true, onClose = null, scrollEnabled = false, doNotOccupyEntireHeight = false, onDismiss, } = props; // Animated value for overlay fade const overlayAnim = useRef(new Animated.Value(0)).current; const [isModalOpen, setIsModalOpen] = useState(isOpen); useEffect(() => { setIsModalOpen(isOpen); }, [isOpen]); // Fade in/out the overlay when isOpen changes useEffect(() => { if (isOpen) { // Fade from 0 -> 0.3 over 100ms Animated.timing(overlayAnim, { toValue: 0.3, duration: 100, easing: Easing.ease, useNativeDriver: false, }).start(); } else { // Immediately reset to 0 if closed overlayAnim.setValue(0); } }, [isOpen, overlayAnim]); /** * Toggles the bottom sheet panel by invoking the onClose callback. */ const togglePanel = () => { onClose && onClose(); }; /** * Handles the hardware back button press. * Closes the bottom sheet if it is open. * * @returns True if the back press is handled. */ const onBackPress = () => { if (isOpen) { togglePanel(); return true; // Prevent default back behavior } return false; }; useEffect(() => { const backHandler = BackHandler.addEventListener("hardwareBackPress", onBackPress); return () => { backHandler.remove(); }; }, [onBackPress]); useImperativeHandle(ref, () => { return { togglePanel, }; }); return (<Modal animationType="fade" transparent={true} hardwareAccelerated={true} visible={isModalOpen} onRequestClose={togglePanel} onDismiss={onDismiss}> {/* Animated overlay that fades in from transparent to a semi-transparent black */} <Animated.View style={{ flex: 1, backgroundColor: overlayAnim.interpolate({ inputRange: [0, 0.2], outputRange: ["rgba(0,0,0,0)", "rgba(0,0,0,0.2)"], }), }} onStartShouldSetResponder={() => { togglePanel(); return true; }}/> {/* Bottom sheet content */} <KeyboardAvoidingView behavior={Platform.OS === "ios" ? "padding" : "height"} enabled={Platform.OS === "ios"} style={{ backgroundColor: theme.color.background1, paddingTop: 25, position: "absolute", bottom: 0, left: 0, right: 0, borderTopLeftRadius: 24, borderTopRightRadius: 24, shadowOffset: { width: 0, height: 6 }, shadowOpacity: 0.37, shadowRadius: 7.49, elevation: 12, paddingHorizontal: 5, maxHeight: style.maxHeight, minHeight: style.minHeight, ...(doNotOccupyEntireHeight ? {} : { height: "100%" }), }}> {scrollEnabled ? (<ScrollView scrollEnabled={scrollEnabled} keyboardShouldPersistTaps="always" style={{ flex: 1 }}> {typeof children === "function" ? children() : children} </ScrollView>) : typeof children === "function" ? (children()) : (children)} </KeyboardAvoidingView> </Modal>); }); export { CometChatBottomSheet }; //# sourceMappingURL=CometChatBottomSheet.js.map