import { styled } from '@mui/material'; import { ReactNode, useState } from 'react'; import { SidePanelListHeader } from './SidePanelListHeader'; import { SidePanelListItem } from './SidePanelListItem'; const StyledSidePanelListWrapper = styled('div')({ display: 'flex', flexDirection: 'column', width: '100%', }); const StyledSidePanelListBody = styled('div')({ display: 'flex', flexDirection: 'row', }); const StyledSidePanelHalf = styled('div')({ display: 'flex', flexDirection: 'column', flex: 1, }); const StyledSidePanelHalfLeft = styled(StyledSidePanelHalf, { shouldForwardProp: (prop) => prop !== 'height' && prop !== 'maxWidth', })<{ height?: number; maxWidth?: number }>(({ theme, height, maxWidth }) => ({ border: `1px solid ${theme.palette.divider}`, borderTop: 0, borderBottomLeftRadius: theme.shape.borderRadiusMedium, overflow: 'auto', ...(height && { height }), ...(maxWidth && { maxWidth }), })); const StyledSidePanelHalfRight = styled(StyledSidePanelHalf)(({ theme }) => ({ border: `1px solid ${theme.palette.divider}`, borderTop: 0, borderLeft: 0, borderBottomRightRadius: theme.shape.borderRadiusMedium, })); type ColumnAlignment = 'start' | 'end' | 'center'; export const StyledSidePanelListColumn = styled('div', { shouldForwardProp: (prop) => prop !== 'maxWidth' && prop !== 'align', })<{ maxWidth?: number; align?: ColumnAlignment }>( ({ theme, maxWidth, align = 'start' }) => ({ display: 'flex', flex: 1, padding: theme.spacing(2), fontSize: theme.fontSizes.smallBody, justifyContent: align, ...(maxWidth && { maxWidth }), textAlign: align, alignItems: 'center', }), ); export type SidePanelListColumn = { header: string; maxWidth?: number; align?: ColumnAlignment; cell: (item: T) => ReactNode; }; interface ISidePanelListProps { items: T[]; columns: SidePanelListColumn[]; sidePanelHeader: string; renderContent: (item: T) => ReactNode; renderItem?: (item: T, children: ReactNode) => ReactNode; height?: number; listEnd?: ReactNode; } export const SidePanelList = ({ items, columns, sidePanelHeader, renderContent, renderItem = (_, children) => children, height, listEnd, }: ISidePanelListProps) => { const [selectedItem, setSelectedItem] = useState(items[0]); if (items.length === 0) { return null; } const activeItem = selectedItem || items[0]; const leftPanelMaxWidth = columns.every(({ maxWidth }) => Boolean(maxWidth)) ? columns.reduce((acc, { maxWidth }) => acc + (maxWidth || 0), 0) : undefined; return ( {items.map((item) => renderItem( item, setSelectedItem(item)} > {columns.map( ({ header, maxWidth, align, cell }) => ( {cell(item)} ), )} , ), )} {listEnd} {renderContent(activeItem)} ); };