react-native-unit-components
Version:
Unit React Native components
192 lines (191 loc) • 9.04 kB
JavaScript
/* eslint-disable @typescript-eslint/no-explicit-any */
import React, { useEffect, useState } from 'react';
import { View } from 'react-native';
import BottomSheet from '../../helpers/BottomSheet/BottomSheet';
import { UnitComponentsMessage } from '../../messages/webMessages/unitComponentsMessages';
import { getStylesObject } from './UNBottomSheetComponent.styles';
import { BottomSheetNativePlaceType, BottomSheetRenderingType, ScrollState } from '../../types/internal/bottomSheet.types';
import { BottomSheetNativeMessage } from '../../messages/nativeMessages/bottomSheetMessage';
import { withReduxStore } from '../../helpers/store/helpers';
import { useListenerToEvent } from '../../hooks/useListenerToEvent';
import { useDispatch, useSelector } from 'react-redux';
import { fullScreenHeight, overFullScreenHeight } from './UNBottomSheetComponent.constants';
import { resetBottomSheetSlice, setIsBottomSheetActive, setIsComponentLoading, setNativePlace, setScrollState, setShouldEnableBottomSheetScroll, setShouldShowBottomSheet } from '../../slices/BottomSheetSlice';
import UNBottomSheetSlotComponent from './components/UNBottomSheetSlotComponent/UNBottomSheetSlotComponent';
import UNBottomSheetNativeComponent from './components/UNBottomSheetNativeComponent/UNBottomSheetNativeComponent';
import { getNativeComponentDataFromEvent } from './UNBottomSheetComponent.utils';
const UNBottomSheetComponent = () => {
const dispatch = useDispatch();
const isBottomSheetActive = useSelector(state => state.bottomSheet.isBottomSheetActive);
const isComponentLoading = useSelector(state => state.bottomSheet.isComponentLoading);
const shouldShowBottomSheet = useSelector(state => state.bottomSheet.shouldShowBottomSheet);
const nativePlace = useSelector(state => state.bottomSheet.nativePlace);
const componentHeight = useSelector(state => state.bottomSheet.componentHeight);
const scrollState = useSelector(state => state.bottomSheet.scrollState);
const shouldEnableBottomSheetScroll = useSelector(state => state.bottomSheet.shouldEnableBottomSheetScroll);
const [renderingType, setRenderingType] = useState();
const [height, setHeight] = useState(0);
const [sliderMaxHeight, setSliderMaxHeight] = useState(overFullScreenHeight);
const [nativeComponentData, setNativeComponentData] = useState();
const [requestRenderingEventData, setRequestRenderingEventData] = useState();
const [componentParams, setComponentParams] = useState();
const [currentBottomSheetRenderingMessage, setCurrentBottomSheetRenderingMessage] = useState();
const styles = getStylesObject();
useEffect(() => {
const setHeightFromNativePlace = () => {
switch (nativePlace) {
// In the case of overFullScreen, set the height to the overFullScreenHeight.
case BottomSheetNativePlaceType.overFullScreen:
setHeight(overFullScreenHeight);
break;
// For modal native place type, set the height to the fullScreenHeight.
case BottomSheetNativePlaceType.modal:
setHeight(fullScreenHeight);
break;
default:
// In general, we want the bottom sheet to fully contain the component,
// thus adjusting its height to the component height, up to the maximum of overFullScreenHeight.
if (componentHeight) {
setHeight(componentHeight < overFullScreenHeight ? componentHeight : overFullScreenHeight);
}
break;
}
};
const setSliderMaxHeightFromNativePlace = () => {
if (nativePlace === BottomSheetNativePlaceType.modal) {
setSliderMaxHeight(fullScreenHeight);
} else {
setSliderMaxHeight(overFullScreenHeight);
}
};
// Check if the inner contained component is still loading or the bottom sheet should not be shown.
if (isComponentLoading || !shouldShowBottomSheet) {
// If so, hide the bottom sheet by setting the height to 0.
setHeight(0);
} else {
// If not, display the bottom sheet by calculating and setting the height based on the native place type.
setHeightFromNativePlace();
setSliderMaxHeightFromNativePlace();
}
}, [componentHeight, nativePlace, isComponentLoading, shouldShowBottomSheet]);
useEffect(() => {
const resetBottomSheetManagerState = () => {
setComponentParams(undefined);
setRequestRenderingEventData(undefined);
setNativeComponentData(undefined);
setRenderingType(undefined);
setHeight(0);
setSliderMaxHeight(overFullScreenHeight);
};
if (!isBottomSheetActive) {
dispatch(resetBottomSheetSlice());
resetBottomSheetManagerState();
}
}, [isBottomSheetActive, dispatch]);
const requestRendering = rendering => {
if (isBottomSheetActive) {
dispatch(setShouldShowBottomSheet(false));
}
handleRequestRendering(rendering);
if (isBottomSheetActive) {
setTimeout(() => dispatch(setShouldShowBottomSheet(true)), 400);
} else {
dispatch(setIsBottomSheetActive(true));
dispatch(setShouldShowBottomSheet(true));
}
};
const handleCloseFlow = () => {
dispatch(setIsBottomSheetActive(false));
};
useListenerToEvent({
busEventKey: BottomSheetNativeMessage.REQUEST_RENDERING,
action: requestRendering
});
useListenerToEvent({
busEventKey: UnitComponentsMessage.UNIT_REQUEST_CLOSE_FLOW,
action: handleCloseFlow
});
const handleRequestRendering = rendering => {
if (rendering === currentBottomSheetRenderingMessage) {
return;
} else {
setCurrentBottomSheetRenderingMessage(rendering);
}
dispatch(setIsComponentLoading(true));
switch (rendering.type) {
//if slot check if we know this component and want to show it, otherwise get directly the component
case BottomSheetRenderingType.Slot:
determineRenderingTypeFromEvent(rendering.data);
break;
case BottomSheetRenderingType.NativeComponent:
setupDataForNativeComponent(rendering.data);
break;
default:
break;
}
};
const determineRenderingTypeFromEvent = event => {
const nativeComponentDataFromEvent = getNativeComponentDataFromEvent(event);
if (nativeComponentDataFromEvent) {
setupDataForNativeComponent(nativeComponentDataFromEvent);
return;
}
setupDataForSlotComponent(event);
};
const setupDataForNativeComponent = eventData => {
const nativePlace = eventData.nativePlace ? eventData.nativePlace : BottomSheetNativePlaceType.modal;
setRenderingType(BottomSheetRenderingType.NativeComponent);
dispatch(setNativePlace(nativePlace));
setNativeComponentData(eventData);
dispatch(setIsComponentLoading(false)); //todo: work with events?
};
const setupDataForSlotComponent = eventData => {
setRenderingType(BottomSheetRenderingType.Slot);
const componentParamsFromEvent = {
componentName: eventData.componentName ? eventData.componentName : componentParams?.componentName,
componentResourceId: eventData.componentResourceId ? eventData.componentResourceId : componentParams?.componentResourceId
};
setComponentParams(componentParamsFromEvent);
dispatch(setNativePlace(eventData.requestRenderingEvent.data.nativePlace));
setRequestRenderingEventData(eventData.requestRenderingEvent);
};
const handleWebViewScroll = () => {
if (scrollState === ScrollState.unScrollable) return;
dispatch(setScrollState(ScrollState.onlyWebView));
dispatch(setShouldEnableBottomSheetScroll(false));
};
const renderBottomSheetComponent = () => {
switch (renderingType) {
case BottomSheetRenderingType.Slot:
return requestRenderingEventData ? /*#__PURE__*/React.createElement(UNBottomSheetSlotComponent, {
requestRenderingEvent: requestRenderingEventData,
componentName: componentParams?.componentName,
componentResourceId: componentParams?.componentResourceId
}) : null;
case BottomSheetRenderingType.NativeComponent:
return nativeComponentData ? /*#__PURE__*/React.createElement(UNBottomSheetNativeComponent, {
nativeComponentData: nativeComponentData
}) : null;
default:
return null;
}
};
return /*#__PURE__*/React.createElement(View, {
pointerEvents: isBottomSheetActive ? undefined : 'none',
style: styles.container
}, /*#__PURE__*/React.createElement(BottomSheet, {
isOpen: isBottomSheetActive,
onOpen: () => dispatch(setIsBottomSheetActive(true)),
onClose: () => dispatch(setIsBottomSheetActive(false)),
height: height,
animationDuration: 200,
expandToMaxHeightEnabled: false,
handleWebViewScroll: () => handleWebViewScroll(),
shouldEnableBottomSheetScroll: shouldEnableBottomSheetScroll,
nativePlace: nativePlace,
isComponentLoading: isComponentLoading,
sliderMaxHeight: sliderMaxHeight
}, renderBottomSheetComponent()));
};
export default withReduxStore(UNBottomSheetComponent);
//# sourceMappingURL=UNBottomSheetComponent.js.map