Source

Utils/DataDisplay/TableItemsList.js

import React, {Fragment} from "react";
import PropTypes from "prop-types";
import clsx from "clsx";
import { makeStyles } from "@material-ui/core/styles";
import ListItem from "@material-ui/core/ListItem";
import ListSubheader from "@material-ui/core/ListSubheader";
import Typography from "@material-ui/core/Typography";
import { AutoSizer, List } from "react-virtualized";
import TextWithHoverTooltip from "./TextWithHoverTooltip";
import { MoreSettingsIconButton } from "../Buttons";

const listStyles = makeStyles(theme => ({
    root: {
        '& > .ReactVirtualized__Grid__innerScrollContainer': {
            backgroundColor: theme.palette.background.main1,
            color: theme.palette.text.main1
        }
    },
    textItem: {
        '&:hover': {
            overflow: "visible",
            whiteSpace: "unset",
        }
    },
    header: {
        alignItems: "center",
        backgroundColor: theme.palette.background.subLight,
        color: theme.palette.text.special2,
        display: "flex",
        height: 48,
        justifyContent: "center"
    },
    headerText: {
        ...theme.typography.subheader,
        flexGrow: 1,
        textAlign: "center"
    },
    listWrapper: {
        flexGrow: 1,
        width: "100%",
    },
    customisable: {
        paddingLeft: "1em"
    }
}), {name: "TableItemsList"});

/**
 * <h3>Overview</h3>
 * An AutoSizer and List components from react-virtualized library with custom styling.
 * Used to display items from an array from an item's tables property.
 * <br>
 * For full documentation check out react-virtualized docs on
 * <a href="https://github.com/bvaughn/react-virtualized/blob/master/docs/AutoSizer.md" target="_blank">AutoSizer</a>
 * and
 * <a href="https://github.com/bvaughn/react-virtualized/blob/master/docs/List.md" target="_blank">List</a>.
 *
 * @constructor
 * @category Utils
 * @subcategory Data Display
 * @param {Object} props
 * @param {boolean} [props.customisable = true] - If <code>true</code> settings button will be visible.
 * @param {function} [props.getItemStyle] - Should return a style object for an item with specified index.
 * @param {function} [props.getName] - Should return a name for an item with specified index.
 * @param {string} [props.headerText] - The header of the {@link TableItemsList}.
 * @param {number} props.itemIndex - The index of currently selected item.
 * @param {string} [props.itemText = "Object"] - The prefix used to name items from table.
 * @param {function} props.onItemInTableSelected - Callback fired when an item in table is selected.
 * @param {function} [props.onSettingsClick]  - Callback fired when settings button was clicked on.
 * @param {number} [props.rowHeight = 53] - The height of a row in a list.
 * @param {Object[]} props.table - The one of arrays from item's tables property.
 * @returns {React.ReactElement}
 */
function TableItemsList(props) {
    const {
        customisable,
        headerText,
        itemIndex,
        itemText,
        onItemInTableSelected,
        onSettingsClick,
        rowHeight,
        table
    } = props;

    const listClasses = listStyles();

    const rowRenderer = ({key, index, style}) => {
        let primary = itemText + " " + (table[index] + 1);
        if (typeof props.getName === "function") {
            primary = props.getName(table[index]);
        }

        let border = undefined;
        if (typeof props.getItemsStyle === "function") {
            border = props.getItemsStyle(table[index]);
        }

        return (
            <ListItem
                button={true}
                divider={true}
                key={key}
                selected={table[index] === itemIndex}
                onClick={() => onItemInTableSelected(table[index])}
                style={{ ...style, ...border }}
            >
                <TextWithHoverTooltip
                    text={primary}
                    TooltipProps={{
                        id: key,
                        placement: "right"
                    }}
                />
            </ListItem>
        )
    };

    return (
        <Fragment>
            {headerText &&
                <ListSubheader
                    disableSticky={true}
                    className={listClasses.header}
                    component={"header"}
                >
                    {customisable &&
                        <MoreSettingsIconButton
                            edge={"start"}
                            onClick={onSettingsClick}
                            TooltipProps={{
                                WrapperProps: {
                                    'aria-label': "more-settings-icon-button-wrapper",
                                    style: { display: "flex" }
                                }
                            }}
                        />
                    }
                    <Typography
                        className={clsx(
                            listClasses.headerText,
                            listClasses.textItem,
                            {[listClasses.customisable]: customisable}
                        )}
                        noWrap={true}
                    >
                        {headerText}
                    </Typography>
                </ListSubheader>
            }
            <div aria-label={"list wrapper"} className={listClasses.listWrapper}>
                <AutoSizer>
                    {({height, width}) => (
                        <List
                            className={listClasses.root}
                            height={height}
                            rowHeight={rowHeight}
                            rowCount={table.length}
                            rowRenderer={rowRenderer}
                            width={width}
                        />
                    )}
                </AutoSizer>
            </div>
        </Fragment>
    );
}

TableItemsList.propTypes = {
    customisable: PropTypes.bool,
    getItemsStyle: PropTypes.func,
    getName: PropTypes.func,
    headerText: PropTypes.string,
    itemIndex: PropTypes.number,
    itemText: PropTypes.string,
    onItemInTableSelected: PropTypes.func,
    onSettingsClick: PropTypes.func,
    rowHeight: PropTypes.number,
    table: PropTypes.array.isRequired,
};

TableItemsList.defaultProps = {
    customisable: true,
    itemText: "Object",
    rowHeight: 53,
};

export default TableItemsList;