UNPKG

es-grid-template

Version:

es-grid-template

361 lines (347 loc) 13.1 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import React from 'react'; import classNames from 'classnames'; import { TableContext } from "./useContext"; import Pagination from 'rc-master-ui/es/pagination'; import { Toolbar } from 'rc-master-ui'; import { Maximize, Minimize } from 'becoxy-icons'; import { ColumnsChoose } from "./ColumnsChoose"; import { numericFormatter } from 'react-numeric-component'; import TableWrapper from "./table/TableWrapper"; import { getTableHeight, sumSize, updateColumnWidthsRecursive } from "./hook/utils"; import { useVirtualizer } from '@tanstack/react-virtual'; import { useLocale } from "rc-master-ui/es/locale"; const TableContainer = props => { const { t, table, id, prefix, commandClick, editAble, rowKey, format, dataSource, originData, expandable, wrapSettings, recordDoubleClick, // triggerFilter, selectionSettings, isSelectionChange, setIsSelectionChange, onContextMenu, contextMenuItems, setSorterChange, setFilterChange, height, minHeight, showToolbar, toolbarItems, actionTemplate, pagination, fullScreen, showColumnChoose, summary, locale, lang, groupColumns, columns, propsColumns, triggerChangeColumns, columnHidden, expanded, setExpanded, showEmptyText, infiniteScroll, next, loading, windowSize, contextMenuOpen, contextMenuClick, contextMenuHidden, isFullScreen, setIsFullScreen, isDataTree, setColumns, columnSizing, columnSizingInfo, rowClassName, onRowStyles, onRowFooterStyles, onRowHeaderStyles, title, dataSourceFilter, onExpandClick, setIsExpandClick, recordClick, ...rest } = props; const [paginationLocal] = useLocale('Pagination'); const [tableLocal] = useLocale('Table'); const tableContainerRef = React.useRef(null); const containerRef = React.useRef(null); const bottomToolbarRef = React.useRef(null); const topToolbarRef = React.useRef(null); const [tableHeight, settableHeight] = React.useState(0); const [focusedCell, setFocusedCell] = React.useState(undefined); React.useEffect(() => { // const totalHeight = minHeight ?? height const totalHeight = getTableHeight(height, minHeight); if (totalHeight) { const topHeight = topToolbarRef.current ? topToolbarRef.current.offsetHeight : 0; const bottomHeight = bottomToolbarRef.current ? bottomToolbarRef.current.offsetHeight : 0; settableHeight(totalHeight - topHeight - bottomHeight); } }, [id, height, editAble, minHeight]); React.useEffect(() => { const handleClickOutside = event => { const element = event.target; const container = document.querySelector(".be-popup-container"); const containerContextMenu = document.querySelector(".popup-context-menu"); const tableBody = document.querySelector(`#${id} .ui-rc-grid-tbody`); const itemContainer = document.querySelector(`#${id} .ui-rc-toolbar-selection-overflow-item`); const itemHeader = document.querySelector(`#${id} .ui-rc-table-thead`); const isInsideContainer = element.closest(".be-popup-container") && container; const isInsideContainerContext = containerContextMenu && element.closest(".popup-context-menu"); const isInsideToolbar = element.closest(`.ui-rc-toolbar-selection-overflow-item`) && itemContainer; const isInsideHeader = itemHeader && itemHeader.contains(event.target); if (isInsideContainer || isInsideToolbar || isInsideHeader || isInsideContainerContext || element.id === id) { return; } if (containerRef.current && tableBody && !tableBody.contains(event.target)) { setFocusedCell(undefined); setIsSelectionChange(prev => ({ ...prev, isChange: false })); } }; document.addEventListener('mousedown', handleClickOutside); return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, []); const visibleColumns = table.getVisibleLeafColumns(); const fixedLeftColumns = table.getState().columnPinning.left ? visibleColumns.filter(vc => table.getState().columnPinning.left?.includes(vc.id)) : []; const fixedRightColumns = table.getState().columnPinning.right ? visibleColumns.filter(vc => table.getState().columnPinning.right?.includes(vc.id)) : []; //we are using a slightly different virtualization strategy for columns (compared to virtual rows) in order to support dynamic row heights const columnVirtualizer = useVirtualizer({ count: visibleColumns.length, estimateSize: index => visibleColumns[index].getSize(), //estimate width of each column for accurate scrollbar dragging getScrollElement: () => tableContainerRef.current, horizontal: true, // measureElement(element) { // return element?.getBoundingClientRect().width; // }, measureElement: typeof window !== 'undefined' && navigator.userAgent.indexOf('Firefox') === -1 ? element => element?.getBoundingClientRect().height : undefined, overscan: 3 //how many columns to render on each side off screen each way (adjust this for performance) }); const virtualColumns = columnVirtualizer.getVirtualItems(); const cacheColumns = columnVirtualizer.measurementsCache; const rightCols = table.getState().columnPinning.right?.length ? [...cacheColumns].slice(-(table.getState().columnPinning.right?.length ?? 0)) : []; const leftCols = [...cacheColumns].slice(0, table.getState().columnPinning.left?.length ?? 0); const rightWidth = sumSize(rightCols); const leftWidth = sumSize(leftCols); //different virtualization strategy for columns - instead of absolute and translateY, we add empty columns to the left and right let virtualPaddingLeft; let virtualPaddingRight; const pdRight = columnVirtualizer.getTotalSize() - (virtualColumns[virtualColumns.length - 1]?.end ?? 0); if (columnVirtualizer && virtualColumns?.length) { virtualPaddingLeft = fixedLeftColumns && fixedLeftColumns.length > 0 ? (virtualColumns[0]?.start ?? 0) - leftWidth > 0 ? (virtualColumns[0]?.start ?? 0) - leftWidth : 0 : virtualColumns[0]?.start ?? 0; // virtualPaddingLeft = leftCols.length === rss.length ? (virtualColumns[0]?.start ?? 0) : 0; // columnVirtualizer.getTotalSize() - (virtualColumns[virtualColumns.length - 1]?.end ?? 0) - rightWidth > 0 ? columnVirtualizer.getTotalSize() - (virtualColumns[virtualColumns.length - 1]?.end ?? 0) - rightWidth : 0; virtualPaddingRight = fixedRightColumns && fixedRightColumns.length > 0 ? pdRight - rightWidth > 0 ? pdRight - rightWidth : 0 : pdRight; // virtualPaddingRight = columnVirtualizer.getTotalSize() - (virtualColumns[virtualColumns.length - 1]?.end ?? 0) } const columnSizingState = table.getState().columnSizing; React.useEffect(() => { requestAnimationFrame(() => { columnVirtualizer.measure(); }); }, [columnSizingState, columnVirtualizer]); React.useEffect(() => { if (!tableContainerRef.current) { return; } // const containerWidth = tableContainerRef.current.offsetWidth // const totalWidth = table.getTotalSize() // if (totalWidth && totalWidth <= containerWidth) { // return // } if (columnSizingInfo.isResizingColumn === false) { const aa = updateColumnWidthsRecursive(propsColumns, columnSizing); setColumns(aa); // requestAnimationFrame(() => { // columnVirtualizer.measure() // }) } }, [columnSizingInfo]); const triggerCommandClick = args => { // const { id: idCommand, rowId, rowData, index } = args // const tmpData = [...dataSource] if (commandClick) { commandClick({ ...args, rows: originData }); } }; return /*#__PURE__*/React.createElement("div", { ref: containerRef, id: id }, (showToolbar !== false || fullScreen !== false || title) && /*#__PURE__*/React.createElement("div", { ref: topToolbarRef, className: classNames(`${prefix}-grid-top-toolbar`, {}) }, /*#__PURE__*/React.createElement("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' } }, /*#__PURE__*/React.createElement("div", { style: { flex: 1, overflow: 'hidden' } }, /*#__PURE__*/React.createElement(Toolbar, { items: (toolbarItems ?? []).filter(it => it.position !== 'Bottom'), mode: 'scroll' })), /*#__PURE__*/React.createElement("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: '.25rem' } }, pagination && pagination.onChange && pagination?.position && pagination?.position[0] === 'topRight' && /*#__PURE__*/React.createElement(Pagination, _extends({ showSizeChanger: true, responsive: true, size: 'small', rootClassName: 'top-pagination', showTotal: (totalItems, range) => // @ts-ignore `${range[0]}-${range[1]} / ${totalItems} ${t ? t(pagination?.locale?.items ?? 'items') : 'items'}` }, pagination)), typeof actionTemplate === 'function' ? actionTemplate() : actionTemplate, fullScreen !== false && (isFullScreen ? /*#__PURE__*/React.createElement(Minimize, { fontSize: 16, onClick: () => { setIsFullScreen(!isFullScreen); }, "data-tooltip-id": `${id}-tooltip-content`, "data-tooltip-content": locale?.table?.minimized || tableLocal?.minimized || 'Minimized' }) : /*#__PURE__*/React.createElement(Maximize, { fontSize: 16, onClick: () => { setIsFullScreen(!isFullScreen); }, "data-tooltip-id": `${id}-tooltip-content`, "data-tooltip-content": locale?.table?.fullScreen || tableLocal?.fullScreen || 'Full screen' })), showColumnChoose && /*#__PURE__*/React.createElement(ColumnsChoose, { id: id, table: table, locale: locale, tableLocal: tableLocal, columnHidden: columnHidden, columns: columns, originColumns: propsColumns, t: t, columnsGroup: groupColumns, triggerChangeColumns: triggerChangeColumns }))), /*#__PURE__*/React.createElement("div", { style: { textAlign: 'center' } }, typeof title === 'function' ? title?.(originData) : title)), /*#__PURE__*/React.createElement(TableContext.Provider, { value: { t, locale, lang, prefix, id, rowKey, format, expandable, expanded, setExpanded, dataSource, originData, // triggerFilter, wrapSettings, recordDoubleClick, recordClick, selectionSettings, isSelectionChange, setIsSelectionChange, onContextMenu, setSorterChange, setFilterChange, windowSize, isDataTree, focusedCell, setFocusedCell, rowClassName, onRowStyles, onRowFooterStyles, onRowHeaderStyles, table, pagination, dataSourceFilter, onExpandClick, setIsExpandClick } }, /*#__PURE__*/React.createElement(TableWrapper, _extends({}, rest, { contextMenuItems: contextMenuItems, height: tableHeight, minHeight: minHeight, id: id, prefix: prefix, table: table, tableContainerRef: tableContainerRef, commandClick: triggerCommandClick, contextMenuClick: contextMenuClick, contextMenuHidden: contextMenuHidden, contextMenuOpen: contextMenuOpen, editAble: editAble, showEmptyText: showEmptyText, summary: summary, dataSource: dataSource, infiniteScroll: infiniteScroll, next: next, loading: loading, columnVirtualizer: columnVirtualizer, virtualPaddingLeft: virtualPaddingLeft, virtualPaddingRight: virtualPaddingRight, fixedLeftColumns: fixedLeftColumns, fixedRightColumns: fixedRightColumns }))), /*#__PURE__*/React.createElement("div", { ref: bottomToolbarRef }, pagination && !infiniteScroll && /*#__PURE__*/React.createElement(Pagination, _extends({ pageSizeOptions: [20, 50, 100, 1000, 10000], rootClassName: 'pagination-template', showSizeChanger: true, size: 'small', total: pagination.total, pageSize: pagination.onChange ? pagination.pageSize : table.getState().pagination.pageSize, showTotal: (totalItems, range) => `${numericFormatter((range[0] ?? 0).toString(), { thousandSeparator: '.' })}-${numericFormatter((range[1] ?? 0).toString(), { thousandSeparator: '.' })} / ${numericFormatter((totalItems ?? 0).toString(), { thousandSeparator: '.' })} ${pagination?.locale?.items || paginationLocal?.items || ''}` }, pagination, { onChange: (page, pageSize1) => { if (pagination.onChange) { pagination.onChange(page, pageSize1); table.setPageIndex(page - 1); table.setPageSize(pageSize1); } else { table.setPageIndex(page - 1); table.setPageSize(pageSize1); } }, responsive: true })))); }; export default TableContainer;