@mui/x-data-grid
Version:
The Community plan edition of the MUI X Data Grid components.
329 lines (327 loc) • 16.2 kB
JavaScript
"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;