@mui/x-data-grid-pro
Version:
The Pro plan edition of the MUI X Data Grid components.
258 lines (252 loc) • 12.7 kB
JavaScript
'use client';
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridColumnReorder = exports.columnReorderStateInitializer = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _composeClasses = _interopRequireDefault(require("@mui/utils/composeClasses"));
var _RtlProvider = require("@mui/system/RtlProvider");
var _xDataGrid = require("@mui/x-data-grid");
var _columnReorderSelector = require("./columnReorderSelector");
const CURSOR_MOVE_DIRECTION_LEFT = 'left';
const CURSOR_MOVE_DIRECTION_RIGHT = 'right';
const getCursorMoveDirectionX = (currentCoordinates, nextCoordinates) => {
return currentCoordinates.x <= nextCoordinates.x ? CURSOR_MOVE_DIRECTION_RIGHT : CURSOR_MOVE_DIRECTION_LEFT;
};
const hasCursorPositionChanged = (currentCoordinates, nextCoordinates) => currentCoordinates.x !== nextCoordinates.x || currentCoordinates.y !== nextCoordinates.y;
const useUtilityClasses = ownerState => {
const {
classes
} = ownerState;
const slots = {
columnHeaderDragging: ['columnHeader--dragging']
};
return (0, _composeClasses.default)(slots, _xDataGrid.getDataGridUtilityClass, classes);
};
const columnReorderStateInitializer = state => (0, _extends2.default)({}, state, {
columnReorder: {
dragCol: ''
}
});
/**
* @requires useGridColumns (method)
*/
exports.columnReorderStateInitializer = columnReorderStateInitializer;
const useGridColumnReorder = (apiRef, props) => {
const logger = (0, _xDataGrid.useGridLogger)(apiRef, 'useGridColumnReorder');
const dragColNode = React.useRef(null);
const cursorPosition = React.useRef({
x: 0,
y: 0
});
const originColumnIndex = React.useRef(null);
const forbiddenIndexes = React.useRef({});
const removeDnDStylesTimeout = React.useRef(undefined);
const ownerState = {
classes: props.classes
};
const classes = useUtilityClasses(ownerState);
const isRtl = (0, _RtlProvider.useRtl)();
React.useEffect(() => {
return () => {
clearTimeout(removeDnDStylesTimeout.current);
};
}, []);
const handleDragEnd = React.useCallback((params, event) => {
const dragColField = (0, _columnReorderSelector.gridColumnReorderDragColSelector)(apiRef);
if (props.disableColumnReorder || !dragColField) {
return;
}
logger.debug('End dragging col');
event.preventDefault();
// Prevent drag events propagation.
// For more information check here https://github.com/mui/mui-x/issues/2680.
event.stopPropagation();
clearTimeout(removeDnDStylesTimeout.current);
// For more information check here https://github.com/mui/mui-x/issues/14678
if (dragColNode.current.classList.contains(classes.columnHeaderDragging)) {
dragColNode.current.classList.remove(classes.columnHeaderDragging);
}
dragColNode.current = null;
// Check if the column was dropped outside the grid.
if (event.dataTransfer.dropEffect === 'none' && !props.keepColumnPositionIfDraggedOutside) {
// Accessing params.field may contain the wrong field as header elements are reused
apiRef.current.setColumnIndex(dragColField, originColumnIndex.current);
originColumnIndex.current = null;
} else {
// Emit the columnOrderChange event only once when the reordering stops.
const columnOrderChangeParams = {
column: apiRef.current.getColumn(dragColField),
targetIndex: apiRef.current.getColumnIndexRelativeToVisibleColumns(dragColField),
oldIndex: originColumnIndex.current
};
apiRef.current.publishEvent('columnOrderChange', columnOrderChangeParams);
}
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
columnReorder: (0, _extends2.default)({}, state.columnReorder, {
dragCol: ''
})
}));
}, [apiRef, props.disableColumnReorder, props.keepColumnPositionIfDraggedOutside, logger, classes.columnHeaderDragging]);
const handleDragStart = React.useCallback((params, event) => {
if (props.disableColumnReorder || params.colDef.disableReorder) {
return;
}
logger.debug(`Start dragging col ${params.field}`);
// Prevent drag events propagation.
// For more information check here https://github.com/mui/mui-x/issues/2680.
event.stopPropagation();
dragColNode.current = event.currentTarget;
dragColNode.current.classList.add(classes.columnHeaderDragging);
const handleDragEndEvent = dragEndEvent => {
dragColNode.current.removeEventListener('dragend', handleDragEndEvent);
apiRef.current.publishEvent('columnHeaderDragEndNative', params, dragEndEvent);
};
dragColNode.current.addEventListener('dragend', handleDragEndEvent);
if (event.dataTransfer) {
event.dataTransfer.effectAllowed = 'move';
}
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
columnReorder: (0, _extends2.default)({}, state.columnReorder, {
dragCol: params.field
})
}));
removeDnDStylesTimeout.current = setTimeout(() => {
dragColNode.current.classList.remove(classes.columnHeaderDragging);
});
originColumnIndex.current = apiRef.current.getColumnIndex(params.field, false);
const draggingColumnGroupPath = apiRef.current.getColumnGroupPath(params.field);
const columnIndex = originColumnIndex.current;
const allColumns = apiRef.current.getAllColumns();
const groupsLookup = apiRef.current.getAllGroupDetails();
const getGroupPathFromColumnIndex = colIndex => {
const field = allColumns[colIndex].field;
return apiRef.current.getColumnGroupPath(field);
};
// The limitingGroupId is the id of the group from which the dragged column should not escape
let limitingGroupId = null;
draggingColumnGroupPath.forEach(groupId => {
if (!groupsLookup[groupId]?.freeReordering) {
// Only consider group that are made of more than one column
if (columnIndex > 0 && getGroupPathFromColumnIndex(columnIndex - 1).includes(groupId)) {
limitingGroupId = groupId;
} else if (columnIndex + 1 < allColumns.length && getGroupPathFromColumnIndex(columnIndex + 1).includes(groupId)) {
limitingGroupId = groupId;
}
}
});
forbiddenIndexes.current = {};
for (let indexToForbid = 0; indexToForbid < allColumns.length; indexToForbid += 1) {
const leftIndex = indexToForbid <= columnIndex ? indexToForbid - 1 : indexToForbid;
const rightIndex = indexToForbid < columnIndex ? indexToForbid : indexToForbid + 1;
if (limitingGroupId !== null) {
// verify this indexToForbid will be linked to the limiting group. Otherwise forbid it
let allowIndex = false;
if (leftIndex >= 0 && getGroupPathFromColumnIndex(leftIndex).includes(limitingGroupId)) {
allowIndex = true;
} else if (rightIndex < allColumns.length && getGroupPathFromColumnIndex(rightIndex).includes(limitingGroupId)) {
allowIndex = true;
}
if (!allowIndex) {
forbiddenIndexes.current[indexToForbid] = true;
}
}
// Verify we are not splitting another group
if (leftIndex >= 0 && rightIndex < allColumns.length) {
getGroupPathFromColumnIndex(rightIndex).forEach(groupId => {
if (getGroupPathFromColumnIndex(leftIndex).includes(groupId)) {
if (!draggingColumnGroupPath.includes(groupId)) {
// moving here split the group groupId in two distincts chunks
if (!groupsLookup[groupId]?.freeReordering) {
forbiddenIndexes.current[indexToForbid] = true;
}
}
}
});
}
}
}, [props.disableColumnReorder, classes.columnHeaderDragging, logger, apiRef]);
const handleDragEnter = React.useCallback((params, event) => {
event.preventDefault();
// Prevent drag events propagation.
// For more information check here https://github.com/mui/mui-x/issues/2680.
event.stopPropagation();
}, []);
const handleDragOver = React.useCallback((params, event) => {
const dragColField = (0, _columnReorderSelector.gridColumnReorderDragColSelector)(apiRef);
if (!dragColField) {
return;
}
logger.debug(`Dragging over col ${params.field}`);
event.preventDefault();
// Prevent drag events propagation.
// For more information check here https://github.com/mui/mui-x/issues/2680.
event.stopPropagation();
const coordinates = {
x: event.clientX,
y: event.clientY
};
if (params.field !== dragColField && hasCursorPositionChanged(cursorPosition.current, coordinates)) {
const targetColIndex = apiRef.current.getColumnIndex(params.field, false);
const targetColVisibleIndex = apiRef.current.getColumnIndex(params.field, true);
const targetCol = apiRef.current.getColumn(params.field);
const dragColIndex = apiRef.current.getColumnIndex(dragColField, false);
const visibleColumns = apiRef.current.getVisibleColumns();
const allColumns = apiRef.current.getAllColumns();
const cursorMoveDirectionX = getCursorMoveDirectionX(cursorPosition.current, coordinates);
const hasMovedLeft = cursorMoveDirectionX === CURSOR_MOVE_DIRECTION_LEFT && (isRtl ? dragColIndex < targetColIndex : targetColIndex < dragColIndex);
const hasMovedRight = cursorMoveDirectionX === CURSOR_MOVE_DIRECTION_RIGHT && (isRtl ? targetColIndex < dragColIndex : dragColIndex < targetColIndex);
if (hasMovedLeft || hasMovedRight) {
let canBeReordered;
let indexOffsetInHiddenColumns = 0;
if (!targetCol.disableReorder) {
canBeReordered = true;
} else if (hasMovedLeft) {
canBeReordered = targetColVisibleIndex > 0 && !visibleColumns[targetColVisibleIndex - 1].disableReorder;
} else {
canBeReordered = targetColVisibleIndex < visibleColumns.length - 1 && !visibleColumns[targetColVisibleIndex + 1].disableReorder;
}
if (forbiddenIndexes.current[targetColIndex]) {
let nextVisibleColumnField;
let indexWithOffset = targetColIndex + indexOffsetInHiddenColumns;
if (hasMovedLeft) {
nextVisibleColumnField = targetColVisibleIndex > 0 ? visibleColumns[targetColVisibleIndex - 1].field : null;
while (indexWithOffset > 0 && allColumns[indexWithOffset].field !== nextVisibleColumnField && forbiddenIndexes.current[indexWithOffset]) {
indexOffsetInHiddenColumns -= 1;
indexWithOffset = targetColIndex + indexOffsetInHiddenColumns;
}
} else {
nextVisibleColumnField = targetColVisibleIndex + 1 < visibleColumns.length ? visibleColumns[targetColVisibleIndex + 1].field : null;
while (indexWithOffset < allColumns.length - 1 && allColumns[indexWithOffset].field !== nextVisibleColumnField && forbiddenIndexes.current[indexWithOffset]) {
indexOffsetInHiddenColumns += 1;
indexWithOffset = targetColIndex + indexOffsetInHiddenColumns;
}
}
if (forbiddenIndexes.current[indexWithOffset] || allColumns[indexWithOffset].field === nextVisibleColumnField) {
// If we ended up on a visible column, or a forbidden one, we cannot do the reorder
canBeReordered = false;
}
}
const canBeReorderedProcessed = apiRef.current.unstable_applyPipeProcessors('canBeReordered', canBeReordered, {
targetIndex: targetColVisibleIndex
});
if (canBeReorderedProcessed) {
apiRef.current.setColumnIndex(dragColField, targetColIndex + indexOffsetInHiddenColumns);
}
}
cursorPosition.current = coordinates;
}
}, [apiRef, logger, isRtl]);
(0, _xDataGrid.useGridEvent)(apiRef, 'columnHeaderDragStart', handleDragStart);
(0, _xDataGrid.useGridEvent)(apiRef, 'columnHeaderDragEnter', handleDragEnter);
(0, _xDataGrid.useGridEvent)(apiRef, 'columnHeaderDragOver', handleDragOver);
(0, _xDataGrid.useGridEvent)(apiRef, 'columnHeaderDragEndNative', handleDragEnd);
(0, _xDataGrid.useGridEvent)(apiRef, 'cellDragEnter', handleDragEnter);
(0, _xDataGrid.useGridEvent)(apiRef, 'cellDragOver', handleDragOver);
(0, _xDataGrid.useGridEventPriority)(apiRef, 'columnOrderChange', props.onColumnOrderChange);
};
exports.useGridColumnReorder = useGridColumnReorder;
;