wip:milestone 0 fixes
Some checks failed
CI/CD Pipeline / unit-tests (push) Failing after 1m16s
CI/CD Pipeline / integration-tests (push) Failing after 2m32s
CI/CD Pipeline / lint (push) Successful in 5m22s
CI/CD Pipeline / e2e-tests (push) Has been skipped
CI/CD Pipeline / build (push) Has been skipped

This commit is contained in:
2026-03-15 12:35:42 +02:00
parent 6708cf28a7
commit cffdf8af86
61266 changed files with 4511646 additions and 1938 deletions

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,112 @@
import { createSelector, createSelectorMemoized } from '../../../utils/createSelector';
/**
* Get the columns state
* @category Columns
*/
export var gridColumnsStateSelector = function gridColumnsStateSelector(state) {
return state.columns;
};
/**
* Get an array of column fields in the order rendered on screen.
* @category Columns
*/
export var gridColumnFieldsSelector = createSelector(gridColumnsStateSelector, function (columnsState) {
return columnsState.orderedFields;
});
/**
* Get the columns as a lookup (an object containing the field for keys and the definition for values).
* @category Columns
*/
export var gridColumnLookupSelector = createSelector(gridColumnsStateSelector, function (columnsState) {
return columnsState.lookup;
});
/**
* Get an array of column definitions in the order rendered on screen..
* @category Columns
*/
export var gridColumnDefinitionsSelector = createSelectorMemoized(gridColumnFieldsSelector, gridColumnLookupSelector, function (allFields, lookup) {
return allFields.map(function (field) {
return lookup[field];
});
});
/**
* Get the column visibility model, containing the visibility status of each column.
* If a column is not registered in the model, it is visible.
* @category Visible Columns
*/
export var gridColumnVisibilityModelSelector = createSelector(gridColumnsStateSelector, function (columnsState) {
return columnsState.columnVisibilityModel;
});
/**
* Get the visible columns as a lookup (an object containing the field for keys and the definition for values).
* @category Visible Columns
*/
export var gridVisibleColumnDefinitionsSelector = createSelectorMemoized(gridColumnDefinitionsSelector, gridColumnVisibilityModelSelector, function (columns, columnVisibilityModel) {
return columns.filter(function (column) {
return columnVisibilityModel[column.field] !== false;
});
});
/**
* Get the field of each visible column.
* @category Visible Columns
*/
export var gridVisibleColumnFieldsSelector = createSelectorMemoized(gridVisibleColumnDefinitionsSelector, function (visibleColumns) {
return visibleColumns.map(function (column) {
return column.field;
});
});
/**
* Get the left position in pixel of each visible columns relative to the left of the first column.
* @category Visible Columns
*/
export var gridColumnPositionsSelector = createSelectorMemoized(gridVisibleColumnDefinitionsSelector, function (visibleColumns) {
var positions = [];
var currentPosition = 0;
for (var i = 0; i < visibleColumns.length; i += 1) {
positions.push(currentPosition);
currentPosition += visibleColumns[i].computedWidth;
}
return positions;
});
/**
* Get the summed width of all the visible columns.
* @category Visible Columns
*/
export var gridColumnsTotalWidthSelector = createSelector(gridVisibleColumnDefinitionsSelector, gridColumnPositionsSelector, function (visibleColumns, positions) {
var colCount = visibleColumns.length;
if (colCount === 0) {
return 0;
}
return positions[colCount - 1] + visibleColumns[colCount - 1].computedWidth;
});
/**
* Get the filterable columns as an array.
* @category Columns
*/
export var gridFilterableColumnDefinitionsSelector = createSelectorMemoized(gridColumnDefinitionsSelector, function (columns) {
return columns.filter(function (col) {
return col.filterable;
});
});
/**
* Get the filterable columns as a lookup (an object containing the field for keys and the definition for values).
* @category Columns
*/
export var gridFilterableColumnLookupSelector = createSelectorMemoized(gridColumnDefinitionsSelector, function (columns) {
return columns.reduce(function (acc, col) {
if (col.filterable) {
acc[col.field] = col;
}
return acc;
}, {});
});

View File

@@ -0,0 +1,344 @@
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
import _extends from "@babel/runtime/helpers/esm/extends";
import { DEFAULT_GRID_COL_TYPE_KEY, GRID_STRING_COL_DEF } from '../../../colDef';
import { gridColumnsStateSelector, gridColumnVisibilityModelSelector } from './gridColumnsSelector';
import { clamp } from '../../../utils/utils';
import { gridDensityFactorSelector } from '../density/densitySelector';
import { gridColumnGroupsHeaderMaxDepthSelector } from '../columnGrouping/gridColumnGroupsSelector';
export var COLUMNS_DIMENSION_PROPERTIES = ['maxWidth', 'minWidth', 'width', 'flex'];
/**
* Computes width for flex columns.
* Based on CSS Flexbox specification:
* https://drafts.csswg.org/css-flexbox-1/#resolve-flexible-lengths
*/
export function computeFlexColumnsWidth(_ref) {
var initialFreeSpace = _ref.initialFreeSpace,
totalFlexUnits = _ref.totalFlexUnits,
flexColumns = _ref.flexColumns;
var uniqueFlexColumns = new Set(flexColumns.map(function (col) {
return col.field;
}));
var flexColumnsLookup = {
all: {},
frozenFields: [],
freeze: function freeze(field) {
var value = flexColumnsLookup.all[field];
if (value && value.frozen !== true) {
flexColumnsLookup.all[field].frozen = true;
flexColumnsLookup.frozenFields.push(field);
}
}
};
// Step 5 of https://drafts.csswg.org/css-flexbox-1/#resolve-flexible-lengths
function loopOverFlexItems() {
// 5a: If all the flex items on the line are frozen, free space has been distributed.
if (flexColumnsLookup.frozenFields.length === uniqueFlexColumns.size) {
return;
}
var violationsLookup = {
min: {},
max: {}
};
var remainingFreeSpace = initialFreeSpace;
var flexUnits = totalFlexUnits;
var totalViolation = 0;
// 5b: Calculate the remaining free space
flexColumnsLookup.frozenFields.forEach(function (field) {
remainingFreeSpace -= flexColumnsLookup.all[field].computedWidth;
flexUnits -= flexColumnsLookup.all[field].flex;
});
for (var i = 0; i < flexColumns.length; i += 1) {
var column = flexColumns[i];
if (flexColumnsLookup.all[column.field] && flexColumnsLookup.all[column.field].frozen === true) {
continue;
}
// 5c: Distribute remaining free space proportional to the flex factors
var widthPerFlexUnit = remainingFreeSpace / flexUnits;
var computedWidth = widthPerFlexUnit * column.flex;
// 5d: Fix min/max violations
if (computedWidth < column.minWidth) {
totalViolation += column.minWidth - computedWidth;
computedWidth = column.minWidth;
violationsLookup.min[column.field] = true;
} else if (computedWidth > column.maxWidth) {
totalViolation += column.maxWidth - computedWidth;
computedWidth = column.maxWidth;
violationsLookup.max[column.field] = true;
}
flexColumnsLookup.all[column.field] = {
frozen: false,
computedWidth: computedWidth,
flex: column.flex
};
}
// 5e: Freeze over-flexed items
if (totalViolation < 0) {
// Freeze all the items with max violations
Object.keys(violationsLookup.max).forEach(function (field) {
flexColumnsLookup.freeze(field);
});
} else if (totalViolation > 0) {
// Freeze all the items with min violations
Object.keys(violationsLookup.min).forEach(function (field) {
flexColumnsLookup.freeze(field);
});
} else {
// Freeze all items
flexColumns.forEach(function (_ref2) {
var field = _ref2.field;
flexColumnsLookup.freeze(field);
});
}
// 5f: Return to the start of this loop
loopOverFlexItems();
}
loopOverFlexItems();
return flexColumnsLookup.all;
}
/**
* Compute the `computedWidth` (ie: the width the column should have during rendering) based on the `width` / `flex` / `minWidth` / `maxWidth` properties of `GridColDef`.
* The columns already have been merged with there `type` default values for `minWidth`, `maxWidth` and `width`, thus the `!` for those properties below.
* TODO: Unit test this function in depth and only keep basic cases for the whole grid testing.
* TODO: Improve the `GridColDef` typing to reflect the fact that `minWidth` / `maxWidth` and `width` can't be null after the merge with the `type` default values.
*/
export var hydrateColumnsWidth = function hydrateColumnsWidth(rawState, viewportInnerWidth) {
var columnsLookup = {};
var totalFlexUnits = 0;
var widthAllocatedBeforeFlex = 0;
var flexColumns = [];
// For the non-flex columns, compute their width
// For the flex columns, compute there minimum width and how much width must be allocated during the flex allocation
rawState.orderedFields.forEach(function (columnField) {
var newColumn = _extends({}, rawState.lookup[columnField]);
if (rawState.columnVisibilityModel[columnField] === false) {
newColumn.computedWidth = 0;
} else {
var computedWidth;
if (newColumn.flex && newColumn.flex > 0) {
totalFlexUnits += newColumn.flex;
computedWidth = 0;
flexColumns.push(newColumn);
} else {
computedWidth = clamp(newColumn.width || GRID_STRING_COL_DEF.width, newColumn.minWidth || GRID_STRING_COL_DEF.minWidth, newColumn.maxWidth || GRID_STRING_COL_DEF.maxWidth);
}
widthAllocatedBeforeFlex += computedWidth;
newColumn.computedWidth = computedWidth;
}
columnsLookup[columnField] = newColumn;
});
var initialFreeSpace = Math.max(viewportInnerWidth - widthAllocatedBeforeFlex, 0);
// Allocate the remaining space to the flex columns
if (totalFlexUnits > 0 && viewportInnerWidth > 0) {
var computedColumnWidths = computeFlexColumnsWidth({
initialFreeSpace: initialFreeSpace,
totalFlexUnits: totalFlexUnits,
flexColumns: flexColumns
});
Object.keys(computedColumnWidths).forEach(function (field) {
columnsLookup[field].computedWidth = computedColumnWidths[field].computedWidth;
});
}
return _extends({}, rawState, {
lookup: columnsLookup
});
};
/**
* Apply the order and the dimensions of the initial state.
* The columns not registered in `orderedFields` will be placed after the imported columns.
*/
export var applyInitialState = function applyInitialState(columnsState, initialState) {
if (!initialState) {
return columnsState;
}
var _initialState$ordered = initialState.orderedFields,
orderedFields = _initialState$ordered === void 0 ? [] : _initialState$ordered,
_initialState$dimensi = initialState.dimensions,
dimensions = _initialState$dimensi === void 0 ? {} : _initialState$dimensi;
var columnsWithUpdatedDimensions = Object.keys(dimensions);
if (columnsWithUpdatedDimensions.length === 0 && orderedFields.length === 0) {
return columnsState;
}
var orderedFieldsLookup = {};
var cleanOrderedFields = [];
for (var i = 0; i < orderedFields.length; i += 1) {
var _field = orderedFields[i];
// Ignores the fields in the initialState that matches no field on the current column state
if (columnsState.lookup[_field]) {
orderedFieldsLookup[_field] = true;
cleanOrderedFields.push(_field);
}
}
var newOrderedFields = cleanOrderedFields.length === 0 ? columnsState.orderedFields : [].concat(cleanOrderedFields, _toConsumableArray(columnsState.orderedFields.filter(function (field) {
return !orderedFieldsLookup[field];
})));
var newColumnLookup = _extends({}, columnsState.lookup);
var _loop = function _loop() {
var field = columnsWithUpdatedDimensions[_i];
var newColDef = _extends({}, newColumnLookup[field], {
hasBeenResized: true
});
Object.entries(dimensions[field]).forEach(function (_ref3) {
var _ref4 = _slicedToArray(_ref3, 2),
key = _ref4[0],
value = _ref4[1];
newColDef[key] = value === -1 ? Infinity : value;
});
newColumnLookup[field] = newColDef;
};
for (var _i = 0; _i < columnsWithUpdatedDimensions.length; _i += 1) {
_loop();
}
var newColumnsState = _extends({}, columnsState, {
orderedFields: newOrderedFields,
lookup: newColumnLookup
});
return newColumnsState;
};
function getDefaultColTypeDef(columnTypes, type) {
var colDef = columnTypes[DEFAULT_GRID_COL_TYPE_KEY];
if (type && columnTypes[type]) {
colDef = columnTypes[type];
}
return colDef;
}
export var createColumnsState = function createColumnsState(_ref5) {
var _apiRef$current$getRo, _apiRef$current$getRo2, _apiRef$current;
var apiRef = _ref5.apiRef,
columnsToUpsert = _ref5.columnsToUpsert,
initialState = _ref5.initialState,
columnTypes = _ref5.columnTypes,
_ref5$columnVisibilit = _ref5.columnVisibilityModel,
columnVisibilityModel = _ref5$columnVisibilit === void 0 ? gridColumnVisibilityModelSelector(apiRef) : _ref5$columnVisibilit,
_ref5$keepOnlyColumns = _ref5.keepOnlyColumnsToUpsert,
keepOnlyColumnsToUpsert = _ref5$keepOnlyColumns === void 0 ? false : _ref5$keepOnlyColumns;
var isInsideStateInitializer = !apiRef.current.state.columns;
var columnsState;
if (isInsideStateInitializer) {
columnsState = {
orderedFields: [],
lookup: {},
columnVisibilityModel: columnVisibilityModel
};
} else {
var currentState = gridColumnsStateSelector(apiRef.current.state);
columnsState = {
orderedFields: keepOnlyColumnsToUpsert ? [] : _toConsumableArray(currentState.orderedFields),
lookup: _extends({}, currentState.lookup),
// Will be cleaned later if keepOnlyColumnsToUpsert=true
columnVisibilityModel: columnVisibilityModel
};
}
var columnsToKeep = {};
if (keepOnlyColumnsToUpsert && !isInsideStateInitializer) {
columnsToKeep = Object.keys(columnsState.lookup).reduce(function (acc, key) {
return _extends({}, acc, _defineProperty({}, key, false));
}, {});
}
var columnsToUpsertLookup = {};
columnsToUpsert.forEach(function (newColumn) {
var field = newColumn.field;
columnsToUpsertLookup[field] = true;
columnsToKeep[field] = true;
var existingState = columnsState.lookup[field];
if (existingState == null) {
existingState = _extends({}, getDefaultColTypeDef(columnTypes, newColumn.type), {
field: field,
hasBeenResized: false
});
columnsState.orderedFields.push(field);
} else if (keepOnlyColumnsToUpsert) {
columnsState.orderedFields.push(field);
}
// If the column type has changed - merge the existing state with the default column type definition
if (existingState && existingState.type !== newColumn.type) {
existingState = _extends({}, getDefaultColTypeDef(columnTypes, newColumn.type), {
field: field
});
}
var hasBeenResized = existingState.hasBeenResized;
COLUMNS_DIMENSION_PROPERTIES.forEach(function (key) {
if (newColumn[key] !== undefined) {
hasBeenResized = true;
if (newColumn[key] === -1) {
newColumn[key] = Infinity;
}
}
});
columnsState.lookup[field] = _extends({}, existingState, newColumn, {
hasBeenResized: hasBeenResized
});
});
if (keepOnlyColumnsToUpsert && !isInsideStateInitializer) {
Object.keys(columnsState.lookup).forEach(function (field) {
if (!columnsToKeep[field]) {
delete columnsState.lookup[field];
}
});
}
var columnsStateWithPreProcessing = apiRef.current.unstable_applyPipeProcessors('hydrateColumns', columnsState);
var columnsStateWithPortableColumns = applyInitialState(columnsStateWithPreProcessing, initialState);
return hydrateColumnsWidth(columnsStateWithPortableColumns, (_apiRef$current$getRo = (_apiRef$current$getRo2 = (_apiRef$current = apiRef.current).getRootDimensions) == null || (_apiRef$current$getRo2 = _apiRef$current$getRo2.call(_apiRef$current)) == null ? void 0 : _apiRef$current$getRo2.viewportInnerSize.width) != null ? _apiRef$current$getRo : 0);
};
export var mergeColumnsState = function mergeColumnsState(columnsState) {
return function (state) {
return _extends({}, state, {
columns: columnsState
});
};
};
export function getFirstNonSpannedColumnToRender(_ref6) {
var firstColumnToRender = _ref6.firstColumnToRender,
apiRef = _ref6.apiRef,
firstRowToRender = _ref6.firstRowToRender,
lastRowToRender = _ref6.lastRowToRender,
visibleRows = _ref6.visibleRows;
var firstNonSpannedColumnToRender = firstColumnToRender;
for (var i = firstRowToRender; i < lastRowToRender; i += 1) {
var row = visibleRows[i];
if (row) {
var rowId = visibleRows[i].id;
var cellColSpanInfo = apiRef.current.unstable_getCellColSpanInfo(rowId, firstColumnToRender);
if (cellColSpanInfo && cellColSpanInfo.spannedByColSpan) {
firstNonSpannedColumnToRender = cellColSpanInfo.leftVisibleCellIndex;
}
}
}
return firstNonSpannedColumnToRender;
}
export function getFirstColumnIndexToRender(_ref7) {
var firstColumnIndex = _ref7.firstColumnIndex,
minColumnIndex = _ref7.minColumnIndex,
columnBuffer = _ref7.columnBuffer,
firstRowToRender = _ref7.firstRowToRender,
lastRowToRender = _ref7.lastRowToRender,
apiRef = _ref7.apiRef,
visibleRows = _ref7.visibleRows;
var initialFirstColumnToRender = Math.max(firstColumnIndex - columnBuffer, minColumnIndex);
var firstColumnToRender = getFirstNonSpannedColumnToRender({
firstColumnToRender: initialFirstColumnToRender,
apiRef: apiRef,
firstRowToRender: firstRowToRender,
lastRowToRender: lastRowToRender,
visibleRows: visibleRows
});
return firstColumnToRender;
}
export function getTotalHeaderHeight(apiRef, headerHeight) {
var densityFactor = gridDensityFactorSelector(apiRef);
var maxDepth = gridColumnGroupsHeaderMaxDepthSelector(apiRef);
return Math.floor(headerHeight * densityFactor) * ((maxDepth != null ? maxDepth : 0) + 1);
}

View File

@@ -0,0 +1 @@
export { gridColumnFieldsSelector, gridColumnLookupSelector, gridColumnDefinitionsSelector, gridColumnVisibilityModelSelector, gridVisibleColumnDefinitionsSelector, gridVisibleColumnFieldsSelector, gridColumnPositionsSelector, gridColumnsTotalWidthSelector, gridFilterableColumnDefinitionsSelector, gridFilterableColumnLookupSelector } from './gridColumnsSelector';

View File

@@ -0,0 +1,102 @@
import * as React from 'react';
import { useGridApiMethod } from '../../utils/useGridApiMethod';
import { useGridApiEventHandler } from '../../utils/useGridApiEventHandler';
/**
* @requires useGridColumns (method, event)
* @requires useGridParamsApi (method)
*/
export var useGridColumnSpanning = function useGridColumnSpanning(apiRef) {
var lookup = React.useRef({});
var setCellColSpanInfo = React.useCallback(function (rowId, columnIndex, cellColSpanInfo) {
var sizes = lookup.current;
if (!sizes[rowId]) {
sizes[rowId] = {};
}
sizes[rowId][columnIndex] = cellColSpanInfo;
}, []);
var getCellColSpanInfo = React.useCallback(function (rowId, columnIndex) {
var _lookup$current$rowId;
return (_lookup$current$rowId = lookup.current[rowId]) == null ? void 0 : _lookup$current$rowId[columnIndex];
}, []);
// Calculate `colSpan` for the cell.
var calculateCellColSpan = React.useCallback(function (params) {
var columnIndex = params.columnIndex,
rowId = params.rowId,
minFirstColumnIndex = params.minFirstColumnIndex,
maxLastColumnIndex = params.maxLastColumnIndex,
columns = params.columns;
var columnsLength = columns.length;
var column = columns[columnIndex];
var colSpan = typeof column.colSpan === 'function' ? column.colSpan(apiRef.current.getCellParams(rowId, column.field)) : column.colSpan;
if (!colSpan || colSpan === 1) {
setCellColSpanInfo(rowId, columnIndex, {
spannedByColSpan: false,
cellProps: {
colSpan: 1,
width: column.computedWidth
}
});
return {
colSpan: 1
};
}
var width = column.computedWidth;
for (var j = 1; j < colSpan; j += 1) {
var nextColumnIndex = columnIndex + j;
// Cells should be spanned only within their column section (left-pinned, right-pinned and unpinned).
if (nextColumnIndex >= minFirstColumnIndex && nextColumnIndex < maxLastColumnIndex) {
var nextColumn = columns[nextColumnIndex];
width += nextColumn.computedWidth;
setCellColSpanInfo(rowId, columnIndex + j, {
spannedByColSpan: true,
rightVisibleCellIndex: Math.min(columnIndex + colSpan, columnsLength - 1),
leftVisibleCellIndex: columnIndex
});
}
setCellColSpanInfo(rowId, columnIndex, {
spannedByColSpan: false,
cellProps: {
colSpan: colSpan,
width: width
}
});
}
return {
colSpan: colSpan
};
}, [apiRef, setCellColSpanInfo]);
// Calculate `colSpan` for each cell in the row
var calculateColSpan = React.useCallback(function (_ref) {
var rowId = _ref.rowId,
minFirstColumn = _ref.minFirstColumn,
maxLastColumn = _ref.maxLastColumn,
columns = _ref.columns;
for (var i = minFirstColumn; i < maxLastColumn; i += 1) {
var cellProps = calculateCellColSpan({
columnIndex: i,
rowId: rowId,
minFirstColumnIndex: minFirstColumn,
maxLastColumnIndex: maxLastColumn,
columns: columns
});
if (cellProps.colSpan > 1) {
i += cellProps.colSpan - 1;
}
}
}, [calculateCellColSpan]);
var columnSpanningPublicApi = {
unstable_getCellColSpanInfo: getCellColSpanInfo
};
var columnSpanningPrivateApi = {
calculateColSpan: calculateColSpan
};
useGridApiMethod(apiRef, columnSpanningPublicApi, 'public');
useGridApiMethod(apiRef, columnSpanningPrivateApi, 'private');
var handleColumnReorderChange = React.useCallback(function () {
// `colSpan` needs to be recalculated after column reordering
lookup.current = {};
}, []);
useGridApiEventHandler(apiRef, 'columnOrderChange', handleColumnReorderChange);
};

View File

@@ -0,0 +1,320 @@
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import _extends from "@babel/runtime/helpers/esm/extends";
import * as React from 'react';
import { useGridApiMethod } from '../../utils/useGridApiMethod';
import { useGridLogger } from '../../utils/useGridLogger';
import { gridColumnFieldsSelector, gridColumnDefinitionsSelector, gridColumnLookupSelector, gridColumnsStateSelector, gridColumnVisibilityModelSelector, gridVisibleColumnDefinitionsSelector, gridColumnPositionsSelector } from './gridColumnsSelector';
import { GridSignature, useGridApiEventHandler } from '../../utils/useGridApiEventHandler';
import { useGridRegisterPipeProcessor, useGridRegisterPipeApplier } from '../../core/pipeProcessing';
import { hydrateColumnsWidth, createColumnsState, mergeColumnsState, COLUMNS_DIMENSION_PROPERTIES } from './gridColumnsUtils';
import { GridPreferencePanelsValue } from '../preferencesPanel';
import { getGridDefaultColumnTypes } from '../../../colDef';
import { jsx as _jsx } from "react/jsx-runtime";
var defaultColumnTypes = getGridDefaultColumnTypes();
export var columnsStateInitializer = function columnsStateInitializer(state, props, apiRef) {
var _props$initialState, _ref, _props$columnVisibili, _props$initialState2;
var columnsState = createColumnsState({
apiRef: apiRef,
columnTypes: defaultColumnTypes,
columnsToUpsert: props.columns,
initialState: (_props$initialState = props.initialState) == null ? void 0 : _props$initialState.columns,
columnVisibilityModel: (_ref = (_props$columnVisibili = props.columnVisibilityModel) != null ? _props$columnVisibili : (_props$initialState2 = props.initialState) == null || (_props$initialState2 = _props$initialState2.columns) == null ? void 0 : _props$initialState2.columnVisibilityModel) != null ? _ref : {},
keepOnlyColumnsToUpsert: true
});
return _extends({}, state, {
columns: columnsState
});
};
/**
* @requires useGridParamsApi (method)
* @requires useGridDimensions (method, event) - can be after
* TODO: Impossible priority - useGridParamsApi also needs to be after useGridColumns
*/
export function useGridColumns(apiRef, props) {
var _props$initialState4, _props$slotProps2;
var logger = useGridLogger(apiRef, 'useGridColumns');
var columnTypes = defaultColumnTypes;
var previousColumnsProp = React.useRef(props.columns);
var previousColumnTypesProp = React.useRef(columnTypes);
apiRef.current.registerControlState({
stateId: 'visibleColumns',
propModel: props.columnVisibilityModel,
propOnChange: props.onColumnVisibilityModelChange,
stateSelector: gridColumnVisibilityModelSelector,
changeEvent: 'columnVisibilityModelChange'
});
var setGridColumnsState = React.useCallback(function (columnsState) {
logger.debug('Updating columns state.');
apiRef.current.setState(mergeColumnsState(columnsState));
apiRef.current.forceUpdate();
apiRef.current.publishEvent('columnsChange', columnsState.orderedFields);
}, [logger, apiRef]);
/**
* API METHODS
*/
var getColumn = React.useCallback(function (field) {
return gridColumnLookupSelector(apiRef)[field];
}, [apiRef]);
var getAllColumns = React.useCallback(function () {
return gridColumnDefinitionsSelector(apiRef);
}, [apiRef]);
var getVisibleColumns = React.useCallback(function () {
return gridVisibleColumnDefinitionsSelector(apiRef);
}, [apiRef]);
var getColumnIndex = React.useCallback(function (field) {
var useVisibleColumns = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
var columns = useVisibleColumns ? gridVisibleColumnDefinitionsSelector(apiRef) : gridColumnDefinitionsSelector(apiRef);
return columns.findIndex(function (col) {
return col.field === field;
});
}, [apiRef]);
var getColumnPosition = React.useCallback(function (field) {
var index = getColumnIndex(field);
return gridColumnPositionsSelector(apiRef)[index];
}, [apiRef, getColumnIndex]);
var setColumnVisibilityModel = React.useCallback(function (model) {
var currentModel = gridColumnVisibilityModelSelector(apiRef);
if (currentModel !== model) {
apiRef.current.setState(function (state) {
return _extends({}, state, {
columns: createColumnsState({
apiRef: apiRef,
columnTypes: columnTypes,
columnsToUpsert: [],
initialState: undefined,
columnVisibilityModel: model,
keepOnlyColumnsToUpsert: false
})
});
});
apiRef.current.forceUpdate();
}
}, [apiRef, columnTypes]);
var updateColumns = React.useCallback(function (columns) {
var columnsState = createColumnsState({
apiRef: apiRef,
columnTypes: columnTypes,
columnsToUpsert: columns,
initialState: undefined,
keepOnlyColumnsToUpsert: false
});
setGridColumnsState(columnsState);
}, [apiRef, setGridColumnsState, columnTypes]);
var setColumnVisibility = React.useCallback(function (field, isVisible) {
var _columnVisibilityMode;
var columnVisibilityModel = gridColumnVisibilityModelSelector(apiRef);
var isCurrentlyVisible = (_columnVisibilityMode = columnVisibilityModel[field]) != null ? _columnVisibilityMode : true;
if (isVisible !== isCurrentlyVisible) {
var newModel = _extends({}, columnVisibilityModel, _defineProperty({}, field, isVisible));
apiRef.current.setColumnVisibilityModel(newModel);
}
}, [apiRef]);
var getColumnIndexRelativeToVisibleColumns = React.useCallback(function (field) {
var allColumns = gridColumnFieldsSelector(apiRef);
return allColumns.findIndex(function (col) {
return col === field;
});
}, [apiRef]);
var setColumnIndex = React.useCallback(function (field, targetIndexPosition) {
var allColumns = gridColumnFieldsSelector(apiRef);
var oldIndexPosition = getColumnIndexRelativeToVisibleColumns(field);
if (oldIndexPosition === targetIndexPosition) {
return;
}
logger.debug("Moving column ".concat(field, " to index ").concat(targetIndexPosition));
var updatedColumns = _toConsumableArray(allColumns);
var fieldRemoved = updatedColumns.splice(oldIndexPosition, 1)[0];
updatedColumns.splice(targetIndexPosition, 0, fieldRemoved);
setGridColumnsState(_extends({}, gridColumnsStateSelector(apiRef.current.state), {
orderedFields: updatedColumns
}));
var params = {
column: apiRef.current.getColumn(field),
targetIndex: apiRef.current.getColumnIndexRelativeToVisibleColumns(field),
oldIndex: oldIndexPosition
};
apiRef.current.publishEvent('columnIndexChange', params);
}, [apiRef, logger, setGridColumnsState, getColumnIndexRelativeToVisibleColumns]);
var setColumnWidth = React.useCallback(function (field, width) {
var _apiRef$current$getRo, _apiRef$current$getRo2;
logger.debug("Updating column ".concat(field, " width to ").concat(width));
var columnsState = gridColumnsStateSelector(apiRef.current.state);
var column = columnsState.lookup[field];
var newColumn = _extends({}, column, {
width: width,
hasBeenResized: true
});
setGridColumnsState(hydrateColumnsWidth(_extends({}, columnsState, {
lookup: _extends({}, columnsState.lookup, _defineProperty({}, field, newColumn))
}), (_apiRef$current$getRo = (_apiRef$current$getRo2 = apiRef.current.getRootDimensions()) == null ? void 0 : _apiRef$current$getRo2.viewportInnerSize.width) != null ? _apiRef$current$getRo : 0));
apiRef.current.publishEvent('columnWidthChange', {
element: apiRef.current.getColumnHeaderElement(field),
colDef: newColumn,
width: width
});
}, [apiRef, logger, setGridColumnsState]);
var columnApi = {
getColumn: getColumn,
getAllColumns: getAllColumns,
getColumnIndex: getColumnIndex,
getColumnPosition: getColumnPosition,
getVisibleColumns: getVisibleColumns,
getColumnIndexRelativeToVisibleColumns: getColumnIndexRelativeToVisibleColumns,
updateColumns: updateColumns,
setColumnVisibilityModel: setColumnVisibilityModel,
setColumnVisibility: setColumnVisibility,
setColumnWidth: setColumnWidth
};
var columnReorderApi = {
setColumnIndex: setColumnIndex
};
useGridApiMethod(apiRef, columnApi, 'public');
useGridApiMethod(apiRef, columnReorderApi, props.signature === GridSignature.DataGrid ? 'private' : 'public');
/**
* PRE-PROCESSING
*/
var stateExportPreProcessing = React.useCallback(function (prevState, context) {
var _props$initialState$c, _props$initialState3;
var columnsStateToExport = {};
var columnVisibilityModelToExport = gridColumnVisibilityModelSelector(apiRef);
var shouldExportColumnVisibilityModel =
// Always export if the `exportOnlyDirtyModels` property is not activated
!context.exportOnlyDirtyModels ||
// Always export if the model is controlled
props.columnVisibilityModel != null ||
// Always export if the model has been initialized
// TODO v6 Do a nullish check instead to export even if the initial model equals "{}"
Object.keys((_props$initialState$c = (_props$initialState3 = props.initialState) == null || (_props$initialState3 = _props$initialState3.columns) == null ? void 0 : _props$initialState3.columnVisibilityModel) != null ? _props$initialState$c : {}).length > 0 ||
// Always export if the model is not empty
Object.keys(columnVisibilityModelToExport).length > 0;
if (shouldExportColumnVisibilityModel) {
columnsStateToExport.columnVisibilityModel = columnVisibilityModelToExport;
}
columnsStateToExport.orderedFields = gridColumnFieldsSelector(apiRef);
var columns = gridColumnDefinitionsSelector(apiRef);
var dimensions = {};
columns.forEach(function (colDef) {
if (colDef.hasBeenResized) {
var colDefDimensions = {};
COLUMNS_DIMENSION_PROPERTIES.forEach(function (propertyName) {
var propertyValue = colDef[propertyName];
if (propertyValue === Infinity) {
propertyValue = -1;
}
colDefDimensions[propertyName] = propertyValue;
});
dimensions[colDef.field] = colDefDimensions;
}
});
if (Object.keys(dimensions).length > 0) {
columnsStateToExport.dimensions = dimensions;
}
return _extends({}, prevState, {
columns: columnsStateToExport
});
}, [apiRef, props.columnVisibilityModel, (_props$initialState4 = props.initialState) == null ? void 0 : _props$initialState4.columns]);
var stateRestorePreProcessing = React.useCallback(function (params, context) {
var _context$stateToResto;
var columnVisibilityModelToImport = (_context$stateToResto = context.stateToRestore.columns) == null ? void 0 : _context$stateToResto.columnVisibilityModel;
var initialState = context.stateToRestore.columns;
if (columnVisibilityModelToImport == null && initialState == null) {
return params;
}
var columnsState = createColumnsState({
apiRef: apiRef,
columnTypes: columnTypes,
columnsToUpsert: [],
initialState: initialState,
columnVisibilityModel: columnVisibilityModelToImport,
keepOnlyColumnsToUpsert: false
});
apiRef.current.setState(mergeColumnsState(columnsState));
if (initialState != null) {
apiRef.current.publishEvent('columnsChange', columnsState.orderedFields);
}
return params;
}, [apiRef, columnTypes]);
var preferencePanelPreProcessing = React.useCallback(function (initialValue, value) {
if (value === GridPreferencePanelsValue.columns) {
var _props$slotProps;
var ColumnsPanel = props.slots.columnsPanel;
return /*#__PURE__*/_jsx(ColumnsPanel, _extends({}, (_props$slotProps = props.slotProps) == null ? void 0 : _props$slotProps.columnsPanel));
}
return initialValue;
}, [props.slots.columnsPanel, (_props$slotProps2 = props.slotProps) == null ? void 0 : _props$slotProps2.columnsPanel]);
var addColumnMenuItems = React.useCallback(function (columnMenuItems) {
if (props.disableColumnSelector) {
return columnMenuItems;
}
return [].concat(_toConsumableArray(columnMenuItems), ['columnMenuColumnsItem']);
}, [props.disableColumnSelector]);
useGridRegisterPipeProcessor(apiRef, 'columnMenu', addColumnMenuItems);
useGridRegisterPipeProcessor(apiRef, 'exportState', stateExportPreProcessing);
useGridRegisterPipeProcessor(apiRef, 'restoreState', stateRestorePreProcessing);
useGridRegisterPipeProcessor(apiRef, 'preferencePanel', preferencePanelPreProcessing);
/**
* EVENTS
*/
var prevInnerWidth = React.useRef(null);
var handleGridSizeChange = function handleGridSizeChange(viewportInnerSize) {
if (prevInnerWidth.current !== viewportInnerSize.width) {
prevInnerWidth.current = viewportInnerSize.width;
setGridColumnsState(hydrateColumnsWidth(gridColumnsStateSelector(apiRef.current.state), viewportInnerSize.width));
}
};
useGridApiEventHandler(apiRef, 'viewportInnerSizeChange', handleGridSizeChange);
/**
* APPLIERS
*/
var hydrateColumns = React.useCallback(function () {
logger.info("Columns pipe processing have changed, regenerating the columns");
var columnsState = createColumnsState({
apiRef: apiRef,
columnTypes: columnTypes,
columnsToUpsert: [],
initialState: undefined,
keepOnlyColumnsToUpsert: false
});
setGridColumnsState(columnsState);
}, [apiRef, logger, setGridColumnsState, columnTypes]);
useGridRegisterPipeApplier(apiRef, 'hydrateColumns', hydrateColumns);
/**
* EFFECTS
*/
// The effect do not track any value defined synchronously during the 1st render by hooks called after `useGridColumns`
// As a consequence, the state generated by the 1st run of this useEffect will always be equal to the initialization one
var isFirstRender = React.useRef(true);
React.useEffect(function () {
if (isFirstRender.current) {
isFirstRender.current = false;
return;
}
logger.info("GridColumns have changed, new length ".concat(props.columns.length));
if (previousColumnsProp.current === props.columns && previousColumnTypesProp.current === columnTypes) {
return;
}
var columnsState = createColumnsState({
apiRef: apiRef,
columnTypes: columnTypes,
initialState: undefined,
// If the user provides a model, we don't want to set it in the state here because it has it's dedicated `useEffect` which calls `setColumnVisibilityModel`
columnsToUpsert: props.columns,
keepOnlyColumnsToUpsert: true
});
previousColumnsProp.current = props.columns;
previousColumnTypesProp.current = columnTypes;
setGridColumnsState(columnsState);
}, [logger, apiRef, setGridColumnsState, props.columns, columnTypes]);
React.useEffect(function () {
if (props.columnVisibilityModel !== undefined) {
apiRef.current.setColumnVisibilityModel(props.columnVisibilityModel);
}
}, [apiRef, logger, props.columnVisibilityModel]);
}