Files
pos-dashboard-v2/src/@menu/components/vertical-menu/MenuSection.tsx
T
2025-08-05 12:35:40 +07:00

146 lines
4.5 KiB
TypeScript

'use client'
// React Imports
import { forwardRef } from 'react'
import type { ForwardRefRenderFunction, CSSProperties, ReactElement, ReactNode } from 'react'
// Third-party Imports
import classnames from 'classnames'
import type { CSSObject } from '@emotion/styled'
// Type Imports
import type { MenuSectionStyles } from './Menu'
import type { ChildrenType, RootStylesType } from '../../types'
// Hook Imports
import useVerticalNav from '../../hooks/useVerticalNav'
import useVerticalMenu from '../../hooks/useVerticalMenu'
// Util Imports
import { menuClasses } from '../../utils/menuClasses'
// Styled Component Imports
import StyledMenuIcon from '../../styles/StyledMenuIcon'
import StyledMenuPrefix from '../../styles/StyledMenuPrefix'
import StyledMenuSuffix from '../../styles/StyledMenuSuffix'
import StyledMenuSectionLabel from '../../styles/StyledMenuSectionLabel'
import StyledVerticalMenuSection from '../../styles/vertical/StyledVerticalMenuSection'
export type MenuSectionProps = Partial<ChildrenType> &
RootStylesType & {
label: ReactNode
icon?: ReactElement
prefix?: ReactNode
suffix?: ReactNode
/**
* @ignore
*/
className?: string
}
type MenuSectionElement = keyof MenuSectionStyles
const menuSectionWrapperStyles: CSSProperties = {
display: 'inline-block',
inlineSize: '100%',
position: 'relative',
listStyle: 'none',
padding: 0,
overflow: 'hidden'
}
const menuSectionContentStyles: CSSProperties = {
display: 'flex',
alignItems: 'center',
inlineSize: '100%',
position: 'relative',
paddingBlock: '0.75rem',
paddingInline: '1.25rem',
overflow: 'hidden'
}
const MenuSection: ForwardRefRenderFunction<HTMLLIElement, MenuSectionProps> = (props, ref) => {
// Props
const { children, icon, className, prefix, suffix, label, rootStyles, ...rest } = props
// Hooks
const { isCollapsed, isHovered } = useVerticalNav()
const { menuSectionStyles, collapsedMenuSectionLabel, textTruncate } = useVerticalMenu()
const getMenuSectionStyles = (element: MenuSectionElement): CSSObject | undefined => {
// If the menuSectionStyles prop is provided, get the styles for the element from the prop
if (menuSectionStyles) {
return menuSectionStyles[element]
}
}
return (
// eslint-disable-next-line lines-around-comment
// Menu Section
<StyledVerticalMenuSection
ref={ref}
rootStyles={rootStyles}
menuSectionStyles={getMenuSectionStyles('root')}
className={classnames(menuClasses.menuSectionRoot, className)}
>
{/* Menu Section Content Wrapper */}
<ul className={menuClasses.menuSectionWrapper} {...rest} style={menuSectionWrapperStyles}>
{/* Menu Section Content */}
<li className={menuClasses.menuSectionContent} style={menuSectionContentStyles}>
{icon && (
<StyledMenuIcon className={menuClasses.icon} rootStyles={getMenuSectionStyles('icon')}>
{icon}
</StyledMenuIcon>
)}
{prefix && (
<StyledMenuPrefix
isCollapsed={isCollapsed}
className={menuClasses.prefix}
rootStyles={getMenuSectionStyles('prefix')}
>
{prefix}
</StyledMenuPrefix>
)}
{collapsedMenuSectionLabel && isCollapsed && !isHovered ? (
<StyledMenuSectionLabel
isCollapsed={isCollapsed}
isHovered={isHovered}
className={menuClasses.menuSectionLabel}
rootStyles={getMenuSectionStyles('label')}
textTruncate={textTruncate}
>
{collapsedMenuSectionLabel}
</StyledMenuSectionLabel>
) : (
label && (
<StyledMenuSectionLabel
isCollapsed={isCollapsed}
isHovered={isHovered}
className={menuClasses.menuSectionLabel}
rootStyles={getMenuSectionStyles('label')}
textTruncate={textTruncate}
>
{label}
</StyledMenuSectionLabel>
)
)}
{suffix && (
<StyledMenuSuffix
isCollapsed={isCollapsed}
className={menuClasses.suffix}
rootStyles={getMenuSectionStyles('suffix')}
>
{suffix}
</StyledMenuSuffix>
)}
</li>
{/* Render Child */}
{children}
</ul>
</StyledVerticalMenuSection>
)
}
export default forwardRef<HTMLLIElement, MenuSectionProps>(MenuSection)