Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
components.layout.sidebar.SidebarList.tsx Maven / Gradle / Ivy
import MuiIcon from 'components/common/MuiIcon';
import { GearsIcon, useGearsIconInfo } from 'components/process/GearsIcon';
import SidebarContextProvider from 'contexts/SidebarContext';
import { useLayoutContext } from 'hooks/layout';
import {
SidebarItemSx, useSidebarChildItemActive, useSidebarContext, useSidebarItemActive,
useSidebarItemOnClick, useSidebarItemSX
} from 'hooks/sidebar';
import _ from 'lodash';
import React, { useEffect, useRef, useState } from 'react';
import { ReactChildren } from 'types/react';
import {
SidebarItemData, SidebarItemDataCascading, SidebarItemDataGroup, SidebarItemDataIcon,
SidebarItemDataLink
} from 'types/sidebar';
import { ThemeIcon } from 'types/theming';
import Types, { GearsIconType } from 'types/types';
import { decomposeRefPath } from 'utils/path';
import {
Badge, Box, Collapse, IconButton, List, ListItemButton, ListItemIcon, ListItemText,
ListSubheader, Tooltip, Typography, useTheme
} from '@mui/material';
import { isSidebarMatchFunction } from '../dashboard/DashboardSidebar';
import SidebarMenu from '../dashboard/SidebarMenu';
type ItemsProps = {
items: SidebarItemData[]
}
export const SidebarList = ({items}: ItemsProps) => {
const context = useSidebarContext()
const theme = useTheme()
return (
0 ? 22 : 0}px`, flexShrink: 0}} />
)
}
export const SidebarItems = ({items}: ItemsProps): JSX.Element => {
return (
{items.map((item, index) => )}
)
}
const SidebarGenericItem = ({item, isFirstItem}: {item: SidebarItemData, isFirstItem?: boolean}) => {
switch (item.type) {
case "group":
return (item)} isFirstItem={isFirstItem} />
case "cascading":
return (item)} />
default:
return (item)}/>
}
}
const SidebarGroupTitle = ({item, isFirstItem}: {item: SidebarItemDataGroup, isFirstItem?: boolean}) => {
const { sidebarState } = useLayoutContext()
const { sidebarType } = useSidebarContext()
const show = sidebarType != "sidebar" || sidebarState.kind == 'permanent' && sidebarState.expandState == "expanded"
return (
<>
{/*sidebarType != "sidebar" || sidebarState.expand != "collapsed" && sidebarState.expand != "none"} > */}
{ item.label }
>
)
}
const SidebarCascadingItem = ({item}: {item: SidebarItemDataCascading}) => {
const childActive = useSidebarChildItemActive(item)
const { level, sidebarType, filter } = useSidebarContext()
const isMatch = isSidebarMatchFunction(filter)
const [open, setOpen] = useState(filter ? !isMatch(item) : false)
const onClick = useSidebarItemOnClick(item)
const {itemSx, textSx} = useSidebarItemSX(item)
const active = useSidebarItemActive(item)
const {sidebarState} = useLayoutContext()
const cascadingType = sidebarState.expandState == "collapsed" || sidebarState.expandState == "none" || level > 1 ? "menu" : "list"
const openList = cascadingType == "list" && open
const ref = useRef()
const [anchorEl, setAnchorEl] = useState(null);
useEffect(() => {
setOpen(filter ? !isMatch(item) : false)
}, [filter])
useEffect(() => {
if (childActive && !open)
setOpen(true)
}, [childActive])
const handleClick = (e: React.SyntheticEvent) => {
e.preventDefault()
e.stopPropagation()
// open sidebar menu
if (cascadingType == "menu")
// @ts-ignore
setAnchorEl(ref.current);
// open list
if (cascadingType == "list")
handleListOpen(e)
if (onClick)
onClick(e)
}
const handleListOpen = (e: React.SyntheticEvent) => {
e.preventDefault()
e.stopPropagation()
if (cascadingType == "menu")
// @ts-ignore
setAnchorEl(ref.current)
if (cascadingType == "list")
setOpen(open => !open)
}
return (
<>
{/* @ts-ignore*/}
{item.label}} />
{ cascadingType == "menu" || sidebarType == "menu"
?
: null
}
>
)
}
const SidebarLink = ({item}: {item: SidebarItemDataLink}) => {
const onClick = useSidebarItemOnClick(item)
const { itemSx, textSx } = useSidebarItemSX(item)
const active = useSidebarItemActive(item)
return (
{onClick(e);}}
sx={{...itemSx, paddingRight: "45px"}}
>
{item.label}} />
)
}
export const SidebarIcon = ({item}: {item: SidebarItemData}) => {
const active = useSidebarItemActive(item)
// @ts-ignore
const { counts } = useSidebarContext()
const badgeCount = getItemBadges(item).reduce((partialSum, badge) => partialSum + counts[badge], 0)
return (
({
// @ts-ignore
...theme.components?.badge,
})
}}
>
)
}
const getItemBadges = (item: SidebarItemData): string[] => {
const children = getItemChildren(item)
const badges = children
.flatMap(child => getItemBadges(child))
.filter(badge => badge != 'allBadge')
const badge = getItemBadge(item)
return badge ? [badge, ...badges] : badges
}
function getItemBadge(item: SidebarItemData): string | undefined {
return asItemCascading(item)?.badge || asItemLink(item)?.badge
}
function isItemLink(item: SidebarItemData): boolean {
return item.type == "item" || item.type == undefined
}
function isItemCascading(item: SidebarItemData): boolean {
return item.type == "cascading"
}
function isItemGroup(item: SidebarItemData): boolean {
return item.type == "group"
}
function asItemLink(item: SidebarItemData): SidebarItemDataLink | undefined {
return isItemLink(item) ? Types.as(item) : undefined
}
function asItemCascading(item: SidebarItemData): SidebarItemDataCascading | undefined {
return isItemCascading(item) ? Types.as(item) : undefined
}
function asItemGroup(item: SidebarItemData): SidebarItemDataGroup | undefined {
return isItemGroup(item) ? Types.as(item) : undefined
}
function getItemChildren(item: SidebarItemData): SidebarItemData[] {
switch (item.type) {
case "cascading":
return Types.as(item)?.children || []
case "group":
return Types.as(item)?.children || []
default:
return []
}
}
const useSidebarIconSelector = ({item, active}: {item: SidebarItemData, active: boolean}): GearsIconType => {
const itemIcon = selectItemIcon(active, Types.as(item))
const toIconType = (itemIcon: any): GearsIconType => {
if (Types.isObject(itemIcon)) {
// @ts-ignore
if (itemIcon.__kind == "icon")
return itemIcon as GearsIconType
else {
return { __kind: "icon", ...(itemIcon as ThemeIcon) }
}
} else if (typeof itemIcon == "string") {
return { __kind: "icon", name: itemIcon }
} else {
return {__kind: "icon"}
}
}
if (item.ref && decomposeRefPath(item.ref)?.domain == "default") {
const ret = useGearsIconInfo({gearsRef: item.ref, icon: toIconType(itemIcon).name, active})
return ret
} else if (itemIcon) {
return toIconType(itemIcon)
} else if (item.ref) {
// go look for the icon in the theme
return useGearsIconInfo({gearsRef: item.ref, active})
}
return {__kind: "icon"}
}
function selectItemIcon(active: boolean, item: SidebarItemDataIcon): string | ThemeIcon | GearsIconType | undefined {
if (active)
return item.activeIcon
else
return item.icon
}
const SidebarItemIcon = ({item, active}: {item: SidebarItemData, active: boolean}) => {
if (item.type != "cascading" && item.type != "item")
return null
const baseIcon = active ? _.get(item, "activeIcon") : _.get(item, "icon")
const iconName = typeof baseIcon == "string" ? baseIcon : _.get(baseIcon, "name")
const icon = useGearsIconInfo({gearsRef: item.ref, icon: iconName, override: true, active: active})
const color = active ? 'primary.main' : undefined
return
}
const SidebarTooltip = ({children, title}: {children: ReactChildren, title: string}) => {
const { level } = useSidebarContext()
const { props: {side, expandedWidth, collapsedWidth}, sidebarState: { expandState } } = useLayoutContext()
const diff = parseInt(collapsedWidth,10) - parseInt(expandedWidth, 10)
if (level == 0 && expandState == "collapsed") {
return (
{children}
)
}
else return children
}
const ActiveIndicator = ({active}: {active: boolean}) => (
theme.palette.primary.main,
marginLeft: "-12px",
borderRadius: "99px",
marginRight: "5px",
transition: "all .2s linear",
}}
/>
)