UNPKG

@ui5/webcomponents-react

Version:

React Wrapper for UI5 Web Components and additional components

121 lines (120 loc) 3.79 kB
import { enrichEventWithDetails } from '@ui5/webcomponents-react-base'; import { DEFAULT_COLUMN_WIDTH } from '../defaults/Column/index.js'; import { CELL_PADDING_PX } from './useDynamicColumnWidths.js'; function setResizerProps(props, { instance, header }) { const { dispatch, virtualRowsRange, rows, webComponentsReactProperties } = instance; const { onAutoResize, tableRef, isTreeTable } = webComponentsReactProperties; const { autoResizable, id: accessor } = header; if (!document || !tableRef.current || !autoResizable || !rows.length || !virtualRowsRange) { return props; } return { ...props, onDoubleClick: e => { let largest = getMeasureMax(accessor, virtualRowsRange, tableRef.current, isTreeTable); if (largest === -1) { return; } largest = largest > DEFAULT_COLUMN_WIDTH ? largest : DEFAULT_COLUMN_WIDTH; if (typeof onAutoResize === 'function') { onAutoResize(enrichEventWithDetails(e, { columnId: accessor, width: largest })); } if (e.defaultPrevented) { return; } dispatch({ type: 'AUTO_RESIZE', payload: { [accessor]: largest } }); } }; } function calculateContentWidth(cell) { let contentWidth = 0; Array.from(cell.children).forEach(child => { contentWidth += child.scrollWidth; }); return contentWidth; } function getMeasureMax(accessor, virtualRowsRange, tableNode, isTreeTable) { let maxWidth = 0; let cellWithMaxWidthContent = null; /** * recursively find the largest visible cell of the current column */ function recursiveFindMaxWidth(row, accessor, remainingRows) { if (!row || remainingRows === 0) { return; } const cellNode = row.querySelector(`[data-column-id-cell="${accessor}"]`); const cellTextElement = cellNode?.querySelector(`[data-column-id-cell-text="${accessor}"]`); if (cellTextElement) { // for tree tables the indent (margin) has to be taken into account if (isTreeTable && cellNode?.dataset.isFirstColumn) { const cellWidth = calculateContentWidth(cellNode); if (maxWidth < cellWidth) { maxWidth = cellWidth; cellWithMaxWidthContent = false; } } else { const currWidth = cellTextElement.scrollWidth; if (maxWidth < currWidth) { maxWidth = currWidth; // only use the cell with the largest content for measuring cellWithMaxWidthContent = cellNode; } } } // if custom content (`Cell`) is rendered, the `cellTextElement` is not available. // In this case only the content of the first visible cell is used for measuring if (cellWithMaxWidthContent === null) { cellWithMaxWidthContent = cellNode; } recursiveFindMaxWidth(row.nextElementSibling, accessor, remainingRows - 1); } const firstRow = tableNode.querySelector(`[data-virtual-row-index="${virtualRowsRange.startIndex}"]`); recursiveFindMaxWidth(firstRow, accessor, virtualRowsRange.endIndex - virtualRowsRange.startIndex); if (cellWithMaxWidthContent === false) { return Math.ceil(maxWidth + CELL_PADDING_PX + 2 /* account for rounding error and border */); } if (!cellWithMaxWidthContent) { return -1; } return Math.ceil(calculateContentWidth(cellWithMaxWidthContent) + CELL_PADDING_PX + 2 /* account for rounding error and border */); } const setCellProps = (props, { cell: { column: { id } } }) => { return [props, { ['data-column-id-cell']: id }]; }; export const useAutoResize = hooks => { hooks.getResizerProps.push(setResizerProps); hooks.getCellProps.push(setCellProps); }; useAutoResize.pluginName = 'useAutoResize';