@mui/x-data-grid
Version:
The community edition of the data grid component (MUI X).
374 lines (322 loc) • 17.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.columnsStateInitializer = void 0;
exports.useGridColumns = useGridColumns;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _useGridApiMethod = require("../../utils/useGridApiMethod");
var _useGridLogger = require("../../utils/useGridLogger");
var _gridColumnsSelector = require("./gridColumnsSelector");
var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
var _pipeProcessing = require("../../core/pipeProcessing");
var _gridColumnsUtils = require("./gridColumnsUtils");
var _preferencesPanel = require("../preferencesPanel");
var _jsxRuntime = require("react/jsx-runtime");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
const columnsStateInitializer = (state, props, apiRef) => {
var _props$initialState, _props$initialState$c, _props$initialState2, _ref, _props$columnVisibili, _props$initialState3, _props$initialState3$;
const isUsingColumnVisibilityModel = !!props.columnVisibilityModel || !!((_props$initialState = props.initialState) != null && (_props$initialState$c = _props$initialState.columns) != null && _props$initialState$c.columnVisibilityModel);
apiRef.current.unstable_caches.columns = {
isUsingColumnVisibilityModel
};
const columnsTypes = (0, _gridColumnsUtils.computeColumnTypes)(props.columnTypes);
const columnsState = (0, _gridColumnsUtils.createColumnsState)({
apiRef,
columnTypes: columnsTypes,
columnsToUpsert: props.columns,
initialState: (_props$initialState2 = props.initialState) == null ? void 0 : _props$initialState2.columns,
shouldRegenColumnVisibilityModelFromColumns: !isUsingColumnVisibilityModel,
currentColumnVisibilityModel: (_ref = (_props$columnVisibili = props.columnVisibilityModel) != null ? _props$columnVisibili : (_props$initialState3 = props.initialState) == null ? void 0 : (_props$initialState3$ = _props$initialState3.columns) == null ? void 0 : _props$initialState3$.columnVisibilityModel) != null ? _ref : {},
keepOnlyColumnsToUpsert: true
});
return (0, _extends2.default)({}, state, {
columns: columnsState
});
};
/**
* @requires useGridParamsApi (method)
* @requires useGridDimensions (method, event) - can be after
* TODO: Impossible priority - useGridParamsApi also needs to be after useGridColumns
*/
exports.columnsStateInitializer = columnsStateInitializer;
function useGridColumns(apiRef, props) {
var _props$initialState5, _props$componentsProp2;
const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridColumns');
const columnTypes = React.useMemo(() => (0, _gridColumnsUtils.computeColumnTypes)(props.columnTypes), [props.columnTypes]);
const previousColumnsProp = React.useRef(props.columns);
const previousColumnTypesProp = React.useRef(columnTypes);
apiRef.current.unstable_registerControlState({
stateId: 'visibleColumns',
propModel: props.columnVisibilityModel,
propOnChange: props.onColumnVisibilityModelChange,
stateSelector: _gridColumnsSelector.gridColumnVisibilityModelSelector,
changeEvent: 'columnVisibilityModelChange'
});
const setGridColumnsState = React.useCallback(columnsState => {
logger.debug('Updating columns state.');
apiRef.current.setState((0, _gridColumnsUtils.mergeColumnsState)(columnsState));
apiRef.current.forceUpdate();
apiRef.current.publishEvent('columnsChange', columnsState.all);
}, [logger, apiRef]);
/**
* API METHODS
*/
const getColumn = React.useCallback(field => (0, _gridColumnsSelector.gridColumnLookupSelector)(apiRef)[field], [apiRef]);
const getAllColumns = React.useCallback(() => (0, _gridColumnsSelector.gridColumnDefinitionsSelector)(apiRef), [apiRef]);
const getVisibleColumns = React.useCallback(() => (0, _gridColumnsSelector.gridVisibleColumnDefinitionsSelector)(apiRef), [apiRef]);
const getColumnsMeta = React.useCallback(() => (0, _gridColumnsSelector.gridColumnsMetaSelector)(apiRef), [apiRef]);
const getColumnIndex = React.useCallback((field, useVisibleColumns = true) => {
const columns = useVisibleColumns ? (0, _gridColumnsSelector.gridVisibleColumnDefinitionsSelector)(apiRef) : (0, _gridColumnsSelector.gridColumnDefinitionsSelector)(apiRef);
return columns.findIndex(col => col.field === field);
}, [apiRef]);
const getColumnPosition = React.useCallback(field => {
const index = getColumnIndex(field);
return (0, _gridColumnsSelector.gridColumnPositionsSelector)(apiRef)[index];
}, [apiRef, getColumnIndex]);
const setColumnVisibilityModel = React.useCallback(model => {
const currentModel = (0, _gridColumnsSelector.gridColumnVisibilityModelSelector)(apiRef);
if (currentModel !== model) {
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
columns: (0, _gridColumnsUtils.createColumnsState)({
apiRef,
columnTypes,
columnsToUpsert: [],
initialState: undefined,
shouldRegenColumnVisibilityModelFromColumns: false,
currentColumnVisibilityModel: model,
keepOnlyColumnsToUpsert: false
})
}));
apiRef.current.forceUpdate();
}
}, [apiRef, columnTypes]);
const updateColumns = React.useCallback(columns => {
const columnsState = (0, _gridColumnsUtils.createColumnsState)({
apiRef,
columnTypes,
columnsToUpsert: columns,
initialState: undefined,
shouldRegenColumnVisibilityModelFromColumns: true,
keepOnlyColumnsToUpsert: false
});
setGridColumnsState(columnsState);
}, [apiRef, setGridColumnsState, columnTypes]);
const updateColumn = React.useCallback(column => apiRef.current.updateColumns([column]), [apiRef]);
const setColumnVisibility = React.useCallback((field, isVisible) => {
// We keep updating the `hide` option of `GridColDef` when not controlling the model to avoid any breaking change.
// `updateColumns` take care of updating the model itself if needs be.
// TODO v6: stop using the `hide` field even when the model is not defined
if (apiRef.current.unstable_caches.columns.isUsingColumnVisibilityModel) {
var _columnVisibilityMode;
const columnVisibilityModel = (0, _gridColumnsSelector.gridColumnVisibilityModelSelector)(apiRef);
const isCurrentlyVisible = (_columnVisibilityMode = columnVisibilityModel[field]) != null ? _columnVisibilityMode : true;
if (isVisible !== isCurrentlyVisible) {
const newModel = (0, _extends2.default)({}, columnVisibilityModel, {
[field]: isVisible
});
apiRef.current.setColumnVisibilityModel(newModel);
}
} else {
const column = apiRef.current.getColumn(field);
const newColumn = (0, _extends2.default)({}, column, {
hide: !isVisible
});
apiRef.current.updateColumns([newColumn]);
const params = {
field,
colDef: newColumn,
isVisible
};
apiRef.current.publishEvent('columnVisibilityChange', params);
}
}, [apiRef]);
const setColumnIndex = React.useCallback((field, targetIndexPosition) => {
const allColumns = (0, _gridColumnsSelector.gridColumnFieldsSelector)(apiRef);
const oldIndexPosition = allColumns.findIndex(col => col === field);
if (oldIndexPosition === targetIndexPosition) {
return;
}
logger.debug(`Moving column ${field} to index ${targetIndexPosition}`);
const updatedColumns = [...allColumns];
const fieldRemoved = updatedColumns.splice(oldIndexPosition, 1)[0];
updatedColumns.splice(targetIndexPosition, 0, fieldRemoved);
setGridColumnsState((0, _extends2.default)({}, (0, _gridColumnsSelector.gridColumnsSelector)(apiRef.current.state), {
all: updatedColumns
}));
const params = {
field,
element: apiRef.current.getColumnHeaderElement(field),
colDef: apiRef.current.getColumn(field),
targetIndex: targetIndexPosition,
oldIndex: oldIndexPosition
};
apiRef.current.publishEvent('columnOrderChange', params);
}, [apiRef, logger, setGridColumnsState]);
const setColumnWidth = React.useCallback((field, width) => {
logger.debug(`Updating column ${field} width to ${width}`);
const column = apiRef.current.getColumn(field);
const newColumn = (0, _extends2.default)({}, column, {
width
});
apiRef.current.updateColumns([newColumn]);
apiRef.current.publishEvent('columnWidthChange', {
element: apiRef.current.getColumnHeaderElement(field),
colDef: newColumn,
width
});
}, [apiRef, logger]);
const columnApi = {
getColumn,
getAllColumns,
getColumnIndex,
getColumnPosition,
getVisibleColumns,
getColumnsMeta,
updateColumn,
updateColumns,
setColumnVisibilityModel,
setColumnVisibility,
setColumnIndex,
setColumnWidth
};
(0, _useGridApiMethod.useGridApiMethod)(apiRef, columnApi, 'GridColumnApi');
/**
* PRE-PROCESSING
*/
const stateExportPreProcessing = React.useCallback((prevState, context) => {
const columnsStateToExport = {};
if (apiRef.current.unstable_caches.columns.isUsingColumnVisibilityModel) {
var _props$initialState$c2, _props$initialState4, _props$initialState4$;
const columnVisibilityModelToExport = (0, _gridColumnsSelector.gridColumnVisibilityModelSelector)(apiRef);
const shouldExportColumnVisibilityModel = // Always export if the `exportOnlyDirtyModels` property is 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$c2 = (_props$initialState4 = props.initialState) == null ? void 0 : (_props$initialState4$ = _props$initialState4.columns) == null ? void 0 : _props$initialState4$.columnVisibilityModel) != null ? _props$initialState$c2 : {}).length > 0 || // Always export if the model is not empty
Object.keys(columnVisibilityModelToExport).length > 0;
if (shouldExportColumnVisibilityModel) {
columnsStateToExport.columnVisibilityModel = columnVisibilityModelToExport;
}
}
columnsStateToExport.orderedFields = (0, _gridColumnsSelector.gridColumnFieldsSelector)(apiRef);
const columns = (0, _gridColumnsSelector.gridColumnDefinitionsSelector)(apiRef);
const dimensions = {};
columns.forEach(colDef => {
if (colDef.hasBeenResized) {
const colDefDimensions = {};
_gridColumnsUtils.COLUMNS_DIMENSION_PROPERTIES.forEach(propertyName => {
let 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 (0, _extends2.default)({}, prevState, {
columns: columnsStateToExport
});
}, [apiRef, props.columnVisibilityModel, (_props$initialState5 = props.initialState) == null ? void 0 : _props$initialState5.columns]);
const stateRestorePreProcessing = React.useCallback((params, context) => {
var _context$stateToResto;
const columnVisibilityModelToImport = apiRef.current.unstable_caches.columns.isUsingColumnVisibilityModel ? (_context$stateToResto = context.stateToRestore.columns) == null ? void 0 : _context$stateToResto.columnVisibilityModel : undefined;
const initialState = context.stateToRestore.columns;
if (columnVisibilityModelToImport == null && initialState == null) {
return params;
}
const columnsState = (0, _gridColumnsUtils.createColumnsState)({
apiRef,
columnTypes,
columnsToUpsert: [],
initialState,
shouldRegenColumnVisibilityModelFromColumns: !apiRef.current.unstable_caches.columns.isUsingColumnVisibilityModel,
currentColumnVisibilityModel: columnVisibilityModelToImport,
keepOnlyColumnsToUpsert: false
});
apiRef.current.setState((0, _gridColumnsUtils.mergeColumnsState)(columnsState));
if (initialState != null) {
apiRef.current.publishEvent('columnsChange', columnsState.all);
}
return params;
}, [apiRef, columnTypes]);
const preferencePanelPreProcessing = React.useCallback((initialValue, value) => {
if (value === _preferencesPanel.GridPreferencePanelsValue.columns) {
var _props$componentsProp;
const ColumnsPanel = props.components.ColumnsPanel;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(ColumnsPanel, (0, _extends2.default)({}, (_props$componentsProp = props.componentsProps) == null ? void 0 : _props$componentsProp.columnsPanel));
}
return initialValue;
}, [props.components.ColumnsPanel, (_props$componentsProp2 = props.componentsProps) == null ? void 0 : _props$componentsProp2.columnsPanel]);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'exportState', stateExportPreProcessing);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'restoreState', stateRestorePreProcessing);
(0, _pipeProcessing.useGridRegisterPipeProcessor)(apiRef, 'preferencePanel', preferencePanelPreProcessing);
/**
* EVENTS
*/
const prevInnerWidth = React.useRef(null);
const handleGridSizeChange = viewportInnerSize => {
if (prevInnerWidth.current !== viewportInnerSize.width) {
prevInnerWidth.current = viewportInnerSize.width;
setGridColumnsState((0, _gridColumnsUtils.hydrateColumnsWidth)((0, _gridColumnsSelector.gridColumnsSelector)(apiRef.current.state), viewportInnerSize.width));
}
};
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'viewportInnerSizeChange', handleGridSizeChange);
(0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'columnVisibilityChange', props.onColumnVisibilityChange);
/**
* APPLIERS
*/
const hydrateColumns = React.useCallback(() => {
logger.info(`Columns pipe processing have changed, regenerating the columns`);
const columnsState = (0, _gridColumnsUtils.createColumnsState)({
apiRef,
columnTypes,
columnsToUpsert: [],
initialState: undefined,
shouldRegenColumnVisibilityModelFromColumns: !apiRef.current.unstable_caches.columns.isUsingColumnVisibilityModel,
keepOnlyColumnsToUpsert: false
});
setGridColumnsState(columnsState);
}, [apiRef, logger, setGridColumnsState, columnTypes]);
(0, _pipeProcessing.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
const isFirstRender = React.useRef(true);
React.useEffect(() => {
if (isFirstRender.current) {
isFirstRender.current = false;
return;
}
logger.info(`GridColumns have changed, new length ${props.columns.length}`);
if (previousColumnsProp.current === props.columns && previousColumnTypesProp.current === columnTypes) {
return;
}
const columnsState = (0, _gridColumnsUtils.createColumnsState)({
apiRef,
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`
shouldRegenColumnVisibilityModelFromColumns: !apiRef.current.unstable_caches.columns.isUsingColumnVisibilityModel,
columnsToUpsert: props.columns,
keepOnlyColumnsToUpsert: true
});
previousColumnsProp.current = props.columns;
previousColumnTypesProp.current = columnTypes;
setGridColumnsState(columnsState);
}, [logger, apiRef, setGridColumnsState, props.columns, columnTypes]);
React.useEffect(() => {
if (props.columnVisibilityModel !== undefined) {
apiRef.current.setColumnVisibilityModel(props.columnVisibilityModel);
}
}, [apiRef, logger, props.columnVisibilityModel]);
}