import * as React from 'react'; import { useCallback } from 'react'; import type { ContextType, SidebarEventListener, SidebarEventType } from './types'; import { useTheme } from '@mui/styles'; import useMediaQuery from '@mui/material/useMediaQuery'; const RightSideBarContext = React.createContext(undefined); const RightSideBarProvider: React.FC = ({ children }) => { const [mainComponent, setMainComponent] = React.useState(null); const [open, setOpen] = React.useState(false); const [openSecondary, setOpenSecondary] = React.useState(false); const [componentsArray, setComponentsArray] = React.useState([]); const [drawerLocked, setDrawerLocked] = React.useState(false); const [showDrawer, setShowDrawer] = React.useState(false); const eventListeners = React.useRef>({}); const [defaultMod, setDefaultMod] = React.useState(true); const durationTime = { enter: 500, exit: 400 }; const theme = useTheme(); const isMdUp = useMediaQuery(theme.breakpoints.up(1439)); const removeEventListener = useCallback( (type: SidebarEventType, listener: SidebarEventListener) => { eventListeners.current[type] = eventListeners.current[type]?.filter(l => l !== listener); }, [] ); const addEventListener = useCallback( (type: SidebarEventType, listener: SidebarEventListener) => { (eventListeners.current[type] ??= []).push(listener); return () => { removeEventListener(type, listener); }; }, [removeEventListener] ); const dispatchEvent = useCallback((type: SidebarEventType, event?: Event) => { eventListeners.current[type]?.forEach(listener => { listener?.(event); }); }, []); const displayDifComponent = useCallback((Components: React.ReactNode) => { setMainComponent(Components); }, []); const setDrawerBehavior = useCallback( (event?: Event) => { if (isMdUp) { setDrawerLocked(true); dispatchEvent('open', event); setOpen(true); } }, [dispatchEvent, isMdUp] ); const setComponentSecondaryDrawer = useCallback((Component: React.ReactNode) => { setComponentsArray(oldArray => [Component, ...oldArray]); }, []); const clearComponentsArray = () => { setTimeout(() => { setComponentsArray([]); }, 500); }; const handleComponentsArray = useCallback(() => { if (componentsArray.length > 1) { return setComponentsArray(oldArray => oldArray.slice(1)); } if (componentsArray.length === 1) { clearComponentsArray(); setOpenSecondary(false); } }, [componentsArray.length]); const handleMainDrawer = useCallback( (event?: Event) => { setDefaultMod(!defaultMod); if (open && drawerLocked) { setDrawerLocked(false); open && dispatchEvent('closed', event); return setOpen(false); } if (open && isMdUp) { dispatchEvent('locked', event); return setDrawerLocked(true); } if (!open) { if (isMdUp) { dispatchEvent('locked', event); setDrawerLocked(true); } dispatchEvent('open', event); return setOpen(true); } open && dispatchEvent('closed', event); return setOpen(false); }, [defaultMod, dispatchEvent, drawerLocked, isMdUp, open] ); const value: ContextType = { mainComponent, displayDifComponent, open, setOpen, setDrawerBehavior, openSecondary, setOpenSecondary, componentsArray, setComponentSecondaryDrawer, handleComponentsArray, clearComponentsArray, handleMainDrawer, drawerLocked, setDrawerLocked, setShowDrawer, showDrawer, durationTime, addEventListener, removeEventListener, dispatchEvent, defaultMod, setDefaultMod }; return {children}; }; function useRightSideBar() { const context = React.useContext(RightSideBarContext); if (context === undefined) { throw new Error('useRightSideBar must be used within a RightSideBarProvider'); } return context; } export { RightSideBarProvider, useRightSideBar };