154 lines
4.5 KiB
TypeScript
Raw Normal View History

2024-02-18 01:44:48 -05:00
// ** React Import
import { ReactNode, useRef, useState } from 'react'
// ** MUI Import
import List from '@mui/material/List'
import Box, { BoxProps } from '@mui/material/Box'
import { styled, useTheme } from '@mui/material/styles'
// ** Third Party Components
import PerfectScrollbar from 'react-perfect-scrollbar'
// ** Type Import
import { Settings } from '../../../../../core/context/settingsContext'
import { VerticalNavItemsType } from '../../../../../core/layouts/types'
// ** Component Imports
import Drawer from './Drawer'
import VerticalNavItems from './VerticalNavItems'
import VerticalNavHeader from './VerticalNavHeader'
// ** Util Import
import { hexToRGBA } from '../../../../../core/utils/hex-to-rgba'
interface Props {
hidden: boolean
navWidth: number
settings: Settings
children: ReactNode
navVisible: boolean
toggleNavVisibility: () => void
setNavVisible: (value: boolean) => void
verticalNavItems?: VerticalNavItemsType
saveSettings: (values: Settings) => void
verticalNavMenuContent?: (props?: any) => ReactNode
afterVerticalNavMenuContent?: (props?: any) => ReactNode
beforeVerticalNavMenuContent?: (props?: any) => ReactNode
}
const StyledBoxForShadow = styled(Box)<BoxProps>({
top: 50,
left: -8,
zIndex: 2,
height: 75,
display: 'none',
position: 'absolute',
pointerEvents: 'none',
width: 'calc(100% + 15px)',
'&.d-block': {
display: 'block'
}
})
const Navigation = (props: Props) => {
// ** Props
const {
hidden,
afterVerticalNavMenuContent,
beforeVerticalNavMenuContent,
verticalNavMenuContent: userVerticalNavMenuContent
} = props
// ** States
const [groupActive, setGroupActive] = useState<string[]>([])
const [currentActiveGroup, setCurrentActiveGroup] = useState<string[]>([])
// ** Ref
const shadowRef = useRef(null)
// ** Hooks
const theme = useTheme()
// ** Fixes Navigation InfiniteScroll
const handleInfiniteScroll = (ref: HTMLElement) => {
if (ref) {
// @ts-ignore
ref._getBoundingClientRect = ref.getBoundingClientRect
ref.getBoundingClientRect = () => {
// @ts-ignore
const original = ref._getBoundingClientRect()
return { ...original, height: Math.floor(original.height) }
}
}
}
// ** Scroll Menu
const scrollMenu = (container: any) => {
container = hidden ? container.target : container
if (shadowRef && container.scrollTop > 0) {
// @ts-ignore
if (!shadowRef.current.classList.contains('d-block')) {
// @ts-ignore
shadowRef.current.classList.add('d-block')
}
} else {
// @ts-ignore
shadowRef.current.classList.remove('d-block')
}
}
const ScrollWrapper = hidden ? Box : PerfectScrollbar
return (
<Drawer {...props}>
<VerticalNavHeader {...props} />
<StyledBoxForShadow
ref={shadowRef}
sx={{
background: `linear-gradient(${theme.palette.background.default} 40%,${hexToRGBA(
theme.palette.background.default,
0.1
)} 95%,${hexToRGBA(theme.palette.background.default, 0.05)})`
}}
/>
<Box sx={{ height: '100%', position: 'relative', overflow: 'hidden' }}>
{/* @ts-ignore */}
<ScrollWrapper
{...(hidden
? {
onScroll: (container: any) => scrollMenu(container),
sx: { height: '100%', overflowY: 'auto', overflowX: 'hidden' }
}
: {
options: { wheelPropagation: false },
onScrollY: (container: any) => scrollMenu(container),
containerRef: (ref: any) => handleInfiniteScroll(ref)
})}
>
{beforeVerticalNavMenuContent ? beforeVerticalNavMenuContent(props) : null}
<Box sx={{ height: '100%', display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}>
{userVerticalNavMenuContent ? (
userVerticalNavMenuContent(props)
) : (
<List className='nav-items' sx={{ transition: 'padding .25s ease', pr: 4.5 }}>
<VerticalNavItems
groupActive={groupActive}
setGroupActive={setGroupActive}
currentActiveGroup={currentActiveGroup}
setCurrentActiveGroup={setCurrentActiveGroup}
{...props}
/>
</List>
)}
</Box>
</ScrollWrapper>
</Box>
{afterVerticalNavMenuContent ? afterVerticalNavMenuContent(props) : null}
</Drawer>
)
}
export default Navigation