@mui/x-data-grid
Version:
The community edition of the data grid component (MUI X).
153 lines (130 loc) • 5.47 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 } from './gridColumnGroupsSelector';
import { gridColumnLookupSelector } from '../columns/gridColumnsSelector';
import { useGridApiMethod } from '../../utils/useGridApiMethod';
export function hasGroupPath(lookupElement) {
return lookupElement.groupPath !== undefined;
}
// This is the recurrence function that help writing `unwrapGroupingColumnModel()`
const recurrentUnwrapGroupingColumnModel = (columnGroupNode, parents, unwrappedGroupingModelToComplet) => {
if (isLeaf(columnGroupNode)) {
if (unwrappedGroupingModelToComplet[columnGroupNode.field] !== undefined) {
throw new Error([`MUI: columnGroupingModel contains duplicated field`, `column field ${columnGroupNode.field} occurrs two times in the grouping model:`, `- ${unwrappedGroupingModelToComplet[columnGroupNode.field].join(' > ')}`, `- ${parents.join(' > ')}`].join('\n'));
}
unwrappedGroupingModelToComplet[columnGroupNode.field] = parents;
return;
}
const {
groupId,
children
} = columnGroupNode;
children.forEach(child => {
recurrentUnwrapGroupingColumnModel(child, [...parents, groupId], unwrappedGroupingModelToComplet);
});
};
/**
* This is a function that provide for each column the array of its parents.
* Parents are ordered from the root to the leaf.
* @param columnGroupingModel The model such as provided in DataGrid props
* @returns An object `{[field]: groupIds}` where `groupIds` is the parents of the column `field`
*/
export const unwrapGroupingColumnModel = columnGroupingModel => {
if (!columnGroupingModel) {
return {};
}
const unwrappedSubTree = {};
columnGroupingModel.forEach(columnGroupNode => {
recurrentUnwrapGroupingColumnModel(columnGroupNode, [], unwrappedSubTree);
});
return unwrappedSubTree;
};
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: An element of the columnGroupingModel does not have either `field` or `groupId`.');
}
if (!children) {
console.warn(`MUI: 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: The groupId ${groupId} is used multiple times in the columnGroupingModel.`);
}
groupLookup = _extends({}, groupLookup, subTreeLookup, {
[groupId]: groupParam
});
});
return _extends({}, groupLookup);
};
export const columnGroupsStateInitializer = (state, props) => {
var _props$columnGrouping;
const groupLookup = createGroupLookup((_props$columnGrouping = props.columnGroupingModel) != null ? _props$columnGrouping : []);
return _extends({}, state, {
columnGrouping: {
lookup: groupLookup,
groupCollapsedModel: {}
}
});
};
/**
* @requires useGridColumns (method, event)
* @requires useGridParamsApi (method)
*/
export const useGridColumnGrouping = (apiRef, props) => {
var _props$experimentalFe2;
/**
* API METHODS
*/
const getColumnGroupPath = React.useCallback(field => {
var _columnLookup$field$g, _columnLookup$field;
const columnLookup = gridColumnLookupSelector(apiRef);
return (_columnLookup$field$g = (_columnLookup$field = columnLookup[field]) == null ? void 0 : _columnLookup$field.groupPath) != null ? _columnLookup$field$g : [];
}, [apiRef]);
const getAllGroupDetails = React.useCallback(() => {
const columnGroupLookup = gridColumnGroupsLookupSelector(apiRef);
return columnGroupLookup;
}, [apiRef]);
const columnGroupingApi = {
unstable_getColumnGroupPath: getColumnGroupPath,
unstable_getAllGroupDetails: getAllGroupDetails
};
useGridApiMethod(apiRef, columnGroupingApi, 'GridColumnGroupingApi');
/**
* EFFECTS
*/
// The effect does 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
const isFirstRender = React.useRef(true);
React.useEffect(() => {
var _props$experimentalFe, _props$columnGrouping2;
if (isFirstRender.current) {
isFirstRender.current = false;
return;
}
if (!((_props$experimentalFe = props.experimentalFeatures) != null && _props$experimentalFe.columnGrouping)) {
return;
}
const groupLookup = createGroupLookup((_props$columnGrouping2 = props.columnGroupingModel) != null ? _props$columnGrouping2 : []);
apiRef.current.setState(state => _extends({}, state, {
columnGrouping: _extends({}, state.columnGrouping, {
lookup: groupLookup
})
}));
}, [apiRef, props.columnGroupingModel, (_props$experimentalFe2 = props.experimentalFeatures) == null ? void 0 : _props$experimentalFe2.columnGrouping]);
};