import React from 'react'; import clsx from 'clsx'; import { createStyles, Theme, withStyles, WithStyles } from '@material-ui/core/styles'; import TableCell from '@material-ui/core/TableCell'; import Paper from '@material-ui/core/Paper'; import { AutoSizer, Column, Table, TableCellRenderer, TableHeaderProps } from 'react-virtualized'; declare module '@material-ui/core/styles/withStyles' { // Augment the BaseCSSProperties so that we can control jss-rtl interface BaseCSSProperties { /* * Used to control if the rule-set should be affected by rtl transformation */ flip?: boolean; } } const styles = (theme: Theme) => createStyles({ flexContainer: { display: 'flex', alignItems: 'center', boxSizing: 'border-box', }, table: { // temporary right-to-left patch, waiting for // https://github.com/bvaughn/react-virtualized/issues/454 '& .ReactVirtualized__Table__headerRow': { flip: false, paddingRight: theme.direction === 'rtl' ? '0 !important' : undefined, }, }, tableRow: { cursor: 'pointer', }, tableRowHover: { '&:hover': { backgroundColor: theme.palette.grey[200], }, }, tableCell: { flex: 1, }, noClick: { cursor: 'initial', }, }); interface ColumnData { dataKey: string; label: string; numeric?: boolean; width: number; } interface Row { index: number; } interface MuiVirtualizedTableProps extends WithStyles { columns: ColumnData[]; headerHeight?: number; onRowClick?: () => void; rowCount: number; rowGetter: (row: Row) => Data; rowHeight?: number; } class MuiVirtualizedTable extends React.PureComponent { static defaultProps = { headerHeight: 48, rowHeight: 48, }; getRowClassName = ({ index }: Row) => { const { classes, onRowClick } = this.props; return clsx(classes.tableRow, classes.flexContainer, { [classes.tableRowHover]: index !== -1 && onRowClick != null, }); }; cellRenderer: TableCellRenderer = ({ cellData, columnIndex }) => { const { columns, classes, rowHeight, onRowClick } = this.props; return ( {cellData} ); }; headerRenderer = ({ label, columnIndex }: TableHeaderProps & { columnIndex: number }) => { const { headerHeight, columns, classes } = this.props; return ( {label} ); }; render() { const { classes, columns, rowHeight, headerHeight, ...tableProps } = this.props; return ( {({ height, width }) => ( {columns.map(({ dataKey, ...other }, index) => { return ( this.headerRenderer({ ...headerProps, columnIndex: index, }) } className={classes.flexContainer} cellRenderer={this.cellRenderer} dataKey={dataKey} {...other} /> ); })}
)}
); } } const VirtualizedTable = withStyles(styles)(MuiVirtualizedTable); // --- interface Data { calories: number; carbs: number; dessert: string; fat: number; id: number; protein: number; } type Sample = [string, number, number, number, number]; const sample: Sample[] = [ ['Frozen yoghurt', 159, 6.0, 24, 4.0], ['Ice cream sandwich', 237, 9.0, 37, 4.3], ['Eclair', 262, 16.0, 24, 6.0], ['Cupcake', 305, 3.7, 67, 4.3], ['Gingerbread', 356, 16.0, 49, 3.9], ]; function createData( id: number, dessert: string, calories: number, fat: number, carbs: number, protein: number, ): Data { return { id, dessert, calories, fat, carbs, protein }; } const rows: Data[] = []; for (let i = 0; i < 200; i += 1) { const randomSelection = sample[Math.floor(Math.random() * sample.length)]; rows.push(createData(i, ...randomSelection)); } export default function ReactVirtualizedTable() { return ( rows[index]} columns={[ { width: 200, label: 'Dessert', dataKey: 'dessert', }, { width: 120, label: 'Calories\u00A0(g)', dataKey: 'calories', numeric: true, }, { width: 120, label: 'Fat\u00A0(g)', dataKey: 'fat', numeric: true, }, { width: 120, label: 'Carbs\u00A0(g)', dataKey: 'carbs', numeric: true, }, { width: 120, label: 'Protein\u00A0(g)', dataKey: 'protein', numeric: true, }, ]} /> ); }