UNPKG

baseui

Version:

A React Component library implementing the Base design language

794 lines (778 loc) • 29.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DataTable = DataTable; var React = _interopRequireWildcard(require("react")); var _reactWindow = require("react-window"); var _reactVirtualizedAutoSizer = _interopRequireDefault(require("react-virtualized-auto-sizer")); var _button = require("../button"); var _styles = require("../styles"); var _tooltip = require("../tooltip"); var _constants = require("./constants"); var _headerCell = _interopRequireDefault(require("./header-cell")); var _measureColumnWidths = _interopRequireDefault(require("./measure-column-widths")); var _locale = require("../locale"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } /* Copyright (c) Uber Technologies, Inc. This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. */ // @ts-ignore // consider pulling this out to a prop if useful. const HEADER_ROW_HEIGHT = 48; // @ts-ignore const sum = ns => ns.reduce((s, n) => s + n, 0); function CellPlacement({ columnIndex, rowIndex, data, style }) { const [css, theme] = (0, _styles.useStyletron)(); // ignores the table header row if (rowIndex === 0) { return null; } let backgroundColor = theme.colors.backgroundPrimary; if (Boolean(rowIndex % 2) && columnIndex === data.columnHighlightIndex || rowIndex === data.rowHighlightIndex) { backgroundColor = theme.colors.backgroundTertiary; } else if (rowIndex % 2 || columnIndex === data.columnHighlightIndex) { backgroundColor = theme.colors.backgroundSecondary; } const Cell = data.columns[columnIndex].renderCell; const value = data.columns[columnIndex].mapDataToValue(data.rows[rowIndex - 1].data); return /*#__PURE__*/React.createElement("div", { className: css({ ...theme.borders.border200, backgroundColor, borderTop: 'none', borderBottom: 'none', borderLeft: 'none', // do not render a border on cells in the right-most column // @ts-ignore borderRight: columnIndex === data.columns.length - 1 ? 'none' : null, boxSizing: 'border-box' }), style: style, onMouseEnter: () => data.onRowMouseEnter(rowIndex, data.rows[rowIndex - 1]) }, /*#__PURE__*/React.createElement(Cell, { value: value, onSelect: data.isSelectable && columnIndex === 0 ? () => data.onSelectOne(data.rows[rowIndex - 1]) : undefined, isSelected: data.isRowSelected(data.rows[rowIndex - 1].id), textQuery: data.textQuery, x: columnIndex, y: rowIndex - 1 })); } // @ts-ignore function compareCellPlacement(prevProps, nextProps) { // header cells are not rendered through this component if (prevProps.rowIndex === 0) { return true; } if (prevProps.data.columns !== nextProps.data.columns || prevProps.data.rows !== nextProps.data.rows || prevProps.style !== nextProps.style) { return false; } if (prevProps.data.isSelectable === nextProps.data.isSelectable && prevProps.data.columnHighlightIndex === nextProps.data.columnHighlightIndex && prevProps.data.rowHighlightIndex === nextProps.data.rowHighlightIndex && prevProps.data.textQuery === nextProps.data.textQuery && prevProps.data.isRowSelected === nextProps.data.isRowSelected) { return true; } // at this point we know that the rowHighlightIndex or the columnHighlightIndex has changed. // row does not need to re-render if not transitioning _from_ or _to_ highlighted // also ensures that all cells are invalidated on column-header hover if (prevProps.rowIndex !== prevProps.data.rowHighlightIndex && prevProps.rowIndex !== nextProps.data.rowHighlightIndex && prevProps.data.columnHighlightIndex === nextProps.data.columnHighlightIndex && prevProps.data.isRowSelected === nextProps.data.isRowSelected) { return true; } // similar to the row highlight optimization, do not update the cell if not in the previously // highlighted column or next highlighted. if (prevProps.columnIndex !== prevProps.data.columnHighlightIndex && prevProps.columnIndex !== nextProps.data.columnHighlightIndex && prevProps.data.rowHighlightIndex === nextProps.data.rowHighlightIndex && prevProps.data.isRowSelected === nextProps.data.isRowSelected) { return true; } return false; } const CellPlacementMemo = /*#__PURE__*/React.memo(CellPlacement, compareCellPlacement); CellPlacementMemo.displayName = 'CellPlacement'; const HeaderContext = /*#__PURE__*/React.createContext({ columns: [], columnHighlightIndex: -1, emptyMessage: '', filters: new Map(), loading: false, loadingMessage: '', isScrollingX: false, isSelectable: false, isSelectedAll: false, isSelectedIndeterminate: false, measuredWidths: [], onMouseEnter: () => {}, onMouseLeave: () => {}, onResize: () => {}, onSelectMany: () => {}, onSelectNone: () => {}, onSort: () => {}, resizableColumnWidths: false, rowActions: [], rowHeight: 0, rowHighlightIndex: -1, rows: [], scrollLeft: 0, sortIndex: -1, // @ts-ignore sortDirection: null, tableHeight: 0, widths: [] }); HeaderContext.displayName = 'HeaderContext'; function Header(props) { const [css, theme] = (0, _styles.useStyletron)(); const [startResizePos, setStartResizePos] = React.useState(0); const [endResizePos, setEndResizePos] = React.useState(0); // eslint-disable-next-line @typescript-eslint/no-explicit-any const headerCellRef = React.useRef(null); const RULER_OFFSET = 2; const isResizingThisColumn = props.resizeIndex === props.index; const isResizing = props.resizeIndex >= 0; // @ts-ignore function getPositionX(el) { if (typeof document !== 'undefined') { const rect = el.getBoundingClientRect(); return rect.left + window.scrollX; } return 0; } React.useLayoutEffect(() => { function handleMouseMove(event) { if (isResizingThisColumn) { event.preventDefault(); if (headerCellRef.current) { const left = getPositionX(headerCellRef.current); const width = event.clientX - left - 5; const max = Math.ceil(props.resizeMaxWidth); const min = Math.ceil(props.resizeMinWidth); if (min === max) { return; } if (width >= min && width <= max) { setEndResizePos(event.clientX - RULER_OFFSET); } if (width < min) { setEndResizePos(left + min - RULER_OFFSET); } if (width > max) { setEndResizePos(max - width - RULER_OFFSET); } } } } // eslint-disable-next-line @typescript-eslint/no-unused-vars function handleMouseUp(event) { props.onResize(props.index, endResizePos - startResizePos); props.onResizeIndexChange(-1); setStartResizePos(0); setEndResizePos(0); } if (typeof document !== 'undefined') { if (isResizingThisColumn) { document.addEventListener('mousemove', handleMouseMove); document.addEventListener('mouseup', handleMouseUp); } } return () => { if (typeof document !== 'undefined') { document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mouseup', handleMouseUp); } }; }, [isResizingThisColumn, setEndResizePos, setStartResizePos, setEndResizePos, props.onResize, props.onResizeIndexChange, props.index, endResizePos, startResizePos, headerCellRef.current]); return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(_headerCell.default, { ref: headerCellRef, index: props.index, sortable: props.isSortable, isHovered: !isResizing && props.hoverIndex === props.index, isSelectable: props.isSelectable && props.index === 0, isSelectedAll: props.isSelectedAll, isSelectedIndeterminate: props.isSelectedIndeterminate, onMouseEnter: () => { if (!isResizing) { props.onMouseEnter(props.index); } }, onMouseLeave: () => { if (!isResizing) { props.onMouseLeave(); } }, onSelectAll: props.onSelectMany, onSelectNone: props.onSelectNone, onSort: props.onSort // @ts-ignore , sortDirection: props.sortIndex === props.index ? props.sortDirection : null, title: props.columnTitle }), props.resizableColumnWidths && /*#__PURE__*/React.createElement("div", { className: css({ position: 'relative', display: 'flex', alignItems: 'center' }) }, /*#__PURE__*/React.createElement("div", { role: "presentation", onMouseDown: event => { props.onResizeIndexChange(props.index); const x = getPositionX(event.target); setStartResizePos(x); setEndResizePos(x); }, className: css({ // @ts-ignore backgroundColor: isResizingThisColumn ? theme.colors.contentPrimary : null, cursor: 'ew-resize', position: 'absolute', height: '100%', width: '3px', ':hover': { backgroundColor: theme.colors.contentPrimary } }), style: { right: `${(RULER_OFFSET + endResizePos - startResizePos) * -1}px` } }, isResizingThisColumn && /*#__PURE__*/React.createElement("div", { className: css({ backgroundColor: theme.colors.contentPrimary, position: 'absolute', height: `${props.tableHeight}px`, right: '1px', width: '1px' }) })))); } function Headers() { const [css, theme] = (0, _styles.useStyletron)(); const locale = React.useContext(_locale.LocaleContext); const ctx = React.useContext(HeaderContext); const [resizeIndex, setResizeIndex] = React.useState(-1); return /*#__PURE__*/React.createElement("div", { className: css({ position: 'sticky', top: 0, left: 0, width: `${sum(ctx.widths)}px`, height: `${HEADER_ROW_HEIGHT}px`, display: 'flex', // this feels bad.. the absolutely positioned children elements // stack on top of this element with the layer component. zIndex: 2 }) }, ctx.columns.map((column, columnIndex) => { const activeFilter = ctx.filters ? ctx.filters.get(column.title) : null; return /*#__PURE__*/React.createElement(React.Fragment, { key: columnIndex }, /*#__PURE__*/React.createElement(_tooltip.Tooltip, { key: columnIndex, placement: _tooltip.PLACEMENT.bottomLeft, isOpen: ctx.columnHighlightIndex === columnIndex && Boolean(activeFilter), content: () => { return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("p", { className: css({ ...theme.typography.font100, color: theme.colors.contentInversePrimary }) }, locale.datatable.filterAppliedTo, " ", column.title), activeFilter && /*#__PURE__*/React.createElement("p", { className: css({ ...theme.typography.font150, color: theme.colors.contentInversePrimary }) }, activeFilter.description)); } }, /*#__PURE__*/React.createElement("div", { className: css({ ...theme.borders.border200, backgroundColor: theme.colors.backgroundPrimary, borderTop: 'none', borderLeft: 'none', // @ts-ignore borderRight: columnIndex === ctx.columns.length - 1 ? 'none' : null, boxSizing: 'border-box', display: 'flex' }), style: { width: ctx.widths[columnIndex] } }, /*#__PURE__*/React.createElement(Header, { columnTitle: column.title, hoverIndex: ctx.columnHighlightIndex, index: columnIndex, isSortable: column.sortable, isSelectable: ctx.isSelectable, isSelectedAll: ctx.isSelectedAll, isSelectedIndeterminate: ctx.isSelectedIndeterminate, onMouseEnter: ctx.onMouseEnter, onMouseLeave: ctx.onMouseLeave, onResize: ctx.onResize, onResizeIndexChange: setResizeIndex, onSelectMany: ctx.onSelectMany, onSelectNone: ctx.onSelectNone, onSort: () => ctx.onSort(columnIndex), resizableColumnWidths: ctx.resizableColumnWidths, resizeIndex: resizeIndex, resizeMinWidth: ctx.measuredWidths[columnIndex], resizeMaxWidth: column.maxWidth || Infinity, sortIndex: ctx.sortIndex, sortDirection: ctx.sortDirection, tableHeight: ctx.tableHeight })))); })); } // @ts-ignore function LoadingOrEmptyMessage(props) { const [css, theme] = (0, _styles.useStyletron)(); return /*#__PURE__*/React.createElement("p", { className: css({ ...theme.typography.ParagraphSmall, color: theme.colors.contentPrimary, marginLeft: theme.sizing.scale500 }) }, typeof props.children === 'function' ? props.children() : String(props.children)); } // replaces the content of the virtualized window with contents. in this case, // we are prepending a table header row before the table rows (children to the fn). const InnerTableElement = /*#__PURE__*/React.forwardRef((props, ref) => { const [, theme] = (0, _styles.useStyletron)(); const ctx = React.useContext(HeaderContext); // no need to render the cells until the columns have been measured if (!ctx.widths.filter(Boolean).length) { return null; } const RENDERING = 0; const LOADING = 1; const EMPTY = 2; let viewState = RENDERING; if (ctx.loading) { viewState = LOADING; } else if (ctx.rows.length === 0) { viewState = EMPTY; } const highlightedRow = ctx.rows[ctx.rowHighlightIndex - 1]; return /*#__PURE__*/React.createElement("div", { ref: ref, "data-baseweb": "data-table", style: props.style }, /*#__PURE__*/React.createElement(Headers, null), viewState === LOADING && /*#__PURE__*/React.createElement(LoadingOrEmptyMessage, null, ctx.loadingMessage), viewState === EMPTY && /*#__PURE__*/React.createElement(LoadingOrEmptyMessage, null, ctx.emptyMessage), viewState === RENDERING && props.children, ctx.rowActions && Boolean(ctx.rowActions.length) && ctx.rowHighlightIndex > 0 && Boolean(highlightedRow) && !ctx.isScrollingX && /*#__PURE__*/React.createElement("div", { style: { alignItems: 'center', backgroundColor: theme.colors.backgroundTertiary, display: 'flex', height: `${ctx.rowHeight}px`, padding: '0 16px', paddingLeft: theme.sizing.scale300, paddingRight: theme.sizing.scale300, position: 'absolute', right: theme.direction !== 'rtl' ? 0 - ctx.scrollLeft : 'initial', left: theme.direction === 'rtl' ? 0 : 'initial', top: (ctx.rowHighlightIndex - 1) * ctx.rowHeight + HEADER_ROW_HEIGHT } }, (typeof ctx.rowActions === 'function' ? ctx.rowActions(highlightedRow) : ctx.rowActions).map(rowAction => { if (rowAction.renderButton) { const RowActionButton = rowAction.renderButton; return /*#__PURE__*/React.createElement(RowActionButton, null); } const RowActionIcon = rowAction.renderIcon; return /*#__PURE__*/React.createElement(_button.Button, { key: rowAction.label, onClick: event => rowAction.onClick({ event, row: ctx.rows[ctx.rowHighlightIndex - 1] }), size: _button.SIZE.compact, kind: _button.KIND.tertiary, shape: _button.SHAPE.round, title: rowAction.label, overrides: { BaseButton: { style: { marginLeft: theme.sizing.scale300, paddingTop: theme.sizing.scale100, paddingRight: theme.sizing.scale100, paddingBottom: theme.sizing.scale100, paddingLeft: theme.sizing.scale100 } } } }, /*#__PURE__*/React.createElement(RowActionIcon, { size: 24 })); }))); }); InnerTableElement.displayName = 'InnerTableElement'; // @ts-ignore function MeasureScrollbarWidth(props) { const [css] = (0, _styles.useStyletron)(); const outerRef = React.useRef(); const innerRef = React.useRef(); React.useEffect(() => { if (outerRef.current && innerRef.current) { const width = outerRef.current.offsetWidth - innerRef.current.offsetWidth; props.onWidthChange(width); } }, [outerRef.current, innerRef.current]); return /*#__PURE__*/React.createElement("div", { className: css({ height: 0, visibility: 'hidden', overflow: 'scroll' }) // @ts-ignore , ref: outerRef }, /*#__PURE__*/React.createElement("div", { ref: innerRef })); } function DataTable({ selectable, batchActions, columns, filters, emptyMessage, loading, loadingMessage, onIncludedRowsChange, onRowHighlightChange, onSelectMany, onSelectNone, onSelectOne, onSort, resizableColumnWidths = false, rows: allRows, rowActions = [], rowHeight = 36, rowHighlightIndex: rowHighlightIndexControlled, selectedRowIds, sortIndex, sortDirection, textQuery = '', controlRef }) { const [, theme] = (0, _styles.useStyletron)(); const locale = React.useContext(_locale.LocaleContext); const rowHeightAtIndex = React.useCallback(index => { if (index === 0) { return HEADER_ROW_HEIGHT; } return rowHeight; }, [rowHeight]); // We use state for our ref, to allow hooks to update when the ref changes. const [gridRef, setGridRef] = React.useState(null); const [measuredWidths, setMeasuredWidths] = React.useState(columns.map(() => 0)); const [resizeDeltas, setResizeDeltas] = React.useState(columns.map(() => 0)); React.useEffect(() => { setMeasuredWidths(prev => { return columns.map((v, index) => prev[index] || 0); }); setResizeDeltas(prev => { return columns.map((v, index) => prev[index] || 0); }); }, [columns]); const resetAfterColumnIndex = React.useCallback(columnIndex => { if (gridRef) { // trigger react-window to layout the elements again gridRef.resetAfterColumnIndex(columnIndex, true); } }, [gridRef]); const handleWidthsChange = React.useCallback(nextWidths => { setMeasuredWidths(nextWidths); resetAfterColumnIndex(0); }, [setMeasuredWidths, resetAfterColumnIndex]); const handleColumnResize = React.useCallback((columnIndex, delta) => { setResizeDeltas(prev => { prev[columnIndex] = Math.max(prev[columnIndex] + delta, 0); return [...prev]; }); resetAfterColumnIndex(columnIndex); }, [setResizeDeltas, resetAfterColumnIndex]); const [scrollLeft, setScrollLeft] = React.useState(0); const [isScrollingX, setIsScrollingX] = React.useState(false); const [recentlyScrolledX, setRecentlyScrolledX] = React.useState(false); React.useLayoutEffect(() => { if (recentlyScrolledX !== isScrollingX) { setIsScrollingX(recentlyScrolledX); } if (recentlyScrolledX) { const timeout = setTimeout(() => { setRecentlyScrolledX(false); }, 200); return () => clearTimeout(timeout); } }, [recentlyScrolledX]); const handleScroll = React.useCallback(params => { setScrollLeft(params.scrollLeft); if (params.scrollLeft !== scrollLeft) { setRecentlyScrolledX(true); } }, [scrollLeft, setScrollLeft, setRecentlyScrolledX]); const sortedIndices = React.useMemo(() => { let toSort = allRows.map((r, i) => [r, i]); const index = sortIndex; if (index !== null && index !== undefined && index !== -1 && columns[index]) { const sortFn = columns[index].sortFn; // @ts-ignore const getValue = row => columns[index].mapDataToValue(row.data); if (sortDirection === _constants.SORT_DIRECTIONS.ASC) { toSort.sort((a, b) => sortFn(getValue(a[0]), getValue(b[0]))); } else if (sortDirection === _constants.SORT_DIRECTIONS.DESC) { toSort.sort((a, b) => sortFn(getValue(b[0]), getValue(a[0]))); } } return toSort.map(el => el[1]); }, [sortIndex, sortDirection, columns, allRows]); const filteredIndices = React.useMemo(() => { const set = new Set(allRows.map((_, idx) => idx)); // @ts-ignore Array.from(filters || new Set(), f => f).forEach(([title, filter]) => { const columnIndex = columns.findIndex(c => c.title === title); const column = columns[columnIndex]; if (!column) { return; } const filterFn = column.buildFilter(filter); Array.from(set).forEach(idx => { if (!filterFn(column.mapDataToValue(allRows[idx].data))) { set.delete(idx); } }); }); if (textQuery) { // @ts-ignore const stringishColumnIndices = []; for (let i = 0; i < columns.length; i++) { if (columns[i].textQueryFilter) { // @ts-ignore stringishColumnIndices.push(i); } } Array.from(set).forEach(idx => { // @ts-ignore const matches = stringishColumnIndices.some(cdx => { const column = columns[cdx]; const textQueryFilter = column.textQueryFilter; if (textQueryFilter) { return textQueryFilter(textQuery, column.mapDataToValue(allRows[idx].data)); } return false; }); if (!matches) { set.delete(idx); } }); } return set; }, [filters, textQuery, columns, allRows]); const rows = React.useMemo(() => { const result = sortedIndices.filter(idx => filteredIndices.has(idx)).map(idx => allRows[idx]); if (onIncludedRowsChange) { onIncludedRowsChange(result); } return result; }, [sortedIndices, filteredIndices, onIncludedRowsChange, allRows]); const [browserScrollbarWidth, setBrowserScrollbarWidth] = React.useState(0); const normalizedWidths = React.useMemo(() => { const resizedWidths = measuredWidths.map((w, i) => Math.floor(w) + Math.floor(resizeDeltas[i])); if (gridRef) { const gridProps = gridRef.props; let isContentTallerThanContainer = false; let visibleRowHeight = 0; for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) { visibleRowHeight += rowHeightAtIndex(rowIndex); if (visibleRowHeight >= gridProps.height) { isContentTallerThanContainer = true; break; } } const scrollbarWidth = isContentTallerThanContainer ? browserScrollbarWidth : 0; const remainder = gridProps.width - sum(resizedWidths) - scrollbarWidth; const padding = Math.floor(remainder / columns.filter(c => c ? c.fillWidth : true).length); if (padding > 0) { const result = []; // -1 so that we loop over all but the last item for (let i = 0; i < resizedWidths.length - 1; i++) { if (columns[i] && columns[i].fillWidth) { // @ts-ignore result.push(resizedWidths[i] + padding); } else { // @ts-ignore result.push(resizedWidths[i]); } } // @ts-ignore result.push(gridProps.width - sum(result) - scrollbarWidth); return result; } } return resizedWidths; }, [gridRef, measuredWidths, resizeDeltas, browserScrollbarWidth, rows.length, columns]); React.useEffect(() => { resetAfterColumnIndex(0); }, [normalizedWidths]); const isSelectable = (batchActions ? !!batchActions.length : false) || !!selectable; const isSelectedAll = React.useMemo(() => { if (!selectedRowIds) { return false; } return !!rows.length && selectedRowIds.size >= rows.length; }, [selectedRowIds, rows.length]); const isSelectedIndeterminate = React.useMemo(() => { if (!selectedRowIds) { return false; } return !!selectedRowIds.size && selectedRowIds.size < rows.length; }, [selectedRowIds, rows.length]); const isRowSelected = React.useCallback(id => { if (selectedRowIds) { return selectedRowIds.has(id); } return false; }, [selectedRowIds]); const handleSelectMany = React.useCallback(() => { if (onSelectMany) { onSelectMany(rows); } }, [rows, onSelectMany]); const handleSelectNone = React.useCallback(() => { if (onSelectNone) { onSelectNone(); } }, [onSelectNone]); const handleSelectOne = React.useCallback(row => { if (onSelectOne) { onSelectOne(row); } }, [onSelectOne]); const handleSort = React.useCallback(columnIndex => { if (onSort) { onSort(columnIndex); } }, [onSort]); React.useImperativeHandle(controlRef, () => ({ clearSelection: handleSelectNone, getRows: () => rows }), [handleSelectNone, rows]); const [columnHighlightIndex, setColumnHighlightIndex] = React.useState(-1); const [rowHighlightIndex, setRowHighlightIndex] = React.useState(-1); // @ts-ignore function handleRowHighlightIndexChange(nextIndex) { setRowHighlightIndex(nextIndex); if (gridRef) { if (nextIndex >= 0) { gridRef.scrollToItem({ rowIndex: nextIndex }); } if (onRowHighlightChange) { onRowHighlightChange(nextIndex, rows[nextIndex - 1]); } } } const handleRowMouseEnter = React.useCallback(nextIndex => { setColumnHighlightIndex(-1); if (nextIndex !== rowHighlightIndex) { handleRowHighlightIndexChange(nextIndex); } }, [rowHighlightIndex]); // @ts-ignore function handleColumnHeaderMouseEnter(columnIndex) { setColumnHighlightIndex(columnIndex); handleRowHighlightIndexChange(-1); } function handleColumnHeaderMouseLeave() { setColumnHighlightIndex(-1); } React.useEffect(() => { if (typeof rowHighlightIndexControlled === 'number') { handleRowHighlightIndexChange(rowHighlightIndexControlled); } }, [rowHighlightIndexControlled]); const itemData = React.useMemo(() => { return { columnHighlightIndex, rowHighlightIndex, isRowSelected, isSelectable, onRowMouseEnter: handleRowMouseEnter, onSelectOne: handleSelectOne, columns: columns, rows, textQuery }; }, [handleRowMouseEnter, columnHighlightIndex, isRowSelected, isSelectable, rowHighlightIndex, rows, columns, handleSelectOne, textQuery]); return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(_measureColumnWidths.default, { columns: columns, rows: rows, widths: measuredWidths, isSelectable: isSelectable, onWidthsChange: handleWidthsChange }), /*#__PURE__*/React.createElement(MeasureScrollbarWidth // @ts-ignore , { onWidthChange: w => setBrowserScrollbarWidth(w) }), /*#__PURE__*/React.createElement(_reactVirtualizedAutoSizer.default, null, ({ height, width }) => /*#__PURE__*/React.createElement(HeaderContext.Provider, { value: { columns: columns, columnHighlightIndex, emptyMessage: emptyMessage || locale.datatable.emptyState, filters: filters, loading: Boolean(loading), loadingMessage: loadingMessage || locale.datatable.loadingState, isScrollingX, isSelectable, isSelectedAll, isSelectedIndeterminate, measuredWidths, onMouseEnter: handleColumnHeaderMouseEnter, onMouseLeave: handleColumnHeaderMouseLeave, onResize: handleColumnResize, onSelectMany: handleSelectMany, onSelectNone: handleSelectNone, onSort: handleSort, resizableColumnWidths, rowActions, rowHeight, rowHighlightIndex, rows, scrollLeft, // @ts-ignore sortDirection: sortDirection || null, sortIndex: typeof sortIndex === 'number' ? sortIndex : -1, tableHeight: height, widths: normalizedWidths } }, /*#__PURE__*/React.createElement(_reactWindow.VariableSizeGrid // eslint-disable-next-line @typescript-eslint/no-explicit-any , { ref: node => setGridRef(node), overscanRowCount: 10, overscanColumnCount: 5, innerElementType: InnerTableElement, columnCount: columns.length, columnWidth: columnIndex => normalizedWidths[columnIndex], height: height - 2 // plus one to account for additional header row , rowCount: rows.length + 1, rowHeight: rowHeightAtIndex, width: width - 2, itemData: itemData, onScroll: handleScroll, style: { ...theme.borders.border200, borderColor: theme.colors.borderOpaque }, direction: theme.direction === 'rtl' ? 'rtl' : 'ltr' }, CellPlacementMemo)))); }