import { useImperativeHandle, useLayoutEffect, forwardRef, useEffect, useState, Fragment, useRef } from "react"; import { Platform, Animated, Easing, View } from "react-native"; import { type MenuButton as MenuButtonType } from "./components/menuButton/type"; import { type IMenuRef } from "./type"; import type IMenuProps from "./type"; import stylesheet, { useStyles } from "./stylesheet"; import MenuButton from "./components/menuButton"; import { NCoreUIKitMenu, NCoreUIKitTheme } from "../../core/hooks"; import type { RefForwardingComponent } from "../../types"; import { SafeAreaView } from "react-native-safe-area-context"; import { Portal } from "../../helpers/portalize"; import Modal from "../modal"; import Seperator from "../seperator"; import SiteLogo from "../siteLogo"; const Menu: RefForwardingComponent = ({ isWorkWithSafeAreaView = true, isWorkWithAnimation = true, renderHeader: RenderHeader, renderFooter: RenderFooter, portalName = "menu-system", isWorkWithPortal = true, isWorkWithModal = true, close: closeAction, siteLogoProps, customTheme, navigation, modalProps, isCollapse, onClosed, onOpened, buttons, onClose, onOpen, style, id, ...props }, ref) => { const { colors, spaces } = NCoreUIKitTheme.useContext(customTheme); const { headerContainer: headerContainerDynamicStyle, seperator: seperatorDynamicStyle, container: containerDynamicStyle } = useStyles({ colors, spaces }); const [ isOpacityVisible, setIsOpacityVisible ] = useState(false); const [ measures, setMeasures ] = useState(null); const [ isActive, setIsActive ] = useState(false); const animatedX = useRef(new Animated.Value(0)).current; useImperativeHandle( ref, () => ({ close, open }), [] ); useEffect(() => { if(measures !== null) { animatedX.setValue(measures * -1); if(!isOpacityVisible) setIsOpacityVisible(true); if(isActive) setIsActive(false); } }, [measures]); useEffect(() => { if(isCollapse !== undefined) setIsActive(isCollapse); }, [isCollapse]); useLayoutEffect(() => { if(isActive && isOpacityVisible) { if(onOpen) onOpen({ id }); if(isWorkWithAnimation) { openAnimation(); } else { animatedX.setValue(0); if(onOpened) onOpened({ id }); } } else { if(onClose) onClose({ id }); if(!isWorkWithModal) { if(isWorkWithAnimation) { closeAnimation(); } else { animatedX.setValue(measures! * -1); if(onClosed) onClosed({ id }); } } } }, [ isOpacityVisible, isActive ]); const open = () => { setIsActive(true); }; const close = () => { if(onClose) onClose({ id }); if(isWorkWithModal) { if(isWorkWithAnimation) { closeAnimation(); } else { animatedX.setValue(measures! * -1); if(onClosed) onClosed({ id }); } } else { setIsActive(false); } }; const openAnimation = () => { Animated.timing(animatedX, { useNativeDriver: Platform.OS !== "web", easing: Easing.linear, duration: 300, toValue: 0 }).start(({ finished }) => { if(finished) { if(onOpened) onOpened({ id }); } }); }; const closeAnimation = () => { Animated.timing(animatedX, { useNativeDriver: Platform.OS !== "web", toValue: measures! * -1, easing: Easing.linear, duration: 300 }).start(({ finished }) => { if(finished) { if(onClosed) onClosed({ id }); } }); }; const updateMenuButtonCollabs = ({ depthMap, status }: { depthMap: Array; status: boolean; }) => { const state = NCoreUIKitMenu.get({ id }); if(!state) { return; } const recursivelyCatch = (item: Array, index = 0): Array => { const tIndex = depthMap[index]; return item.map((c_item, c_index) => { if(c_index !== tIndex) { return c_item; } if(index === depthMap.length - 1) { return { ...c_item, isCollapse: status }; } return { ...c_item, subButtons: recursivelyCatch(c_item.subButtons as Array, index + 1) }; }); }; const newButtons = recursivelyCatch(state.buttons); state.buttons = newButtons; NCoreUIKitMenu.update({ menuData: state, id: id }); }; const renderHeader = () => { if(RenderHeader) { return ; } return ; }; const renderButtons = () => { if(!buttons || !buttons.length) { return null; } return buttons.map((buttonItem, buttonIndex) => { return ; }); }; const renderFooter = () => { if(!RenderFooter) { return null; } return ; }; const renderSafeAreaContext = () => { if(!isWorkWithSafeAreaView) { return {renderHeader()} ; } return {renderHeader()} {renderButtons()} {renderFooter()} ; }; const renderContent = () => { return { const width = event.nativeEvent.layout.width; setMeasures(width); }} > {renderSafeAreaContext()} ; }; if(isWorkWithModal && measures !== null) { return { close(); }} portalName={portalName} isActive={isActive} id="menu-modal" > {renderContent()} ; } if(isWorkWithPortal && measures !== null) { return {renderContent()} ; } return renderContent(); }; export default forwardRef(Menu);