diff --git a/docs/pages/api-docs/data-grid.md b/docs/pages/api-docs/data-grid.md index d4996d42fb5f7..c8253c1b7e09e 100644 --- a/docs/pages/api-docs/data-grid.md +++ b/docs/pages/api-docs/data-grid.md @@ -49,12 +49,13 @@ import { DataGrid } from '@material-ui/data-grid'; | onCellEnter | (param: GridCellParams, event: React.MouseEvent) => void | | Callback fired when a mouse enter event comes from a cell element. | | onCellLeave | (param: GridCellParams, event: React.MouseEvent) => void | | Callback fired when a mouse leave event comes from a cell element. | | onCellModeChange | (params: GridCellModeChangeParams) => void | | Callback fired when the cell mode changed. | -| onColumnHeaderClick | (param: GridColParams, event: React.MouseEvent) => void | | Callback fired when a click event comes from a column header element. | -| onColumnHeaderDoubleClick | (param: GridColParams, event: React.MouseEvent) => void | | Callback fired when a double click event comes from a column header element. | -| onColumnHeaderOver | (param: GridColParams, event: React.MouseEvent) => void | | Callback fired when a mouseover event comes from a column header element. | -| onColumnHeaderOut | (param: GridColParams, event: React.MouseEvent) => void | | Callback fired when a mouseout event comes from a column header element. | -| onColumnHeaderEnter | (param: GridColParams, event: React.MouseEvent) => void | | Callback fired when a mouse enter event comes from a column header element. | -| onColumnHeaderLeave | (param: GridColParams, event: React.MouseEvent) => void | | Callback fired when a mouse leave event comes from a column header element. | +| onColumnHeaderClick | (param: GridColumnHeaderParams, event: React.MouseEvent) => void | | Callback fired when a click event comes from a column header element. | +| onColumnHeaderDoubleClick | (param: GridColumnHeaderParams, event: React.MouseEvent) => void | | Callback fired when a double click event comes from a column header element. | +| onColumnHeaderOver | (param: GridColumnHeaderParams, event: React.MouseEvent) => void | | Callback fired when a mouseover event comes from a column header element. | +| onColumnHeaderOut | (param: GridColumnHeaderParams, event: React.MouseEvent) => void | | Callback fired when a mouseout event comes from a column header element. | +| onColumnHeaderEnter | (param: GridColumnHeaderParams, event: React.MouseEvent) => void | | Callback fired when a mouse enter event comes from a column header element. | +| onColumnHeaderLeave | (param: GridColumnHeaderParams, event: React.MouseEvent) => void | | Callback fired when a mouse leave event comes from a column header element. | +| onColumnOrderChange | (param: GridColumnOrderChangeParams, event: React.MouseEvent) => void | | Callback fired when a column is reordered. | | onError | (args: any) => void | | Callback fired when an exception is thrown in the grid, or when the `showError` API method is called. | | onEditCellChange | (params: GridEditCellParams) => void | | Callback fired when the edit cell value changed. | | onEditCellChangeCommitted | (params: GridEditCellParams) => void | | Callback fired when the cell changes are committed. | diff --git a/docs/pages/api-docs/x-grid.md b/docs/pages/api-docs/x-grid.md index 70d636a801620..27cd1415265cd 100644 --- a/docs/pages/api-docs/x-grid.md +++ b/docs/pages/api-docs/x-grid.md @@ -52,12 +52,13 @@ import { XGrid } from '@material-ui/x-grid'; | onCellEnter | (param: GridCellParams, event: React.MouseEvent) => void | | Callback fired when a mouse enter event comes from a cell element. | | onCellLeave | (param: GridCellParams, event: React.MouseEvent) => void | | Callback fired when a mouse leave event comes from a cell element. | | onCellModeChange | (params: GridCellModeChangeParams) => void | | Callback fired when the cell mode changed. | -| onColumnHeaderClick | (param: GridColParams, event: React.MouseEvent) => void | | Callback fired when a click event comes from a column header element. | -| onColumnHeaderDoubleClick | (param: GridColParams, event: React.MouseEvent) => void | | Callback fired when a double click event comes from a column header element. | -| onColumnHeaderOver | (param: GridColParams, event: React.MouseEvent) => void | | Callback fired when a mouseover event comes from a column header element. | -| onColumnHeaderOut | (param: GridColParams, event: React.MouseEvent) => void | | Callback fired when a mouseout event comes from a column header element. | -| onColumnHeaderEnter | (param: GridColParams, event: React.MouseEvent) => void | | Callback fired when a mouse enter event comes from a column header element. | -| onColumnHeaderLeave | (param: GridColParams, event: React.MouseEvent) => void | | Callback fired when a mouse leave event comes from a column header element. | +| onColumnHeaderClick | (param: GridColumnHeaderParams, event: React.MouseEvent) => void | | Callback fired when a click event comes from a column header element. | +| onColumnHeaderDoubleClick | (param: GridColumnHeaderParams, event: React.MouseEvent) => void | | Callback fired when a double click event comes from a column header element. | +| onColumnHeaderOver | (param: GridColumnHeaderParams, event: React.MouseEvent) => void | | Callback fired when a mouseover event comes from a column header element. | +| onColumnHeaderOut | (param: GridColumnHeaderParams, event: React.MouseEvent) => void | | Callback fired when a mouseout event comes from a column header element. | +| onColumnHeaderEnter | (param: GridColumnHeaderParams, event: React.MouseEvent) => void | | Callback fired when a mouse enter event comes from a column header element. | +| onColumnHeaderLeave | (param: GridColumnHeaderParams, event: React.MouseEvent) => void | | Callback fired when a mouse leave event comes from a column header element. | +| onColumnOrderChange | (param: GridColumnOrderChangeParams, event: React.MouseEvent) => void | | Callback fired when a column is reordered. | | onError | (args: any) => void | | Callback fired when an exception is thrown in the grid, or when the `showError` API method is called. | | onEditCellChange | (params: GridEditCellParams) => void | | Callback fired when the edit cell value changed. | | onEditCellChangeCommitted | (params: GridEditCellParams) => void | | Callback fired when the cell changes are committed. | diff --git a/docs/src/pages/components/data-grid/columns/columns.md b/docs/src/pages/components/data-grid/columns/columns.md index d336fcaab61ba..9de526173479f 100644 --- a/docs/src/pages/components/data-grid/columns/columns.md +++ b/docs/src/pages/components/data-grid/columns/columns.md @@ -150,11 +150,11 @@ To disable column reordering, set the prop `disableColumnReorder={true}`. In addition, column reordering emits the following events that can be imported: -- `COL_REORDER_START`: emitted when dragging of a header cell starts. -- `COL_REORDER_DRAG_ENTER`: emitted when the cursor enters another header cell while dragging. -- `COL_REORDER_DRAG_OVER`: emitted when dragging a header cell over another header cell. -- `COL_REORDER_DRAG_OVER_HEADER`: emitted when dragging a header cell over the `ColumnsHeader` component. -- `COL_REORDER_STOP`: emitted when dragging of a header cell stops. +- `columnReordering:dragStart`: emitted when dragging of a header cell starts. +- `columnReordering:dragEnter`: emitted when the cursor enters another header cell while dragging. +- `columnReordering:dragOver`: emitted when dragging a header cell over another header cell. +- `columnReordering:dragOverHeader`: emitted when dragging a header cell over the `ColumnsHeader` component. +- `columnReordering:dragEnd`: emitted when dragging of a header cell stops. {{"demo": "pages/components/data-grid/columns/ColumnOrderingGrid.js", "disableAd": true, "bg": "inline"}} diff --git a/docs/src/pages/components/data-grid/rendering/rendering.md b/docs/src/pages/components/data-grid/rendering/rendering.md index 5880a8adc4947..74a8231c3f7b2 100644 --- a/docs/src/pages/components/data-grid/rendering/rendering.md +++ b/docs/src/pages/components/data-grid/rendering/rendering.md @@ -119,7 +119,7 @@ const columns: GridColDef[] = [ field: 'date', width: 150, type: 'date', - renderHeader: (params: GridColParams) => ( + renderHeader: (params: GridColumnHeaderParams) => ( {'Birthday '} diff --git a/packages/grid/_modules_/grid/components/GridCheckboxRenderer.tsx b/packages/grid/_modules_/grid/components/GridCheckboxRenderer.tsx index f084d38aae347..f276b42fda8b0 100644 --- a/packages/grid/_modules_/grid/components/GridCheckboxRenderer.tsx +++ b/packages/grid/_modules_/grid/components/GridCheckboxRenderer.tsx @@ -4,11 +4,11 @@ import { useGridSelector } from '../hooks/features/core/useGridSelector'; import { visibleSortedGridRowsSelector } from '../hooks/features/filter/gridFilterSelector'; import { gridRowCountSelector } from '../hooks/features/rows/gridRowsSelector'; import { selectedGridRowsCountSelector } from '../hooks/features/selection/gridSelectionSelector'; -import { GridColParams } from '../models/params/gridColParams'; +import { GridColumnHeaderParams } from '../models/params/gridColumnHeaderParams'; import { GridCellParams } from '../models/params/gridCellParams'; import { GridApiContext } from './GridApiContext'; -export const GridHeaderCheckbox: React.FC = () => { +export const GridHeaderCheckbox: React.FC = () => { const apiRef = React.useContext(GridApiContext); const visibleRows = useGridSelector(apiRef, visibleSortedGridRowsSelector); diff --git a/packages/grid/_modules_/grid/components/GridScrollArea.tsx b/packages/grid/_modules_/grid/components/GridScrollArea.tsx index a4fdd934073b6..2936463f2e5b3 100644 --- a/packages/grid/_modules_/grid/components/GridScrollArea.tsx +++ b/packages/grid/_modules_/grid/components/GridScrollArea.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { - GRID_COL_REORDER_START, - GRID_COL_REORDER_STOP, + GRID_COLUMN_REORDER_START, + GRID_COLUMN_REORDER_DRAG_END, GRID_ROWS_SCROLL, } from '../constants/eventsConstants'; import { useGridApiEventHandler } from '../hooks/root/useGridApiEventHandler'; @@ -69,8 +69,8 @@ export const GridScrollArea = React.memo(function GridScrollArea(props: ScrollAr }, []); useGridApiEventHandler(api as GridApiRef, GRID_ROWS_SCROLL, handleScrolling); - useGridApiEventHandler(api as GridApiRef, GRID_COL_REORDER_START, toggleDragging); - useGridApiEventHandler(api as GridApiRef, GRID_COL_REORDER_STOP, toggleDragging); + useGridApiEventHandler(api as GridApiRef, GRID_COLUMN_REORDER_START, toggleDragging); + useGridApiEventHandler(api as GridApiRef, GRID_COLUMN_REORDER_DRAG_END, toggleDragging); return dragging ? (
apiRef!.current.onColItemDragStart(column, event.currentTarget), - [apiRef, column], - ); - const onDragEnter = React.useCallback((event) => apiRef!.current.onColItemDragEnter(event), [ - apiRef, - ]); - const onDragOver = React.useCallback( - (event) => - apiRef!.current.onColItemDragOver(column, { - x: event.clientX, - y: event.clientY, - }), - [apiRef, column], - ); - const publish = React.useCallback( (eventName: string) => (event: React.MouseEvent) => apiRef!.current.publishEvent( @@ -102,6 +90,16 @@ export const GridColumnHeaderItem = ({ [publish], ); + const draggableEventHandlers = React.useMemo( + () => ({ + onDragStart: publish(GRID_COLUMN_REORDER_START), + onDragEnter: publish(GRID_COLUMN_REORDER_DRAG_ENTER), + onDragOver: publish(GRID_COLUMN_REORDER_DRAG_OVER), + onDragEnd: publish(GRID_COLUMN_REORDER_DRAG_END), + }), + [publish], + ); + const cssClasses = classnames( GRID_HEADER_CELL_CSS_CLASS, column.headerClassName, @@ -116,12 +114,6 @@ export const GridColumnHeaderItem = ({ }, ); - const dragConfig = { - draggable: !disableColumnReorder, - onDragStart, - onDragEnter, - onDragOver, - }; const width = column.width!; let ariaSort: any; @@ -159,7 +151,11 @@ export const GridColumnHeaderItem = ({ {...ariaSort} {...mouseEventsHandlers} > -
+
{!disableColumnMenu && isColumnNumeric && !column.disableColumnMenu && columnMenuIconButton}
{isColumnNumeric && columnTitleIconButtons} diff --git a/packages/grid/_modules_/grid/components/columnHeaders/GridColumnHeaders.tsx b/packages/grid/_modules_/grid/components/columnHeaders/GridColumnHeaders.tsx index 4386f018459e0..1de6cfe7b677f 100644 --- a/packages/grid/_modules_/grid/components/columnHeaders/GridColumnHeaders.tsx +++ b/packages/grid/_modules_/grid/components/columnHeaders/GridColumnHeaders.tsx @@ -9,7 +9,9 @@ import { GridEmptyCell } from '../cell/GridEmptyCell'; import { GridScrollArea } from '../GridScrollArea'; import { GridColumnHeadersItemCollection } from './GridColumnHeadersItemCollection'; import { gridDensityHeaderHeightSelector } from '../../hooks/features/density/densitySelector'; +import { gridColumnReorderDragColSelector } from '../../hooks/features/columnReorder/columnReorderSelector'; import { gridContainerSizesSelector } from '../../hooks/root/gridContainerSizesSelector'; +import { GRID_COLUMN_REORDER_DRAG_OVER_HEADER } from '../../constants/eventsConstants'; export const gridScrollbarStateSelector = (state: GridState) => state.scrollBar; @@ -24,6 +26,7 @@ export const GridColumnsHeader = React.forwardRef(function G const headerHeight = useGridSelector(apiRef, gridDensityHeaderHeightSelector); const renderCtx = useGridSelector(apiRef, renderStateSelector).renderContext; const { hasScrollX } = useGridSelector(apiRef, gridScrollbarStateSelector); + const dragCol = useGridSelector(apiRef, gridColumnReorderDragColSelector); const wrapperCssClasses = `MuiDataGrid-colCellWrapper ${hasScrollX ? 'scroll' : ''}`; const renderedCols = React.useMemo(() => { @@ -35,7 +38,12 @@ export const GridColumnsHeader = React.forwardRef(function G const handleDragOver = !disableColumnReorder && apiRef - ? (event) => apiRef.current.onColHeaderDragOver(event, ref as React.RefObject) + ? (event) => + apiRef.current.publishEvent( + GRID_COLUMN_REORDER_DRAG_OVER_HEADER, + apiRef.current.getColumnHeaderParams(dragCol), + event, + ) : undefined; return ( diff --git a/packages/grid/_modules_/grid/constants/eventsConstants.ts b/packages/grid/_modules_/grid/constants/eventsConstants.ts index 7c466f75714af..1bcefd0eb28dd 100644 --- a/packages/grid/_modules_/grid/constants/eventsConstants.ts +++ b/packages/grid/_modules_/grid/constants/eventsConstants.ts @@ -57,11 +57,13 @@ export const GRID_ROWS_SCROLL_END = 'scroll:rowEnd'; export const GRID_COL_RESIZE_START = 'colResizing:start'; export const GRID_COL_RESIZE_STOP = 'colResizing:stop'; -export const GRID_COL_REORDER_START = 'colReordering:dragStart'; -export const GRID_COL_REORDER_DRAG_OVER_HEADER = 'colReordering:dragOverHeader'; -export const GRID_COL_REORDER_DRAG_OVER = 'colReordering:dragOver'; -export const GRID_COL_REORDER_DRAG_ENTER = 'colReordering:dragEnter'; -export const GRID_COL_REORDER_STOP = 'colReordering:dragStop'; +export const GRID_COLUMN_ORDER_CHANGE = 'columnOrderChange'; + +export const GRID_COLUMN_REORDER_START = 'columnReordering:dragStart'; +export const GRID_COLUMN_REORDER_DRAG_OVER_HEADER = 'columnReordering:dragOverHeader'; +export const GRID_COLUMN_REORDER_DRAG_OVER = 'columnReordering:dragOver'; +export const GRID_COLUMN_REORDER_DRAG_ENTER = 'columnReordering:dragEnter'; +export const GRID_COLUMN_REORDER_DRAG_END = 'columnReordering:dragEnd'; export const GRID_ROWS_UPDATED = 'rowsUpdated'; export const GRID_ROWS_SET = 'rowsSet'; diff --git a/packages/grid/_modules_/grid/hooks/features/columnReorder/useGridColumnReorder.tsx b/packages/grid/_modules_/grid/hooks/features/columnReorder/useGridColumnReorder.tsx index 2b203db56cbd5..d1d4dab64f006 100644 --- a/packages/grid/_modules_/grid/hooks/features/columnReorder/useGridColumnReorder.tsx +++ b/packages/grid/_modules_/grid/hooks/features/columnReorder/useGridColumnReorder.tsx @@ -1,21 +1,20 @@ import * as React from 'react'; -import { GridColDef } from '../../../models/colDef'; import { useLogger } from '../../utils/useLogger'; import { GridApiRef } from '../../../models/api/gridApiRef'; import { - GRID_DRAGEND, - GRID_COL_REORDER_START, - GRID_COL_REORDER_DRAG_OVER, - GRID_COL_REORDER_DRAG_OVER_HEADER, - GRID_COL_REORDER_DRAG_ENTER, - GRID_COL_REORDER_STOP, + GRID_COLUMN_REORDER_START, + GRID_COLUMN_REORDER_DRAG_OVER, + GRID_COLUMN_REORDER_DRAG_OVER_HEADER, + GRID_COLUMN_REORDER_DRAG_ENTER, + GRID_COLUMN_REORDER_DRAG_END, } from '../../../constants/eventsConstants'; import { GRID_HEADER_CELL_DROP_ZONE_CSS_CLASS, GRID_HEADER_CELL_DRAGGING_CSS_CLASS, } from '../../../constants/cssClassesConstants'; -import { useGridApiMethod } from '../../root/useGridApiMethod'; -import { ColumnReorderApi, CursorCoordinates } from '../../../models/api/columnReorderApi'; +import { GridColumnHeaderParams } from '../../../models/params/gridColumnHeaderParams'; +import { CursorCoordinates } from '../../../models/cursorCoordinates'; +import { useGridApiEventHandler } from '../../root/useGridApiEventHandler'; import { useGridSelector } from '../core/useGridSelector'; import { useGridState } from '../core/useGridState'; import { gridColumnReorderDragColSelector } from './columnReorderSelector'; @@ -51,35 +50,22 @@ export const useGridColumnReorder = (apiRef: GridApiRef): void => { }); const removeDnDStylesTimeout = React.useRef(); - const handleDragEnd = React.useCallback((): void => { - logger.debug('End dragging col'); - apiRef.current.publishEvent(GRID_COL_REORDER_STOP); - - clearTimeout(removeDnDStylesTimeout.current); - - columnsHeaderRef.current!.classList.remove(GRID_HEADER_CELL_DROP_ZONE_CSS_CLASS); - dragColNode.current!.removeEventListener(GRID_DRAGEND, handleDragEnd); - dragColNode.current = null; - - setGridState((oldState) => ({ - ...oldState, - columnReorder: { ...oldState.columnReorder, dragCol: '' }, - })); - forceUpdate(); - }, [apiRef, setGridState, forceUpdate, logger]); + React.useEffect(() => { + return () => { + clearTimeout(removeDnDStylesTimeout.current); + }; + }, []); - const onColItemDragStart = React.useCallback( - (col: GridColDef, currentTarget: HTMLElement): void => { - logger.debug(`Start dragging col ${col.field}`); - apiRef.current.publishEvent(GRID_COL_REORDER_START); + const handleColumnReorderStart = React.useCallback( + (params: GridColumnHeaderParams, event: React.MouseEvent) => { + logger.debug(`Start dragging col ${params.field}`); - dragColNode.current = currentTarget; - dragColNode.current.addEventListener(GRID_DRAGEND, handleDragEnd, { once: true }); + dragColNode.current = event.currentTarget; dragColNode.current.classList.add(GRID_HEADER_CELL_DRAGGING_CSS_CLASS); setGridState((oldState) => ({ ...oldState, - columnReorder: { ...oldState.columnReorder, dragCol: col.field }, + columnReorder: { ...oldState.columnReorder, dragCol: params.field }, })); forceUpdate(); @@ -87,40 +73,28 @@ export const useGridColumnReorder = (apiRef: GridApiRef): void => { dragColNode.current!.classList.remove(GRID_HEADER_CELL_DRAGGING_CSS_CLASS); }); }, - [apiRef, setGridState, forceUpdate, handleDragEnd, logger], + [forceUpdate, logger, setGridState], ); - React.useEffect(() => { - return () => { - clearTimeout(removeDnDStylesTimeout.current); - }; - }, []); - - const onColHeaderDragOver = React.useCallback( - (event: Event, ref: React.RefObject) => { + const handleColumnReorderEnd = React.useCallback( + (params: GridColumnHeaderParams, event: React.MouseEvent) => { event.preventDefault(); - apiRef.current.publishEvent(GRID_COL_REORDER_DRAG_OVER_HEADER); - columnsHeaderRef.current = ref.current; - columnsHeaderRef.current!.classList.add(GRID_HEADER_CELL_DROP_ZONE_CSS_CLASS); }, - [apiRef], + [], ); - const onColItemDragEnter = React.useCallback( - (event: Event) => { + const handleColumnItemDragOver = React.useCallback( + (params: GridColumnHeaderParams, event: React.MouseEvent) => { + logger.debug(`Dragging over col ${params.field}`); event.preventDefault(); - apiRef.current.publishEvent(GRID_COL_REORDER_DRAG_ENTER); - }, - [apiRef], - ); - const onColItemDragOver = React.useCallback( - (col: GridColDef, coordinates: CursorCoordinates): void => { - logger.debug(`Dragging over col ${col.field}`); - apiRef.current.publishEvent(GRID_COL_REORDER_DRAG_OVER); + const coordinates = { x: event.clientX, y: event.clientY }; - if (col.field !== dragCol && hasCursorPositionChanged(cursorPosition.current, coordinates)) { - const targetColIndex = apiRef.current.getColumnIndex(col.field, false); + if ( + params.field !== dragCol && + hasCursorPositionChanged(cursorPosition.current, coordinates) + ) { + const targetColIndex = apiRef.current.getColumnIndex(params.field, false); const dragColIndex = apiRef.current.getColumnIndex(dragCol, false); if ( @@ -131,7 +105,7 @@ export const useGridColumnReorder = (apiRef: GridApiRef): void => { CURSOR_MOVE_DIRECTION_LEFT && targetColIndex < dragColIndex) ) { - apiRef.current.moveColumn(dragCol, targetColIndex); + apiRef.current.setColumnIndex(dragCol, targetColIndex); } cursorPosition.current = coordinates; @@ -140,12 +114,36 @@ export const useGridColumnReorder = (apiRef: GridApiRef): void => { [apiRef, dragCol, logger], ); - const colReorderApi: ColumnReorderApi = { - onColItemDragStart, - onColHeaderDragOver, - onColItemDragOver, - onColItemDragEnter, - }; + const handleHeaderDragOver = React.useCallback( + (params: GridColumnHeaderParams, event: React.MouseEvent) => { + columnsHeaderRef.current = event.currentTarget; + columnsHeaderRef.current!.classList.add(GRID_HEADER_CELL_DROP_ZONE_CSS_CLASS); + }, + [], + ); + + const handleColumnItemDragEnd = React.useCallback( + (params: GridColumnHeaderParams, event: React.MouseEvent): void => { + logger.debug('End dragging col'); + event.preventDefault(); + + clearTimeout(removeDnDStylesTimeout.current); + + columnsHeaderRef.current!.classList.remove(GRID_HEADER_CELL_DROP_ZONE_CSS_CLASS); + dragColNode.current = null; + + setGridState((oldState) => ({ + ...oldState, + columnReorder: { ...oldState.columnReorder, dragCol: '' }, + })); + forceUpdate(); + }, + [logger, setGridState, forceUpdate], + ); - useGridApiMethod(apiRef, colReorderApi, 'ColReorderApi'); + useGridApiEventHandler(apiRef, GRID_COLUMN_REORDER_START, handleColumnReorderStart); + useGridApiEventHandler(apiRef, GRID_COLUMN_REORDER_DRAG_ENTER, handleColumnReorderEnd); + useGridApiEventHandler(apiRef, GRID_COLUMN_REORDER_DRAG_OVER, handleColumnItemDragOver); + useGridApiEventHandler(apiRef, GRID_COLUMN_REORDER_DRAG_OVER_HEADER, handleHeaderDragOver); + useGridApiEventHandler(apiRef, GRID_COLUMN_REORDER_DRAG_END, handleColumnItemDragEnd); }; diff --git a/packages/grid/_modules_/grid/hooks/features/columns/useGridColumns.ts b/packages/grid/_modules_/grid/hooks/features/columns/useGridColumns.ts index e1c169a6cca1f..2d509d25822a8 100644 --- a/packages/grid/_modules_/grid/hooks/features/columns/useGridColumns.ts +++ b/packages/grid/_modules_/grid/hooks/features/columns/useGridColumns.ts @@ -1,5 +1,5 @@ import * as React from 'react'; -import { GRID_COLUMNS_UPDATED } from '../../../constants/eventsConstants'; +import { GRID_COLUMNS_UPDATED, GRID_COLUMN_ORDER_CHANGE } from '../../../constants/eventsConstants'; import { GridApiRef } from '../../../models/api/gridApiRef'; import { GridColumnApi } from '../../../models/api/gridColumnApi'; import { gridCheckboxSelectionColDef } from '../../../models/colDef/gridCheckboxSelection'; @@ -13,6 +13,7 @@ import { import { GridColumnTypesRecord } from '../../../models/colDef/gridColTypeDef'; import { getGridDefaultColumnTypes } from '../../../models/colDef/gridDefaultColumnTypes'; import { getGridColDef } from '../../../models/colDef/getGridColDef'; +import { GridColumnOrderChangeParams } from '../../../models/params/gridColumnOrderChangeParams'; import { mergeGridColTypes } from '../../../utils/mergeUtils'; import { useGridApiMethod } from '../../root/useGridApiMethod'; import { optionsSelector } from '../../utils/optionsSelector'; @@ -165,16 +166,30 @@ export function useGridColumns(columns: GridColumns, apiRef: GridApiRef): void { [forceUpdate, getColumnFromField, updateColumns], ); - const moveColumn = React.useCallback( + const setColumnIndex = React.useCallback( (field: string, targetIndexPosition: number) => { - logger.debug(`Moving column ${field} to index ${targetIndexPosition}`); const oldIndexPosition = gridState.columns.all.findIndex((col) => col === field); + if (oldIndexPosition === targetIndexPosition) { + return; + } + + logger.debug(`Moving column ${field} to index ${targetIndexPosition}`); + + const params: GridColumnOrderChangeParams = { + field, + element: apiRef.current.getColumnHeaderElement(field), + colDef: apiRef.current.getColumnFromField(field), + targetIndex: targetIndexPosition, + oldIndex: oldIndexPosition, + api: apiRef.current, + }; + apiRef.current.publishEvent(GRID_COLUMN_ORDER_CHANGE, params); const updatedColumns = [...gridState.columns.all]; updatedColumns.splice(targetIndexPosition, 0, updatedColumns.splice(oldIndexPosition, 1)[0]); - updateState({ ...gridState.columns, all: updatedColumns }, false); + updateState({ ...gridState.columns, all: updatedColumns }); }, - [gridState.columns, logger, updateState], + [apiRef, gridState.columns, logger, updateState], ); const colApi: GridColumnApi = { @@ -187,7 +202,7 @@ export function useGridColumns(columns: GridColumns, apiRef: GridApiRef): void { updateColumn, updateColumns, toggleColumn, - moveColumn, + setColumnIndex, }; useGridApiMethod(apiRef, colApi, 'ColApi'); diff --git a/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts b/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts index c6554f05ce5af..7a5e28772738a 100644 --- a/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts +++ b/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts @@ -3,7 +3,7 @@ import { GridApiRef } from '../../../models/api/gridApiRef'; import { GridParamsApi } from '../../../models/api/gridParamsApi'; import { GridRowId } from '../../../models/gridRows'; import { GridCellParams, GridValueGetterParams } from '../../../models/params/gridCellParams'; -import { GridColParams } from '../../../models/params/gridColParams'; +import { GridColumnHeaderParams } from '../../../models/params/gridColumnHeaderParams'; import { GridRowParams } from '../../../models/params/gridRowParams'; import { getGridCellElement, @@ -26,7 +26,7 @@ function warnMissingColumn(field) { } export function useGridParamsApi(apiRef: GridApiRef) { const getColumnHeaderParams = React.useCallback( - (field: string): GridColParams => ({ + (field: string): GridColumnHeaderParams => ({ field, element: apiRef.current.getColumnHeaderElement(field), colDef: apiRef.current.getColumnFromField(field), diff --git a/packages/grid/_modules_/grid/hooks/features/sorting/useGridSorting.ts b/packages/grid/_modules_/grid/hooks/features/sorting/useGridSorting.ts index c11e4a38724d9..af48acdb35160 100644 --- a/packages/grid/_modules_/grid/hooks/features/sorting/useGridSorting.ts +++ b/packages/grid/_modules_/grid/hooks/features/sorting/useGridSorting.ts @@ -14,7 +14,7 @@ import { GridCellValue } from '../../../models/gridCell'; import { GridColDef } from '../../../models/colDef/gridColDef'; import { GridFeatureModeConstant } from '../../../models/gridFeatureMode'; import { GridCellParams } from '../../../models/params/gridCellParams'; -import { GridColParams } from '../../../models/params/gridColParams'; +import { GridColumnHeaderParams } from '../../../models/params/gridColumnHeaderParams'; import { GridSortModelParams } from '../../../models/params/gridSortModelParams'; import { GridRowModel, GridRowsProp } from '../../../models/gridRows'; import { @@ -209,7 +209,7 @@ export const useGridSorting = (apiRef: GridApiRef, rowsProp: GridRowsProp) => { ); const headerClickHandler = React.useCallback( - ({ colDef }: GridColParams) => { + ({ colDef }: GridColumnHeaderParams) => { sortColumn(colDef); }, [sortColumn], diff --git a/packages/grid/_modules_/grid/hooks/features/useGridColumnResize.tsx b/packages/grid/_modules_/grid/hooks/features/useGridColumnResize.tsx index 6eb9ddaf15514..76508d471bcb7 100644 --- a/packages/grid/_modules_/grid/hooks/features/useGridColumnResize.tsx +++ b/packages/grid/_modules_/grid/hooks/features/useGridColumnResize.tsx @@ -16,8 +16,7 @@ import { getFieldFromHeaderElem, findHeaderElementFromField, } from '../../utils/domUtils'; -import { GridApiRef } from '../../models'; -import { CursorCoordinates } from '../../models/api/columnReorderApi'; +import { GridApiRef, CursorCoordinates } from '../../models'; const MIN_COL_WIDTH = 50; let cachedSupportsTouchActionNone = false; diff --git a/packages/grid/_modules_/grid/hooks/root/useEvents.ts b/packages/grid/_modules_/grid/hooks/root/useEvents.ts index e04c1c52d2dcb..88fa0cec28b27 100644 --- a/packages/grid/_modules_/grid/hooks/root/useEvents.ts +++ b/packages/grid/_modules_/grid/hooks/root/useEvents.ts @@ -32,6 +32,7 @@ import { GRID_COLUMN_HEADER_DOUBLE_CLICK, GRID_COLUMN_HEADER_OVER, GRID_COLUMN_HEADER_OUT, + GRID_COLUMN_ORDER_CHANGE, GRID_CELL_KEYDOWN, GRID_CELL_BLUR, } from '../../constants/eventsConstants'; @@ -98,6 +99,7 @@ export function useEvents(gridRootRef: React.RefObject, apiRef: useGridApiOptionHandler(apiRef, GRID_COLUMN_HEADER_OUT, options.onColumnHeaderOut); useGridApiOptionHandler(apiRef, GRID_COLUMN_HEADER_ENTER, options.onColumnHeaderEnter); useGridApiOptionHandler(apiRef, GRID_COLUMN_HEADER_LEAVE, options.onColumnHeaderLeave); + useGridApiOptionHandler(apiRef, GRID_COLUMN_ORDER_CHANGE, options.onColumnOrderChange); useGridApiOptionHandler(apiRef, GRID_CELL_CLICK, options.onCellClick); useGridApiOptionHandler(apiRef, GRID_CELL_DOUBLE_CLICK, options.onCellDoubleClick); diff --git a/packages/grid/_modules_/grid/models/api/columnReorderApi.ts b/packages/grid/_modules_/grid/models/api/columnReorderApi.ts deleted file mode 100644 index ebcf40f0d21db..0000000000000 --- a/packages/grid/_modules_/grid/models/api/columnReorderApi.ts +++ /dev/null @@ -1,40 +0,0 @@ -import * as React from 'react'; -import { GridColDef } from '../colDef/gridColDef'; - -export interface CursorCoordinates { - x: number; - y: number; -} - -/** - * The column reorder API interface that is available in the grid [[apiRef]]. - */ -export interface ColumnReorderApi { - /** - * Column item drag start event handler. - * @param column - * @param target - * @returns void - */ - onColItemDragStart: (column: GridColDef, target: HTMLElement) => void; - /** - * Column header drag over event handler. - * @param event - * @param ref - * @returns void - */ - onColHeaderDragOver: (event: Event, ref: React.RefObject) => void; - /** - * Column item drag over event handler. - * @param column - * @param coordinates - * @returns void - */ - onColItemDragOver: (column: GridColDef, coordinates: CursorCoordinates) => void; - /** - * Column item drag enter event handler. - * @param event - * @returns void - */ - onColItemDragEnter: (event: Event) => void; -} diff --git a/packages/grid/_modules_/grid/models/api/gridApi.ts b/packages/grid/_modules_/grid/models/api/gridApi.ts index a36f6889af844..9b7ebab3e0c72 100644 --- a/packages/grid/_modules_/grid/models/api/gridApi.ts +++ b/packages/grid/_modules_/grid/models/api/gridApi.ts @@ -8,7 +8,6 @@ import { GridEditRowApi } from './gridEditRowApi'; import { PreferencesPanelApi } from './preferencesPanelApi'; import { GridRowApi } from './gridRowApi'; import { GridColumnApi } from './gridColumnApi'; -import { ColumnReorderApi } from './columnReorderApi'; import { GridSelectionApi } from './gridSelectionApi'; import { GridSortApi } from './gridSortApi'; import { GridPaginationApi } from './gridPaginationApi'; @@ -32,7 +31,6 @@ export type GridApi = GridCoreApi & GridEditRowApi & GridParamsApi & GridColumnApi & - ColumnReorderApi & GridSelectionApi & GridSortApi & GridVirtualizationApi & diff --git a/packages/grid/_modules_/grid/models/api/gridColumnApi.ts b/packages/grid/_modules_/grid/models/api/gridColumnApi.ts index 02248d5523f5d..ee5e8bea0907b 100644 --- a/packages/grid/_modules_/grid/models/api/gridColumnApi.ts +++ b/packages/grid/_modules_/grid/models/api/gridColumnApi.ts @@ -57,5 +57,5 @@ export interface GridColumnApi { * @param field * @param targetIndexPosition . */ - moveColumn: (field: string, targetIndexPosition: number) => void; + setColumnIndex: (field: string, targetIndexPosition: number) => void; } diff --git a/packages/grid/_modules_/grid/models/api/gridParamsApi.ts b/packages/grid/_modules_/grid/models/api/gridParamsApi.ts index 35095dc3d812c..cc49558a471bf 100644 --- a/packages/grid/_modules_/grid/models/api/gridParamsApi.ts +++ b/packages/grid/_modules_/grid/models/api/gridParamsApi.ts @@ -1,7 +1,7 @@ import { GridCellValue } from '../gridCell'; import { GridRowId } from '../gridRows'; import { GridCellParams } from '../params/gridCellParams'; -import { GridColParams } from '../params/gridColParams'; +import { GridColumnHeaderParams } from '../params/gridColumnHeaderParams'; import { GridRowParams } from '../params/gridRowParams'; export interface GridParamsApi { @@ -44,5 +44,5 @@ export interface GridParamsApi { * Get the header params that are passed in events. * @param field */ - getColumnHeaderParams: (field: string) => GridColParams; + getColumnHeaderParams: (field: string) => GridColumnHeaderParams; } diff --git a/packages/grid/_modules_/grid/models/colDef/gridColDef.ts b/packages/grid/_modules_/grid/models/colDef/gridColDef.ts index d947351afb99c..cb2a01899f1b9 100644 --- a/packages/grid/_modules_/grid/models/colDef/gridColDef.ts +++ b/packages/grid/_modules_/grid/models/colDef/gridColDef.ts @@ -7,7 +7,7 @@ import { GridValueFormatterParams, GridValueGetterParams, } from '../params/gridCellParams'; -import { GridColParams } from '../params/gridColParams'; +import { GridColumnHeaderParams } from '../params/gridColumnHeaderParams'; import { GridComparatorFn } from '../gridSortModel'; import { GridColType, GridNativeColTypes } from './gridColType'; @@ -110,7 +110,7 @@ export interface GridColDef { * Allows to render a component in the column header cell. * @param params */ - renderHeader?: (params: GridColParams) => React.ReactElement; + renderHeader?: (params: GridColumnHeaderParams) => React.ReactElement; /** * Header cell element alignment. */ diff --git a/packages/grid/_modules_/grid/models/cursorCoordinates.ts b/packages/grid/_modules_/grid/models/cursorCoordinates.ts new file mode 100644 index 0000000000000..bda9d1928d706 --- /dev/null +++ b/packages/grid/_modules_/grid/models/cursorCoordinates.ts @@ -0,0 +1,4 @@ +export interface CursorCoordinates { + x: number; + y: number; +} diff --git a/packages/grid/_modules_/grid/models/gridOptions.tsx b/packages/grid/_modules_/grid/models/gridOptions.tsx index 7a2e84640d294..91d9cdb943f3e 100644 --- a/packages/grid/_modules_/grid/models/gridOptions.tsx +++ b/packages/grid/_modules_/grid/models/gridOptions.tsx @@ -9,7 +9,7 @@ import { GridDensity, GridDensityTypes } from './gridDensity'; import { GridEditRowsModel } from './gridEditRowModel'; import { GridFeatureMode, GridFeatureModeConstant } from './gridFeatureMode'; import { GridCellParams } from './params/gridCellParams'; -import { GridColParams } from './params/gridColParams'; +import { GridColumnHeaderParams } from './params/gridColumnHeaderParams'; import { GridFilterModelParams } from './params/gridFilterModelParams'; import { GridPageChangeParams } from './params/gridPageChangeParams'; import { GridRowParams } from './params/gridRowParams'; @@ -25,6 +25,7 @@ import { GridEditRowModelParams, } from './params/gridEditCellParams'; import { GridRowScrollEndParams } from './params/gridRowScrollEndParams'; +import { GridColumnOrderChangeParams } from './params/gridColumnOrderChangeParams'; // TODO add multiSortKey /** @@ -261,34 +262,45 @@ export interface GridOptions { onCellValueChange?: (params: GridEditCellValueParams) => void; /** * Callback fired when a click event comes from a column header element. - * @param param With all properties from [[GridColParams]]. + * @param param With all properties from [[GridColumnHeaderParams]]. + * @param event [[React.MouseEvent]]. */ - onColumnHeaderClick?: (param: GridColParams, event: React.MouseEvent) => void; + onColumnHeaderClick?: (param: GridColumnHeaderParams, event: React.MouseEvent) => void; /** * Callback fired when a double click event comes from a column header element. - * @param param With all properties from [[GridColParams]]. + * @param param With all properties from [[GridColumnHeaderParams]]. + * @param event [[React.MouseEvent]]. */ - onColumnHeaderDoubleClick?: (param: GridColParams, event: React.MouseEvent) => void; + onColumnHeaderDoubleClick?: (param: GridColumnHeaderParams, event: React.MouseEvent) => void; /** * Callback fired when a mouseover event comes from a column header element. - * @param param With all properties from [[GridColParams]]. + * @param param With all properties from [[GridColumnHeaderParams]]. + * @param event [[React.MouseEvent]]. */ - onColumnHeaderOver?: (param: GridColParams, event: React.MouseEvent) => void; + onColumnHeaderOver?: (param: GridColumnHeaderParams, event: React.MouseEvent) => void; /** * Callback fired when a mouseout event comes from a column header element. - * @param param With all properties from [[GridColParams]]. + * @param param With all properties from [[GridColumnHeaderParams]]. + * @param event [[React.MouseEvent]]. */ - onColumnHeaderOut?: (param: GridColParams, event: React.MouseEvent) => void; + onColumnHeaderOut?: (param: GridColumnHeaderParams, event: React.MouseEvent) => void; /** * Callback fired when a mouse enter event comes from a column header element. - * @param param With all properties from [[GridColParams]]. + * @param param With all properties from [[GridColumnHeaderParams]]. + * @param event [[React.MouseEvent]]. */ - onColumnHeaderEnter?: (param: GridColParams, event: React.MouseEvent) => void; + onColumnHeaderEnter?: (param: GridColumnHeaderParams, event: React.MouseEvent) => void; /** * Callback fired when a mouse leave event comes from a column header element. - * @param param With all properties from [[GridColParams]]. + * @param param With all properties from [[GridColumnHeaderParams]]. + * @param event [[React.MouseEvent]]. + */ + onColumnHeaderLeave?: (param: GridColumnHeaderParams, event: React.MouseEvent) => void; + /** + * Callback fired when a column is reordered. + * @param param With all properties from [[GridColumnHeaderParams]]. */ - onColumnHeaderLeave?: (param: GridColParams, event: React.MouseEvent) => void; + onColumnOrderChange?: (param: GridColumnOrderChangeParams) => void; /** * Callback fired when the Filter model changes before the filters are applied. * @param param With all properties from [[GridFilterModelParams]]. diff --git a/packages/grid/_modules_/grid/models/index.ts b/packages/grid/_modules_/grid/models/index.ts index 4d85995ec11f5..2448a37e5d72d 100644 --- a/packages/grid/_modules_/grid/models/index.ts +++ b/packages/grid/_modules_/grid/models/index.ts @@ -1,4 +1,5 @@ export * from './colDef'; +export * from './cursorCoordinates'; export * from './gridContainerProps'; export * from './elementSize'; export * from './gridEditRowModel'; diff --git a/packages/grid/_modules_/grid/models/params/gridColParams.ts b/packages/grid/_modules_/grid/models/params/gridColumnHeaderParams.ts similarity index 92% rename from packages/grid/_modules_/grid/models/params/gridColParams.ts rename to packages/grid/_modules_/grid/models/params/gridColumnHeaderParams.ts index 67c1c3e982edd..a002458ada4f4 100644 --- a/packages/grid/_modules_/grid/models/params/gridColParams.ts +++ b/packages/grid/_modules_/grid/models/params/gridColumnHeaderParams.ts @@ -1,7 +1,7 @@ /** * Object passed as parameter in the column [[GridColDef]] header renderer. */ -export interface GridColParams { +export interface GridColumnHeaderParams { /** * The HTMLElement column header element. */ diff --git a/packages/grid/_modules_/grid/models/params/gridColumnOrderChangeParams.ts b/packages/grid/_modules_/grid/models/params/gridColumnOrderChangeParams.ts new file mode 100644 index 0000000000000..846d7b3206078 --- /dev/null +++ b/packages/grid/_modules_/grid/models/params/gridColumnOrderChangeParams.ts @@ -0,0 +1,29 @@ +/** + * Object passed as parameter of the column order change event. + */ +export interface GridColumnOrderChangeParams { + /** + * The HTMLElement column header element. + */ + element?: HTMLElement | null; + /** + * The column field of the column that triggered the event. + */ + field: string; + /** + * The column of the current header component. + */ + colDef: any; + /** + * The target column index. + */ + targetIndex: number; + /** + * The old column index. + */ + oldIndex: number; + /** + * API ref that let you manipulate the grid. + */ + api: any; +} diff --git a/packages/grid/_modules_/grid/models/params/index.ts b/packages/grid/_modules_/grid/models/params/index.ts index 63861f2b1c01e..20e72a2433969 100644 --- a/packages/grid/_modules_/grid/models/params/index.ts +++ b/packages/grid/_modules_/grid/models/params/index.ts @@ -1,6 +1,7 @@ export * from './gridCellParams'; export * from './gridEditCellParams'; -export * from './gridColParams'; +export * from './gridColumnHeaderParams'; +export * from './gridColumnOrderChangeParams'; export * from './gridSlotComponentProps'; export * from './gridFilterModelParams'; export * from './gridPageChangeParams'; diff --git a/packages/grid/x-grid/src/tests/events.XGrid.test.tsx b/packages/grid/x-grid/src/tests/events.XGrid.test.tsx index f31b03572cc86..42bd436cc56e5 100644 --- a/packages/grid/x-grid/src/tests/events.XGrid.test.tsx +++ b/packages/grid/x-grid/src/tests/events.XGrid.test.tsx @@ -7,7 +7,7 @@ import { import { expect } from 'chai'; import { XGrid, - GridColParams, + GridColumnHeaderParams, useGridApiRef, XGridProps, GridRowParams, @@ -72,7 +72,7 @@ describe(' - Events Params', () => { describe('columnHeaderParams', () => { it('should include the correct params', () => { - let eventArgs: { params: GridColParams; event: React.MouseEvent } | null = null; + let eventArgs: { params: GridColumnHeaderParams; event: React.MouseEvent } | null = null; const handleClick = (params, event) => { eventArgs = { params, event }; }; diff --git a/packages/grid/x-grid/src/tests/reorder.XGrid.test.tsx b/packages/grid/x-grid/src/tests/reorder.XGrid.test.tsx index f20ca4dceaa76..873c3a0903643 100644 --- a/packages/grid/x-grid/src/tests/reorder.XGrid.test.tsx +++ b/packages/grid/x-grid/src/tests/reorder.XGrid.test.tsx @@ -51,7 +51,7 @@ describe(' - Reorder', () => { expect(getColumnHeadersTextContent()).to.deep.equal(['id', 'brand']); act(() => { - apiRef!.current.moveColumn('id', 1); + apiRef!.current.setColumnIndex('id', 1); }); setProps({ width: 200 }); await raf(); @@ -76,7 +76,7 @@ describe(' - Reorder', () => { const { forceUpdate } = render(); expect(getColumnHeadersTextContent()).to.deep.equal(['brand', 'desc', 'type']); - apiRef!.current.moveColumn('brand', 2); + apiRef!.current.setColumnIndex('brand', 2); expect(getColumnHeadersTextContent()).to.deep.equal(['desc', 'type', 'brand']); forceUpdate(); // test stability expect(getColumnHeadersTextContent()).to.deep.equal(['desc', 'type', 'brand']);