VirtualTable.js 3.89 KB
Newer Older
1
import React, { useRef, useState, useEffect } from 'react';
2 3 4
import BasicTable from "@wisdom-components/basictable";
import classNames from 'classnames';
import ResizeObserver from 'rc-resize-observer';
5
import { VariableSizeGrid as Grid } from 'react-window';
6 7 8
import './VirtualTable.less';
const VirtualTable = (props) => {
    const TABLE_ROW_HEIGHT = 40;
9
    const { columns, scroll,theme } = props;
10
    const [tableWidth, setTableWidth] = useState(0);
11
    const widthColumnCount = columns.filter(({ width }) => !width).length;
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
    const totalWidth = columns.reduce((final, curr) => {
        return final += (curr.width ?? 0)
    }, 0);
    const mergedColumns = columns.map((column) => {
        if (totalWidth < tableWidth) {
            return {
                ...column,
                width: Math.floor(tableWidth / totalWidth * column.width),
            };
        }
        if (column.width) {
            return column;
        }
        return {
            ...column,
            width: Math.floor(tableWidth / widthColumnCount),
        };
    });
    const gridRef = useRef();
    const [connectObject] = useState(() => {
        const obj = {};
        Object.defineProperty(obj, 'scrollLeft', {
            get: () => {
                if (gridRef.current) {
                    return gridRef.current?.state?.scrollLeft;
                }
                return null;
            },
            set: (scrollLeft) => {
                if (gridRef.current) {
                    gridRef.current.scrollTo({
                        scrollLeft,
                    });
                }
            },
        });
        return obj;
    });
    const resetVirtualGrid = () => {
        gridRef.current?.resetAfterIndices({
            columnIndex: 0,
            shouldForceUpdate: true,
        });
    };
56
    useEffect(() => resetVirtualGrid, [tableWidth, props.dataSource]);
57
    const renderVirtualList = (rawData, { scrollbarSize, ref, onScroll }) => {
58 59 60 61 62 63
        ref.current = connectObject;
        const totalHeight = rawData.length * TABLE_ROW_HEIGHT;

        return (
            <Grid
                ref={gridRef}
64
                className={`${theme==='BI'?'BI-':''}virtual-grid`}
65 66
                columnCount={mergedColumns.length}
                columnWidth={(index) => {
67
                    const { width } = mergedColumns[index];
68 69 70 71 72 73 74 75 76
                    return totalHeight > scroll.y && index === mergedColumns.length - 1
                        ? width - scrollbarSize - 1
                        : width;
                }}
                height={scroll.y}
                rowCount={rawData.length}
                rowHeight={() => TABLE_ROW_HEIGHT}
                width={tableWidth}
                // width={'100%'}
77
                onScroll={({ scrollLeft }) => {
78 79 80 81 82
                    onScroll({
                        scrollLeft,
                    });
                }}
            >
83
                {({ columnIndex, rowIndex, style }) => (
84
                    <div
85
                        className={classNames(`${theme==='BI'?'BI-':''}virtual-table-cell`, {
86 87 88 89 90 91 92 93 94 95 96 97
                            'virtual-table-cell-last': columnIndex === mergedColumns.length - 1,
                        })}
                        style={style}
                    >
                        {rawData[rowIndex][mergedColumns[columnIndex].dataIndex]}
                    </div>
                )}
            </Grid>
        );
    };
    return (
        <ResizeObserver
98
            onResize={({ width }) => {
99 100 101 102 103 104
                setTableWidth(width);
            }}
        >
            <BasicTable
                {...props}
                size={'small'}
105
                className={`${theme==='BI'?'BI-':''}virtual-table`}
106 107 108 109 110 111 112 113 114
                columns={mergedColumns}
                pagination={false}
                components={{
                    body: renderVirtualList,
                }}
            />
        </ResizeObserver>
    );
};
115
export default VirtualTable;