@mui/x-data-grid-pro
Version:
The Pro plan edition of the Data Grid components (MUI X).
239 lines (233 loc) • 11.4 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridColumnPinning = exports.columnPinningStateInitializer = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _xDataGrid = require("@mui/x-data-grid");
var _internals = require("@mui/x-data-grid/internals");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const columnPinningStateInitializer = (state, props, apiRef) => {
apiRef.current.caches.columnPinning = {
orderedFieldsBeforePinningColumns: null
};
let model;
if (props.pinnedColumns) {
model = props.pinnedColumns;
} else if (props.initialState?.pinnedColumns) {
model = props.initialState.pinnedColumns;
} else {
model = {};
}
return (0, _extends2.default)({}, state, {
pinnedColumns: model
});
};
exports.columnPinningStateInitializer = columnPinningStateInitializer;
const useGridColumnPinning = (apiRef, props) => {
const pinnedColumns = (0, _xDataGrid.useGridSelector)(apiRef, _internals.gridPinnedColumnsSelector);
/**
* PRE-PROCESSING
*/
const calculateScrollLeft = React.useCallback((initialValue, params) => {
const visiblePinnedColumns = (0, _internals.gridVisiblePinnedColumnDefinitionsSelector)(apiRef);
if (!params.colIndex || visiblePinnedColumns.left.length === 0 && visiblePinnedColumns.right.length === 0) {
return initialValue;
}
const visibleColumns = (0, _xDataGrid.gridVisibleColumnDefinitionsSelector)(apiRef);
const columnsTotalWidth = (0, _xDataGrid.gridColumnsTotalWidthSelector)(apiRef);
const columnPositions = (0, _xDataGrid.gridColumnPositionsSelector)(apiRef);
const clientWidth = apiRef.current.virtualScrollerRef.current.clientWidth;
// When using RTL, `scrollLeft` becomes negative, so we must ensure that we only compare values.
const scrollLeft = Math.abs(apiRef.current.virtualScrollerRef.current.scrollLeft);
const offsetWidth = visibleColumns[params.colIndex].computedWidth;
const offsetLeft = columnPositions[params.colIndex];
const leftPinnedColumnsWidth = columnPositions[visiblePinnedColumns.left.length];
const rightPinnedColumnsWidth = columnsTotalWidth - columnPositions[columnPositions.length - visiblePinnedColumns.right.length];
const elementBottom = offsetLeft + offsetWidth;
if (elementBottom - (clientWidth - rightPinnedColumnsWidth) > scrollLeft) {
const left = elementBottom - (clientWidth - rightPinnedColumnsWidth);
return (0, _extends2.default)({}, initialValue, {
left
});
}
if (offsetLeft < scrollLeft + leftPinnedColumnsWidth) {
const left = offsetLeft - leftPinnedColumnsWidth;
return (0, _extends2.default)({}, initialValue, {
left
});
}
return initialValue;
}, [apiRef]);
const addColumnMenuItems = React.useCallback((columnMenuItems, colDef) => {
if (props.disableColumnPinning) {
return columnMenuItems;
}
if (colDef.pinnable === false) {
return columnMenuItems;
}
return [...columnMenuItems, 'columnMenuPinningItem'];
}, [props.disableColumnPinning]);
const checkIfCanBeReordered = React.useCallback((initialValue, {
targetIndex
}) => {
const visiblePinnedColumns = (0, _internals.gridVisiblePinnedColumnDefinitionsSelector)(apiRef);
if (visiblePinnedColumns.left.length === 0 && visiblePinnedColumns.right.length === 0) {
return initialValue;
}
if (visiblePinnedColumns.left.length > 0 && targetIndex < visiblePinnedColumns.left.length) {
return false;
}
if (visiblePinnedColumns.right.length > 0) {
const visibleColumns = (0, _xDataGrid.gridVisibleColumnDefinitionsSelector)(apiRef);
const firstRightPinnedColumnIndex = visibleColumns.length - visiblePinnedColumns.right.length;
return targetIndex >= firstRightPinnedColumnIndex ? false : initialValue;
}
return initialValue;
}, [apiRef]);
const stateExportPreProcessing = React.useCallback((prevState, context) => {
const pinnedColumnsToExport = (0, _internals.gridPinnedColumnsSelector)(apiRef.current.state);
const shouldExportPinnedColumns =
// Always export if the `exportOnlyDirtyModels` property is not activated
!context.exportOnlyDirtyModels ||
// Always export if the model is controlled
props.pinnedColumns != null ||
// Always export if the model has been initialized
props.initialState?.pinnedColumns != null ||
// Export if the model is not empty
(pinnedColumnsToExport.left ?? []).length > 0 || (pinnedColumnsToExport.right ?? []).length > 0;
if (!shouldExportPinnedColumns) {
return prevState;
}
return (0, _extends2.default)({}, prevState, {
pinnedColumns: pinnedColumnsToExport
});
}, [apiRef, props.pinnedColumns, props.initialState?.pinnedColumns]);
const stateRestorePreProcessing = React.useCallback((params, context) => {
const newPinnedColumns = context.stateToRestore.pinnedColumns;
if (newPinnedColumns != null) {
setState(apiRef, newPinnedColumns);
}
return params;
}, [apiRef]);
(0, _internals.useGridRegisterPipeProcessor)(apiRef, 'scrollToIndexes', calculateScrollLeft);
(0, _internals.useGridRegisterPipeProcessor)(apiRef, 'columnMenu', addColumnMenuItems);
(0, _internals.useGridRegisterPipeProcessor)(apiRef, 'canBeReordered', checkIfCanBeReordered);
(0, _internals.useGridRegisterPipeProcessor)(apiRef, 'exportState', stateExportPreProcessing);
(0, _internals.useGridRegisterPipeProcessor)(apiRef, 'restoreState', stateRestorePreProcessing);
apiRef.current.registerControlState({
stateId: 'pinnedColumns',
propModel: props.pinnedColumns,
propOnChange: props.onPinnedColumnsChange,
stateSelector: _internals.gridPinnedColumnsSelector,
changeEvent: 'pinnedColumnsChange'
});
const pinColumn = React.useCallback((field, side) => {
if (apiRef.current.isColumnPinned(field) === side) {
return;
}
const otherSide = side === _xDataGrid.GridPinnedColumnPosition.RIGHT ? _xDataGrid.GridPinnedColumnPosition.LEFT : _xDataGrid.GridPinnedColumnPosition.RIGHT;
const newPinnedColumns = {
[side]: [...(pinnedColumns[side] || []), field],
[otherSide]: (pinnedColumns[otherSide] || []).filter(column => column !== field)
};
apiRef.current.setPinnedColumns(newPinnedColumns);
}, [apiRef, pinnedColumns]);
const unpinColumn = React.useCallback(field => {
apiRef.current.setPinnedColumns({
left: (pinnedColumns.left || []).filter(column => column !== field),
right: (pinnedColumns.right || []).filter(column => column !== field)
});
}, [apiRef, pinnedColumns.left, pinnedColumns.right]);
const getPinnedColumns = React.useCallback(() => {
return (0, _internals.gridPinnedColumnsSelector)(apiRef.current.state);
}, [apiRef]);
const setPinnedColumns = React.useCallback(newPinnedColumns => {
setState(apiRef, newPinnedColumns);
apiRef.current.forceUpdate();
}, [apiRef]);
const isColumnPinned = React.useCallback(field => {
const leftPinnedColumns = pinnedColumns.left || [];
if (leftPinnedColumns.includes(field)) {
return _xDataGrid.GridPinnedColumnPosition.LEFT;
}
const rightPinnedColumns = pinnedColumns.right || [];
if (rightPinnedColumns.includes(field)) {
return _xDataGrid.GridPinnedColumnPosition.RIGHT;
}
return false;
}, [pinnedColumns.left, pinnedColumns.right]);
const columnPinningApi = {
pinColumn,
unpinColumn,
getPinnedColumns,
setPinnedColumns,
isColumnPinned
};
(0, _xDataGrid.useGridApiMethod)(apiRef, columnPinningApi, 'public');
const handleColumnOrderChange = params => {
if (!apiRef.current.caches.columnPinning.orderedFieldsBeforePinningColumns) {
return;
}
const {
column,
targetIndex,
oldIndex
} = params;
const delta = targetIndex > oldIndex ? 1 : -1;
const latestColumnFields = (0, _xDataGrid.gridColumnFieldsSelector)(apiRef);
/**
* When a column X is reordered to somewhere else, the position where this column X is dropped
* on must be moved to left or right to make room for it. The ^^^ below represents the column
* which gave space to receive X.
*
* | X | B | C | D | -> | B | C | D | X | (for example X moved to after D, so delta=1)
* ^^^ ^^^
*
* | A | B | C | X | -> | X | A | B | C | (for example X moved before A, so delta=-1)
* ^^^ ^^^
*
* If column P is pinned, it will not move to provide space. However, it will jump to the next
* non-pinned column.
*
* | X | B | P | D | -> | B | D | P | X | (for example X moved to after D, with P pinned)
* ^^^ ^^^
*/
const siblingField = latestColumnFields[targetIndex - delta];
const newOrderedFieldsBeforePinningColumns = [...apiRef.current.caches.columnPinning.orderedFieldsBeforePinningColumns];
// The index to start swapping fields
let i = newOrderedFieldsBeforePinningColumns.findIndex(currentColumn => currentColumn === column.field);
// The index of the field to swap with
let j = i + delta;
// When to stop swapping fields.
// We stop one field before because the swap is done with i + 1 (if delta=1)
const stop = newOrderedFieldsBeforePinningColumns.findIndex(currentColumn => currentColumn === siblingField);
while (delta > 0 ? i < stop : i > stop) {
// If the field to swap with is a pinned column, jump to the next
while (apiRef.current.isColumnPinned(newOrderedFieldsBeforePinningColumns[j])) {
j += delta;
}
const temp = newOrderedFieldsBeforePinningColumns[i];
newOrderedFieldsBeforePinningColumns[i] = newOrderedFieldsBeforePinningColumns[j];
newOrderedFieldsBeforePinningColumns[j] = temp;
i = j;
j = i + delta;
}
apiRef.current.caches.columnPinning.orderedFieldsBeforePinningColumns = newOrderedFieldsBeforePinningColumns;
};
(0, _xDataGrid.useGridApiEventHandler)(apiRef, 'columnOrderChange', handleColumnOrderChange);
React.useEffect(() => {
if (props.pinnedColumns) {
apiRef.current.setPinnedColumns(props.pinnedColumns);
}
}, [apiRef, props.pinnedColumns]);
};
exports.useGridColumnPinning = useGridColumnPinning;
function setState(apiRef, model) {
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
pinnedColumns: model
}));
}