UNPKG

@mui/x-data-grid

Version:

The Community plan edition of the MUI X Data Grid components.

329 lines (327 loc) 16.2 kB
"use strict"; 'use client'; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.useGridColumnHeaders = exports.GridColumnHeaderRow = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var React = _interopRequireWildcard(require("react")); var _clsx = _interopRequireDefault(require("clsx")); var _styles = require("@mui/material/styles"); var _xVirtualizer = require("@mui/x-virtualizer"); var _utils = require("../../utils"); var _useGridRootProps = require("../../utils/useGridRootProps"); var _useGridPrivateApiContext = require("../../utils/useGridPrivateApiContext"); var _useGridEvent = require("../../utils/useGridEvent"); var _GridColumnHeaderItem = require("../../../components/columnHeaders/GridColumnHeaderItem"); var _gridDimensionsSelectors = require("../dimensions/gridDimensionsSelectors"); var _virtualization = require("../virtualization"); var _GridColumnGroupHeader = require("../../../components/columnHeaders/GridColumnGroupHeader"); var _columns = require("../columns"); var _gridColumnGroupsSelector = require("../columnGrouping/gridColumnGroupsSelector"); var _GridScrollbarFillerCell = require("../../../components/GridScrollbarFillerCell"); var _getPinnedCellOffset = require("../../../internals/utils/getPinnedCellOffset"); var _GridColumnHeaderSeparator = require("../../../components/columnHeaders/GridColumnHeaderSeparator"); var _gridClasses = require("../../../constants/gridClasses"); var _cellBorderUtils = require("../../../utils/cellBorderUtils"); var _constants = require("../../../internals/constants"); var _jsxRuntime = require("react/jsx-runtime"); const GridColumnHeaderRow = exports.GridColumnHeaderRow = (0, _styles.styled)('div', { name: 'MuiDataGrid', slot: 'ColumnHeaderRow' })({ display: 'flex' }); const useGridColumnHeaders = props => { const { visibleColumns, sortColumnLookup, filterColumnLookup, columnHeaderTabIndexState, columnGroupHeaderTabIndexState, columnHeaderFocus, columnGroupHeaderFocus, headerGroupingMaxDepth, columnMenuState, columnVisibility, columnGroupsHeaderStructure, hasOtherElementInTabSequence } = props; const [dragCol, setDragCol] = React.useState(''); const [resizeCol, setResizeCol] = React.useState(''); const apiRef = (0, _useGridPrivateApiContext.useGridPrivateApiContext)(); const rootProps = (0, _useGridRootProps.useGridRootProps)(); const columnGroupsModel = (0, _utils.useGridSelector)(apiRef, _gridColumnGroupsSelector.gridColumnGroupsUnwrappedModelSelector); const columnPositions = (0, _utils.useGridSelector)(apiRef, _columns.gridColumnPositionsSelector); const renderContext = (0, _utils.useGridSelector)(apiRef, _virtualization.gridRenderContextColumnsSelector); const pinnedColumns = (0, _utils.useGridSelector)(apiRef, _columns.gridVisiblePinnedColumnDefinitionsSelector); const columnsLookup = (0, _utils.useGridSelector)(apiRef, _columns.gridColumnLookupSelector); const offsetLeft = (0, _xVirtualizer.computeOffsetLeft)(columnPositions, renderContext, pinnedColumns.left.length); const columnsTotalWidth = (0, _utils.useGridSelector)(apiRef, _gridDimensionsSelectors.gridColumnsTotalWidthSelector); const gridHasFiller = (0, _utils.useGridSelector)(apiRef, _gridDimensionsSelectors.gridHasFillerSelector); const headerHeight = (0, _utils.useGridSelector)(apiRef, _gridDimensionsSelectors.gridHeaderHeightSelector); const groupHeaderHeight = (0, _utils.useGridSelector)(apiRef, _gridDimensionsSelectors.gridGroupHeaderHeightSelector); const scrollbarWidth = (0, _utils.useGridSelector)(apiRef, _gridDimensionsSelectors.gridVerticalScrollbarWidthSelector); const handleColumnResizeStart = React.useCallback(params => setResizeCol(params.field), []); const handleColumnResizeStop = React.useCallback(() => setResizeCol(''), []); const handleColumnReorderStart = React.useCallback(params => setDragCol(params.field), []); const handleColumnReorderStop = React.useCallback(() => setDragCol(''), []); const leftRenderContext = React.useMemo(() => { return pinnedColumns.left.length ? { firstColumnIndex: 0, lastColumnIndex: pinnedColumns.left.length } : null; }, [pinnedColumns.left.length]); const rightRenderContext = React.useMemo(() => { return pinnedColumns.right.length ? { firstColumnIndex: visibleColumns.length - pinnedColumns.right.length, lastColumnIndex: visibleColumns.length } : null; }, [pinnedColumns.right.length, visibleColumns.length]); (0, _useGridEvent.useGridEvent)(apiRef, 'columnResizeStart', handleColumnResizeStart); (0, _useGridEvent.useGridEvent)(apiRef, 'columnResizeStop', handleColumnResizeStop); (0, _useGridEvent.useGridEvent)(apiRef, 'columnHeaderDragStart', handleColumnReorderStart); (0, _useGridEvent.useGridEvent)(apiRef, 'columnHeaderDragEndNative', handleColumnReorderStop); // Helper for computation common between getColumnHeaders and getColumnGroupHeaders const getColumnsToRender = params => { const { renderContext: currentContext = renderContext } = params || {}; const firstColumnToRender = currentContext.firstColumnIndex; // HACK: renderContext ins't always synchronized, this should be handled properly. const lastColumnToRender = Math.min(currentContext.lastColumnIndex, visibleColumns.length); const renderedColumns = visibleColumns.slice(firstColumnToRender, lastColumnToRender); return { renderedColumns, firstColumnToRender, lastColumnToRender }; }; const getFillers = (params, children, leftOverflow, borderBottom = false) => { const isPinnedRight = params?.position === _constants.PinnedColumnPosition.RIGHT; const isNotPinned = params?.position === undefined; const hasScrollbarFiller = pinnedColumns.right.length > 0 && isPinnedRight || pinnedColumns.right.length === 0 && isNotPinned; const leftOffsetWidth = offsetLeft - leftOverflow; return /*#__PURE__*/(0, _jsxRuntime.jsxs)(React.Fragment, { children: [isNotPinned && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { role: "presentation", style: { width: leftOffsetWidth } }), children, isNotPinned && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", { role: "presentation", className: (0, _clsx.default)(_gridClasses.gridClasses.filler, borderBottom && _gridClasses.gridClasses['filler--borderBottom']) }), hasScrollbarFiller && /*#__PURE__*/(0, _jsxRuntime.jsx)(_GridScrollbarFillerCell.GridScrollbarFillerCell, { header: true, pinnedRight: isPinnedRight, borderBottom: borderBottom, borderTop: false })] }); }; if (process.env.NODE_ENV !== "production") getFillers.displayName = "getFillers"; const getColumnHeaders = (params, other = {}) => { const { renderedColumns, firstColumnToRender } = getColumnsToRender(params); const columns = []; for (let i = 0; i < renderedColumns.length; i += 1) { const colDef = renderedColumns[i]; const columnIndex = firstColumnToRender + i; const isFirstColumn = columnIndex === 0; const tabIndex = columnHeaderTabIndexState !== null && columnHeaderTabIndexState.field === colDef.field || isFirstColumn && !hasOtherElementInTabSequence ? 0 : -1; const hasFocus = columnHeaderFocus !== null && columnHeaderFocus.field === colDef.field; const open = columnMenuState.open && columnMenuState.field === colDef.field; const pinnedPosition = params?.position; const pinnedOffset = (0, _getPinnedCellOffset.getPinnedCellOffset)(pinnedPosition, colDef.computedWidth, columnIndex, columnPositions, columnsTotalWidth, scrollbarWidth); const siblingWithBorderingSeparator = pinnedPosition === _constants.PinnedColumnPosition.RIGHT ? renderedColumns[i - 1] : renderedColumns[i + 1]; const isSiblingFocused = siblingWithBorderingSeparator ? columnHeaderFocus !== null && columnHeaderFocus.field === siblingWithBorderingSeparator.field : false; const isLastUnpinned = columnIndex + 1 === columnPositions.length - pinnedColumns.right.length; const indexInSection = i; const sectionLength = renderedColumns.length; const showLeftBorder = (0, _cellBorderUtils.shouldCellShowLeftBorder)(pinnedPosition, indexInSection); const showRightBorder = (0, _cellBorderUtils.shouldCellShowRightBorder)(pinnedPosition, indexInSection, sectionLength, rootProps.showColumnVerticalBorder, gridHasFiller); columns.push(/*#__PURE__*/(0, _jsxRuntime.jsx)(_GridColumnHeaderItem.GridColumnHeaderItem, (0, _extends2.default)({}, sortColumnLookup[colDef.field], { columnMenuOpen: open, filterItemsCounter: filterColumnLookup[colDef.field] && filterColumnLookup[colDef.field].length, headerHeight: headerHeight, isDragging: colDef.field === dragCol, colDef: colDef, colIndex: columnIndex, isResizing: resizeCol === colDef.field, isLast: columnIndex === columnPositions.length - 1, hasFocus: hasFocus, tabIndex: tabIndex, pinnedPosition: pinnedPosition, pinnedOffset: pinnedOffset, isLastUnpinned: isLastUnpinned, isSiblingFocused: isSiblingFocused, showLeftBorder: showLeftBorder, showRightBorder: showRightBorder }, other), colDef.field)); } return getFillers(params, columns, 0); }; const getColumnHeadersRow = () => { return /*#__PURE__*/(0, _jsxRuntime.jsxs)(GridColumnHeaderRow, { role: "row", "aria-rowindex": headerGroupingMaxDepth + 1, ownerState: rootProps, className: _gridClasses.gridClasses['row--borderBottom'], style: { height: headerHeight }, children: [leftRenderContext && getColumnHeaders({ position: _constants.PinnedColumnPosition.LEFT, renderContext: leftRenderContext }, { disableReorder: true }), getColumnHeaders({ renderContext }), rightRenderContext && getColumnHeaders({ position: _constants.PinnedColumnPosition.RIGHT, renderContext: rightRenderContext }, { disableReorder: true, separatorSide: _GridColumnHeaderSeparator.GridColumnHeaderSeparatorSides.Left })] }); }; if (process.env.NODE_ENV !== "production") getColumnHeadersRow.displayName = "getColumnHeadersRow"; const getColumnGroupHeaders = ({ depth, params }) => { const columnsToRender = getColumnsToRender(params); if (columnsToRender.renderedColumns.length === 0) { return null; } const { firstColumnToRender, lastColumnToRender } = columnsToRender; const rowStructure = columnGroupsHeaderStructure[depth]; const firstColumnFieldToRender = visibleColumns[firstColumnToRender].field; const firstGroupToRender = columnGroupsModel[firstColumnFieldToRender]?.[depth] ?? null; const firstGroupIndex = rowStructure.findIndex(({ groupId, columnFields }) => groupId === firstGroupToRender && columnFields.includes(firstColumnFieldToRender)); const lastColumnFieldToRender = visibleColumns[lastColumnToRender - 1].field; const lastGroupToRender = columnGroupsModel[lastColumnFieldToRender]?.[depth] ?? null; const lastGroupIndex = rowStructure.findIndex(({ groupId, columnFields }) => groupId === lastGroupToRender && columnFields.includes(lastColumnFieldToRender)); const visibleColumnGroupHeader = rowStructure.slice(firstGroupIndex, lastGroupIndex + 1).map(groupStructure => { return (0, _extends2.default)({}, groupStructure, { columnFields: groupStructure.columnFields.filter(field => columnVisibility[field] !== false) }); }).filter(groupStructure => groupStructure.columnFields.length > 0); const firstVisibleColumnIndex = visibleColumnGroupHeader[0].columnFields.indexOf(firstColumnFieldToRender); const hiddenGroupColumns = visibleColumnGroupHeader[0].columnFields.slice(0, firstVisibleColumnIndex); const leftOverflow = hiddenGroupColumns.reduce((acc, field) => { const column = columnsLookup[field]; return acc + (column.computedWidth ?? 0); }, 0); let columnIndex = firstColumnToRender; const children = visibleColumnGroupHeader.map(({ groupId, columnFields }, index) => { const hasFocus = columnGroupHeaderFocus !== null && columnGroupHeaderFocus.depth === depth && columnFields.includes(columnGroupHeaderFocus.field); const tabIndex = columnGroupHeaderTabIndexState !== null && columnGroupHeaderTabIndexState.depth === depth && columnFields.includes(columnGroupHeaderTabIndexState.field) ? 0 : -1; const headerInfo = { groupId, width: columnFields.reduce((acc, field) => acc + columnsLookup[field].computedWidth, 0), fields: columnFields, colIndex: columnIndex, hasFocus, tabIndex }; const pinnedPosition = params.position; const pinnedOffset = (0, _getPinnedCellOffset.getPinnedCellOffset)(pinnedPosition, headerInfo.width, columnIndex, columnPositions, columnsTotalWidth, scrollbarWidth); columnIndex += columnFields.length; let indexInSection = index; if (pinnedPosition === _constants.PinnedColumnPosition.LEFT) { // Group headers can expand to multiple columns, we need to adjust the index indexInSection = columnIndex - 1; } return /*#__PURE__*/(0, _jsxRuntime.jsx)(_GridColumnGroupHeader.GridColumnGroupHeader, { groupId: groupId, width: headerInfo.width, fields: headerInfo.fields, colIndex: headerInfo.colIndex, depth: depth, isLastColumn: index === visibleColumnGroupHeader.length - 1, maxDepth: headerGroupingMaxDepth, height: groupHeaderHeight, hasFocus: hasFocus, tabIndex: tabIndex, pinnedPosition: pinnedPosition, pinnedOffset: pinnedOffset, showLeftBorder: (0, _cellBorderUtils.shouldCellShowLeftBorder)(pinnedPosition, indexInSection), showRightBorder: (0, _cellBorderUtils.shouldCellShowRightBorder)(pinnedPosition, indexInSection, visibleColumnGroupHeader.length, rootProps.showColumnVerticalBorder, gridHasFiller) }, index); }); return getFillers(params, children, leftOverflow); }; const getColumnGroupHeadersRows = () => { if (headerGroupingMaxDepth === 0) { return null; } const headerRows = []; for (let depth = 0; depth < headerGroupingMaxDepth; depth += 1) { headerRows.push(/*#__PURE__*/(0, _jsxRuntime.jsxs)(GridColumnHeaderRow, { role: "row", "aria-rowindex": depth + 1, ownerState: rootProps, style: { height: groupHeaderHeight }, children: [leftRenderContext && getColumnGroupHeaders({ depth, params: { position: _constants.PinnedColumnPosition.LEFT, renderContext: leftRenderContext, maxLastColumn: leftRenderContext.lastColumnIndex } }), getColumnGroupHeaders({ depth, params: { renderContext } }), rightRenderContext && getColumnGroupHeaders({ depth, params: { position: _constants.PinnedColumnPosition.RIGHT, renderContext: rightRenderContext, maxLastColumn: rightRenderContext.lastColumnIndex } })] }, depth)); } return headerRows; }; return { renderContext, leftRenderContext, rightRenderContext, pinnedColumns, visibleColumns, columnPositions, getFillers, getColumnHeadersRow, getColumnsToRender, getColumnGroupHeadersRows, getPinnedCellOffset: _getPinnedCellOffset.getPinnedCellOffset, isDragging: !!dragCol, getInnerProps: () => ({ role: 'rowgroup' }) }; }; exports.useGridColumnHeaders = useGridColumnHeaders;