UNPKG

react-native-unit-components

Version:

Unit React Native components

180 lines 6.79 kB
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } import React, { useEffect, useRef, useState } from 'react'; import { Animated, BackHandler, Easing, Image, PanResponder, Platform, TouchableOpacity, View } from 'react-native'; import { CloseIcon } from '../../assets/images'; import { androidStatusBarHeight, fullScreenHeight, isAndroid10AndAbove, statusBarHeight } from '../../components/UNBottomSheetComponent/UNBottomSheetComponent.constants'; import { getStylesObject } from './BottomSheet.styles'; import { useIsBackFromLongBackground } from '../../hooks/useAppStateListener'; import { BottomSheetNativePlaceType } from '../../types/internal/bottomSheet.types'; import { UNBaseView } from '../../nativeComponents/UNBaseView'; const BottomSheet = props => { const isStatic = props.nativePlace === BottomSheetNativePlaceType.modal; const panelHeightValue = useRef(new Animated.Value(props.sliderMaxHeight)).current; const fadeAnim = useRef(new Animated.Value(0)).current; const styles = getStylesObject(fadeAnim); const [isPanelOpened, setIsPanelOpened] = useState(props.isOpen); const [contentHeight, setContentHeight] = useState(undefined); const [currentHeight, setCurrentHeight] = useState(props.sliderMaxHeight); const [dy, setDy] = useState(0); const isAppInactive = useIsBackFromLongBackground(); const _parentPanResponder = PanResponder.create({ onMoveShouldSetPanResponderCapture: (_, gestureState) => { if (isStatic) return false; return props.shouldEnableBottomSheetScroll && Math.abs(gestureState.dy) > 10; }, onPanResponderMove(_, gestureState) { if (props.shouldEnableBottomSheetScroll && gestureState.dy < 5) { props.handleWebViewScroll(); } if (currentHeight + gestureState.dy < 0) return; if (!props.expandToMaxHeightEnabled && contentHeight && currentHeight + gestureState.dy < props.sliderMaxHeight - contentHeight) return; panelHeightValue.setValue(currentHeight + gestureState.dy); setDy(gestureState.dy); }, onPanResponderRelease: () => { if (dy > 0) { collapse(); } else if (!props.expandToMaxHeightEnabled) { contentHeight && setToContentHeight(contentHeight); } else { expand(); } } }); useEffect(() => { // on App Active State change reset the bottom-sheet if (isAppInactive) { setContentHeight(0); _dismiss(false); } }, [isAppInactive]); useEffect(() => { if (props.isOpen && !isPanelOpened) { fadeIn(); } else if (isPanelOpened) { setContentHeight(0); _dismiss(); } }, [props.isOpen]); useEffect(() => { BackHandler.addEventListener('hardwareBackPress', _onBackPress); const id = panelHeightValue.addListener(e => setCurrentHeight(e.value)); return () => { BackHandler.removeEventListener('hardwareBackPress', _onBackPress); panelHeightValue.removeListener(id); }; }, []); const fadeIn = () => { setIsPanelOpened(true); Animated.timing(fadeAnim, { toValue: 0.3, duration: 500, useNativeDriver: false }).start(); }; const fadeOut = () => { /* withTimeout - most of the time we declare 'Close' after the animation is end. In a case that the app is not active we do it without timeout. (Otherwise a race condition may occur.) */ setIsPanelOpened(false); Animated.timing(fadeAnim, { toValue: 0, duration: 500, useNativeDriver: false }).start(); }; const setToContentHeight = contentHeight => { Animated.timing(panelHeightValue, { duration: props.animationDuration, easing: Easing.quad, toValue: props.sliderMaxHeight - contentHeight, useNativeDriver: false }).start(); }; const expand = () => { const { animationDuration } = props; props.onOpen(); if (contentHeight && currentHeight > props.sliderMaxHeight - contentHeight) { setToContentHeight(contentHeight); return; } Animated.timing(panelHeightValue, { duration: animationDuration, easing: Easing.quad, toValue: 0, useNativeDriver: false }).start(); }; const collapse = () => { if (contentHeight && currentHeight > props.sliderMaxHeight - contentHeight) { _dismiss(); return; } contentHeight && setToContentHeight(contentHeight); }; const _onBackPress = () => { isPanelOpened && collapse(); return isPanelOpened; }; const _setSize = e => { const newContentHeight = e.nativeEvent.layout.height; setContentHeight(newContentHeight); setToContentHeight(newContentHeight); }; const _dismiss = (withAnimation = true) => { const { animationDuration } = props; Animated.timing(panelHeightValue, { duration: withAnimation ? animationDuration : 0, easing: Easing.quad, toValue: props.sliderMaxHeight, useNativeDriver: false }).start(() => { props.onClose(); }); fadeOut(); }; const { children } = props; const isModal = props.nativePlace === BottomSheetNativePlaceType.modal; return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(TouchableOpacity, { style: styles.outsideContainer, activeOpacity: 1, onPress: () => _dismiss() }, /*#__PURE__*/React.createElement(Animated.View, { style: styles.animation })), /*#__PURE__*/React.createElement(Animated.View, _extends({}, _parentPanResponder.panHandlers, { style: { ...styles.container, borderTopLeftRadius: isModal ? 0 : styles.container.borderTopLeftRadius, borderTopRightRadius: isModal ? 0 : styles.container.borderTopRightRadius, height: props.sliderMaxHeight, marginTop: fullScreenHeight - props.sliderMaxHeight - (!isModal && isAndroid10AndAbove ? androidStatusBarHeight : 0), transform: [{ translateY: panelHeightValue }], paddingTop: Platform.OS === 'ios' && isModal ? statusBarHeight : 0 } }), /*#__PURE__*/React.createElement(View, { style: styles.outerContent }, /*#__PURE__*/React.createElement(TouchableOpacity, { activeOpacity: 1, style: styles.closeButton, onPress: () => _dismiss() }, /*#__PURE__*/React.createElement(Image, { source: CloseIcon })), /*#__PURE__*/React.createElement(View, { onLayout: _setSize }, /*#__PURE__*/React.createElement(UNBaseView, { style: { height: props.height } }, children))))); }; export default BottomSheet; //# sourceMappingURL=BottomSheet.js.map