@mui/x-data-grid
Version:
The Community plan edition of the Data Grid components (MUI X).
131 lines (129 loc) • 5.63 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
const _excluded = ["groupId", "children"];
import * as React from 'react';
import { isLeaf } from '../../../models/gridColumnGrouping';
import { gridColumnGroupsLookupSelector, gridColumnGroupsUnwrappedModelSelector } from './gridColumnGroupsSelector';
import { useGridApiMethod } from '../../utils/useGridApiMethod';
import { getColumnGroupsHeaderStructure, unwrapGroupingColumnModel } from './gridColumnGroupsUtils';
import { useGridApiEventHandler } from '../../utils/useGridApiEventHandler';
import { gridColumnFieldsSelector, gridVisibleColumnFieldsSelector } from '../columns';
const createGroupLookup = columnGroupingModel => {
let groupLookup = {};
columnGroupingModel.forEach(node => {
if (isLeaf(node)) {
return;
}
const {
groupId,
children
} = node,
other = _objectWithoutPropertiesLoose(node, _excluded);
if (!groupId) {
throw new Error('MUI X: An element of the columnGroupingModel does not have either `field` or `groupId`.');
}
if (process.env.NODE_ENV !== 'production') {
if (!children) {
console.warn(`MUI X: group groupId=${groupId} has no children.`);
}
}
const groupParam = _extends({}, other, {
groupId
});
const subTreeLookup = createGroupLookup(children);
if (subTreeLookup[groupId] !== undefined || groupLookup[groupId] !== undefined) {
throw new Error(`MUI X: The groupId ${groupId} is used multiple times in the columnGroupingModel.`);
}
groupLookup = _extends({}, groupLookup, subTreeLookup, {
[groupId]: groupParam
});
});
return _extends({}, groupLookup);
};
export const columnGroupsStateInitializer = (state, props, apiRef) => {
if (!props.columnGroupingModel) {
return state;
}
const columnFields = gridColumnFieldsSelector(apiRef);
const visibleColumnFields = gridVisibleColumnFieldsSelector(apiRef);
const groupLookup = createGroupLookup(props.columnGroupingModel ?? []);
const unwrappedGroupingModel = unwrapGroupingColumnModel(props.columnGroupingModel ?? []);
const columnGroupsHeaderStructure = getColumnGroupsHeaderStructure(columnFields, unwrappedGroupingModel, apiRef.current.state.pinnedColumns ?? {});
const maxDepth = visibleColumnFields.length === 0 ? 0 : Math.max(...visibleColumnFields.map(field => unwrappedGroupingModel[field]?.length ?? 0));
return _extends({}, state, {
columnGrouping: {
lookup: groupLookup,
unwrappedGroupingModel,
headerStructure: columnGroupsHeaderStructure,
maxDepth
}
});
};
/**
* @requires useGridColumns (method, event)
* @requires useGridParamsApi (method)
*/
export const useGridColumnGrouping = (apiRef, props) => {
/**
* API METHODS
*/
const getColumnGroupPath = React.useCallback(field => {
const unwrappedGroupingModel = gridColumnGroupsUnwrappedModelSelector(apiRef);
return unwrappedGroupingModel[field] ?? [];
}, [apiRef]);
const getAllGroupDetails = React.useCallback(() => {
const columnGroupLookup = gridColumnGroupsLookupSelector(apiRef);
return columnGroupLookup;
}, [apiRef]);
const columnGroupingApi = {
getColumnGroupPath,
getAllGroupDetails
};
useGridApiMethod(apiRef, columnGroupingApi, 'public');
const handleColumnIndexChange = React.useCallback(() => {
const unwrappedGroupingModel = unwrapGroupingColumnModel(props.columnGroupingModel ?? []);
apiRef.current.setState(state => {
const orderedFields = state.columns?.orderedFields ?? [];
const pinnedColumns = state.pinnedColumns ?? {};
const columnGroupsHeaderStructure = getColumnGroupsHeaderStructure(orderedFields, unwrappedGroupingModel, pinnedColumns);
return _extends({}, state, {
columnGrouping: _extends({}, state.columnGrouping, {
headerStructure: columnGroupsHeaderStructure
})
});
});
}, [apiRef, props.columnGroupingModel]);
const updateColumnGroupingState = React.useCallback(columnGroupingModel => {
// @ts-expect-error Move this logic to `Pro` package
const pinnedColumns = apiRef.current.getPinnedColumns?.() ?? {};
const columnFields = gridColumnFieldsSelector(apiRef);
const visibleColumnFields = gridVisibleColumnFieldsSelector(apiRef);
const groupLookup = createGroupLookup(columnGroupingModel ?? []);
const unwrappedGroupingModel = unwrapGroupingColumnModel(columnGroupingModel ?? []);
const columnGroupsHeaderStructure = getColumnGroupsHeaderStructure(columnFields, unwrappedGroupingModel, pinnedColumns);
const maxDepth = visibleColumnFields.length === 0 ? 0 : Math.max(...visibleColumnFields.map(field => unwrappedGroupingModel[field]?.length ?? 0));
apiRef.current.setState(state => {
return _extends({}, state, {
columnGrouping: {
lookup: groupLookup,
unwrappedGroupingModel,
headerStructure: columnGroupsHeaderStructure,
maxDepth
}
});
});
}, [apiRef]);
useGridApiEventHandler(apiRef, 'columnIndexChange', handleColumnIndexChange);
useGridApiEventHandler(apiRef, 'columnsChange', () => {
updateColumnGroupingState(props.columnGroupingModel);
});
useGridApiEventHandler(apiRef, 'columnVisibilityModelChange', () => {
updateColumnGroupingState(props.columnGroupingModel);
});
/**
* EFFECTS
*/
React.useEffect(() => {
updateColumnGroupingState(props.columnGroupingModel);
}, [updateColumnGroupingState, props.columnGroupingModel]);
};