// Copyright (C) The Arvados Authors. All rights reserved. // // SPDX-License-Identifier: AGPL-3.0 import React, { useEffect, useRef } from 'react'; import { Tabs, Tab, List, ListItemButton } from '@mui/material'; import { CustomStyleRulesCallback } from 'common/custom-theme'; import { WithStyles, withStyles } from '@mui/styles'; import classNames from 'classnames'; import { ArvadosTheme } from 'common/custom-theme'; import { InlinePulser } from 'components/loading/inline-pulser'; type TabbedListClasses = 'root' | 'tabs' | 'tabPanel' | 'listItem' | 'selected' | 'spinner' | 'notFoundLabel'; const tabbedListStyles: CustomStyleRulesCallback = (theme: ArvadosTheme) => ({ root: { display: 'flex', flexDirection: 'column', height: '100%', overflowY: 'auto', }, tabs: { backgroundColor: theme.palette.background.paper, position: 'sticky', top: 0, zIndex: 1, borderBottom: '1px solid lightgrey', }, tabPanel: { overflowY: 'scroll', }, listItem: { cursor: 'pointer', '&:hover': { backgroundColor: theme.palette.grey[200], } }, selected: { backgroundColor: `${theme.palette.grey['300']} !important` }, spinner: { display: 'flex', justifyContent: 'center', alignItems: 'center', height: '4rem', }, notFoundLabel: { cursor: 'default', padding: theme.spacing(1), color: theme.palette.grey[700], textAlign: 'center', }, }); type TabPanelProps = { children: React.ReactNode; value: number; index: number; }; type TabbedListProps = { tabbedListContents: Record; injectedStyles?: string; selectedIndex?: number; selectedTab?: number; includeContentsLength: boolean; isWorking?: boolean; handleSelect?: (selection: T) => React.MouseEventHandler | undefined; renderListItem?: (item: T) => React.ReactNode; handleTabChange?: (event: React.SyntheticEvent, newValue: number) => void; }; export const TabbedList = withStyles(tabbedListStyles)(({ tabbedListContents, selectedIndex, selectedTab, isWorking, injectedStyles, classes, handleSelect, renderListItem, handleTabChange, includeContentsLength }: TabbedListProps & WithStyles) => { const tabNr = selectedTab || 0; const listRefs = useRef([]); const tabLabels = Object.keys(tabbedListContents); useEffect(() => { if (selectedIndex !== undefined && listRefs.current[selectedIndex]) { listRefs.current[selectedIndex].scrollIntoView({ behavior: 'smooth', block: 'center' }); } }, [selectedIndex]); const TabPanel = ({ children, value, index }: TabPanelProps) => { return ; }; return (
{tabLabels.map((label) => ( ))}
{isWorking ?
: {tabbedListContents[tabLabels[tabNr]].length === 0 &&
no matching {tabLabels[tabNr]} found
} {tabbedListContents[tabLabels[tabNr]].map((item, i) => (
{ if (!!el) listRefs.current[i] = el}}> {renderListItem ? renderListItem(item) : JSON.stringify(item)}
))}
}
); });