From bc6b9f7113ec54bbe0cc0fee3853a9d6b6035bfb Mon Sep 17 00:00:00 2001 From: damien Date: Wed, 3 Mar 2021 19:22:02 +0100 Subject: [PATCH 01/22] remove event capture --- packages/grid/_modules_/grid/components/GridCell.tsx | 3 +++ packages/grid/_modules_/grid/components/GridRow.tsx | 11 ++++++++++- .../grid/_modules_/grid/components/GridRowCells.tsx | 5 +++++ packages/grid/_modules_/grid/utils/paramsUtils.ts | 1 - 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/grid/_modules_/grid/components/GridCell.tsx b/packages/grid/_modules_/grid/components/GridCell.tsx index 57ff12801d0bf..37342ec2c4ecf 100644 --- a/packages/grid/_modules_/grid/components/GridCell.tsx +++ b/packages/grid/_modules_/grid/components/GridCell.tsx @@ -18,6 +18,7 @@ export interface GridCellProps { tabIndex?: number; value?: GridCellValue; width: number; + onClick?: ((event: React.MouseEvent) => void) ; } export const GridCell: React.FC = React.memo((props) => { @@ -36,6 +37,7 @@ export const GridCell: React.FC = React.memo((props) => { tabIndex, value, width, + onClick } = props; const valueToRender = formattedValue || value; @@ -68,6 +70,7 @@ export const GridCell: React.FC = React.memo((props) => { maxHeight: height, }} tabIndex={tabIndex} + onClick={onClick} > {children || valueToRender?.toString()} diff --git a/packages/grid/_modules_/grid/components/GridRow.tsx b/packages/grid/_modules_/grid/components/GridRow.tsx index 427ceaf65ddf7..19ab111b06bb2 100644 --- a/packages/grid/_modules_/grid/components/GridRow.tsx +++ b/packages/grid/_modules_/grid/components/GridRow.tsx @@ -1,7 +1,8 @@ import * as React from 'react'; +import { GRID_ROW_CLICK } from '../constants/eventsConstants'; import { GridRowId } from '../models'; import { GRID_ROW_CSS_CLASS } from '../constants/cssClassesConstants'; -import { classnames } from '../utils'; +import { buildGridRowParams, classnames } from '../utils'; import { gridDensityRowHeightSelector } from '../hooks/features/density'; import { GridApiContext } from './GridApiContext'; import { useGridSelector } from '../hooks/features/core/useGridSelector'; @@ -18,6 +19,13 @@ export const GridRow: React.FC = ({ selected, id, className, rowIndex, const apiRef = React.useContext(GridApiContext); const rowHeight = useGridSelector(apiRef, gridDensityRowHeightSelector); + const onClick = React.useCallback((event: React.MouseEvent)=>{ + const rowModel = apiRef?.current.getRowFromId(id)!; + const element = event.target as HTMLElement + const commonParams =buildGridRowParams({rowModel, rowIndex, element: element!, api: apiRef!.current}); + apiRef?.current.publishEvent(GRID_ROW_CLICK, commonParams); + }, [apiRef, id, rowIndex] ); + return (
= ({ selected, id, className, rowIndex, maxHeight: rowHeight, minHeight: rowHeight, }} + onClick={onClick} > {children}
diff --git a/packages/grid/_modules_/grid/components/GridRowCells.tsx b/packages/grid/_modules_/grid/components/GridRowCells.tsx index d8af0d65cf69e..60ead990a4c68 100644 --- a/packages/grid/_modules_/grid/components/GridRowCells.tsx +++ b/packages/grid/_modules_/grid/components/GridRowCells.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import { GRID_CELL_CLICK } from '../constants/eventsConstants'; import { gridEditRowsStateSelector } from '../hooks/features/rows/gridEditRowsSelector'; import { GridCellClassParams, @@ -101,6 +102,9 @@ export const GridRowCells: React.FC = React.memo((props) => { // TODO add formatted value to cellParams? formattedValueProp = { formattedValue: column.valueFormatter(cellParams) }; } + const onClick = ()=>{ + api?.current.publishEvent(GRID_CELL_CLICK, cellParams); + } ; if (editCellState == null && column.renderCell) { cellComponent = column.renderCell(cellParams); @@ -131,6 +135,7 @@ export const GridRowCells: React.FC = React.memo((props) => { cellFocus !== null && cellFocus.rowIndex === rowIndex && cellFocus.colIndex === colIdx + firstColIdx, + onClick }; return cellProps; diff --git a/packages/grid/_modules_/grid/utils/paramsUtils.ts b/packages/grid/_modules_/grid/utils/paramsUtils.ts index f2430026b1e09..41b42127ee59f 100644 --- a/packages/grid/_modules_/grid/utils/paramsUtils.ts +++ b/packages/grid/_modules_/grid/utils/paramsUtils.ts @@ -79,7 +79,6 @@ export function buildGridRowParams({ api, }: { rowModel: GridRowModel; - colDef: GridColDef; rowIndex: number; api: GridApi; element?: HTMLElement; From 576aed0732867a3a222e5d0021073b0f11add495 Mon Sep 17 00:00:00 2001 From: damien Date: Mon, 8 Mar 2021 16:48:11 +0100 Subject: [PATCH 02/22] refactor event system --- .../grid/_modules_/grid/GridComponent.tsx | 2 + .../_modules_/grid/components/GridCell.tsx | 78 ++++++++- .../_modules_/grid/components/GridRow.tsx | 67 +++++++- .../grid/components/GridRowCells.tsx | 29 +--- .../columnHeaders/GridColumnHeaderItem.tsx | 21 ++- .../grid/constants/eventsConstants.ts | 10 +- .../grid/hooks/features/rows/index.ts | 1 + .../hooks/features/rows/useGridCellApi.ts | 97 +++++++++++ .../hooks/features/rows/useGridEditRows.ts | 27 +-- .../_modules_/grid/hooks/root/useEvents.ts | 160 +++--------------- .../grid/hooks/root/useGridApiEventHandler.ts | 2 +- .../grid/_modules_/grid/models/api/gridApi.ts | 2 + .../_modules_/grid/models/api/gridCellApi.ts | 17 ++ .../grid/models/api/gridEditRowApi.ts | 6 - .../grid/_modules_/grid/models/api/index.ts | 1 + .../_modules_/grid/models/gridOptions.tsx | 22 ++- .../grid/models/params/gridCellParams.ts | 2 +- .../grid/models/params/gridRowParams.ts | 2 +- .../grid/_modules_/grid/utils/domUtils.ts | 11 ++ .../src/stories/grid-events.stories.tsx | 36 +++- 20 files changed, 362 insertions(+), 231 deletions(-) create mode 100644 packages/grid/_modules_/grid/hooks/features/rows/useGridCellApi.ts create mode 100644 packages/grid/_modules_/grid/models/api/gridCellApi.ts diff --git a/packages/grid/_modules_/grid/GridComponent.tsx b/packages/grid/_modules_/grid/GridComponent.tsx index 15489cdfe0f21..b367d03c5800d 100644 --- a/packages/grid/_modules_/grid/GridComponent.tsx +++ b/packages/grid/_modules_/grid/GridComponent.tsx @@ -21,6 +21,7 @@ import { useGridColumns } from './hooks/features/columns/useGridColumns'; import { useGridState } from './hooks/features/core/useGridState'; import { useGridPagination } from './hooks/features/pagination/useGridPagination'; import { useGridPreferencesPanel } from './hooks/features/preferencesPanel/useGridPreferencesPanel'; +import { useGridCellApi } from './hooks/features/rows/useGridCellApi'; import { useGridRows } from './hooks/features/rows/useGridRows'; import { useGridEditRows } from './hooks/features/rows/useGridEditRows'; import { useGridSorting } from './hooks/features/sorting/useGridSorting'; @@ -75,6 +76,7 @@ export const GridComponent = React.forwardRef) => void) ; } export const GridCell: React.FC = React.memo((props) => { @@ -33,15 +42,24 @@ export const GridCell: React.FC = React.memo((props) => { height, isEditable, rowIndex, + rowId, showRightBorder, tabIndex, value, width, - onClick } = props; const valueToRender = formattedValue || value; const cellRef = React.useRef(null); + const apiRef = React.useContext(GridApiContext); + + const getParams = React.useCallback(() => { + if (rowId == null || field == null || !apiRef?.current) { + return null; + } + + return apiRef!.current.getCellParams(rowId, field); + }, [apiRef, field, rowId]); React.useEffect(() => { if (hasFocus && cellRef.current) { @@ -49,6 +67,53 @@ export const GridCell: React.FC = React.memo((props) => { } }, [hasFocus]); + const handleClick = React.useCallback( + (event: React.MouseEvent) => { + const params = getParams(); + if (params?.colDef.disableClickEventBubbling) { + event.stopPropagation(); + } + + apiRef?.current.publishEvent(GRID_CELL_CLICK, params, event); + }, + [apiRef, getParams], + ); + + const handleDoubleClick = React.useCallback( + (event: React.MouseEvent) => { + apiRef?.current.publishEvent(GRID_DOUBLE_CELL_CLICK, getParams(), event); + }, + [apiRef, getParams], + ); + + const handleHover = React.useCallback( + (event: React.MouseEvent) => { + apiRef?.current.publishEvent(GRID_CELL_OVER, getParams(), event); + }, + [apiRef, getParams], + ); + + const handleOut = React.useCallback( + (event: React.MouseEvent) => { + apiRef?.current.publishEvent(GRID_CELL_OUT, getParams(), event); + }, + [apiRef, getParams], + ); + + const handleEnter = React.useCallback( + (event: React.MouseEvent) => { + apiRef?.current.publishEvent(GRID_CELL_ENTER, getParams(), event); + }, + [apiRef, getParams], + ); + + const handleLeave = React.useCallback( + (event: React.MouseEvent) => { + apiRef?.current.publishEvent(GRID_CELL_LEAVE, getParams(), event); + }, + [apiRef, getParams], + ); + return (
= React.memo((props) => { maxHeight: height, }} tabIndex={tabIndex} - onClick={onClick} + onClick={handleClick} + onDoubleClick={handleDoubleClick} + onMouseEnter={handleEnter} + onMouseLeave={handleLeave} + onMouseOver={handleHover} + onMouseOut={handleOut} > {children || valueToRender?.toString()}
diff --git a/packages/grid/_modules_/grid/components/GridRow.tsx b/packages/grid/_modules_/grid/components/GridRow.tsx index 19ab111b06bb2..9e0521f48dcc0 100644 --- a/packages/grid/_modules_/grid/components/GridRow.tsx +++ b/packages/grid/_modules_/grid/components/GridRow.tsx @@ -1,5 +1,12 @@ import * as React from 'react'; -import { GRID_ROW_CLICK } from '../constants/eventsConstants'; +import { + GRID_DOUBLE_ROW_CLICK, + GRID_ROW_CLICK, + GRID_ROW_ENTER, + GRID_ROW_LEAVE, + GRID_ROW_OUT, + GRID_ROW_OVER, +} from '../constants/eventsConstants'; import { GridRowId } from '../models'; import { GRID_ROW_CSS_CLASS } from '../constants/cssClassesConstants'; import { buildGridRowParams, classnames } from '../utils'; @@ -19,12 +26,51 @@ export const GridRow: React.FC = ({ selected, id, className, rowIndex, const apiRef = React.useContext(GridApiContext); const rowHeight = useGridSelector(apiRef, gridDensityRowHeightSelector); - const onClick = React.useCallback((event: React.MouseEvent)=>{ - const rowModel = apiRef?.current.getRowFromId(id)!; - const element = event.target as HTMLElement - const commonParams =buildGridRowParams({rowModel, rowIndex, element: element!, api: apiRef!.current}); - apiRef?.current.publishEvent(GRID_ROW_CLICK, commonParams); - }, [apiRef, id, rowIndex] ); + const handleClick = React.useCallback( + (event: React.MouseEvent) => { + const params = apiRef?.current.getRowParams(id)!; + apiRef?.current.publishEvent(GRID_ROW_CLICK, params, event); + }, + [apiRef, id], + ); + const handleDoubleClick = React.useCallback( + (event: React.MouseEvent) => { + const params = apiRef?.current.getRowParams(id)!; + apiRef?.current.publishEvent(GRID_DOUBLE_ROW_CLICK, params, event); + }, + [apiRef, id], + ); + const handleMouseOver = React.useCallback( + (event: React.MouseEvent) => { + const params = apiRef?.current.getRowParams(id)!; + apiRef?.current.publishEvent(GRID_ROW_OVER, params, event); + }, + [apiRef, id], + ); + + const handleMouseOut = React.useCallback( + (event: React.MouseEvent) => { + const params = apiRef?.current.getRowParams(id)!; + apiRef?.current.publishEvent(GRID_ROW_OUT, params, event); + }, + [apiRef, id], + ); + + const handleMouseEnter = React.useCallback( + (event: React.MouseEvent) => { + const params = apiRef?.current.getRowParams(id)!; + apiRef?.current.publishEvent(GRID_ROW_ENTER, params, event); + }, + [apiRef, id], + ); + + const handleMouseLeave = React.useCallback( + (event: React.MouseEvent) => { + const params = apiRef?.current.getRowParams(id)!; + apiRef?.current.publishEvent(GRID_ROW_LEAVE, params, event); + }, + [apiRef, id], + ); return (
= ({ selected, id, className, rowIndex, maxHeight: rowHeight, minHeight: rowHeight, }} - onClick={onClick} + onClick={handleClick} + onDoubleClick={handleDoubleClick} + onMouseOver={handleMouseOver} + onMouseOut={handleMouseOut} + onMouseEnter={handleMouseEnter} + onMouseLeave={handleMouseLeave} > {children}
diff --git a/packages/grid/_modules_/grid/components/GridRowCells.tsx b/packages/grid/_modules_/grid/components/GridRowCells.tsx index 60ead990a4c68..0d5fd3f83f6d5 100644 --- a/packages/grid/_modules_/grid/components/GridRowCells.tsx +++ b/packages/grid/_modules_/grid/components/GridRowCells.tsx @@ -51,9 +51,9 @@ export const GridRowCells: React.FC = React.memo((props) => { cellFocus, showCellRightBorder, } = props; - const api = React.useContext(GridApiContext); - const rowHeight = useGridSelector(api, gridDensityRowHeightSelector); - const editRowsState = useGridSelector(api, gridEditRowsStateSelector); + const apiRef = React.useContext(GridApiContext); + const rowHeight = useGridSelector(apiRef, gridDensityRowHeightSelector); + const editRowsState = useGridSelector(apiRef, gridEditRowsStateSelector); const cellsProps = columns.slice(firstColIdx, lastColIdx + 1).map((column, colIdx) => { const isLastColumn = firstColIdx + colIdx === columns.length - 1; @@ -64,15 +64,7 @@ export const GridRowCells: React.FC = React.memo((props) => { ? showCellRightBorder : !removeLastBorderRight && !props.extendRowFullWidth; - let value = row[column.field!]; - const cellParams: GridCellParams = buildGridCellParams({ - rowModel: row, - colDef: column, - rowIndex, - colIndex: colIdx, - value, - api: api!.current!, - }); + const cellParams: GridCellParams = apiRef!.current.getCellParams(row.id, column.field); let cssClassProp = { cssClass: '' }; if (column.cellClassName) { @@ -91,20 +83,11 @@ export const GridRowCells: React.FC = React.memo((props) => { const editCellState = editRowsState[row.id] && editRowsState[row.id][column.field]; let cellComponent: React.ReactElement | null = null; - if (column.valueGetter) { - // Value getter override the original value - value = column.valueGetter(cellParams); - cellParams.value = value; - } - let formattedValueProp = {}; if (column.valueFormatter) { // TODO add formatted value to cellParams? formattedValueProp = { formattedValue: column.valueFormatter(cellParams) }; } - const onClick = ()=>{ - api?.current.publishEvent(GRID_CELL_CLICK, cellParams); - } ; if (editCellState == null && column.renderCell) { cellComponent = column.renderCell(cellParams); @@ -118,9 +101,10 @@ export const GridRowCells: React.FC = React.memo((props) => { } const cellProps: GridCellProps & { children: any } = { - value, + value: cellParams.value, field: column.field, width, + rowId: row.id, height: rowHeight, showRightBorder, ...formattedValueProp, @@ -135,7 +119,6 @@ export const GridRowCells: React.FC = React.memo((props) => { cellFocus !== null && cellFocus.rowIndex === rowIndex && cellFocus.colIndex === colIdx + firstColIdx, - onClick }; return cellProps; diff --git a/packages/grid/_modules_/grid/components/columnHeaders/GridColumnHeaderItem.tsx b/packages/grid/_modules_/grid/components/columnHeaders/GridColumnHeaderItem.tsx index f74774a9efe6c..b9c8ac2376162 100644 --- a/packages/grid/_modules_/grid/components/columnHeaders/GridColumnHeaderItem.tsx +++ b/packages/grid/_modules_/grid/components/columnHeaders/GridColumnHeaderItem.tsx @@ -73,15 +73,18 @@ export const GridColumnHeaderItem = ({ }), [apiRef, column], ); - const onHeaderTitleClick = React.useCallback(() => { - const colHeaderParams: GridColParams = { - field: column.field, - colDef: column, - colIndex, - api: apiRef!.current, - }; - apiRef!.current.publishEvent(GRID_COLUMN_HEADER_CLICK, colHeaderParams); - }, [apiRef, colIndex, column]); + const onHeaderTitleClick = React.useCallback( + (event: React.MouseEvent) => { + const colHeaderParams: GridColParams = { + field: column.field, + colDef: column, + colIndex, + api: apiRef!.current, + }; + apiRef!.current.publishEvent(GRID_COLUMN_HEADER_CLICK, colHeaderParams, event); + }, + [apiRef, colIndex, column], + ); const cssClasses = classnames( GRID_HEADER_CELL_CSS_CLASS, diff --git a/packages/grid/_modules_/grid/constants/eventsConstants.ts b/packages/grid/_modules_/grid/constants/eventsConstants.ts index 4dab2c660ba8d..06dc7a48c220d 100644 --- a/packages/grid/_modules_/grid/constants/eventsConstants.ts +++ b/packages/grid/_modules_/grid/constants/eventsConstants.ts @@ -19,10 +19,16 @@ export const GRID_UNMOUNT = 'unmount'; export const GRID_ELEMENT_FOCUS_OUT = 'gridFocusOut'; export const GRID_CELL_CLICK = 'cellClick'; export const GRID_DOUBLE_CELL_CLICK = 'doubleCellClick'; -export const GRID_CELL_HOVER = 'cellHover'; +export const GRID_CELL_OVER = 'cellOver'; +export const GRID_CELL_OUT = 'cellOut'; +export const GRID_CELL_ENTER = 'cellEnter'; +export const GRID_CELL_LEAVE = 'cellLeave'; export const GRID_ROW_CLICK = 'rowClick'; export const GRID_DOUBLE_ROW_CLICK = 'doubleRowClick'; -export const GRID_ROW_HOVER = 'rowHover'; +export const GRID_ROW_OVER = 'rowOver'; +export const GRID_ROW_OUT = 'rowOut'; +export const GRID_ROW_ENTER = 'rowEnter'; +export const GRID_ROW_LEAVE = 'rowLeave'; export const GRID_ROW_SELECTED = 'rowSelected'; export const GRID_SELECTION_CHANGED = 'selectionChange'; export const GRID_COLUMN_HEADER_CLICK = 'columnClick'; diff --git a/packages/grid/_modules_/grid/hooks/features/rows/index.ts b/packages/grid/_modules_/grid/hooks/features/rows/index.ts index e2f92894b076c..87bae9f1fce90 100644 --- a/packages/grid/_modules_/grid/hooks/features/rows/index.ts +++ b/packages/grid/_modules_/grid/hooks/features/rows/index.ts @@ -1,5 +1,6 @@ export * from './gridRowsSelector'; export * from './gridRowsState'; +export * from './useGridCellApi'; export * from './useGridRows'; export * from './gridEditRowsSelector'; export * from './useGridEditRows'; diff --git a/packages/grid/_modules_/grid/hooks/features/rows/useGridCellApi.ts b/packages/grid/_modules_/grid/hooks/features/rows/useGridCellApi.ts new file mode 100644 index 0000000000000..3cd860eb9945b --- /dev/null +++ b/packages/grid/_modules_/grid/hooks/features/rows/useGridCellApi.ts @@ -0,0 +1,97 @@ +import * as React from 'react'; +import { GridApiRef } from '../../../models/api/gridApiRef'; +import { GridCellApi } from '../../../models/api/gridCellApi'; +import { GridRowId } from '../../../models/gridRows'; +import { GridCellParams } from '../../../models/params/gridCellParams'; +import { GridRowParams } from '../../../models/params/gridRowParams'; +import { getGridCellElement, getGridRowElement } from '../../../utils/domUtils'; +import { useGridApiMethod } from '../../root/useGridApiMethod'; + +export function useGridCellApi(apiRef: GridApiRef) { + const getRowParams = React.useCallback( + (id: GridRowId) => { + const params: GridRowParams = { + element: apiRef.current.getRowElement(id), + columns: apiRef.current.getAllColumns(), + getValue: (columnField: string) => apiRef.current.getCellValue(id, columnField), + row: apiRef.current.getRowFromId(id), + rowIndex: apiRef.current.getRowIndexFromId(id), + api: apiRef.current, + }; + return params; + }, + [apiRef], + ); + + const getCellParams = React.useCallback( + (id: GridRowId, field: string) => { + const colDef = apiRef.current.getColumnFromField(field); + const element = apiRef.current.getCellElement(id, field); + + const params: GridCellParams = { + element, + value: apiRef.current.getCellValue(id, field), + field, + getValue: (columnField: string) => apiRef.current.getCellValue(id, columnField), + row: apiRef.current.getRowFromId(id), + colDef: apiRef.current.getColumnFromField(field), + rowIndex: apiRef.current.getRowIndexFromId(id), + colIndex: apiRef.current.getColumnIndex(field, true), + api: apiRef.current, + }; + const isEditableAttr = element && element.getAttribute('data-editable'); + params.isEditable = + isEditableAttr != null + ? isEditableAttr === 'true' + : colDef && apiRef.current.isCellEditable(params); + + return params; + }, + [apiRef], + ); + + const getCellValue = React.useCallback( + (id: GridRowId, field: string) => { + const colDef = apiRef.current.getColumnFromField(field); + const rowModel = apiRef.current.getRowFromId(id); + + if (!colDef || !colDef.valueGetter) { + return rowModel[field]; + } + + return colDef.valueGetter(apiRef.current.getCellParams(id, field)); + }, + [apiRef], + ); + + const getRowElement = React.useCallback( + (id: GridRowId): HTMLDivElement | null => { + if (!apiRef.current.rootElementRef!.current) { + return null; + } + return getGridRowElement(apiRef.current.rootElementRef!.current!, id); + }, + [apiRef], + ); + const getCellElement = React.useCallback( + (id: GridRowId, field: string): HTMLDivElement | null => { + if (!apiRef.current.rootElementRef!.current) { + return null; + } + return getGridCellElement(apiRef.current.rootElementRef!.current!, { id, field }); + }, + [apiRef], + ); + + useGridApiMethod( + apiRef, + { + getCellValue, + getCellParams, + getCellElement, + getRowParams, + getRowElement, + }, + 'CellApi', + ); +} diff --git a/packages/grid/_modules_/grid/hooks/features/rows/useGridEditRows.ts b/packages/grid/_modules_/grid/hooks/features/rows/useGridEditRows.ts index ebbc87ad26332..f97034ede3a57 100644 --- a/packages/grid/_modules_/grid/hooks/features/rows/useGridEditRows.ts +++ b/packages/grid/_modules_/grid/hooks/features/rows/useGridEditRows.ts @@ -17,7 +17,6 @@ import { GridEditCellParams, GridEditRowModelParams, } from '../../../models/params/gridEditCellParams'; -import { buildGridCellParams } from '../../../utils/paramsUtils'; import { useGridApiEventHandler } from '../../root/useGridApiEventHandler'; import { useGridApiMethod } from '../../root/useGridApiMethod'; import { optionsSelector } from '../../utils/optionsSelector'; @@ -28,27 +27,6 @@ export function useGridEditRows(apiRef: GridApiRef) { const [, setGridState, forceUpdate] = useGridState(apiRef); const options = useGridSelector(apiRef, optionsSelector); - const getCellValue = React.useCallback( - (id: GridRowId, field: string) => { - const colDef = apiRef.current.getColumnFromField(field); - const rowModel = apiRef.current.getRowFromId(id); - - if (!colDef || !colDef.valueGetter) { - return rowModel[field]; - } - - return colDef.valueGetter( - buildGridCellParams({ - value: rowModel[field], - colDef, - rowModel, - api: apiRef.current, - }), - ); - }, - [apiRef], - ); - const setCellEditMode = React.useCallback( (id, field) => { setGridState((state) => { @@ -58,7 +36,7 @@ export function useGridEditRows(apiRef: GridApiRef) { const currentCellEditState: GridEditRowsModel = { ...state.editRows }; currentCellEditState[id] = { ...currentCellEditState[id] } || {}; - currentCellEditState[id][field] = { value: getCellValue(id, field) }; + currentCellEditState[id][field] = { value: apiRef.current.getCellValue(id, field) }; const newEditRowsState: GridEditRowsModel = { ...state.editRows, ...currentCellEditState }; @@ -78,7 +56,7 @@ export function useGridEditRows(apiRef: GridApiRef) { }; apiRef.current.publishEvent(GRID_EDIT_ROW_MODEL_CHANGE, editRowParams); }, - [apiRef, forceUpdate, getCellValue, setGridState], + [apiRef, forceUpdate, setGridState], ); const setCellViewMode = React.useCallback( @@ -219,7 +197,6 @@ export function useGridEditRows(apiRef: GridApiRef) { useGridApiMethod( apiRef, { - getCellValue, setCellMode, onEditRowModelChange, onCellModeChange, diff --git a/packages/grid/_modules_/grid/hooks/root/useEvents.ts b/packages/grid/_modules_/grid/hooks/root/useEvents.ts index 2a10d3416583f..d3e48ea1854ca 100644 --- a/packages/grid/_modules_/grid/hooks/root/useEvents.ts +++ b/packages/grid/_modules_/grid/hooks/root/useEvents.ts @@ -1,14 +1,10 @@ import * as React from 'react'; import { GridApiRef } from '../../models/api/gridApiRef'; -import { GridCellParams } from '../../models/params/gridCellParams'; -import { GridColParams } from '../../models/params/gridColParams'; -import { GridRowParams } from '../../models/params/gridRowParams'; import { useGridSelector } from '../features/core/useGridSelector'; import { optionsSelector } from '../utils/optionsSelector'; import { useLogger } from '../utils/useLogger'; import { GRID_CELL_CLICK, - GRID_CLICK, GRID_COL_RESIZE_START, GRID_COL_RESIZE_STOP, GRID_COLUMN_HEADER_CLICK, @@ -17,23 +13,23 @@ import { GRID_KEYUP, GRID_RESIZE, GRID_ROW_CLICK, - GRID_MOUSE_HOVER, - GRID_CELL_HOVER, - GRID_ROW_HOVER, - GRID_COLUMN_HEADER_HOVER, + GRID_CELL_OVER, + GRID_ROW_OVER, GRID_FOCUS_OUT, GRID_ELEMENT_FOCUS_OUT, GRID_COMPONENT_ERROR, GRID_STATE_CHANGE, GRID_DOUBLE_CELL_CLICK, GRID_DOUBLE_ROW_CLICK, - GRID_DOUBLE_CLICK, + GRID_CELL_ENTER, + GRID_CELL_LEAVE, + GRID_CELL_OUT, + GRID_ROW_ENTER, + GRID_ROW_LEAVE, + GRID_ROW_OUT, } from '../../constants/eventsConstants'; -import { GRID_CELL_CSS_CLASS, GRID_ROW_CSS_CLASS } from '../../constants/cssClassesConstants'; -import { findParentElementFromClassName, getIdFromRowElem, isGridCell } from '../../utils/domUtils'; import { useGridApiMethod } from './useGridApiMethod'; import { useGridApiEventHandler } from './useGridApiEventHandler'; -import { buildGridCellParams, buildGridRowParams } from '../../utils/paramsUtils'; import { GridEventsApi } from '../../models/api/gridEventsApi'; export function useEvents(gridRootRef: React.RefObject, apiRef: GridApiRef): void { @@ -47,114 +43,6 @@ export function useEvents(gridRootRef: React.RefObject, apiRef: [apiRef], ); - const getEventParams = React.useCallback( - (event: MouseEvent) => { - if (event.target == null) { - throw new Error( - `Event target null - Target has been removed or component might already be unmounted.`, - ); - } - - const elem = event.target as HTMLElement; - const eventParams: { - cell?: GridCellParams; - row?: GridRowParams; - header?: GridColParams; - } = {}; - - if (isGridCell(elem)) { - const cellEl = findParentElementFromClassName(elem, GRID_CELL_CSS_CLASS)! as HTMLElement; - const rowEl = findParentElementFromClassName(elem, GRID_ROW_CSS_CLASS)! as HTMLElement; - if (rowEl == null) { - return null; - } - const id = getIdFromRowElem(rowEl); - const rowModel = apiRef.current.getRowFromId(id); - const rowIndex = apiRef.current.getRowIndexFromId(id); - const field = cellEl.getAttribute('data-field') as string; - const value = cellEl.getAttribute('data-value'); - const column = apiRef.current.getColumnFromField(field); - if (!column || !column.disableClickEventBubbling) { - const commonParams = { - data: rowModel, - rowIndex, - colDef: column, - rowModel, - api: apiRef.current, - }; - eventParams.cell = buildGridCellParams({ - ...commonParams, - element: cellEl, - value, - }); - eventParams.row = buildGridRowParams({ - ...commonParams, - element: rowEl, - }); - } - } - return eventParams; - }, - [apiRef], - ); - - const onClickHandler = React.useCallback( - (event: MouseEvent) => { - const eventParams = getEventParams(event); - - if (!eventParams) { - return; - } - - if (eventParams.cell) { - apiRef.current.publishEvent(GRID_CELL_CLICK, eventParams.cell); - } - if (eventParams.row) { - apiRef.current.publishEvent(GRID_ROW_CLICK, eventParams.row); - } - }, - [apiRef, getEventParams], - ); - - const onDoubleClickHandler = React.useCallback( - (event: MouseEvent) => { - const eventParams = getEventParams(event); - - if (!eventParams) { - return; - } - - if (eventParams.cell) { - apiRef.current.publishEvent(GRID_DOUBLE_CELL_CLICK, eventParams.cell); - } - if (eventParams.row) { - apiRef.current.publishEvent(GRID_DOUBLE_ROW_CLICK, eventParams.row); - } - }, - [apiRef, getEventParams], - ); - - const onHoverHandler = React.useCallback( - (event: MouseEvent) => { - const eventParams = getEventParams(event); - - if (!eventParams) { - return; - } - - if (eventParams.cell) { - apiRef.current.publishEvent(GRID_CELL_HOVER, eventParams.cell); - } - if (eventParams.row) { - apiRef.current.publishEvent(GRID_ROW_HOVER, eventParams.row); - } - if (eventParams.header) { - apiRef.current.publishEvent(GRID_COLUMN_HEADER_HOVER, eventParams.header); - } - }, - [apiRef, getEventParams], - ); - const onFocusOutHandler = React.useCallback( (event: FocusEvent) => { apiRef.current.publishEvent(GRID_FOCUS_OUT, event); @@ -194,13 +82,21 @@ export function useEvents(gridRootRef: React.RefObject, apiRef: useGridApiEventHandler(apiRef, GRID_COL_RESIZE_STOP, handleResizeStop); useGridApiEventHandler(apiRef, GRID_COLUMN_HEADER_CLICK, options.onColumnHeaderClick); + useGridApiEventHandler(apiRef, GRID_CELL_CLICK, options.onCellClick); - useGridApiEventHandler(apiRef, GRID_ROW_CLICK, options.onRowClick); useGridApiEventHandler(apiRef, GRID_DOUBLE_CELL_CLICK, options.onCellDoubleClick); + useGridApiEventHandler(apiRef, GRID_CELL_OVER, options.onCellOver); + useGridApiEventHandler(apiRef, GRID_CELL_OUT, options.onCellOut); + useGridApiEventHandler(apiRef, GRID_CELL_ENTER, options.onCellEnter); + useGridApiEventHandler(apiRef, GRID_CELL_LEAVE, options.onCellLeave); + useGridApiEventHandler(apiRef, GRID_DOUBLE_ROW_CLICK, options.onRowDoubleClick); + useGridApiEventHandler(apiRef, GRID_ROW_CLICK, options.onRowClick); + useGridApiEventHandler(apiRef, GRID_ROW_OVER, options.onRowOver); + useGridApiEventHandler(apiRef, GRID_ROW_OUT, options.onRowOut); + useGridApiEventHandler(apiRef, GRID_ROW_ENTER, options.onRowEnter); + useGridApiEventHandler(apiRef, GRID_ROW_LEAVE, options.onRowLeave); - useGridApiEventHandler(apiRef, GRID_CELL_HOVER, options.onCellHover); - useGridApiEventHandler(apiRef, GRID_ROW_HOVER, options.onRowHover); useGridApiEventHandler(apiRef, GRID_COMPONENT_ERROR, options.onError); useGridApiEventHandler(apiRef, GRID_STATE_CHANGE, options.onStateChange); @@ -211,11 +107,7 @@ export function useEvents(gridRootRef: React.RefObject, apiRef: const keyUpHandler = getHandler(GRID_KEYUP); const gridRootElem = gridRootRef.current; - gridRootElem.addEventListener(GRID_CLICK, onClickHandler, { capture: true }); - gridRootElem.addEventListener(GRID_DOUBLE_CLICK, onDoubleClickHandler, { capture: true }); - gridRootElem.addEventListener(GRID_MOUSE_HOVER, onHoverHandler, { capture: true }); gridRootElem.addEventListener(GRID_FOCUS_OUT, onFocusOutHandler); - gridRootElem.addEventListener(GRID_KEYDOWN, keyDownHandler); gridRootElem.addEventListener(GRID_KEYUP, keyUpHandler); apiRef.current.isInitialised = true; @@ -224,8 +116,6 @@ export function useEvents(gridRootRef: React.RefObject, apiRef: return () => { logger.debug('Clearing all events listeners'); api.publishEvent(GRID_UNMOUNT); - gridRootElem.removeEventListener(GRID_CLICK, onClickHandler, { capture: true }); - gridRootElem.removeEventListener(GRID_MOUSE_HOVER, onHoverHandler, { capture: true }); gridRootElem.removeEventListener(GRID_FOCUS_OUT, onFocusOutHandler); gridRootElem.removeEventListener(GRID_KEYDOWN, keyDownHandler); gridRootElem.removeEventListener(GRID_KEYUP, keyUpHandler); @@ -233,15 +123,5 @@ export function useEvents(gridRootRef: React.RefObject, apiRef: }; } return undefined; - }, [ - gridRootRef, - apiRef.current?.isInitialised, - getHandler, - logger, - onClickHandler, - onDoubleClickHandler, - onHoverHandler, - onFocusOutHandler, - apiRef, - ]); + }, [gridRootRef, apiRef.current?.isInitialised, getHandler, logger, onFocusOutHandler, apiRef]); } diff --git a/packages/grid/_modules_/grid/hooks/root/useGridApiEventHandler.ts b/packages/grid/_modules_/grid/hooks/root/useGridApiEventHandler.ts index 5e88e6d5e1e03..92e611bdbf1e6 100644 --- a/packages/grid/_modules_/grid/hooks/root/useGridApiEventHandler.ts +++ b/packages/grid/_modules_/grid/hooks/root/useGridApiEventHandler.ts @@ -5,7 +5,7 @@ import { useLogger } from '../utils/useLogger'; export function useGridApiEventHandler( apiRef: GridApiRef, eventName: string, - handler?: (args: any) => void, + handler?: (...args: any) => void, ) { const logger = useLogger('useGridApiEventHandler'); diff --git a/packages/grid/_modules_/grid/models/api/gridApi.ts b/packages/grid/_modules_/grid/models/api/gridApi.ts index 9204c3997af60..a7d9194e98cdc 100644 --- a/packages/grid/_modules_/grid/models/api/gridApi.ts +++ b/packages/grid/_modules_/grid/models/api/gridApi.ts @@ -1,5 +1,6 @@ import { ColumnMenuApi } from './columnMenuApi'; import { ColumnResizeApi } from './columnResizeApi'; +import { GridCellApi } from './gridCellApi'; import { ComponentsApi } from './gridComponentsApi'; import { FilterApi } from './filterApi'; import { GridEditRowApi } from './gridEditRowApi'; @@ -28,6 +29,7 @@ export type GridApi = GridCoreApi & GridEventsApi & GridRowApi & GridEditRowApi & + GridCellApi & GridColumnApi & ColumnReorderApi & GridSelectionApi & diff --git a/packages/grid/_modules_/grid/models/api/gridCellApi.ts b/packages/grid/_modules_/grid/models/api/gridCellApi.ts new file mode 100644 index 0000000000000..da85f23ff9226 --- /dev/null +++ b/packages/grid/_modules_/grid/models/api/gridCellApi.ts @@ -0,0 +1,17 @@ +import { GridCellValue } from '../gridCell'; +import { GridRowId } from '../gridRows'; +import { GridCellParams } from '../params/gridCellParams'; +import { GridRowParams } from '../params/gridRowParams'; + +export interface GridCellApi { + /** + * Get the cell value of a row and field. + * @param id + * @param field + */ + getCellValue: (id: GridRowId, field: string) => GridCellValue; + getCellElement: (id: GridRowId, field: string) => HTMLDivElement | null; + getCellParams: (id: GridRowId, field: string) => GridCellParams; + getRowParams: (id: GridRowId) => GridRowParams; + getRowElement: (id: GridRowId) => HTMLDivElement | null; +} diff --git a/packages/grid/_modules_/grid/models/api/gridEditRowApi.ts b/packages/grid/_modules_/grid/models/api/gridEditRowApi.ts index 0ee6b9e709602..96fb4cfdff019 100644 --- a/packages/grid/_modules_/grid/models/api/gridEditRowApi.ts +++ b/packages/grid/_modules_/grid/models/api/gridEditRowApi.ts @@ -36,12 +36,6 @@ export interface GridEditRowApi { * @param update */ commitCellChange: (id: GridRowId, update: GridEditRowUpdate) => void; - /** - * Get the cell value of a row and field. - * @param id - * @param field - */ - getCellValue: (id: GridRowId, field: string) => GridCellValue; /** * Callback fired when the EditRowModel changed. * @param handler diff --git a/packages/grid/_modules_/grid/models/api/index.ts b/packages/grid/_modules_/grid/models/api/index.ts index 032328ea976f8..36c88c0aa2f09 100644 --- a/packages/grid/_modules_/grid/models/api/index.ts +++ b/packages/grid/_modules_/grid/models/api/index.ts @@ -1,4 +1,5 @@ export * from './gridApiRef'; +export * from './gridCellApi'; export * from './gridCoreApi'; export * from './gridColumnApi'; export * from './gridComponentsApi'; diff --git a/packages/grid/_modules_/grid/models/gridOptions.tsx b/packages/grid/_modules_/grid/models/gridOptions.tsx index cf13904586a69..b19b79b990bbf 100644 --- a/packages/grid/_modules_/grid/models/gridOptions.tsx +++ b/packages/grid/_modules_/grid/models/gridOptions.tsx @@ -1,3 +1,4 @@ +import * as React from 'react'; import { GRID_DEFAULT_LOCALE_TEXT } from '../constants/localeTextConstants'; import { FilterModel } from '../hooks/features/filter/FilterModelState'; import { Logger } from '../hooks/utils/useLogger'; @@ -225,33 +226,40 @@ export interface GridOptions { /** * Callback fired when a click event comes from a cell element. * @param param With all properties from [[GridCellParams]]. + * @param event [[React.MouseEvent]]. */ - onCellClick?: (param: GridCellParams) => void; + onCellClick?: (param: GridCellParams, event: React.MouseEvent) => void; /** * Callback fired when a double click event comes from a cell element. * @param param With all properties from [[CellParams]]. */ - onCellDoubleClick?: (param: GridCellParams) => void; + onCellDoubleClick?: (param: GridCellParams, event: React.MouseEvent) => void; /** * Callback fired when a hover event comes from a cell element. * @param param With all properties from [[GridCellParams]]. */ - onCellHover?: (param: GridCellParams) => void; + onCellOver?: (param: GridCellParams, event: React.MouseEvent) => void; + onCellOut?: (param: GridCellParams, event: React.MouseEvent) => void; + onCellEnter?: (param: GridCellParams, event: React.MouseEvent) => void; + onCellLeave?: (param: GridCellParams, event: React.MouseEvent) => void; /** * Callback fired when a click event comes from a row container element. * @param param With all properties from [[GridRowParams]]. */ - onRowClick?: (param: GridRowParams) => void; + onRowClick?: (param: GridRowParams, event: React.MouseEvent) => void; /** * Callback fired when a click event comes from a row container element. * @param param With all properties from [[RowParams]]. */ - onRowDoubleClick?: (param: GridRowParams) => void; + onRowDoubleClick?: (param: GridRowParams, event: React.MouseEvent) => void; /** * Callback fired when a hover event comes from a row container element. * @param param With all properties from [[GridRowParams]]. */ - onRowHover?: (param: GridRowParams) => void; + onRowOver?: (param: GridRowParams, event: React.MouseEvent) => void; + onRowOut?: (param: GridRowParams, event: React.MouseEvent) => void; + onRowEnter?: (param: GridRowParams, event: React.MouseEvent) => void; + onRowLeave?: (param: GridRowParams, event: React.MouseEvent) => void; /** * Callback fired when one row is selected. * @param param With all properties from [[GridRowSelectedParams]]. @@ -266,7 +274,7 @@ export interface GridOptions { * Callback fired when a click event comes from a column header element. * @param param With all properties from [[GridColParams]]. */ - onColumnHeaderClick?: (param: GridColParams) => void; + onColumnHeaderClick?: (param: GridColParams, event: React.MouseEvent) => void; /** * Callback fired when the sort model changes before a column is sorted. * @param param With all properties from [[GridSortModelParams]]. diff --git a/packages/grid/_modules_/grid/models/params/gridCellParams.ts b/packages/grid/_modules_/grid/models/params/gridCellParams.ts index de00904d825f0..10032d3c8c697 100644 --- a/packages/grid/_modules_/grid/models/params/gridCellParams.ts +++ b/packages/grid/_modules_/grid/models/params/gridCellParams.ts @@ -8,7 +8,7 @@ export interface GridCellParams { /** * The HTMLElement that triggered the event */ - element?: HTMLElement; + element?: HTMLElement | null; /** * The column field of the cell that triggered the event */ diff --git a/packages/grid/_modules_/grid/models/params/gridRowParams.ts b/packages/grid/_modules_/grid/models/params/gridRowParams.ts index 0d9fdec99320c..16b3f44c50558 100644 --- a/packages/grid/_modules_/grid/models/params/gridRowParams.ts +++ b/packages/grid/_modules_/grid/models/params/gridRowParams.ts @@ -8,7 +8,7 @@ export interface GridRowParams { /** * The HTMLElement that triggered the event */ - element?: HTMLElement; + element?: HTMLElement | null; /** * A function that let you get data from other columns. * @param field diff --git a/packages/grid/_modules_/grid/utils/domUtils.ts b/packages/grid/_modules_/grid/utils/domUtils.ts index 1a45e1b3872d0..ed6f22d432012 100644 --- a/packages/grid/_modules_/grid/utils/domUtils.ts +++ b/packages/grid/_modules_/grid/utils/domUtils.ts @@ -5,6 +5,7 @@ import { GRID_ROW_CSS_CLASS, } from '../constants/cssClassesConstants'; import { GridCellIndexCoordinates } from '../models/gridCell'; +import { GridRowId } from '../models/gridRows'; export function isOverflown(element: Element): boolean { return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth; @@ -86,3 +87,13 @@ export function getGridCellElementFromIndexes( `:scope .${GRID_CELL_CSS_CLASS}[aria-colIndex='${colIndex}'][data-rowIndex='${rowIndex}']`, ) as HTMLDivElement; } +export function getGridRowElement(root: Element, id: GridRowId) { + return root.querySelector(`:scope .${GRID_ROW_CSS_CLASS}[data-id='${id}']`) as HTMLDivElement; +} +export function getGridCellElement(root: Element, { id, field }: { id: GridRowId; field: string }) { + const row = getGridRowElement(root, id); + if (!row) { + return null; + } + return row.querySelector(`.${GRID_CELL_CSS_CLASS}[data-field='${field}']`) as HTMLDivElement; +} diff --git a/packages/storybook/src/stories/grid-events.stories.tsx b/packages/storybook/src/stories/grid-events.stories.tsx index bc08224a32201..99dcffd178d99 100644 --- a/packages/storybook/src/stories/grid-events.stories.tsx +++ b/packages/storybook/src/stories/grid-events.stories.tsx @@ -20,8 +20,8 @@ export function AllEvents() { const options: GridOptionsProp = { onRowClick: (params) => action('onRowClick')(params), onCellClick: (params) => action('onCellClick')(params), - onCellHover: (params) => action('onCellHover')(params), - onRowHover: (params) => action('onRowHover')(params), + onCellOver: (params) => action('onCellHover')(params), + onRowOver: (params) => action('onRowHover')(params), onColumnHeaderClick: (params) => action('onColumnHeaderClick')(params), onRowSelected: (params) => action('onRowSelected')(params), onSelectionModelChange: (params) => action('onSelectionChange', { depth: 1 })(params), @@ -43,11 +43,20 @@ export const OnRowClick = () => { return ; }; +export const OnRowDoubleClick = () => { + const data = useData(2000, 200); + + const options: GridOptionsProp = { + onRowDoubleClick: (params) => action('row double click')(params), + }; + + return ; +}; export const OnRowHover = () => { const data = useData(2000, 200); const options: GridOptionsProp = { - onRowHover: (params) => action('Row Hover')(params), + onRowOver: (params) => action('Row over')(params), }; return ; @@ -61,11 +70,30 @@ export const OnCellClick = () => { return ; }; +export const OnCellClickNotPropagated = () => { + const data = useData(2000, 200); + const options: GridOptionsProp = { + onCellClick: (params, event) => { + event.stopPropagation(); + action('cell click')(params); + }, + }; + + return ; +}; +export const OnCellDoubleClick = () => { + const data = useData(2000, 200); + const options: GridOptionsProp = { + onCellDoubleClick: (params) => action('Cell double click')(params), + }; + + return ; +}; export const OnCellHover = () => { const data = useData(2000, 200); const options: GridOptionsProp = { - onCellHover: (params) => action('cell Hover')(params), + onCellOver: (params) => action('cell over')(params), }; return ; From cd5059db2fab2805640dacb1c9340e90a643aa43 Mon Sep 17 00:00:00 2001 From: damien Date: Mon, 8 Mar 2021 16:55:43 +0100 Subject: [PATCH 03/22] fix typo --- packages/storybook/src/stories/grid-events.stories.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/storybook/src/stories/grid-events.stories.tsx b/packages/storybook/src/stories/grid-events.stories.tsx index 99dcffd178d99..bba60ff57be91 100644 --- a/packages/storybook/src/stories/grid-events.stories.tsx +++ b/packages/storybook/src/stories/grid-events.stories.tsx @@ -20,8 +20,8 @@ export function AllEvents() { const options: GridOptionsProp = { onRowClick: (params) => action('onRowClick')(params), onCellClick: (params) => action('onCellClick')(params), - onCellOver: (params) => action('onCellHover')(params), - onRowOver: (params) => action('onRowHover')(params), + onCellOver: (params) => action('onCellOver')(params), + onRowOver: (params) => action('onRowOver')(params), onColumnHeaderClick: (params) => action('onColumnHeaderClick')(params), onRowSelected: (params) => action('onRowSelected')(params), onSelectionModelChange: (params) => action('onSelectionChange', { depth: 1 })(params), From 05754035233056d61eaaa8cad502727ceba71e38 Mon Sep 17 00:00:00 2001 From: damien Date: Mon, 8 Mar 2021 19:16:55 +0100 Subject: [PATCH 04/22] Cleanup --- .../_modules_/grid/components/GridCell.tsx | 3 +- .../_modules_/grid/components/GridRow.tsx | 4 +- .../grid/components/GridRowCells.tsx | 2 - .../hooks/features/filter/useGridFilter.ts | 11 +-- .../hooks/features/rows/useGridCellApi.ts | 31 +++++- .../hooks/features/sorting/useGridSorting.ts | 15 +-- .../grid/models/params/gridCellParams.ts | 8 +- .../grid/models/params/gridRowParams.ts | 6 +- .../grid/_modules_/grid/utils/domUtils.ts | 2 + packages/grid/_modules_/grid/utils/index.ts | 1 - .../grid/_modules_/grid/utils/paramsUtils.ts | 94 ------------------- 11 files changed, 49 insertions(+), 128 deletions(-) delete mode 100644 packages/grid/_modules_/grid/utils/paramsUtils.ts diff --git a/packages/grid/_modules_/grid/components/GridCell.tsx b/packages/grid/_modules_/grid/components/GridCell.tsx index 74f9ab74d2642..caef4b1a0e75f 100644 --- a/packages/grid/_modules_/grid/components/GridCell.tsx +++ b/packages/grid/_modules_/grid/components/GridCell.tsx @@ -8,7 +8,7 @@ import { GRID_CELL_OUT, GRID_DOUBLE_CELL_CLICK, } from '../constants/eventsConstants'; -import { GridAlignment, GridCellParams, GridCellValue, GridRowId } from '../models'; +import { GridAlignment, GridCellValue, GridRowId } from '../models'; import { GRID_CELL_CSS_CLASS } from '../constants/cssClassesConstants'; import { classnames } from '../utils'; import { GridApiContext } from './GridApiContext'; @@ -73,7 +73,6 @@ export const GridCell: React.FC = React.memo((props) => { if (params?.colDef.disableClickEventBubbling) { event.stopPropagation(); } - apiRef?.current.publishEvent(GRID_CELL_CLICK, params, event); }, [apiRef, getParams], diff --git a/packages/grid/_modules_/grid/components/GridRow.tsx b/packages/grid/_modules_/grid/components/GridRow.tsx index 9e0521f48dcc0..e9600a3f05d5d 100644 --- a/packages/grid/_modules_/grid/components/GridRow.tsx +++ b/packages/grid/_modules_/grid/components/GridRow.tsx @@ -9,7 +9,7 @@ import { } from '../constants/eventsConstants'; import { GridRowId } from '../models'; import { GRID_ROW_CSS_CLASS } from '../constants/cssClassesConstants'; -import { buildGridRowParams, classnames } from '../utils'; +import { classnames } from '../utils'; import { gridDensityRowHeightSelector } from '../hooks/features/density'; import { GridApiContext } from './GridApiContext'; import { useGridSelector } from '../hooks/features/core/useGridSelector'; @@ -33,6 +33,7 @@ export const GridRow: React.FC = ({ selected, id, className, rowIndex, }, [apiRef, id], ); + const handleDoubleClick = React.useCallback( (event: React.MouseEvent) => { const params = apiRef?.current.getRowParams(id)!; @@ -40,6 +41,7 @@ export const GridRow: React.FC = ({ selected, id, className, rowIndex, }, [apiRef, id], ); + const handleMouseOver = React.useCallback( (event: React.MouseEvent) => { const params = apiRef?.current.getRowParams(id)!; diff --git a/packages/grid/_modules_/grid/components/GridRowCells.tsx b/packages/grid/_modules_/grid/components/GridRowCells.tsx index 0d5fd3f83f6d5..153235020fa58 100644 --- a/packages/grid/_modules_/grid/components/GridRowCells.tsx +++ b/packages/grid/_modules_/grid/components/GridRowCells.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import { GRID_CELL_CLICK } from '../constants/eventsConstants'; import { gridEditRowsStateSelector } from '../hooks/features/rows/gridEditRowsSelector'; import { GridCellClassParams, @@ -12,7 +11,6 @@ import { import { GridCell, GridCellProps } from './GridCell'; import { GridApiContext } from './GridApiContext'; import { classnames, isFunction } from '../utils'; -import { buildGridCellParams } from '../utils/paramsUtils'; import { gridDensityRowHeightSelector } from '../hooks/features/density/densitySelector'; import { useGridSelector } from '../hooks/features/core/useGridSelector'; diff --git a/packages/grid/_modules_/grid/hooks/features/filter/useGridFilter.ts b/packages/grid/_modules_/grid/hooks/features/filter/useGridFilter.ts index 43de15831459e..48b9d1bc1b47b 100644 --- a/packages/grid/_modules_/grid/hooks/features/filter/useGridFilter.ts +++ b/packages/grid/_modules_/grid/hooks/features/filter/useGridFilter.ts @@ -11,7 +11,6 @@ import { GridFeatureModeConstant } from '../../../models/gridFeatureMode'; import { GridFilterItem, GridLinkOperator } from '../../../models/gridFilterItem'; import { GridFilterModelParams } from '../../../models/params/gridFilterModelParams'; import { GridRowsProp } from '../../../models/gridRows'; -import { buildGridCellParams } from '../../../utils/paramsUtils'; import { isDeepEqual } from '../../../utils/utils'; import { useGridApiEventHandler } from '../../root/useGridApiEventHandler'; import { useGridApiMethod } from '../../root/useGridApiMethod'; @@ -88,14 +87,8 @@ export const useGridFilter = (apiRef: GridApiRef, rowsProp: GridRowsProp): void // This way we have latest rows on the first rendering const rows = sortedGridRowsSelector(state); - rows.forEach((row, rowIndex) => { - const params = buildGridCellParams({ - rowModel: row, - colDef: column, - rowIndex, - value: row[column.field], - api: apiRef!.current!, - }); + rows.forEach((row) => { + const params = apiRef.current.getCellParams(row.id, filterItem.columnField!); const isShown = applyFilterOnRow(params); if (visibleRowsLookup[row.id] == null) { diff --git a/packages/grid/_modules_/grid/hooks/features/rows/useGridCellApi.ts b/packages/grid/_modules_/grid/hooks/features/rows/useGridCellApi.ts index 3cd860eb9945b..f4e9288a3b986 100644 --- a/packages/grid/_modules_/grid/hooks/features/rows/useGridCellApi.ts +++ b/packages/grid/_modules_/grid/hooks/features/rows/useGridCellApi.ts @@ -2,7 +2,7 @@ import * as React from 'react'; import { GridApiRef } from '../../../models/api/gridApiRef'; import { GridCellApi } from '../../../models/api/gridCellApi'; import { GridRowId } from '../../../models/gridRows'; -import { GridCellParams } from '../../../models/params/gridCellParams'; +import { GridCellParams, ValueGetterParams } from '../../../models/params/gridCellParams'; import { GridRowParams } from '../../../models/params/gridRowParams'; import { getGridCellElement, getGridRowElement } from '../../../utils/domUtils'; import { useGridApiMethod } from '../../root/useGridApiMethod'; @@ -11,6 +11,7 @@ export function useGridCellApi(apiRef: GridApiRef) { const getRowParams = React.useCallback( (id: GridRowId) => { const params: GridRowParams = { + id, element: apiRef.current.getRowElement(id), columns: apiRef.current.getAllColumns(), getValue: (columnField: string) => apiRef.current.getCellValue(id, columnField), @@ -30,6 +31,7 @@ export function useGridCellApi(apiRef: GridApiRef) { const params: GridCellParams = { element, + id, value: apiRef.current.getCellValue(id, field), field, getValue: (columnField: string) => apiRef.current.getCellValue(id, columnField), @@ -50,6 +52,29 @@ export function useGridCellApi(apiRef: GridApiRef) { [apiRef], ); + const getValueGetterParams = React.useCallback( + (id: GridRowId, field: string) => { + const element = apiRef.current.getCellElement(id, field); + const row = apiRef.current.getRowFromId(id); + + const params: ValueGetterParams = { + element, + id, + field, + row, + value: row[field], + getValue: (columnField: string) => row[columnField], + colDef: apiRef.current.getColumnFromField(field), + rowIndex: apiRef.current.getRowIndexFromId(id), + colIndex: apiRef.current.getColumnIndex(field, true), + api: apiRef.current, + }; + + return params; + }, + [apiRef], + ); + const getCellValue = React.useCallback( (id: GridRowId, field: string) => { const colDef = apiRef.current.getColumnFromField(field); @@ -59,9 +84,9 @@ export function useGridCellApi(apiRef: GridApiRef) { return rowModel[field]; } - return colDef.valueGetter(apiRef.current.getCellParams(id, field)); + return colDef.valueGetter(getValueGetterParams(id, field)); }, - [apiRef], + [apiRef, getValueGetterParams], ); const getRowElement = React.useCallback( diff --git a/packages/grid/_modules_/grid/hooks/features/sorting/useGridSorting.ts b/packages/grid/_modules_/grid/hooks/features/sorting/useGridSorting.ts index 4304ab1e91369..5aed18491d762 100644 --- a/packages/grid/_modules_/grid/hooks/features/sorting/useGridSorting.ts +++ b/packages/grid/_modules_/grid/hooks/features/sorting/useGridSorting.ts @@ -23,7 +23,6 @@ import { GridSortModel, GridSortDirection, } from '../../../models/gridSortModel'; -import { buildGridCellParams } from '../../../utils/paramsUtils'; import { isDesc, nextGridSortDirection } from '../../../utils/sortingUtils'; import { isDeepEqual } from '../../../utils/utils'; import { useGridApiEventHandler } from '../../root/useGridApiEventHandler'; @@ -104,18 +103,8 @@ export const useGridSorting = (apiRef: GridApiRef, rowsProp: GridRowsProp) => { comparator( row1[field], row2[field], - buildGridCellParams({ - api: apiRef.current, - colDef: apiRef.current.getColumnFromField(field), - rowModel: row1, - value: row1[field], - }), - buildGridCellParams({ - api: apiRef.current, - colDef: apiRef.current.getColumnFromField(field), - rowModel: row2, - value: row2[field], - }), + apiRef.current.getCellParams(row1.id, field), + apiRef.current.getCellParams(row2.id, field) ); return res; }, 0); diff --git a/packages/grid/_modules_/grid/models/params/gridCellParams.ts b/packages/grid/_modules_/grid/models/params/gridCellParams.ts index 10032d3c8c697..06ff0572e780d 100644 --- a/packages/grid/_modules_/grid/models/params/gridCellParams.ts +++ b/packages/grid/_modules_/grid/models/params/gridCellParams.ts @@ -1,10 +1,14 @@ import { GridCellValue } from '../gridCell'; -import { GridRowModel } from '../gridRows'; +import { GridRowId, GridRowModel } from '../gridRows'; /** * Object passed as parameter in the column [[GridColDef]] cell renderer. */ export interface GridCellParams { + /** + * The grid row id + */ + id: GridRowId; /** * The HTMLElement that triggered the event */ @@ -51,7 +55,7 @@ export interface GridCellParams { /** * Alias of GridCellParams. */ -export type ValueGetterParams = GridCellParams; +export type ValueGetterParams =GridCellParams// Omit; /** * Alias of GridCellParams. diff --git a/packages/grid/_modules_/grid/models/params/gridRowParams.ts b/packages/grid/_modules_/grid/models/params/gridRowParams.ts index 16b3f44c50558..5c93482a72cf9 100644 --- a/packages/grid/_modules_/grid/models/params/gridRowParams.ts +++ b/packages/grid/_modules_/grid/models/params/gridRowParams.ts @@ -1,10 +1,14 @@ import { GridCellValue } from '../gridCell'; -import { GridRowModel } from '../gridRows'; +import { GridRowId, GridRowModel } from '../gridRows'; /** * Object passed as parameter in the column [[GridColDef]] cell renderer. */ export interface GridRowParams { + /** + * The grid row id + */ + id: GridRowId; /** * The HTMLElement that triggered the event */ diff --git a/packages/grid/_modules_/grid/utils/domUtils.ts b/packages/grid/_modules_/grid/utils/domUtils.ts index ed6f22d432012..34c09b61af4e1 100644 --- a/packages/grid/_modules_/grid/utils/domUtils.ts +++ b/packages/grid/_modules_/grid/utils/domUtils.ts @@ -87,9 +87,11 @@ export function getGridCellElementFromIndexes( `:scope .${GRID_CELL_CSS_CLASS}[aria-colIndex='${colIndex}'][data-rowIndex='${rowIndex}']`, ) as HTMLDivElement; } + export function getGridRowElement(root: Element, id: GridRowId) { return root.querySelector(`:scope .${GRID_ROW_CSS_CLASS}[data-id='${id}']`) as HTMLDivElement; } + export function getGridCellElement(root: Element, { id, field }: { id: GridRowId; field: string }) { const row = getGridRowElement(root, id); if (!row) { diff --git a/packages/grid/_modules_/grid/utils/index.ts b/packages/grid/_modules_/grid/utils/index.ts index 512fd9dafc275..077ff9ccdf409 100644 --- a/packages/grid/_modules_/grid/utils/index.ts +++ b/packages/grid/_modules_/grid/utils/index.ts @@ -4,7 +4,6 @@ export * from './domUtils'; export * from './classnames'; export * from './keyboardUtils'; export * from './mergeUtils'; -export * from './paramsUtils'; export * from './getGridLocalization'; export * from './material-ui-utils'; export * from './exportAs'; diff --git a/packages/grid/_modules_/grid/utils/paramsUtils.ts b/packages/grid/_modules_/grid/utils/paramsUtils.ts deleted file mode 100644 index 41b42127ee59f..0000000000000 --- a/packages/grid/_modules_/grid/utils/paramsUtils.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { GridCellValue } from '../models/gridCell'; -import { GridRowModel } from '../models/gridRows'; -import { GridColDef } from '../models/colDef/gridColDef'; -import { GridApi } from '../models/api/gridApi'; -import { GridCellParams } from '../models/params/gridCellParams'; -import { GridRowParams } from '../models/params/gridRowParams'; - -let warnedOnce = false; - -export function buildGridCellParams({ - element, - value, - rowIndex, - colIndex, - rowModel, - colDef, - api, -}: { - rowModel: GridRowModel; - colDef: GridColDef; - rowIndex?: number; - colIndex?: number; - value: GridCellValue; - api: GridApi; - element?: HTMLElement; -}): GridCellParams { - const params: GridCellParams = { - element, - value, - field: colDef?.field, - getValue: (field: string) => { - // We are getting the value of another column here, field - const col = api.getColumnFromField(field); - - if (process.env.NODE_ENV !== 'production') { - if (!col && !warnedOnce) { - console.warn( - [ - `Material-UI: You are calling getValue('${field}') but the column \`${field}\` is not defined.`, - `Instead, you can access the data from \`params.row.${field}\`.`, - ].join('\n'), - ); - warnedOnce = true; - } - } - - if (!col || !col.valueGetter) { - return rowModel[field]; - } - - return col.valueGetter( - buildGridCellParams({ - value: rowModel[field], - colDef: col, - rowIndex, - element, - rowModel, - api, - }), - ); - }, - row: rowModel, - colDef, - rowIndex, - colIndex: colIndex || (colDef && api.getColumnIndex(colDef.field, true)), - api, - }; - const isEditableAttr = element && element.getAttribute('data-editable'); - params.isEditable = - isEditableAttr != null ? isEditableAttr === 'true' : colDef && api.isCellEditable(params); - - return params; -} - -export function buildGridRowParams({ - element, - rowIndex, - rowModel, - api, -}: { - rowModel: GridRowModel; - rowIndex: number; - api: GridApi; - element?: HTMLElement; -}): GridRowParams { - return { - element, - columns: api.getAllColumns(), - getValue: (field: string) => rowModel[field], - row: rowModel, - rowIndex, - api, - }; -} From 4cd41eb8cfb1fa914ce76fe89153d151d698fc37 Mon Sep 17 00:00:00 2001 From: damien Date: Tue, 9 Mar 2021 17:55:25 +0100 Subject: [PATCH 05/22] add formattedValue, fix valueGetter, cleanup --- .../_modules_/grid/components/GridCell.tsx | 1 + .../_modules_/grid/components/GridRow.tsx | 1 + .../grid/components/GridRowCells.tsx | 12 ++--- .../hooks/features/rows/useGridCellApi.ts | 53 +++++++++---------- .../hooks/features/sorting/useGridSorting.ts | 2 +- .../grid/models/api/gridEditRowApi.ts | 2 +- .../grid/models/params/gridCellParams.ts | 8 ++- 7 files changed, 38 insertions(+), 41 deletions(-) diff --git a/packages/grid/_modules_/grid/components/GridCell.tsx b/packages/grid/_modules_/grid/components/GridCell.tsx index caef4b1a0e75f..e4aba058906e4 100644 --- a/packages/grid/_modules_/grid/components/GridCell.tsx +++ b/packages/grid/_modules_/grid/components/GridCell.tsx @@ -114,6 +114,7 @@ export const GridCell: React.FC = React.memo((props) => { ); return ( + // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/mouse-events-have-key-events,jsx-a11y/no-noninteractive-element-interactions
= ({ selected, id, className, rowIndex, ); return ( + // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/mouse-events-have-key-events,jsx-a11y/interactive-supports-focus
= React.memo((props) => { const editCellState = editRowsState[row.id] && editRowsState[row.id][column.field]; let cellComponent: React.ReactElement | null = null; - let formattedValueProp = {}; - if (column.valueFormatter) { - // TODO add formatted value to cellParams? - formattedValueProp = { formattedValue: column.valueFormatter(cellParams) }; - } - if (editCellState == null && column.renderCell) { cellComponent = column.renderCell(cellParams); cssClassProp = { cssClass: `${cssClassProp.cssClass} MuiDataGrid-cellWithRenderer` }; @@ -105,18 +99,18 @@ export const GridRowCells: React.FC = React.memo((props) => { rowId: row.id, height: rowHeight, showRightBorder, - ...formattedValueProp, + formattedValue: cellParams.formattedValue, align: column.align || 'left', ...cssClassProp, tabIndex: domIndex === 0 && colIdx === 0 ? 0 : -1, rowIndex, - colIndex: colIdx + firstColIdx, + colIndex: cellParams.colIndex, children: cellComponent, isEditable: cellParams.isEditable, hasFocus: cellFocus !== null && cellFocus.rowIndex === rowIndex && - cellFocus.colIndex === colIdx + firstColIdx, + cellFocus.colIndex === cellParams.colIndex, }; return cellProps; diff --git a/packages/grid/_modules_/grid/hooks/features/rows/useGridCellApi.ts b/packages/grid/_modules_/grid/hooks/features/rows/useGridCellApi.ts index f4e9288a3b986..0e713ecf157eb 100644 --- a/packages/grid/_modules_/grid/hooks/features/rows/useGridCellApi.ts +++ b/packages/grid/_modules_/grid/hooks/features/rows/useGridCellApi.ts @@ -24,55 +24,51 @@ export function useGridCellApi(apiRef: GridApiRef) { [apiRef], ); - const getCellParams = React.useCallback( + const getBaseCellParams = React.useCallback( (id: GridRowId, field: string) => { - const colDef = apiRef.current.getColumnFromField(field); const element = apiRef.current.getCellElement(id, field); + const row = apiRef.current.getRowFromId(id); - const params: GridCellParams = { + const params: ValueGetterParams = { element, id, - value: apiRef.current.getCellValue(id, field), field, - getValue: (columnField: string) => apiRef.current.getCellValue(id, columnField), - row: apiRef.current.getRowFromId(id), + row, + value: row[field], + getValue: (columnField: string) => row[columnField], colDef: apiRef.current.getColumnFromField(field), rowIndex: apiRef.current.getRowIndexFromId(id), colIndex: apiRef.current.getColumnIndex(field, true), api: apiRef.current, }; - const isEditableAttr = element && element.getAttribute('data-editable'); - params.isEditable = - isEditableAttr != null - ? isEditableAttr === 'true' - : colDef && apiRef.current.isCellEditable(params); return params; }, [apiRef], ); - const getValueGetterParams = React.useCallback( + const getCellParams = React.useCallback( (id: GridRowId, field: string) => { + const colDef = apiRef.current.getColumnFromField(field); const element = apiRef.current.getCellElement(id, field); - const row = apiRef.current.getRowFromId(id); - - const params: ValueGetterParams = { - element, - id, - field, - row, - value: row[field], - getValue: (columnField: string) => row[columnField], - colDef: apiRef.current.getColumnFromField(field), - rowIndex: apiRef.current.getRowIndexFromId(id), - colIndex: apiRef.current.getColumnIndex(field, true), - api: apiRef.current, + const value = apiRef.current.getCellValue(id, field); + const baseParams = getBaseCellParams(id, field); + const params: GridCellParams = { + ...baseParams, + value, + getValue: (columnField: string) => apiRef.current.getCellValue(id, columnField), + formattedValue: colDef.valueFormatter ? colDef.valueFormatter(baseParams) : value, }; + const isEditableAttr = element && element.getAttribute('data-editable'); + params.isEditable = + isEditableAttr != null + ? isEditableAttr === 'true' + : colDef && apiRef.current.isCellEditable(params); + return params; }, - [apiRef], + [apiRef, getBaseCellParams], ); const getCellValue = React.useCallback( @@ -84,9 +80,9 @@ export function useGridCellApi(apiRef: GridApiRef) { return rowModel[field]; } - return colDef.valueGetter(getValueGetterParams(id, field)); + return colDef.valueGetter(getBaseCellParams(id, field)); }, - [apiRef, getValueGetterParams], + [apiRef, getBaseCellParams], ); const getRowElement = React.useCallback( @@ -98,6 +94,7 @@ export function useGridCellApi(apiRef: GridApiRef) { }, [apiRef], ); + const getCellElement = React.useCallback( (id: GridRowId, field: string): HTMLDivElement | null => { if (!apiRef.current.rootElementRef!.current) { diff --git a/packages/grid/_modules_/grid/hooks/features/sorting/useGridSorting.ts b/packages/grid/_modules_/grid/hooks/features/sorting/useGridSorting.ts index 5aed18491d762..5081728c899c7 100644 --- a/packages/grid/_modules_/grid/hooks/features/sorting/useGridSorting.ts +++ b/packages/grid/_modules_/grid/hooks/features/sorting/useGridSorting.ts @@ -104,7 +104,7 @@ export const useGridSorting = (apiRef: GridApiRef, rowsProp: GridRowsProp) => { row1[field], row2[field], apiRef.current.getCellParams(row1.id, field), - apiRef.current.getCellParams(row2.id, field) + apiRef.current.getCellParams(row2.id, field), ); return res; }, 0); diff --git a/packages/grid/_modules_/grid/models/api/gridEditRowApi.ts b/packages/grid/_modules_/grid/models/api/gridEditRowApi.ts index 96fb4cfdff019..9575f249df4ee 100644 --- a/packages/grid/_modules_/grid/models/api/gridEditRowApi.ts +++ b/packages/grid/_modules_/grid/models/api/gridEditRowApi.ts @@ -1,4 +1,4 @@ -import { GridCellMode, GridCellValue } from '../gridCell'; +import { GridCellMode } from '../gridCell'; import { GridEditRowsModel, GridEditRowUpdate } from '../gridEditRowModel'; import { GridRowId } from '../gridRows'; import { GridCellParams } from '../params/gridCellParams'; diff --git a/packages/grid/_modules_/grid/models/params/gridCellParams.ts b/packages/grid/_modules_/grid/models/params/gridCellParams.ts index 06ff0572e780d..9da6a80415a06 100644 --- a/packages/grid/_modules_/grid/models/params/gridCellParams.ts +++ b/packages/grid/_modules_/grid/models/params/gridCellParams.ts @@ -21,6 +21,10 @@ export interface GridCellParams { * The cell value, but if the column has valueGetter, use getValue. */ value: GridCellValue; + /** + * The cell value formatted with the column valueFormatter. + */ + formattedValue: GridCellValue; /** * A function that let you get data from other columns. * @param field @@ -55,9 +59,9 @@ export interface GridCellParams { /** * Alias of GridCellParams. */ -export type ValueGetterParams =GridCellParams// Omit; +export type ValueGetterParams = Omit; /** * Alias of GridCellParams. */ -export type ValueFormatterParams = GridCellParams; +export type ValueFormatterParams = Omit; From 59742efd77879423059e34caf1a10b60daa4ff4b Mon Sep 17 00:00:00 2001 From: damien Date: Tue, 9 Mar 2021 17:56:02 +0100 Subject: [PATCH 06/22] fix action panel, improve args control --- packages/storybook/.storybook/preview.tsx | 7 +- .../stories/playground/RecipeReviewCard.tsx | 126 +++++++++++ .../stories/playground/customComponents.tsx | 106 ++++++++++ .../customize-components.stories.tsx | 123 ++--------- .../playground/data-grid.options.stories.tsx | 64 ------ .../stories/playground/options.stories.tsx | 52 ----- .../playground/real-data-demo.stories.tsx | 196 ++++++++---------- 7 files changed, 345 insertions(+), 329 deletions(-) create mode 100644 packages/storybook/src/stories/playground/RecipeReviewCard.tsx create mode 100644 packages/storybook/src/stories/playground/customComponents.tsx delete mode 100644 packages/storybook/src/stories/playground/data-grid.options.stories.tsx delete mode 100644 packages/storybook/src/stories/playground/options.stories.tsx diff --git a/packages/storybook/.storybook/preview.tsx b/packages/storybook/.storybook/preview.tsx index b9f540b2b564f..138849768bc31 100644 --- a/packages/storybook/.storybook/preview.tsx +++ b/packages/storybook/.storybook/preview.tsx @@ -14,7 +14,12 @@ configureActions({ }); export const parameters = { - actions: { argTypesRegex: '^on.*' }, + // The storybook action panel is throwing a serialisation error with mouse events + // due to its circular structure + actions: { + argTypesRegex: + '^on((?!CellClick|CellDoubleClick|CellEnter|CellLeave|CellOut|CellOver|ColumnHeaderClickStateChange|RowClick|RowDoubleClick|RowEnter|RowLeave|RowOut|RowOver).)*$', + }, options: { /** * display the top-level grouping as a "root" in the sidebar diff --git a/packages/storybook/src/stories/playground/RecipeReviewCard.tsx b/packages/storybook/src/stories/playground/RecipeReviewCard.tsx new file mode 100644 index 0000000000000..14c9616a44f91 --- /dev/null +++ b/packages/storybook/src/stories/playground/RecipeReviewCard.tsx @@ -0,0 +1,126 @@ +import React from 'react'; +import { makeStyles, Theme, createStyles } from '@material-ui/core/styles'; +import clsx from 'clsx'; +import Card from '@material-ui/core/Card'; +import CardHeader from '@material-ui/core/CardHeader'; +import CardMedia from '@material-ui/core/CardMedia'; +import CardContent from '@material-ui/core/CardContent'; +import CardActions from '@material-ui/core/CardActions'; +import Collapse from '@material-ui/core/Collapse'; +import Avatar from '@material-ui/core/Avatar'; +import IconButton from '@material-ui/core/IconButton'; +import Typography from '@material-ui/core/Typography'; +import { red } from '@material-ui/core/colors'; +import FavoriteIcon from '@material-ui/icons/Favorite'; +import ShareIcon from '@material-ui/icons/Share'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import MoreVertIcon from '@material-ui/icons/MoreVert'; + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + root: { + maxWidth: 345, + }, + media: { + height: 0, + paddingTop: '56.25%', // 16:9 + }, + expand: { + transform: 'rotate(0deg)', + marginLeft: 'auto', + transition: theme.transitions.create('transform', { + duration: theme.transitions.duration.shortest, + }), + }, + expandOpen: { + transform: 'rotate(180deg)', + }, + avatar: { + backgroundColor: red[500], + }, + }), +); + +export default function RecipeReviewCard() { + const classes = useStyles(); + const [expanded, setExpanded] = React.useState(false); + + const handleExpandClick = () => { + setExpanded(!expanded); + }; + + return ( + + + R + + } + action={ + + + + } + title="Shrimp and Chorizo Paella" + subheader="September 14, 2016" + /> + + + + This impressive paella is a perfect party dish and a fun meal to cook together with your + guests. Add 1 cup of frozen peas along with the mussels, if you like. + + + + + + + + + + + + + + + + Method: + + Heat 1/2 cup of the broth in a pot until simmering, add saffron and set aside for 10 + minutes. + + + Heat oil in a (14- to 16-inch) paella pan or a large, deep skillet over medium-high + heat. Add chicken, shrimp and chorizo, and cook, stirring occasionally until lightly + browned, 6 to 8 minutes. Transfer shrimp to a large plate and set aside, leaving chicken + and chorizo in the pan. Add pimentón, bay leaves, garlic, tomatoes, onion, salt and + pepper, and cook, stirring often until thickened and fragrant, about 10 minutes. Add + saffron broth and remaining 4 1/2 cups chicken broth; bring to a boil. + + + Add rice and stir very gently to distribute. Top with artichokes and peppers, and cook + without stirring, until most of the liquid is absorbed, 15 to 18 minutes. Reduce heat to + medium-low, add reserved shrimp and mussels, tucking them down into the rice, and cook + again without stirring, until mussels have opened and rice is just tender, 5 to 7 + minutes more. (Discard any mussels that don’t open.) + + + Set aside off of the heat to let rest for 10 minutes, and then serve. + + + + + ); +} diff --git a/packages/storybook/src/stories/playground/customComponents.tsx b/packages/storybook/src/stories/playground/customComponents.tsx new file mode 100644 index 0000000000000..ad813f8eea3a7 --- /dev/null +++ b/packages/storybook/src/stories/playground/customComponents.tsx @@ -0,0 +1,106 @@ +import * as React from 'react'; +import LinearProgress from '@material-ui/core/LinearProgress'; +import CodeIcon from '@material-ui/icons/Code'; +import ExpandLessIcon from '@material-ui/icons/ExpandLess'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import Pagination from '@material-ui/lab/Pagination'; +import { + GridFooterContainer, + GridOverlay, + GridColumnMenu, + HideGridColMenuItem, + GridBaseComponentProps, + ColumnMenuProps, +} from '@material-ui/data-grid'; +import RecipeReviewCard from './RecipeReviewCard'; + +export function SortedDescendingIcon() { + return ; +} + +export function SortedAscendingIcon() { + return ; +} + +export function LoadingComponent() { + return ( + +
+ +
+
+ ); +} + +export function NoRowsComponent() { + return ( + + + No Rows + + + ); +} + +export function PaginationComponent(props: GridBaseComponentProps & { color?: 'primary' }) { + const { state, api } = props; + return ( + api.current.setPage(value)} + /> + ); +} + +export function CustomFooter(props) { + const { state, api } = props; + return ( + + + Custom footer is here. + + api.current.setPage(value)} + /> + + ); +} + +export function FooterComponent2(props) { + const { state } = props; + + return ( +
I counted {state.pagination.rowCount} row(s)
+ ); +} + +export function CustomHeader(props) { + return ( +
+ +
+ ); +} + +export function ColumnMenuComponent(props: ColumnMenuProps) { + if (props.api.current.getColumnIndex(props.currentColumn.field) === 1) { + return ; + } + if (props.currentColumn.field === 'id') { + return ; + } + + return ( + + ); +} diff --git a/packages/storybook/src/stories/playground/customize-components.stories.tsx b/packages/storybook/src/stories/playground/customize-components.stories.tsx index 11764d5c309ea..db0bf81337f97 100644 --- a/packages/storybook/src/stories/playground/customize-components.stories.tsx +++ b/packages/storybook/src/stories/playground/customize-components.stories.tsx @@ -4,27 +4,28 @@ import { Story, Meta } from '@storybook/react'; import { GridColDef, XGrid, - GridOverlay, - GridFooterContainer, XGridProps, - HideGridColMenuItem, - ColumnMenuProps, GridBaseComponentProps, - GridColumnMenu, GridPanelProps, GridPreferencesPanel, GridFooter, GridToolbar, } from '@material-ui/x-grid'; -import LinearProgress from '@material-ui/core/LinearProgress'; -import CodeIcon from '@material-ui/icons/Code'; -import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; -import ExpandLessIcon from '@material-ui/icons/ExpandLess'; -import Pagination from '@material-ui/lab/Pagination'; import DoneIcon from '@material-ui/icons/Done'; import ClearIcon from '@material-ui/icons/Clear'; import CreateIcon from '@material-ui/icons/Create'; import { useData } from '../../hooks/useData'; +import { + CustomHeader, + CustomFooter, + FooterComponent2, + LoadingComponent, + NoRowsComponent, + PaginationComponent, + ColumnMenuComponent, + SortedDescendingIcon, + SortedAscendingIcon, +} from './customComponents'; export default { title: 'X-Grid Demos/Custom-Components', @@ -67,16 +68,6 @@ const Template: Story = (args) => { ); }; -function LoadingComponent() { - return ( - -
- -
-
- ); -} - export const Loading = Template.bind({}); Loading.args = { ...defaultData, @@ -86,16 +77,6 @@ Loading.args = { }, }; -function NoRowsComponent() { - return ( - - - No Rows - - - ); -} - export const NoRows = Template.bind({}); NoRows.args = { rows: [], @@ -105,36 +86,15 @@ NoRows.args = { }, }; -function SortedDescending() { - return ; -} - -function SortedAscending() { - return ; -} - export const Icons = Template.bind({}); Icons.args = { ...defaultData, components: { - ColumnSortedDescendingIcon: SortedDescending, - ColumnSortedAscendingIcon: SortedAscending, + ColumnSortedDescendingIcon: SortedDescendingIcon, + ColumnSortedAscendingIcon: SortedAscendingIcon, }, }; -function PaginationComponent(props: GridBaseComponentProps & { color?: 'primary' }) { - const { state, api } = props; - return ( - api.current.setPage(value)} - /> - ); -} - export const CustomPagination = Template.bind({}); CustomPagination.args = { pagination: true, @@ -147,51 +107,18 @@ CustomPagination.args = { }, }; -function FooterComponent(props) { - const { state, api } = props; - return ( - - - This is my custom footer and pagination here!{' '} - - api.current.setPage(value)} - /> - - ); -} - -export const CustomFooter = Template.bind({}); -CustomFooter.args = { +export const CustomFooterDemo = Template.bind({}); +CustomFooterDemo.args = { pagination: true, pageSize: 33, components: { - Footer: FooterComponent, + Footer: CustomFooter, }, componentsProps: { footer: { color: 'blue' }, }, }; -function FooterComponent2(props) { - const { state } = props; - - return ( -
I counted {state.pagination.rowCount} row(s)
- ); -} - -function CustomHeader(props) { - return ( -
- -
- ); -} - export const HeaderAndFooter = Template.bind({}); HeaderAndFooter.args = { pagination: true, @@ -326,24 +253,6 @@ CustomToolbar.args = { }, }; -function ColumnMenuComponent(props: ColumnMenuProps & { color?: string }) { - if (props.currentColumn.field === 'id') { - return ; - } - if (props.currentColumn.field === 'currencyPair') { - return ( -
This is my currency pair column Menu!
- ); - } - return ( - - ); -} - export const CustomColumnMenu = Template.bind({}); CustomColumnMenu.args = { components: { diff --git a/packages/storybook/src/stories/playground/data-grid.options.stories.tsx b/packages/storybook/src/stories/playground/data-grid.options.stories.tsx deleted file mode 100644 index 3f8766d18831a..0000000000000 --- a/packages/storybook/src/stories/playground/data-grid.options.stories.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import * as React from 'react'; -import { Story, Meta } from '@storybook/react'; -import { DataGrid, DataGridProps, GridSortDirection } from '@material-ui/data-grid'; -import { useData } from '../../hooks/useData'; - -export default { - title: 'Data-Grid Demos/Options Events', - component: DataGrid, - parameters: { - options: { selectedPanel: 'storybook/controls/panel' }, - docs: { - page: null, - }, - }, -} as Meta; - -interface StoryExtraArgs { - resizable: boolean; -} - -const Template: Story & StoryExtraArgs> = ({ - resizable, - sortingOrder, - ...args -}) => { - const { rows, columns } = useData(200, 20); - if (resizable) { - columns.forEach((c) => { - c.resizable = true; - }); - } - return ( - ((value as string) === 'null' ? null : value))} - {...args} - /> - ); -}; - -export const Options = Template.bind({}); -Options.args = { - pageSize: 100, - autoPageSize: false, - rowsPerPageOptions: [25, 50, 100], - hideFooterRowCount: false, - hideFooterPagination: false, - hideFooter: false, - disableExtendRowFullWidth: false, - showCellRightBorder: false, - showColumnRightBorder: false, - checkboxSelection: true, - disableSelectionOnClick: false, - sortingOrder: ['asc', 'desc', 'null' as GridSortDirection], - headerHeight: 56, - rowHeight: 52, -}; - -export const ResizableValidation = Template.bind({}); -ResizableValidation.args = { - ...Options.args, - resizable: true, -}; diff --git a/packages/storybook/src/stories/playground/options.stories.tsx b/packages/storybook/src/stories/playground/options.stories.tsx deleted file mode 100644 index e3df8f9e7d42d..0000000000000 --- a/packages/storybook/src/stories/playground/options.stories.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import * as React from 'react'; -import { Story, Meta } from '@storybook/react'; -import { XGrid, GridSortDirection, GridOptionsProp } from '@material-ui/x-grid'; -import { useData } from '../../hooks/useData'; - -export default { - title: 'X-Grid Demos/Options-Events', - component: XGrid, - parameters: { - options: { selectedPanel: 'storybook/controls/panel' }, - docs: { - page: null, - }, - }, -} as Meta; - -const Template: Story = ({ sortingOrder, ...args }) => { - const data = useData(2000, 200); - return ( - ((value as string) === 'null' ? null : value))} - {...args} - /> - ); -}; - -export const Options = Template.bind({}); -Options.args = { - autoHeight: false, - pagination: true, - pageSize: 100, - autoPageSize: false, - rowsPerPageOptions: [25, 50, 100], - hideFooterRowCount: false, - hideFooterPagination: false, - hideFooter: false, - disableExtendRowFullWidth: false, - disableColumnMenu: false, - disableColumnFilter: false, - disableColumnSelector: false, - showCellRightBorder: false, - showColumnRightBorder: false, - disableMultipleSelection: false, - checkboxSelection: true, - disableSelectionOnClick: false, - disableMultipleColumnsSorting: false, - sortingOrder: ['asc', 'desc', 'null' as GridSortDirection], - headerHeight: 56, - rowHeight: 52, -}; diff --git a/packages/storybook/src/stories/playground/real-data-demo.stories.tsx b/packages/storybook/src/stories/playground/real-data-demo.stories.tsx index 372ef04193381..126de9587e559 100644 --- a/packages/storybook/src/stories/playground/real-data-demo.stories.tsx +++ b/packages/storybook/src/stories/playground/real-data-demo.stories.tsx @@ -1,134 +1,107 @@ +import { DataGrid, GridToolbar } from '@material-ui/data-grid'; import * as React from 'react'; import { Story, Meta, DecoratorFn } from '@storybook/react'; -import { XGridProps, GridPreferencePanelsValue, XGrid, GridOptionsProp } from '@material-ui/x-grid'; +import { XGridProps, GridPreferencePanelsValue, XGrid } from '@material-ui/x-grid'; import { useDemoData, DemoDataOptions } from '@material-ui/x-grid-data-generator'; -import Button from '@material-ui/core/Button'; -import { randomInt } from '../../data/random-generator'; +import { useData } from '../../hooks/useData'; +import { + ColumnMenuComponent, + CustomFooter, + LoadingComponent, + NoRowsComponent, + PaginationComponent, + SortedAscendingIcon, + SortedDescendingIcon, +} from './customComponents'; + +export interface PlaygroundProps { + multipleGrid: boolean; + license: 'XGrid' | 'DataGrid'; +} + +const gridContainer: DecoratorFn = (storyFn) =>
{storyFn()}
; export default { title: 'X-Grid Demos/Playground', component: XGrid, + argTypes: { + dataSet: { + defaultValue: 'Commodity', + control: { + type: 'inline-radio', + options: ['Commodity', 'Employee', 'Raw'], + }, + }, + license: { + defaultValue: 'XGrid', + control: { + type: 'inline-radio', + options: ['XGrid', 'DataGrid'], + }, + }, + rowLength: { + defaultValue: 1000, + control: { + type: 'select', + options: [100, 500, 1000, 10000, 50000, 100000, 500000], + }, + }, + multipleGrid: { + defaultValue: false, + control: { + type: 'boolean', + }, + }, + headerHeight: { + control: { type: 'range', min: 20, max: 150, step: 10 }, + }, + rowHeight: { + control: { type: 'range', min: 20, max: 150, step: 10 }, + }, + }, + decorators: [gridContainer], parameters: { options: { selectedPanel: 'storybook/controls/panel' }, - docs: { - page: null, - }, }, } as Meta; -const gridContainer: DecoratorFn = (storyFn) =>
{storyFn()}
; - -export const Commodity: Story = ({ rows, columns, ...args }) => { - const { data, setRowLength, loadNewData } = useDemoData({ dataSet: 'Commodity', rowLength: 100 }); - - return ( - -
- - -
-
- -
-
- ); -}; - -const DemoTemplate: Story = ({ +const DemoTemplate: Story = ({ rows, columns, - rowLength, dataSet, + license, + rowLength, maxColumns, + multipleGrid, ...args }) => { - const { data } = useDemoData({ rowLength, dataSet, maxColumns }); + const isRaw = dataSet.toString() === 'Raw'; + let data: any = useData(isRaw ? rowLength : 0, maxColumns || 20); + const demoData = useDemoData({ rowLength: !isRaw ? rowLength : 0, dataSet, maxColumns }); - return ; -}; - -export const Commodity500 = DemoTemplate.bind({}); -Commodity500.args = { - rowLength: 500, - dataSet: 'Commodity', -}; -Commodity500.decorators = [gridContainer]; - -export const Commodity1000 = DemoTemplate.bind({}); -Commodity1000.args = { - rowLength: 1000, - dataSet: 'Commodity', -}; -Commodity1000.decorators = [gridContainer]; - -export const Commodity10000 = DemoTemplate.bind({}); -Commodity10000.args = { - rowLength: 10000, - dataSet: 'Commodity', -}; -Commodity10000.decorators = [gridContainer]; - -export const Employee100 = DemoTemplate.bind({}); -Employee100.args = { - rowLength: 500, - dataSet: 'Employee', -}; -Employee100.decorators = [gridContainer]; - -export const Employee1000 = DemoTemplate.bind({}); -Employee1000.args = { - rowLength: 1000, - dataSet: 'Employee', -}; -Employee1000.decorators = [gridContainer]; - -export const Employee10000 = DemoTemplate.bind({}); -Employee10000.args = { - rowLength: 10000, - dataSet: 'Commodity', -}; -Employee10000.decorators = [gridContainer]; + if (!isRaw) { + data = demoData.data; + } -export const MultipleEmployee100: Story = (args) => { - const { data } = useDemoData({ dataSet: 'Employee', rowLength: 100 }); + const Grid = license === 'XGrid' ? XGrid : DataGrid; - return ( -
-
- -
-
- -
-
+ return !multipleGrid ? ( + + ) : ( + + + + ); }; -export const XGridDemo = DemoTemplate.bind({}); -XGridDemo.args = { - dataSet: 'Commodity', - rowLength: 100000, - rowHeight: 38, +export const Demo = DemoTemplate.bind({}); +Demo.args = { checkboxSelection: true, }; -XGridDemo.decorators = [gridContainer]; -export const CommodityPreferencesDefaultOpen = DemoTemplate.bind({}); -CommodityPreferencesDefaultOpen.args = { - dataSet: 'Commodity', - rowLength: 500, - state: { preferencePanel: { open: true } }, -}; -CommodityPreferencesDefaultOpen.decorators = [gridContainer]; - -export const CommodityPreferences = DemoTemplate.bind({}); -CommodityPreferences.args = { - dataSet: 'Commodity', - rowLength: 500, +export const ColumnSelector = DemoTemplate.bind({}); +ColumnSelector.args = { state: { preferencePanel: { open: true, @@ -136,4 +109,17 @@ CommodityPreferences.args = { }, }, }; -CommodityPreferences.decorators = [gridContainer]; + +export const Custom = DemoTemplate.bind({}); +Custom.args = { + components: { + Footer: CustomFooter, + ColumnSortedDescendingIcon: SortedDescendingIcon, + ColumnSortedAscendingIcon: SortedAscendingIcon, + NoRowsOverlay: NoRowsComponent, + LoadingOverlay: LoadingComponent, + Pagination: PaginationComponent, + ColumnMenu: ColumnMenuComponent, + Toolbar: GridToolbar, + }, +}; From e396e499ec4bad047937562c99c01993c0c8f180 Mon Sep 17 00:00:00 2001 From: damien Date: Tue, 9 Mar 2021 18:22:11 +0100 Subject: [PATCH 07/22] rename cellApi --- .../grid/_modules_/grid/GridComponent.tsx | 4 ++-- .../grid/hooks/features/rows/index.ts | 2 +- ...{useGridCellApi.ts => useGridParamsApi.ts} | 6 ++--- .../grid/_modules_/grid/models/api/gridApi.ts | 4 ++-- .../api/{gridCellApi.ts => gridParamsApi.ts} | 22 ++++++++++++++++++- .../grid/_modules_/grid/models/api/index.ts | 2 +- 6 files changed, 30 insertions(+), 10 deletions(-) rename packages/grid/_modules_/grid/hooks/features/rows/{useGridCellApi.ts => useGridParamsApi.ts} (95%) rename packages/grid/_modules_/grid/models/api/{gridCellApi.ts => gridParamsApi.ts} (62%) diff --git a/packages/grid/_modules_/grid/GridComponent.tsx b/packages/grid/_modules_/grid/GridComponent.tsx index b367d03c5800d..34e9a7a6a1892 100644 --- a/packages/grid/_modules_/grid/GridComponent.tsx +++ b/packages/grid/_modules_/grid/GridComponent.tsx @@ -21,7 +21,7 @@ import { useGridColumns } from './hooks/features/columns/useGridColumns'; import { useGridState } from './hooks/features/core/useGridState'; import { useGridPagination } from './hooks/features/pagination/useGridPagination'; import { useGridPreferencesPanel } from './hooks/features/preferencesPanel/useGridPreferencesPanel'; -import { useGridCellApi } from './hooks/features/rows/useGridCellApi'; +import { useGridParamsApi } from './hooks/features/rows/useGridParamsApi'; import { useGridRows } from './hooks/features/rows/useGridRows'; import { useGridEditRows } from './hooks/features/rows/useGridEditRows'; import { useGridSorting } from './hooks/features/sorting/useGridSorting'; @@ -76,7 +76,7 @@ export const GridComponent = React.forwardRef { const params: GridRowParams = { @@ -105,7 +105,7 @@ export function useGridCellApi(apiRef: GridApiRef) { [apiRef], ); - useGridApiMethod( + useGridApiMethod( apiRef, { getCellValue, diff --git a/packages/grid/_modules_/grid/models/api/gridApi.ts b/packages/grid/_modules_/grid/models/api/gridApi.ts index a7d9194e98cdc..cfea6b26c03ca 100644 --- a/packages/grid/_modules_/grid/models/api/gridApi.ts +++ b/packages/grid/_modules_/grid/models/api/gridApi.ts @@ -1,6 +1,6 @@ import { ColumnMenuApi } from './columnMenuApi'; import { ColumnResizeApi } from './columnResizeApi'; -import { GridCellApi } from './gridCellApi'; +import { GridParamsApi } from './gridParamsApi'; import { ComponentsApi } from './gridComponentsApi'; import { FilterApi } from './filterApi'; import { GridEditRowApi } from './gridEditRowApi'; @@ -29,7 +29,7 @@ export type GridApi = GridCoreApi & GridEventsApi & GridRowApi & GridEditRowApi & - GridCellApi & + GridParamsApi & GridColumnApi & ColumnReorderApi & GridSelectionApi & diff --git a/packages/grid/_modules_/grid/models/api/gridCellApi.ts b/packages/grid/_modules_/grid/models/api/gridParamsApi.ts similarity index 62% rename from packages/grid/_modules_/grid/models/api/gridCellApi.ts rename to packages/grid/_modules_/grid/models/api/gridParamsApi.ts index da85f23ff9226..053be73ca1b9a 100644 --- a/packages/grid/_modules_/grid/models/api/gridCellApi.ts +++ b/packages/grid/_modules_/grid/models/api/gridParamsApi.ts @@ -3,15 +3,35 @@ import { GridRowId } from '../gridRows'; import { GridCellParams } from '../params/gridCellParams'; import { GridRowParams } from '../params/gridRowParams'; -export interface GridCellApi { +export interface GridParamsApi { /** * Get the cell value of a row and field. * @param id * @param field */ getCellValue: (id: GridRowId, field: string) => GridCellValue; + /** + * Get the cell DOM element + * @param id + * @param field + */ getCellElement: (id: GridRowId, field: string) => HTMLDivElement | null; + /** + * Get the cell params that are passed in events + * @param id + * @param field + */ getCellParams: (id: GridRowId, field: string) => GridCellParams; + /** + * Get the row params that are passed in events + * @param id + * @param field + */ getRowParams: (id: GridRowId) => GridRowParams; + /** + * Get the row DOM element + * @param id + * @param field + */ getRowElement: (id: GridRowId) => HTMLDivElement | null; } diff --git a/packages/grid/_modules_/grid/models/api/index.ts b/packages/grid/_modules_/grid/models/api/index.ts index 36c88c0aa2f09..ff15818a3ce10 100644 --- a/packages/grid/_modules_/grid/models/api/index.ts +++ b/packages/grid/_modules_/grid/models/api/index.ts @@ -1,5 +1,5 @@ export * from './gridApiRef'; -export * from './gridCellApi'; +export * from './gridParamsApi'; export * from './gridCoreApi'; export * from './gridColumnApi'; export * from './gridComponentsApi'; From e87db1ea2422daec531c5533ff91390708c26d8a Mon Sep 17 00:00:00 2001 From: damien Date: Tue, 9 Mar 2021 19:06:39 +0100 Subject: [PATCH 08/22] fix input cell, fix test --- .../components/editCell/EditInputCell.tsx | 6 +++-- .../hooks/features/rows/useGridParamsApi.ts | 18 ++++++++++++- .../src/stories/grid-columns.stories.tsx | 25 ++++++++++++++++++- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/packages/grid/_modules_/grid/components/editCell/EditInputCell.tsx b/packages/grid/_modules_/grid/components/editCell/EditInputCell.tsx index 7f6cbecf4bd12..16cb6306d2777 100644 --- a/packages/grid/_modules_/grid/components/editCell/EditInputCell.tsx +++ b/packages/grid/_modules_/grid/components/editCell/EditInputCell.tsx @@ -7,7 +7,9 @@ import { GridEditRowApi } from '../../models/api/gridEditRowApi'; export function EditInputCell(props: GridCellParams & InputBaseProps) { const { + id, value, + formattedValue, api, field, row, @@ -51,7 +53,7 @@ export function EditInputCell(props: GridCellParams & InputBaseProps) { ); const inputType = mapColDefTypeToInputType(colDef.type); - const formattedValue = + const inputFormattedValue = valueState && isDate(valueState) ? formatDateToLocalInputDate({ value: valueState, withTime: colDef.type === 'dateTime' }) : valueState; @@ -66,7 +68,7 @@ export function EditInputCell(props: GridCellParams & InputBaseProps) { fullWidth className="MuiDataGrid-editCellInputBase" onKeyDown={onKeyDown} - value={formattedValue} + value={inputFormattedValue} onChange={onValueChange} type={inputType} {...inputBaseProps} diff --git a/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts b/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts index cd640777eadae..c1e7f2c022ea6 100644 --- a/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts +++ b/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts @@ -7,7 +7,20 @@ import { GridRowParams } from '../../../models/params/gridRowParams'; import { getGridCellElement, getGridRowElement } from '../../../utils/domUtils'; import { useGridApiMethod } from '../../root/useGridApiMethod'; +let warnedOnce = false; +function warnMissingColumn(field) { + if (!warnedOnce && process.env.NODE_ENV !== 'production') { + console.warn( + [ + `Material-UI: You are calling getValue('${field}') but the column \`${field}\` is not defined.`, + `Instead, you can access the data from \`params.row.${field}\`.`, + ].join('\n'), + ); + warnedOnce = true; + } +} export function useGridParamsApi(apiRef: GridApiRef) { + const getRowParams = React.useCallback( (id: GridRowId) => { const params: GridRowParams = { @@ -35,7 +48,7 @@ export function useGridParamsApi(apiRef: GridApiRef) { field, row, value: row[field], - getValue: (columnField: string) => row[columnField], + getValue: (columnField: string) => apiRef.current.getCellValue(id, columnField), colDef: apiRef.current.getColumnFromField(field), rowIndex: apiRef.current.getRowIndexFromId(id), colIndex: apiRef.current.getColumnIndex(field, true), @@ -76,6 +89,9 @@ export function useGridParamsApi(apiRef: GridApiRef) { const colDef = apiRef.current.getColumnFromField(field); const rowModel = apiRef.current.getRowFromId(id); + if(!colDef) { + warnMissingColumn(field); + } if (!colDef || !colDef.valueGetter) { return rowModel[field]; } diff --git a/packages/storybook/src/stories/grid-columns.stories.tsx b/packages/storybook/src/stories/grid-columns.stories.tsx index c5324dc2cd972..9d89a51621717 100644 --- a/packages/storybook/src/stories/grid-columns.stories.tsx +++ b/packages/storybook/src/stories/grid-columns.stories.tsx @@ -1,7 +1,9 @@ +import { DataGrid } from '@material-ui/data-grid'; import * as React from 'react'; -import { GridColDef, XGrid, GridColTypeDef } from '@material-ui/x-grid'; +import { GridColDef, XGrid, GridColTypeDef, ValueGetterParams } from '@material-ui/x-grid'; import CreateIcon from '@material-ui/icons/Create'; import Button from '@material-ui/core/Button'; +import { getColumnValues } from '../../../../test/utils/helperFn'; import { useData } from '../hooks/useData'; export default { @@ -287,3 +289,24 @@ export const FlexColumnWidth2000 = () => {
); }; + +export const ValueGetter = () => { + const [data,] = React.useState({ + rows:[ { id: 1, age: 1 }, + { id: 2, age: 2 }, + ], + columns: [ + { field: 'id', hide: true }, + { + field: 'fullName', + valueGetter: (params: ValueGetterParams) => params.getValue('age'), + }, + ]}); + + + return ( +
+ +
+ ); +}; From fc3795bf76b35b11953877e64e4c3a66356dd617 Mon Sep 17 00:00:00 2001 From: damien Date: Tue, 9 Mar 2021 19:06:59 +0100 Subject: [PATCH 09/22] pretiter --- .../hooks/features/rows/useGridParamsApi.ts | 3 +-- .../src/stories/grid-columns.stories.tsx | 25 ++++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts b/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts index c1e7f2c022ea6..c2f6356ce820c 100644 --- a/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts +++ b/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts @@ -20,7 +20,6 @@ function warnMissingColumn(field) { } } export function useGridParamsApi(apiRef: GridApiRef) { - const getRowParams = React.useCallback( (id: GridRowId) => { const params: GridRowParams = { @@ -89,7 +88,7 @@ export function useGridParamsApi(apiRef: GridApiRef) { const colDef = apiRef.current.getColumnFromField(field); const rowModel = apiRef.current.getRowFromId(id); - if(!colDef) { + if (!colDef) { warnMissingColumn(field); } if (!colDef || !colDef.valueGetter) { diff --git a/packages/storybook/src/stories/grid-columns.stories.tsx b/packages/storybook/src/stories/grid-columns.stories.tsx index 9d89a51621717..2327e48ffe234 100644 --- a/packages/storybook/src/stories/grid-columns.stories.tsx +++ b/packages/storybook/src/stories/grid-columns.stories.tsx @@ -291,18 +291,19 @@ export const FlexColumnWidth2000 = () => { }; export const ValueGetter = () => { - const [data,] = React.useState({ - rows:[ { id: 1, age: 1 }, - { id: 2, age: 2 }, - ], - columns: [ - { field: 'id', hide: true }, - { - field: 'fullName', - valueGetter: (params: ValueGetterParams) => params.getValue('age'), - }, - ]}); - + const [data] = React.useState({ + rows: [ + { id: 1, age: 1 }, + { id: 2, age: 2 }, + ], + columns: [ + { field: 'id', hide: true }, + { + field: 'fullName', + valueGetter: (params: ValueGetterParams) => params.getValue('age'), + }, + ], + }); return (
From 7e3f8b6fe0ce8f4532f40ddb3bd3773f1399b5f6 Mon Sep 17 00:00:00 2001 From: damien Date: Wed, 10 Mar 2021 11:35:37 +0100 Subject: [PATCH 10/22] small perf tweaks --- .../_modules_/grid/hooks/root/useGridApiMethod.ts | 13 ++++--------- packages/storybook/.storybook/preview.tsx | 2 +- .../storybook/src/stories/grid-columns.stories.tsx | 2 -- .../stories/playground/real-data-demo.stories.tsx | 4 ++-- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/packages/grid/_modules_/grid/hooks/root/useGridApiMethod.ts b/packages/grid/_modules_/grid/hooks/root/useGridApiMethod.ts index 26fae50738771..946667a046129 100644 --- a/packages/grid/_modules_/grid/hooks/root/useGridApiMethod.ts +++ b/packages/grid/_modules_/grid/hooks/root/useGridApiMethod.ts @@ -10,23 +10,18 @@ export function useGridApiMethod>( ) { const logger = useLogger('useGridApiMethod'); const apiMethodsRef = React.useRef(apiMethods); + const [apiMethodsNames] = React.useState(Object.keys(apiMethods)); React.useEffect(() => { apiMethodsRef.current = apiMethods; }, [apiMethods]); React.useEffect(() => { - if (!apiRef.current.isInitialised) { - return; - } - - Object.keys(apiMethods).forEach((methodName) => { + apiMethodsNames.forEach((methodName) => { if (!apiRef.current.hasOwnProperty(methodName)) { logger.debug(`Adding ${apiName}.${methodName} to apiRef`); - apiRef.current[methodName] = (...args) => { - return apiMethodsRef.current[methodName](...args); - }; + apiRef.current[methodName] = (...args) => apiMethodsRef.current[methodName](...args); } }); - }, [apiMethods, apiName, apiRef, logger]); + }, [apiMethodsNames, apiName, apiRef, logger]); } diff --git a/packages/storybook/.storybook/preview.tsx b/packages/storybook/.storybook/preview.tsx index 138849768bc31..bb058e813d5cf 100644 --- a/packages/storybook/.storybook/preview.tsx +++ b/packages/storybook/.storybook/preview.tsx @@ -18,7 +18,7 @@ export const parameters = { // due to its circular structure actions: { argTypesRegex: - '^on((?!CellClick|CellDoubleClick|CellEnter|CellLeave|CellOut|CellOver|ColumnHeaderClickStateChange|RowClick|RowDoubleClick|RowEnter|RowLeave|RowOut|RowOver).)*$', + '^on((?!CellClick|CellDoubleClick|CellEnter|CellLeave|CellOut|CellOver|ColumnHeaderClick|StateChange|RowClick|RowDoubleClick|RowEnter|RowLeave|RowOut|RowOver).)*$', }, options: { /** diff --git a/packages/storybook/src/stories/grid-columns.stories.tsx b/packages/storybook/src/stories/grid-columns.stories.tsx index 2327e48ffe234..ed045f7638d44 100644 --- a/packages/storybook/src/stories/grid-columns.stories.tsx +++ b/packages/storybook/src/stories/grid-columns.stories.tsx @@ -1,9 +1,7 @@ -import { DataGrid } from '@material-ui/data-grid'; import * as React from 'react'; import { GridColDef, XGrid, GridColTypeDef, ValueGetterParams } from '@material-ui/x-grid'; import CreateIcon from '@material-ui/icons/Create'; import Button from '@material-ui/core/Button'; -import { getColumnValues } from '../../../../test/utils/helperFn'; import { useData } from '../hooks/useData'; export default { diff --git a/packages/storybook/src/stories/playground/real-data-demo.stories.tsx b/packages/storybook/src/stories/playground/real-data-demo.stories.tsx index 126de9587e559..330f0d72ba988 100644 --- a/packages/storybook/src/stories/playground/real-data-demo.stories.tsx +++ b/packages/storybook/src/stories/playground/real-data-demo.stories.tsx @@ -40,10 +40,10 @@ export default { }, }, rowLength: { - defaultValue: 1000, + defaultValue: 10000, control: { type: 'select', - options: [100, 500, 1000, 10000, 50000, 100000, 500000], + options: [100, 500, 1000, 2000, 5000, 8000, 10000, 50000, 100000, 500000], }, }, multipleGrid: { From e6e73c0e84623e53b9ece9a1832031776868c88d Mon Sep 17 00:00:00 2001 From: damien Date: Wed, 10 Mar 2021 12:51:25 +0100 Subject: [PATCH 11/22] add missing api doc --- .../_modules_/grid/models/gridOptions.tsx | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/packages/grid/_modules_/grid/models/gridOptions.tsx b/packages/grid/_modules_/grid/models/gridOptions.tsx index b19b79b990bbf..f517a68dd953e 100644 --- a/packages/grid/_modules_/grid/models/gridOptions.tsx +++ b/packages/grid/_modules_/grid/models/gridOptions.tsx @@ -232,33 +232,68 @@ export interface GridOptions { /** * Callback fired when a double click event comes from a cell element. * @param param With all properties from [[CellParams]]. + * @param event [[React.MouseEvent]]. */ onCellDoubleClick?: (param: GridCellParams, event: React.MouseEvent) => void; /** - * Callback fired when a hover event comes from a cell element. + * Callback fired when a mouseover event comes from a cell element. * @param param With all properties from [[GridCellParams]]. + * @param event [[React.MouseEvent]]. */ onCellOver?: (param: GridCellParams, event: React.MouseEvent) => void; + /** + * Callback fired when a mouseout event comes from a cell element. + * @param param With all properties from [[GridCellParams]]. + * @param event [[React.MouseEvent]]. + */ onCellOut?: (param: GridCellParams, event: React.MouseEvent) => void; + /** + * Callback fired when a mouse enter event comes from a cell element. + * @param param With all properties from [[GridCellParams]]. + * @param event [[React.MouseEvent]]. + */ onCellEnter?: (param: GridCellParams, event: React.MouseEvent) => void; + /** + * Callback fired when a mouse leave event comes from a cell element. + * @param param With all properties from [[GridCellParams]]. + * @param event [[React.MouseEvent]]. + */ onCellLeave?: (param: GridCellParams, event: React.MouseEvent) => void; /** * Callback fired when a click event comes from a row container element. * @param param With all properties from [[GridRowParams]]. + * @param event [[React.MouseEvent]]. */ onRowClick?: (param: GridRowParams, event: React.MouseEvent) => void; /** - * Callback fired when a click event comes from a row container element. + * Callback fired when a double click event comes from a row container element. * @param param With all properties from [[RowParams]]. + * @param event [[React.MouseEvent]]. */ onRowDoubleClick?: (param: GridRowParams, event: React.MouseEvent) => void; /** - * Callback fired when a hover event comes from a row container element. + * Callback fired when a mouseover event comes from a row container element. * @param param With all properties from [[GridRowParams]]. + * @param event [[React.MouseEvent]]. */ onRowOver?: (param: GridRowParams, event: React.MouseEvent) => void; + /** + * Callback fired when a mouseout event comes from a row container element. + * @param param With all properties from [[GridRowParams]]. + * @param event [[React.MouseEvent]]. + */ onRowOut?: (param: GridRowParams, event: React.MouseEvent) => void; + /** + * Callback fired when a mouse enter event comes from a row container element. + * @param param With all properties from [[GridRowParams]]. + * @param event [[React.MouseEvent]]. + */ onRowEnter?: (param: GridRowParams, event: React.MouseEvent) => void; + /** + * Callback fired when a mouse leave event comes from a row container element. + * @param param With all properties from [[GridRowParams]]. + * @param event [[React.MouseEvent]]. + */ onRowLeave?: (param: GridRowParams, event: React.MouseEvent) => void; /** * Callback fired when one row is selected. From d1efda9c7b4a2cb8e92a39094a8c40266974565c Mon Sep 17 00:00:00 2001 From: damien Date: Wed, 10 Mar 2021 17:08:13 +0100 Subject: [PATCH 12/22] add col events, cleanup --- .../_modules_/grid/components/GridCell.tsx | 104 ++++++++---------- .../_modules_/grid/components/GridRow.tsx | 74 ++++--------- .../columnHeaders/GridColumnHeaderItem.tsx | 45 +++++--- .../grid/constants/eventsConstants.ts | 32 +++--- .../hooks/features/rows/useGridParamsApi.ts | 33 +++++- .../_modules_/grid/hooks/root/useEvents.ts | 22 +++- .../grid/models/api/gridParamsApi.ts | 13 ++- .../_modules_/grid/models/gridOptions.tsx | 25 +++++ .../grid/models/params/gridCellParams.ts | 2 +- .../grid/models/params/gridColParams.ts | 4 + .../grid/models/params/gridRowParams.ts | 2 +- .../grid/_modules_/grid/utils/domUtils.ts | 17 +-- packages/storybook/.storybook/preview.tsx | 2 +- 13 files changed, 210 insertions(+), 165 deletions(-) diff --git a/packages/grid/_modules_/grid/components/GridCell.tsx b/packages/grid/_modules_/grid/components/GridCell.tsx index e4aba058906e4..4675fdbe76d09 100644 --- a/packages/grid/_modules_/grid/components/GridCell.tsx +++ b/packages/grid/_modules_/grid/components/GridCell.tsx @@ -6,7 +6,7 @@ import { GRID_CELL_OVER, GRID_CELL_LEAVE, GRID_CELL_OUT, - GRID_DOUBLE_CELL_CLICK, + GRID_CELL_DOUBLE_CLICK, } from '../constants/eventsConstants'; import { GridAlignment, GridCellValue, GridRowId } from '../models'; import { GRID_CELL_CSS_CLASS } from '../constants/cssClassesConstants'; @@ -53,13 +53,15 @@ export const GridCell: React.FC = React.memo((props) => { const cellRef = React.useRef(null); const apiRef = React.useContext(GridApiContext); - const getParams = React.useCallback(() => { - if (rowId == null || field == null || !apiRef?.current) { - return null; - } - - return apiRef!.current.getCellParams(rowId, field); - }, [apiRef, field, rowId]); + const cssClasses = classnames( + GRID_CELL_CSS_CLASS, + cssClass, + `MuiDataGrid-cell${capitalize(align)}`, + { + 'MuiDataGrid-withBorder': showRightBorder, + 'MuiDataGrid-cellEditable': isEditable, + }, + ); React.useEffect(() => { if (hasFocus && cellRef.current) { @@ -67,80 +69,60 @@ export const GridCell: React.FC = React.memo((props) => { } }, [hasFocus]); - const handleClick = React.useCallback( - (event: React.MouseEvent) => { - const params = getParams(); + const publishClick = React.useCallback( + (eventName: string) => (event: React.MouseEvent) => { + const params = apiRef!.current.getCellParams(rowId!, field || ''); if (params?.colDef.disableClickEventBubbling) { event.stopPropagation(); } - apiRef?.current.publishEvent(GRID_CELL_CLICK, params, event); + apiRef!.current.publishEvent(eventName, params, event); }, - [apiRef, getParams], + [apiRef, field, rowId], ); - const handleDoubleClick = React.useCallback( - (event: React.MouseEvent) => { - apiRef?.current.publishEvent(GRID_DOUBLE_CELL_CLICK, getParams(), event); - }, - [apiRef, getParams], + const publish = React.useCallback( + (eventName: string) => (event: React.MouseEvent) => + apiRef!.current.publishEvent( + eventName, + apiRef!.current.getCellParams(rowId!, field || ''), + event, + ), + [apiRef, field, rowId], ); - const handleHover = React.useCallback( - (event: React.MouseEvent) => { - apiRef?.current.publishEvent(GRID_CELL_OVER, getParams(), event); - }, - [apiRef, getParams], + const mouseEventsHandlers = React.useMemo( + () => ({ + onClick: publishClick(GRID_CELL_CLICK), + onDoubleClick: publish(GRID_CELL_DOUBLE_CLICK), + onMouseOver: publish(GRID_CELL_OVER), + onMouseOut: publish(GRID_CELL_OUT), + onMouseEnter: publish(GRID_CELL_ENTER), + onMouseLeave: publish(GRID_CELL_LEAVE), + }), + [publish, publishClick], ); - const handleOut = React.useCallback( - (event: React.MouseEvent) => { - apiRef?.current.publishEvent(GRID_CELL_OUT, getParams(), event); - }, - [apiRef, getParams], - ); - - const handleEnter = React.useCallback( - (event: React.MouseEvent) => { - apiRef?.current.publishEvent(GRID_CELL_ENTER, getParams(), event); - }, - [apiRef, getParams], - ); - - const handleLeave = React.useCallback( - (event: React.MouseEvent) => { - apiRef?.current.publishEvent(GRID_CELL_LEAVE, getParams(), event); - }, - [apiRef, getParams], - ); + const style = { + minWidth: width, + maxWidth: width, + lineHeight: `${height - 1}px`, + minHeight: height, + maxHeight: height, + }; return ( - // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/mouse-events-have-key-events,jsx-a11y/no-noninteractive-element-interactions
{children || valueToRender?.toString()}
diff --git a/packages/grid/_modules_/grid/components/GridRow.tsx b/packages/grid/_modules_/grid/components/GridRow.tsx index bed844ced666c..271355647b1a6 100644 --- a/packages/grid/_modules_/grid/components/GridRow.tsx +++ b/packages/grid/_modules_/grid/components/GridRow.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { - GRID_DOUBLE_ROW_CLICK, + GRID_ROW_DOUBLE_CLICK, GRID_ROW_CLICK, GRID_ROW_ENTER, GRID_ROW_LEAVE, @@ -26,56 +26,30 @@ export const GridRow: React.FC = ({ selected, id, className, rowIndex, const apiRef = React.useContext(GridApiContext); const rowHeight = useGridSelector(apiRef, gridDensityRowHeightSelector); - const handleClick = React.useCallback( - (event: React.MouseEvent) => { - const params = apiRef?.current.getRowParams(id)!; - apiRef?.current.publishEvent(GRID_ROW_CLICK, params, event); - }, + const publish = React.useCallback( + (eventName: string) => (event: React.MouseEvent) => + apiRef!.current.publishEvent(eventName, apiRef?.current.getRowParams(id), event), [apiRef, id], ); - const handleDoubleClick = React.useCallback( - (event: React.MouseEvent) => { - const params = apiRef?.current.getRowParams(id)!; - apiRef?.current.publishEvent(GRID_DOUBLE_ROW_CLICK, params, event); - }, - [apiRef, id], - ); - - const handleMouseOver = React.useCallback( - (event: React.MouseEvent) => { - const params = apiRef?.current.getRowParams(id)!; - apiRef?.current.publishEvent(GRID_ROW_OVER, params, event); - }, - [apiRef, id], - ); - - const handleMouseOut = React.useCallback( - (event: React.MouseEvent) => { - const params = apiRef?.current.getRowParams(id)!; - apiRef?.current.publishEvent(GRID_ROW_OUT, params, event); - }, - [apiRef, id], - ); - - const handleMouseEnter = React.useCallback( - (event: React.MouseEvent) => { - const params = apiRef?.current.getRowParams(id)!; - apiRef?.current.publishEvent(GRID_ROW_ENTER, params, event); - }, - [apiRef, id], + const mouseEventsHandlers = React.useMemo( + () => ({ + onClick: publish(GRID_ROW_CLICK), + onDoubleClick: publish(GRID_ROW_DOUBLE_CLICK), + onMouseOver: publish(GRID_ROW_OVER), + onMouseOut: publish(GRID_ROW_OUT), + onMouseEnter: publish(GRID_ROW_ENTER), + onMouseLeave: publish(GRID_ROW_LEAVE), + }), + [publish], ); - const handleMouseLeave = React.useCallback( - (event: React.MouseEvent) => { - const params = apiRef?.current.getRowParams(id)!; - apiRef?.current.publishEvent(GRID_ROW_LEAVE, params, event); - }, - [apiRef, id], - ); + const style = { + maxHeight: rowHeight, + minHeight: rowHeight, + }; return ( - // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/mouse-events-have-key-events,jsx-a11y/interactive-supports-focus
= ({ selected, id, className, rowIndex, className={classnames(GRID_ROW_CSS_CLASS, className, { 'Mui-selected': selected })} aria-rowindex={ariaRowIndex} aria-selected={selected} - style={{ - maxHeight: rowHeight, - minHeight: rowHeight, - }} - onClick={handleClick} - onDoubleClick={handleDoubleClick} - onMouseOver={handleMouseOver} - onMouseOut={handleMouseOut} - onMouseEnter={handleMouseEnter} - onMouseLeave={handleMouseLeave} + style={style} + {...mouseEventsHandlers} > {children}
diff --git a/packages/grid/_modules_/grid/components/columnHeaders/GridColumnHeaderItem.tsx b/packages/grid/_modules_/grid/components/columnHeaders/GridColumnHeaderItem.tsx index b9c8ac2376162..a0e01a2c83dc8 100644 --- a/packages/grid/_modules_/grid/components/columnHeaders/GridColumnHeaderItem.tsx +++ b/packages/grid/_modules_/grid/components/columnHeaders/GridColumnHeaderItem.tsx @@ -1,8 +1,14 @@ import * as React from 'react'; -import { GRID_COLUMN_HEADER_CLICK } from '../../constants/eventsConstants'; +import { + GRID_COLUMN_HEADER_CLICK, + GRID_COLUMN_HEADER_DOUBLE_CLICK, + GRID_COLUMN_HEADER_ENTER, + GRID_COLUMN_HEADER_LEAVE, + GRID_COLUMN_HEADER_OUT, + GRID_COLUMN_HEADER_OVER, +} from '../../constants/eventsConstants'; import { GridColDef, GRID_NUMBER_COLUMN_TYPE } from '../../models/colDef/index'; import { GridOptions } from '../../models/gridOptions'; -import { GridColParams } from '../../models/params/gridColParams'; import { GridSortDirection } from '../../models/gridSortModel'; import { GridApiContext } from '../GridApiContext'; import { GRID_HEADER_CELL_CSS_CLASS } from '../../constants/cssClassesConstants'; @@ -73,17 +79,27 @@ export const GridColumnHeaderItem = ({ }), [apiRef, column], ); - const onHeaderTitleClick = React.useCallback( - (event: React.MouseEvent) => { - const colHeaderParams: GridColParams = { - field: column.field, - colDef: column, - colIndex, - api: apiRef!.current, - }; - apiRef!.current.publishEvent(GRID_COLUMN_HEADER_CLICK, colHeaderParams, event); - }, - [apiRef, colIndex, column], + + const publish = React.useCallback( + (eventName: string) => (event: React.MouseEvent) => + apiRef!.current.publishEvent( + eventName, + apiRef!.current.getColumnHeaderParams(column.field), + event, + ), + [apiRef, column.field], + ); + + const mouseEventsHandlers = React.useMemo( + () => ({ + onClick: publish(GRID_COLUMN_HEADER_CLICK), + onDoubleClick: publish(GRID_COLUMN_HEADER_DOUBLE_CLICK), + onMouseOver: publish(GRID_COLUMN_HEADER_OVER), + onMouseOut: publish(GRID_COLUMN_HEADER_OUT), + onMouseEnter: publish(GRID_COLUMN_HEADER_ENTER), + onMouseLeave: publish(GRID_COLUMN_HEADER_LEAVE), + }), + [publish], ); const cssClasses = classnames( @@ -128,7 +144,6 @@ export const GridColumnHeaderItem = ({ const columnMenuIconButton = ; return ( - // eslint-disable-next-line jsx-a11y/click-events-have-key-events
{!disableColumnMenu && isColumnNumeric && !column.disableColumnMenu && columnMenuIconButton} diff --git a/packages/grid/_modules_/grid/constants/eventsConstants.ts b/packages/grid/_modules_/grid/constants/eventsConstants.ts index 06dc7a48c220d..82f69f38ffa8d 100644 --- a/packages/grid/_modules_/grid/constants/eventsConstants.ts +++ b/packages/grid/_modules_/grid/constants/eventsConstants.ts @@ -1,8 +1,5 @@ // Web standard events export const GRID_RESIZE = 'resize'; -export const GRID_CLICK = 'click'; -export const GRID_DOUBLE_CLICK = 'dblclick'; -export const GRID_MOUSE_HOVER = 'mouseover'; export const GRID_FOCUS_OUT = 'focusout'; export const GRID_KEYDOWN = 'keydown'; export const GRID_KEYUP = 'keyup'; @@ -10,37 +7,42 @@ export const GRID_SCROLL = 'scroll'; export const GRID_DRAGEND = 'dragend'; // GRID events -export const GRID_CELL_CHANGE = 'cellChange'; -export const GRID_CELL_CHANGE_COMMITTED = 'cellChangeCommitted'; -export const GRID_CELL_MODE_CHANGE = 'cellModeChange'; -export const GRID_EDIT_ROW_MODEL_CHANGE = 'editRowModelChange'; export const GRID_COMPONENT_ERROR = 'componentError'; export const GRID_UNMOUNT = 'unmount'; export const GRID_ELEMENT_FOCUS_OUT = 'gridFocusOut'; + +export const GRID_CELL_CHANGE = 'cellChange'; +export const GRID_CELL_CHANGE_COMMITTED = 'cellChangeCommitted'; +export const GRID_CELL_MODE_CHANGE = 'cellModeChange'; export const GRID_CELL_CLICK = 'cellClick'; -export const GRID_DOUBLE_CELL_CLICK = 'doubleCellClick'; +export const GRID_CELL_DOUBLE_CLICK = 'cellDoubleClick'; export const GRID_CELL_OVER = 'cellOver'; export const GRID_CELL_OUT = 'cellOut'; export const GRID_CELL_ENTER = 'cellEnter'; export const GRID_CELL_LEAVE = 'cellLeave'; + export const GRID_ROW_CLICK = 'rowClick'; -export const GRID_DOUBLE_ROW_CLICK = 'doubleRowClick'; +export const GRID_ROW_DOUBLE_CLICK = 'rowDoubleClick'; export const GRID_ROW_OVER = 'rowOver'; export const GRID_ROW_OUT = 'rowOut'; export const GRID_ROW_ENTER = 'rowEnter'; export const GRID_ROW_LEAVE = 'rowLeave'; + +export const GRID_COLUMN_HEADER_CLICK = 'columnHeaderClick'; +export const GRID_COLUMN_HEADER_DOUBLE_CLICK = 'columnHeaderDoubleClick'; +export const GRID_COLUMN_HEADER_OVER = 'columnHeaderOver'; +export const GRID_COLUMN_HEADER_OUT = 'columnHeaderOut'; +export const GRID_COLUMN_HEADER_ENTER = 'columnHeaderEnter'; +export const GRID_COLUMN_HEADER_LEAVE = 'columnHeaderLeave'; + +export const GRID_EDIT_ROW_MODEL_CHANGE = 'editRowModelChange'; export const GRID_ROW_SELECTED = 'rowSelected'; export const GRID_SELECTION_CHANGED = 'selectionChange'; -export const GRID_COLUMN_HEADER_CLICK = 'columnClick'; -export const GRID_COLUMN_HEADER_HOVER = 'columnHeaderHover'; + export const GRID_PAGE_CHANGED = 'pageChange'; export const GRID_PAGESIZE_CHANGED = 'pageSizeChange'; -export const GRID_COLUMN_FILTER_BUTTON_CLICK = 'colFilterButtonClick'; -export const GRID_COLUMN_MENU_BUTTON_CLICK = 'colMenuButtonClick'; -export const GRID_SCROLLING_START = 'scrolling:start'; export const GRID_SCROLLING = 'scrolling'; -export const GRID_SCROLLING_STOP = 'scrolling:stop'; export const GRID_COL_RESIZE_START = 'colResizing:start'; export const GRID_COL_RESIZE_STOP = 'colResizing:stop'; diff --git a/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts b/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts index c2f6356ce820c..cd9fce2ce1e12 100644 --- a/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts +++ b/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts @@ -3,8 +3,13 @@ import { GridApiRef } from '../../../models/api/gridApiRef'; import { GridParamsApi } from '../../../models/api/gridParamsApi'; import { GridRowId } from '../../../models/gridRows'; import { GridCellParams, ValueGetterParams } from '../../../models/params/gridCellParams'; +import { GridColParams } from '../../../models/params/gridColParams'; import { GridRowParams } from '../../../models/params/gridRowParams'; -import { getGridCellElement, getGridRowElement } from '../../../utils/domUtils'; +import { + getGridCellElement, + getGridColumnHeaderElement, + getGridRowElement, +} from '../../../utils/domUtils'; import { useGridApiMethod } from '../../root/useGridApiMethod'; let warnedOnce = false; @@ -20,6 +25,17 @@ function warnMissingColumn(field) { } } export function useGridParamsApi(apiRef: GridApiRef) { + const getColumnHeaderParams = React.useCallback( + (field: string): GridColParams => ({ + field, + element: apiRef.current.getColumnHeaderElement(field), + colDef: apiRef.current.getColumnFromField(field), + colIndex: apiRef.current.getColumnIndex(field, true), + api: apiRef!.current, + }), + [apiRef], + ); + const getRowParams = React.useCallback( (id: GridRowId) => { const params: GridRowParams = { @@ -61,6 +77,10 @@ export function useGridParamsApi(apiRef: GridApiRef) { const getCellParams = React.useCallback( (id: GridRowId, field: string) => { + if (id == null || field == null || !apiRef?.current) { + return null; + } + const colDef = apiRef.current.getColumnFromField(field); const element = apiRef.current.getCellElement(id, field); const value = apiRef.current.getCellValue(id, field); @@ -100,6 +120,15 @@ export function useGridParamsApi(apiRef: GridApiRef) { [apiRef, getBaseCellParams], ); + const getColumnHeaderElement = React.useCallback( + (field: string): HTMLDivElement | null => { + if (!apiRef.current.rootElementRef!.current) { + return null; + } + return getGridColumnHeaderElement(apiRef.current.rootElementRef!.current!, field); + }, + [apiRef], + ); const getRowElement = React.useCallback( (id: GridRowId): HTMLDivElement | null => { if (!apiRef.current.rootElementRef!.current) { @@ -128,6 +157,8 @@ export function useGridParamsApi(apiRef: GridApiRef) { getCellElement, getRowParams, getRowElement, + getColumnHeaderParams, + getColumnHeaderElement, }, 'CellApi', ); diff --git a/packages/grid/_modules_/grid/hooks/root/useEvents.ts b/packages/grid/_modules_/grid/hooks/root/useEvents.ts index d3e48ea1854ca..375c59b5322ea 100644 --- a/packages/grid/_modules_/grid/hooks/root/useEvents.ts +++ b/packages/grid/_modules_/grid/hooks/root/useEvents.ts @@ -19,14 +19,19 @@ import { GRID_ELEMENT_FOCUS_OUT, GRID_COMPONENT_ERROR, GRID_STATE_CHANGE, - GRID_DOUBLE_CELL_CLICK, - GRID_DOUBLE_ROW_CLICK, + GRID_CELL_DOUBLE_CLICK, + GRID_ROW_DOUBLE_CLICK, GRID_CELL_ENTER, GRID_CELL_LEAVE, GRID_CELL_OUT, GRID_ROW_ENTER, GRID_ROW_LEAVE, GRID_ROW_OUT, + GRID_COLUMN_HEADER_LEAVE, + GRID_COLUMN_HEADER_ENTER, + GRID_COLUMN_HEADER_DOUBLE_CLICK, + GRID_COLUMN_HEADER_OVER, + GRID_COLUMN_HEADER_OUT, } from '../../constants/eventsConstants'; import { useGridApiMethod } from './useGridApiMethod'; import { useGridApiEventHandler } from './useGridApiEventHandler'; @@ -82,15 +87,24 @@ export function useEvents(gridRootRef: React.RefObject, apiRef: useGridApiEventHandler(apiRef, GRID_COL_RESIZE_STOP, handleResizeStop); useGridApiEventHandler(apiRef, GRID_COLUMN_HEADER_CLICK, options.onColumnHeaderClick); + useGridApiEventHandler( + apiRef, + GRID_COLUMN_HEADER_DOUBLE_CLICK, + options.onColumnHeaderDoubleClick, + ); + useGridApiEventHandler(apiRef, GRID_COLUMN_HEADER_OVER, options.onColumnHeaderOver); + useGridApiEventHandler(apiRef, GRID_COLUMN_HEADER_OUT, options.onColumnHeaderOut); + useGridApiEventHandler(apiRef, GRID_COLUMN_HEADER_ENTER, options.onColumnHeaderEnter); + useGridApiEventHandler(apiRef, GRID_COLUMN_HEADER_LEAVE, options.onColumnHeaderLeave); useGridApiEventHandler(apiRef, GRID_CELL_CLICK, options.onCellClick); - useGridApiEventHandler(apiRef, GRID_DOUBLE_CELL_CLICK, options.onCellDoubleClick); + useGridApiEventHandler(apiRef, GRID_CELL_DOUBLE_CLICK, options.onCellDoubleClick); useGridApiEventHandler(apiRef, GRID_CELL_OVER, options.onCellOver); useGridApiEventHandler(apiRef, GRID_CELL_OUT, options.onCellOut); useGridApiEventHandler(apiRef, GRID_CELL_ENTER, options.onCellEnter); useGridApiEventHandler(apiRef, GRID_CELL_LEAVE, options.onCellLeave); - useGridApiEventHandler(apiRef, GRID_DOUBLE_ROW_CLICK, options.onRowDoubleClick); + useGridApiEventHandler(apiRef, GRID_ROW_DOUBLE_CLICK, options.onRowDoubleClick); useGridApiEventHandler(apiRef, GRID_ROW_CLICK, options.onRowClick); useGridApiEventHandler(apiRef, GRID_ROW_OVER, options.onRowOver); useGridApiEventHandler(apiRef, GRID_ROW_OUT, options.onRowOut); diff --git a/packages/grid/_modules_/grid/models/api/gridParamsApi.ts b/packages/grid/_modules_/grid/models/api/gridParamsApi.ts index 053be73ca1b9a..5577289d45a38 100644 --- a/packages/grid/_modules_/grid/models/api/gridParamsApi.ts +++ b/packages/grid/_modules_/grid/models/api/gridParamsApi.ts @@ -1,6 +1,7 @@ import { GridCellValue } from '../gridCell'; import { GridRowId } from '../gridRows'; import { GridCellParams } from '../params/gridCellParams'; +import { GridColParams } from '../params/gridColParams'; import { GridRowParams } from '../params/gridRowParams'; export interface GridParamsApi { @@ -21,7 +22,7 @@ export interface GridParamsApi { * @param id * @param field */ - getCellParams: (id: GridRowId, field: string) => GridCellParams; + getCellParams: (id: GridRowId, field: string) => GridCellParams | null; /** * Get the row params that are passed in events * @param id @@ -34,4 +35,14 @@ export interface GridParamsApi { * @param field */ getRowElement: (id: GridRowId) => HTMLDivElement | null; + /** + * Get the column header DOM element + * @param field + */ + getColumnHeaderElement: (field: string) => HTMLDivElement | null; + /** + * Get the header params that are passed in events + * @param field + */ + getColumnHeaderParams: (field: string) => GridColParams; } diff --git a/packages/grid/_modules_/grid/models/gridOptions.tsx b/packages/grid/_modules_/grid/models/gridOptions.tsx index f517a68dd953e..89940fd6636ca 100644 --- a/packages/grid/_modules_/grid/models/gridOptions.tsx +++ b/packages/grid/_modules_/grid/models/gridOptions.tsx @@ -310,6 +310,31 @@ export interface GridOptions { * @param param With all properties from [[GridColParams]]. */ onColumnHeaderClick?: (param: GridColParams, event: React.MouseEvent) => void; + /** + * Callback fired when a double click event comes from a column header element. + * @param param With all properties from [[GridColParams]]. + */ + onColumnHeaderDoubleClick?: (param: GridColParams, event: React.MouseEvent) => void; + /** + * Callback fired when a mouseover event comes from a column header element. + * @param param With all properties from [[GridColParams]]. + */ + onColumnHeaderOver?: (param: GridColParams, event: React.MouseEvent) => void; + /** + * Callback fired when a mouseout event comes from a column header element. + * @param param With all properties from [[GridColParams]]. + */ + onColumnHeaderOut?: (param: GridColParams, event: React.MouseEvent) => void; + /** + * Callback fired when a mouse enter event comes from a column header element. + * @param param With all properties from [[GridColParams]]. + */ + onColumnHeaderEnter?: (param: GridColParams, event: React.MouseEvent) => void; + /** + * Callback fired when a mouse leave event comes from a column header element. + * @param param With all properties from [[GridColParams]]. + */ + onColumnHeaderLeave?: (param: GridColParams, event: React.MouseEvent) => void; /** * Callback fired when the sort model changes before a column is sorted. * @param param With all properties from [[GridSortModelParams]]. diff --git a/packages/grid/_modules_/grid/models/params/gridCellParams.ts b/packages/grid/_modules_/grid/models/params/gridCellParams.ts index 9da6a80415a06..132ad09cb8aed 100644 --- a/packages/grid/_modules_/grid/models/params/gridCellParams.ts +++ b/packages/grid/_modules_/grid/models/params/gridCellParams.ts @@ -10,7 +10,7 @@ export interface GridCellParams { */ id: GridRowId; /** - * The HTMLElement that triggered the event + * The HTMLElement cell element */ element?: HTMLElement | null; /** diff --git a/packages/grid/_modules_/grid/models/params/gridColParams.ts b/packages/grid/_modules_/grid/models/params/gridColParams.ts index e97bc6906d876..d3a885e4c7ba3 100644 --- a/packages/grid/_modules_/grid/models/params/gridColParams.ts +++ b/packages/grid/_modules_/grid/models/params/gridColParams.ts @@ -2,6 +2,10 @@ * Object passed as parameter in the column [[GridColDef]] header renderer. */ export interface GridColParams { + /** + * The HTMLElement column header element + */ + element?: HTMLElement | null; /** * The column field of the column that triggered the event */ diff --git a/packages/grid/_modules_/grid/models/params/gridRowParams.ts b/packages/grid/_modules_/grid/models/params/gridRowParams.ts index 5c93482a72cf9..8d005efd7a491 100644 --- a/packages/grid/_modules_/grid/models/params/gridRowParams.ts +++ b/packages/grid/_modules_/grid/models/params/gridRowParams.ts @@ -10,7 +10,7 @@ export interface GridRowParams { */ id: GridRowId; /** - * The HTMLElement that triggered the event + * The HTMLElement row element */ element?: HTMLElement | null; /** diff --git a/packages/grid/_modules_/grid/utils/domUtils.ts b/packages/grid/_modules_/grid/utils/domUtils.ts index 34c09b61af4e1..89608aea8c2fa 100644 --- a/packages/grid/_modules_/grid/utils/domUtils.ts +++ b/packages/grid/_modules_/grid/utils/domUtils.ts @@ -26,13 +26,6 @@ export function isGridCellRoot(elem: Element | null): boolean { return elem != null && elem.classList.contains(GRID_CELL_CSS_CLASS); } -export function isGridCell(elem: Element | null): boolean { - return ( - elem != null && - (isGridCellRoot(elem) || findParentElementFromClassName(elem, GRID_CELL_CSS_CLASS) !== null) - ); -} - export function isGridHeaderTitleContainer(elem: Element): boolean { return elem && findParentElementFromClassName(elem, GRID_HEADER_CELL_TITLE_CSS_CLASS) !== null; } @@ -41,10 +34,6 @@ export function getIdFromRowElem(rowEl: Element): string { return rowEl.getAttribute('data-id')!; } -export function getFieldFromCellElem(cellEl: Element): string { - return cellEl.getAttribute('data-field')!; -} - export function getFieldFromHeaderElem(colCellEl: Element): string { return colCellEl.getAttribute('data-field')!; } @@ -88,6 +77,12 @@ export function getGridCellElementFromIndexes( ) as HTMLDivElement; } +export function getGridColumnHeaderElement(root: Element, field: string) { + return root.querySelector( + `:scope [role='columnheader'][data-field='${field}']`, + ) as HTMLDivElement; +} + export function getGridRowElement(root: Element, id: GridRowId) { return root.querySelector(`:scope .${GRID_ROW_CSS_CLASS}[data-id='${id}']`) as HTMLDivElement; } diff --git a/packages/storybook/.storybook/preview.tsx b/packages/storybook/.storybook/preview.tsx index bb058e813d5cf..e6b45512938c4 100644 --- a/packages/storybook/.storybook/preview.tsx +++ b/packages/storybook/.storybook/preview.tsx @@ -18,7 +18,7 @@ export const parameters = { // due to its circular structure actions: { argTypesRegex: - '^on((?!CellClick|CellDoubleClick|CellEnter|CellLeave|CellOut|CellOver|ColumnHeaderClick|StateChange|RowClick|RowDoubleClick|RowEnter|RowLeave|RowOut|RowOver).)*$', + '^on((?!CellClick|CellDoubleClick|CellEnter|CellLeave|CellOut|CellOver|ColumnHeaderClick|ColumnHeaderDoubleClick|ColumnHeaderOver|ColumnHeaderOut|ColumnHeaderEnter|ColumnHeaderLeave|StateChange|RowClick|RowDoubleClick|RowEnter|RowLeave|RowOut|RowOver).)*$', }, options: { /** From e1cbee8c87776caedee5d5d49af10b1db52789f2 Mon Sep 17 00:00:00 2001 From: damien Date: Wed, 10 Mar 2021 17:38:17 +0100 Subject: [PATCH 13/22] refactor cells to require id and field --- .../_modules_/grid/components/GridCell.tsx | 29 +++++-------------- .../grid/components/GridEmptyCell.tsx | 23 +++++++++++++++ .../grid/components/GridViewport.tsx | 6 ++-- .../columnHeaders/GridColumnHeaders.tsx | 6 ++-- .../grid/_modules_/grid/components/index.ts | 1 + .../hooks/features/rows/useGridParamsApi.ts | 4 --- .../grid/models/api/gridParamsApi.ts | 2 +- 7 files changed, 38 insertions(+), 33 deletions(-) create mode 100644 packages/grid/_modules_/grid/components/GridEmptyCell.tsx diff --git a/packages/grid/_modules_/grid/components/GridCell.tsx b/packages/grid/_modules_/grid/components/GridCell.tsx index 4675fdbe76d09..f1f3f58df0a33 100644 --- a/packages/grid/_modules_/grid/components/GridCell.tsx +++ b/packages/grid/_modules_/grid/components/GridCell.tsx @@ -1,15 +1,15 @@ -import * as React from 'react'; import { capitalize } from '@material-ui/core/utils'; +import * as React from 'react'; +import { GRID_CELL_CSS_CLASS } from '../constants/cssClassesConstants'; import { GRID_CELL_CLICK, + GRID_CELL_DOUBLE_CLICK, GRID_CELL_ENTER, - GRID_CELL_OVER, GRID_CELL_LEAVE, GRID_CELL_OUT, - GRID_CELL_DOUBLE_CLICK, + GRID_CELL_OVER, } from '../constants/eventsConstants'; import { GridAlignment, GridCellValue, GridRowId } from '../models'; -import { GRID_CELL_CSS_CLASS } from '../constants/cssClassesConstants'; import { classnames } from '../utils'; import { GridApiContext } from './GridApiContext'; @@ -17,8 +17,8 @@ export interface GridCellProps { align: GridAlignment; colIndex?: number; cssClass?: string; - field?: string; - rowId?: GridRowId; + field: string; + rowId: GridRowId; formattedValue?: GridCellValue; hasFocus?: boolean; height: number; @@ -71,7 +71,7 @@ export const GridCell: React.FC = React.memo((props) => { const publishClick = React.useCallback( (eventName: string) => (event: React.MouseEvent) => { - const params = apiRef!.current.getCellParams(rowId!, field || ''); + const params = apiRef!.current.getCellParams(rowId, field || ''); if (params?.colDef.disableClickEventBubbling) { event.stopPropagation(); } @@ -130,18 +130,3 @@ export const GridCell: React.FC = React.memo((props) => { }); GridCell.displayName = 'GridCell'; - -interface EmptyCellProps { - width?: number; - height?: number; -} - -export const GridLeftEmptyCell: React.FC = React.memo(({ width, height }) => - !width || !height ? null : , -); -GridLeftEmptyCell.displayName = 'GridLeftEmptyCell'; - -export const GridRightEmptyCell: React.FC = React.memo(({ width, height }) => - !width || !height ? null : , -); -GridRightEmptyCell.displayName = 'GridRightEmptyCell'; diff --git a/packages/grid/_modules_/grid/components/GridEmptyCell.tsx b/packages/grid/_modules_/grid/components/GridEmptyCell.tsx new file mode 100644 index 0000000000000..0693f7b4f2938 --- /dev/null +++ b/packages/grid/_modules_/grid/components/GridEmptyCell.tsx @@ -0,0 +1,23 @@ +import * as React from 'react'; +import { GRID_CELL_CSS_CLASS } from '../constants/cssClassesConstants'; + +export interface GridEmptyCellProps { + width?: number; + height?: number; +} + +export const GridEmptyCell = React.memo(function GridEmptyCell({width, height}: GridEmptyCellProps) { + if (!width || !height) { + return null; + } + + return
; +}); diff --git a/packages/grid/_modules_/grid/components/GridViewport.tsx b/packages/grid/_modules_/grid/components/GridViewport.tsx index 3d72a8db63542..6d82d753683b4 100644 --- a/packages/grid/_modules_/grid/components/GridViewport.tsx +++ b/packages/grid/_modules_/grid/components/GridViewport.tsx @@ -9,8 +9,8 @@ import { gridSelectionStateSelector } from '../hooks/features/selection/gridSele import { renderStateSelector } from '../hooks/features/virtualization/renderingStateSelector'; import { optionsSelector } from '../hooks/utils/optionsSelector'; import { GridApiContext } from './GridApiContext'; -import { GridLeftEmptyCell, GridRightEmptyCell } from './GridCell'; import { GridDataContainer } from './containers/GridDataContainer'; +import { GridEmptyCell } from './GridEmptyCell'; import { GridRenderingZone } from './GridRenderingZone'; import { GridRow } from './GridRow'; import { GridRowCells } from './GridRowCells'; @@ -56,7 +56,7 @@ export const GridViewport: ViewportType = React.forwardRef( selected={!!selectionState[r.id]} rowIndex={renderState.renderContext!.firstRowIdx! + idx} > - + ( cellFocus={cellFocus} domIndex={idx} /> - diff --git a/packages/grid/_modules_/grid/components/columnHeaders/GridColumnHeaders.tsx b/packages/grid/_modules_/grid/components/columnHeaders/GridColumnHeaders.tsx index 94f8569d53739..1eaf265c449cf 100644 --- a/packages/grid/_modules_/grid/components/columnHeaders/GridColumnHeaders.tsx +++ b/packages/grid/_modules_/grid/components/columnHeaders/GridColumnHeaders.tsx @@ -5,7 +5,7 @@ import { useGridSelector } from '../../hooks/features/core/useGridSelector'; import { renderStateSelector } from '../../hooks/features/virtualization/renderingStateSelector'; import { optionsSelector } from '../../hooks/utils/optionsSelector'; import { GridApiContext } from '../GridApiContext'; -import { GridLeftEmptyCell, GridRightEmptyCell } from '../GridCell'; +import { GridEmptyCell } from '../GridEmptyCell'; import { GridScrollArea } from '../GridScrollArea'; import { gridContainerSizesSelector } from '../GridViewport'; import { GridColumnHeadersItemCollection } from './GridColumnHeadersItemCollection'; @@ -51,9 +51,9 @@ export const GridColumnsHeader = React.forwardRef(function G style={{ minWidth: containerSizes?.totalSizes?.width }} onDragOver={handleDragOver} > - + - +
diff --git a/packages/grid/_modules_/grid/components/index.ts b/packages/grid/_modules_/grid/components/index.ts index 35b31972b71a0..f25672967a6ca 100644 --- a/packages/grid/_modules_/grid/components/index.ts +++ b/packages/grid/_modules_/grid/components/index.ts @@ -22,3 +22,4 @@ export * from './GridStickyContainer'; export * from './GridViewport'; export * from './Watermark'; export * from './GridScrollArea'; +export * from './GridEmptyCell'; diff --git a/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts b/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts index cd9fce2ce1e12..0ad36b5fad262 100644 --- a/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts +++ b/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts @@ -77,10 +77,6 @@ export function useGridParamsApi(apiRef: GridApiRef) { const getCellParams = React.useCallback( (id: GridRowId, field: string) => { - if (id == null || field == null || !apiRef?.current) { - return null; - } - const colDef = apiRef.current.getColumnFromField(field); const element = apiRef.current.getCellElement(id, field); const value = apiRef.current.getCellValue(id, field); diff --git a/packages/grid/_modules_/grid/models/api/gridParamsApi.ts b/packages/grid/_modules_/grid/models/api/gridParamsApi.ts index 5577289d45a38..d85b87d61881b 100644 --- a/packages/grid/_modules_/grid/models/api/gridParamsApi.ts +++ b/packages/grid/_modules_/grid/models/api/gridParamsApi.ts @@ -22,7 +22,7 @@ export interface GridParamsApi { * @param id * @param field */ - getCellParams: (id: GridRowId, field: string) => GridCellParams | null; + getCellParams: (id: GridRowId, field: string) => GridCellParams; /** * Get the row params that are passed in events * @param id From ec2ff8241782028abf971cf0f9c08abc12daf1d9 Mon Sep 17 00:00:00 2001 From: damien Date: Wed, 10 Mar 2021 17:41:59 +0100 Subject: [PATCH 14/22] api docs update --- docs/pages/api-docs/data-grid.md | 17 +++++++++++++++-- docs/pages/api-docs/x-grid.md | 17 +++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/docs/pages/api-docs/data-grid.md b/docs/pages/api-docs/data-grid.md index 7be86e278c35d..871217b3ad57a 100644 --- a/docs/pages/api-docs/data-grid.md +++ b/docs/pages/api-docs/data-grid.md @@ -43,9 +43,18 @@ import { DataGrid } from '@material-ui/data-grid'; | logLevel | string | false | false | Allows to pass the logging level or false to turn off logging. | | nonce | string | | Nonce of the inline styles for [Content Security Policy](https://www.w3.org/TR/2016/REC-CSP2-20161215/#script-src-the-nonce-attribute). | | onCellClick | (param: GridCellParams) => void | | Callback fired when a click event comes from a cell element. | -| onCellHover | (param: GridCellParams) => void | | Callback fired when a hover event comes from a cell element. | +| onCellDoubleClick | (param: GridCellParams) => void | | Callback fired when a double click event comes from a cell element. | +| onCellOver | (param: GridCellParams) => void | | Callback fired when a mouse over event comes from a cell element. | +| onCellOut | (param: GridCellParams) => void | | Callback fired when a mouse out comes from a cell element. | +| onCellEnter | (param: GridCellParams) => void | | Callback fired when a mouse enter event comes from a cell element. | +| onCellLeave | (param: GridCellParams) => 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) => void | | Callback fired when a click event comes from a column header element. | +| onColumnHeaderDoubleClick | (param: GridColParams) => void | | Callback fired when a double click event comes from a column header element. | +| onColumnHeaderOver | (param: GridColParams) => void | | Callback fired when a mouseover event comes from a column header element. | +| onColumnHeaderOut | (param: GridColParams) => void | | Callback fired when a mouseout event comes from a column header element. | +| onColumnHeaderEnter | (param: GridColParams) => void | | Callback fired when a mouse enter event comes from a column header element. | +| onColumnHeaderLeave | (param: GridColParams) => void | | Callback fired when a mouse leave event comes from a column header element. | | 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. | @@ -54,7 +63,11 @@ import { DataGrid } from '@material-ui/data-grid'; | onPageChange | (param: GridPageChangeParams) => void | | Callback fired when the current page has changed. | | onPageSizeChange | (param: GridPageChangeParams) => void | | Callback fired when the page size has changed. | | onRowClick | (param: GridRowParams) => void | | Callback fired when a click event comes from a row container element. | -| onRowHover | (param: GridRowParams) => void | | Callback fired when a hover event comes from a row container element. | +| onRowDoubleClick | (param: GridRowParams) => void | | Callback fired when a double click event comes from a row container element. | +| onRowOver | (param: GridRowParams) => void | | Callback fired when a mouse over comes from a row container element. | +| onRowOut | (param: GridRowParams) => void | | Callback fired when a mouse out comes from a row container element. | +| onRowEnter | (param: GridRowParams) => void | | Callback fired when a mouse enter comes from a row container element. | +| onRowLeave | (param: GridRowParams) => void | | Callback fired when a mouse leave event comes from a row container element. | | onRowSelected | (param: GridRowSelectedParams) => void | | Callback fired when one row is selected. | | onSelectionModelChange | (param: GridSelectionModelChangeParams) => void | | Callback fired when the selection state of one or multiple rows changes. | | onSortModelChange | (param: GridSortModelParams) => void | | Callback fired when the sort model changes before a column is sorted. | diff --git a/docs/pages/api-docs/x-grid.md b/docs/pages/api-docs/x-grid.md index a105537ee1692..cc4a4f3c9033e 100644 --- a/docs/pages/api-docs/x-grid.md +++ b/docs/pages/api-docs/x-grid.md @@ -46,9 +46,18 @@ import { XGrid } from '@material-ui/x-grid'; | logLevel | string | false | false | Allows to pass the logging level or false to turn off logging. | | nonce | string | | Nonce of the inline styles for [Content Security Policy](https://www.w3.org/TR/2016/REC-CSP2-20161215/#script-src-the-nonce-attribute). | | onCellClick | (param: GridCellParams) => void | | Callback fired when a click event comes from a cell element. | -| onCellHover | (param: GridCellParams) => void | | Callback fired when a hover event comes from a cell element. | +| onCellDoubleClick | (param: GridCellParams) => void | | Callback fired when a double click event comes from a cell element. | +| onCellOver | (param: GridCellParams) => void | | Callback fired when a mouse over event comes from a cell element. | +| onCellOut | (param: GridCellParams) => void | | Callback fired when a mouse out comes from a cell element. | +| onCellEnter | (param: GridCellParams) => void | | Callback fired when a mouse enter event comes from a cell element. | +| onCellLeave | (param: GridCellParams) => 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) => void | | Callback fired when a click event comes from a column header element. | +| onColumnHeaderDoubleClick | (param: GridColParams) => void | | Callback fired when a double click event comes from a column header element. | +| onColumnHeaderOver | (param: GridColParams) => void | | Callback fired when a mouseover event comes from a column header element. | +| onColumnHeaderOut | (param: GridColParams) => void | | Callback fired when a mouseout event comes from a column header element. | +| onColumnHeaderEnter | (param: GridColParams) => void | | Callback fired when a mouse enter event comes from a column header element. | +| onColumnHeaderLeave | (param: GridColParams) => void | | Callback fired when a mouse leave event comes from a column header element. | | 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. | @@ -57,7 +66,11 @@ import { XGrid } from '@material-ui/x-grid'; | onPageChange | (param: GridPageChangeParams) => void | | Callback fired when the current page has changed. | | onPageSizeChange | (param: GridPageChangeParams) => void | | Callback fired when the page size has changed. | | onRowClick | (param: GridRowParams) => void | | Callback fired when a click event comes from a row container element. | -| onRowHover | (param: GridRowParams) => void | | Callback fired when a hover event comes from a row container element. | +| onRowDoubleClick | (param: GridRowParams) => void | | Callback fired when a double click event comes from a row container element. | +| onRowOver | (param: GridRowParams) => void | | Callback fired when a mouse over comes from a row container element. | +| onRowOut | (param: GridRowParams) => void | | Callback fired when a mouse out comes from a row container element. | +| onRowEnter | (param: GridRowParams) => void | | Callback fired when a mouse enter comes from a row container element. | +| onRowLeave | (param: GridRowParams) => void | | Callback fired when a mouse leave event comes from a row container element. | | onRowSelected | (param: GridRowSelectedParams) => void | | Callback fired when one row is selected. | | onSelectionModelChange | (param: GridSelectionModelChangeParams) => void | | Callback fired when the selection state of one or multiple rows changes. | | onSortModelChange | (param: GridSortModelParams) => void | | Callback fired when the sort model changes before a column is sorted. | From 837c05a27ef4137b4800fff532ceb809832209f1 Mon Sep 17 00:00:00 2001 From: damien Date: Wed, 10 Mar 2021 19:19:34 +0100 Subject: [PATCH 15/22] add tests --- .../grid/components/GridEmptyCell.tsx | 26 ++- .../grid/components/GridViewport.tsx | 5 +- .../hooks/features/rows/useGridParamsApi.ts | 6 +- .../x-grid/src/tests/events.XGrid.test.tsx | 210 ++++++++++++++++++ .../src/stories/grid-columns.stories.tsx | 17 +- 5 files changed, 243 insertions(+), 21 deletions(-) create mode 100644 packages/grid/x-grid/src/tests/events.XGrid.test.tsx diff --git a/packages/grid/_modules_/grid/components/GridEmptyCell.tsx b/packages/grid/_modules_/grid/components/GridEmptyCell.tsx index 0693f7b4f2938..02ba236662184 100644 --- a/packages/grid/_modules_/grid/components/GridEmptyCell.tsx +++ b/packages/grid/_modules_/grid/components/GridEmptyCell.tsx @@ -6,18 +6,24 @@ export interface GridEmptyCellProps { height?: number; } -export const GridEmptyCell = React.memo(function GridEmptyCell({width, height}: GridEmptyCellProps) { +export const GridEmptyCell = React.memo(function GridEmptyCell({ + width, + height, +}: GridEmptyCellProps) { if (!width || !height) { return null; } - return
; + return ( +
+ ); }); diff --git a/packages/grid/_modules_/grid/components/GridViewport.tsx b/packages/grid/_modules_/grid/components/GridViewport.tsx index 6d82d753683b4..8f30cc9ca577b 100644 --- a/packages/grid/_modules_/grid/components/GridViewport.tsx +++ b/packages/grid/_modules_/grid/components/GridViewport.tsx @@ -70,10 +70,7 @@ export const GridViewport: ViewportType = React.forwardRef( cellFocus={cellFocus} domIndex={idx} /> - + )); }; diff --git a/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts b/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts index 0ad36b5fad262..c258b58b9b67d 100644 --- a/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts +++ b/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts @@ -85,9 +85,11 @@ export function useGridParamsApi(apiRef: GridApiRef) { ...baseParams, value, getValue: (columnField: string) => apiRef.current.getCellValue(id, columnField), - formattedValue: colDef.valueFormatter ? colDef.valueFormatter(baseParams) : value, + formattedValue: value, }; - + if (colDef.valueFormatter) { + params.formattedValue = colDef.valueFormatter(params); + } const isEditableAttr = element && element.getAttribute('data-editable'); params.isEditable = isEditableAttr != null diff --git a/packages/grid/x-grid/src/tests/events.XGrid.test.tsx b/packages/grid/x-grid/src/tests/events.XGrid.test.tsx new file mode 100644 index 0000000000000..36b186460a142 --- /dev/null +++ b/packages/grid/x-grid/src/tests/events.XGrid.test.tsx @@ -0,0 +1,210 @@ +import * as React from 'react'; +import { + createClientRenderStrictMode, + // @ts-ignore + fireEvent, +} from 'test/utils'; +import { expect } from 'chai'; +import { + XGrid, + GridColParams, + useGridApiRef, + XGridProps, + GridRowParams, + GridCellParams, + GridRowsProp, + GridColumns, +} from '@material-ui/x-grid'; +import { getCell, getColumnHeaderCell, getRow } from 'test/utils/helperFn'; + +describe(' - Events Params ', () => { + // TODO v5: replace with createClientRender + const render = createClientRenderStrictMode(); + + const baselineProps: { rows: GridRowsProp; columns: GridColumns } = { + rows: [ + { + id: 1, + first: 'Mike', + age: 11, + }, + { + id: 2, + first: 'Jack', + age: 11, + }, + { + id: 3, + first: 'Mike', + age: 20, + }, + ], + columns: [ + { field: 'id' }, + { field: 'first', editable: true }, + { field: 'age' }, + { + field: 'firstAge', + valueGetter: (params) => `${params.row.first}_${params.row.age}`, + valueFormatter: (params) => `${params.value} yrs`, + }, + ], + }; + + before(function beforeHook() { + if (/jsdom/.test(window.navigator.userAgent)) { + // Need layouting + this.skip(); + } + }); + + let apiRef; + const TestEvents = (props: Partial) => { + apiRef = useGridApiRef(); + return ( +
+ +
+ ); + }; + + describe('columnHeaderParams', () => { + let eventArgs: { params: GridColParams; event: React.MouseEvent } | null = null; + let ageColumnElement; + beforeEach(() => { + const handleClick = (params, event) => { + eventArgs = { params, event }; + }; + render(); + + ageColumnElement = getColumnHeaderCell(3); + fireEvent.click(ageColumnElement); + }); + + it('should contains the column header element', () => { + expect(eventArgs!.params.element).to.equal(ageColumnElement); + }); + it('should contains the column def', () => { + expect(eventArgs!.params.colDef).to.equal(apiRef!.current.getColumnFromField('age')); + }); + it('should contains the column index', () => { + expect(eventArgs!.params.colIndex).to.equal(2); + }); + it('should contains the column field', () => { + expect(eventArgs!.params.field).to.equal('age'); + }); + it('should contains the api', () => { + expect(eventArgs!.params.api).to.equal(apiRef.current); + }); + }); + + describe('RowsParams', () => { + let eventArgs: { params: GridRowParams; event: React.MouseEvent } | null = null; + let row2; + beforeEach(() => { + const handleClick = (params, event) => { + eventArgs = { params, event }; + }; + render(); + + row2 = getRow(1); + fireEvent.click(row2); + }); + + it('should contains the row id', () => { + expect(eventArgs!.params.id).to.equal(2); + }); + it('should contains the element', () => { + expect(eventArgs!.params.element).to.equal(row2); + }); + it('should contains the row model', () => { + expect(eventArgs!.params.row).to.equal(baselineProps.rows[1]); + }); + it('should contains the row index', () => { + expect(eventArgs!.params.rowIndex).to.equal(1); + }); + it('should contains the columns', () => { + expect(eventArgs!.params.columns).to.equal(apiRef!.current.getAllColumns()); + }); + it('should contains the api', () => { + expect(eventArgs!.params.api).to.equal(apiRef.current); + }); + }); + + describe('CellsParams', () => { + let eventArgs: { params: GridCellParams; event: React.MouseEvent } | null = null; + let cell22; + beforeEach(() => { + const handleClick = (params, event) => { + eventArgs = { params, event }; + }; + render(); + + cell22 = getCell(1, 1); + fireEvent.click(cell22); + }); + + it('should contains the cell id', () => { + expect(eventArgs!.params.id).to.equal(2); + }); + it('should contains the cell value', () => { + expect(eventArgs!.params.value).to.equal('Jack'); + }); + + it('should consider value getter', () => { + const cellFirstAge = getCell(1, 3); + fireEvent.click(cellFirstAge); + + expect(eventArgs!.params.value).to.equal('Jack_11'); + }); + it('should consider value formatter', () => { + const cellFirstAge = getCell(1, 3); + fireEvent.click(cellFirstAge); + + expect(eventArgs!.params.formattedValue).to.equal('Jack_11 yrs'); + }); + it('should contains the cell formattedValue', () => { + expect(eventArgs!.params.formattedValue).to.equal('Jack'); + }); + it('should contains the cell isEditable', () => { + expect(eventArgs!.params.isEditable).to.equal(true); + }); + it('should contains the element', () => { + expect(eventArgs!.params.element).to.equal(cell22); + }); + it('should contains the cell model', () => { + expect(eventArgs!.params.row).to.equal(baselineProps.rows[1]); + }); + it('should contains the cell index', () => { + expect(eventArgs!.params.rowIndex).to.equal(1); + }); + it('should contains the column', () => { + expect(eventArgs!.params.colDef).to.equal(apiRef!.current.getColumnFromField('first')); + }); + it('should contains the column index', () => { + expect(eventArgs!.params.colIndex).to.equal(1); + }); + it('should contains the api', () => { + expect(eventArgs!.params.api).to.equal(apiRef.current); + }); + }); + + describe('onCellClick', () => { + it('should bubble to the row', () => { + let events = ''; + const addEventName = (name: string) => () => { + events += `${name}, `; + }; + render( + , + ); + + const cell22 = getCell(1, 1); + fireEvent.click(cell22); + expect(events).to.equal('cellClick, rowClick, '); + }); + }); +}); diff --git a/packages/storybook/src/stories/grid-columns.stories.tsx b/packages/storybook/src/stories/grid-columns.stories.tsx index ed045f7638d44..5d25b93041b8c 100644 --- a/packages/storybook/src/stories/grid-columns.stories.tsx +++ b/packages/storybook/src/stories/grid-columns.stories.tsx @@ -288,17 +288,24 @@ export const FlexColumnWidth2000 = () => { ); }; -export const ValueGetter = () => { +export const ValueGetterAndFormatter = () => { const [data] = React.useState({ rows: [ - { id: 1, age: 1 }, - { id: 2, age: 2 }, + { id: 1, first: 'mark', age: 1 }, + { id: 2, first: 'jack', age: 2 }, ], columns: [ { field: 'id', hide: true }, { - field: 'fullName', - valueGetter: (params: ValueGetterParams) => params.getValue('age'), + field: 'firstAge', + valueGetter: (params: ValueGetterParams) => + `${params.getValue('first')}_${params.getValue('age')}`, + }, + { + field: 'firstAgeFormatted', + valueGetter: (params: ValueGetterParams) => + `${params.getValue('first')}_${params.getValue('age')}`, + valueFormatter: (params) => `${params.value} yrs`, }, ], }); From c3e2120a7df63085be187e3d3b784a6cc63886dd Mon Sep 17 00:00:00 2001 From: damien Date: Wed, 10 Mar 2021 19:28:46 +0100 Subject: [PATCH 16/22] add event arg in api docs --- docs/pages/api-docs/data-grid.md | 36 ++++++++++++++++---------------- docs/pages/api-docs/x-grid.md | 36 ++++++++++++++++---------------- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/docs/pages/api-docs/data-grid.md b/docs/pages/api-docs/data-grid.md index 871217b3ad57a..b38f5e4751fdb 100644 --- a/docs/pages/api-docs/data-grid.md +++ b/docs/pages/api-docs/data-grid.md @@ -42,19 +42,19 @@ import { DataGrid } from '@material-ui/data-grid'; | logger | Logger | null | Pass a custom logger in the components that implements the 'Logger' interface. | | logLevel | string | false | false | Allows to pass the logging level or false to turn off logging. | | nonce | string | | Nonce of the inline styles for [Content Security Policy](https://www.w3.org/TR/2016/REC-CSP2-20161215/#script-src-the-nonce-attribute). | -| onCellClick | (param: GridCellParams) => void | | Callback fired when a click event comes from a cell element. | -| onCellDoubleClick | (param: GridCellParams) => void | | Callback fired when a double click event comes from a cell element. | -| onCellOver | (param: GridCellParams) => void | | Callback fired when a mouse over event comes from a cell element. | -| onCellOut | (param: GridCellParams) => void | | Callback fired when a mouse out comes from a cell element. | -| onCellEnter | (param: GridCellParams) => void | | Callback fired when a mouse enter event comes from a cell element. | -| onCellLeave | (param: GridCellParams) => void | | Callback fired when a mouse leave event comes from a cell element. | +| onCellClick | (param: GridCellParams, event: React.MouseEvent) => void | | Callback fired when a click event comes from a cell element. | +| onCellDoubleClick | (param: GridCellParams, event: React.MouseEvent) => void | | Callback fired when a double click event comes from a cell element. | +| onCellOver | (param: GridCellParams, event: React.MouseEvent) => void | | Callback fired when a mouse over event comes from a cell element. | +| onCellOut | (param: GridCellParams, event: React.MouseEvent) => void | | Callback fired when a mouse out comes from a cell element. | +| 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) => void | | Callback fired when a click event comes from a column header element. | -| onColumnHeaderDoubleClick | (param: GridColParams) => void | | Callback fired when a double click event comes from a column header element. | -| onColumnHeaderOver | (param: GridColParams) => void | | Callback fired when a mouseover event comes from a column header element. | -| onColumnHeaderOut | (param: GridColParams) => void | | Callback fired when a mouseout event comes from a column header element. | -| onColumnHeaderEnter | (param: GridColParams) => void | | Callback fired when a mouse enter event comes from a column header element. | -| onColumnHeaderLeave | (param: GridColParams) => void | | Callback fired when a mouse leave event comes from a column header element. | +| 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. | | 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. | @@ -62,12 +62,12 @@ import { DataGrid } from '@material-ui/data-grid'; | onFilterModelChange | (params: GridFilterModelParams) => void | | Callback fired when the Filter model changes before the filters are applied. | | onPageChange | (param: GridPageChangeParams) => void | | Callback fired when the current page has changed. | | onPageSizeChange | (param: GridPageChangeParams) => void | | Callback fired when the page size has changed. | -| onRowClick | (param: GridRowParams) => void | | Callback fired when a click event comes from a row container element. | -| onRowDoubleClick | (param: GridRowParams) => void | | Callback fired when a double click event comes from a row container element. | -| onRowOver | (param: GridRowParams) => void | | Callback fired when a mouse over comes from a row container element. | -| onRowOut | (param: GridRowParams) => void | | Callback fired when a mouse out comes from a row container element. | -| onRowEnter | (param: GridRowParams) => void | | Callback fired when a mouse enter comes from a row container element. | -| onRowLeave | (param: GridRowParams) => void | | Callback fired when a mouse leave event comes from a row container element. | +| onRowClick | (param: GridRowParams, event: React.MouseEvent) => void | | Callback fired when a click event comes from a row container element. | +| onRowDoubleClick | (param: GridRowParams, event: React.MouseEvent) => void | | Callback fired when a double click event comes from a row container element. | +| onRowOver | (param: GridRowParams, event: React.MouseEvent) => void | | Callback fired when a mouse over comes from a row container element. | +| onRowOut | (param: GridRowParams, event: React.MouseEvent) => void | | Callback fired when a mouse out comes from a row container element. | +| onRowEnter | (param: GridRowParams, event: React.MouseEvent) => void | | Callback fired when a mouse enter comes from a row container element. | +| onRowLeave | (param: GridRowParams, event: React.MouseEvent) => void | | Callback fired when a mouse leave event comes from a row container element. | | onRowSelected | (param: GridRowSelectedParams) => void | | Callback fired when one row is selected. | | onSelectionModelChange | (param: GridSelectionModelChangeParams) => void | | Callback fired when the selection state of one or multiple rows changes. | | onSortModelChange | (param: GridSortModelParams) => void | | Callback fired when the sort model changes before a column is sorted. | diff --git a/docs/pages/api-docs/x-grid.md b/docs/pages/api-docs/x-grid.md index cc4a4f3c9033e..1ec8c66c19683 100644 --- a/docs/pages/api-docs/x-grid.md +++ b/docs/pages/api-docs/x-grid.md @@ -45,19 +45,19 @@ import { XGrid } from '@material-ui/x-grid'; | logger | Logger | null | Pass a custom logger in the components that implements the 'Logger' interface. | | logLevel | string | false | false | Allows to pass the logging level or false to turn off logging. | | nonce | string | | Nonce of the inline styles for [Content Security Policy](https://www.w3.org/TR/2016/REC-CSP2-20161215/#script-src-the-nonce-attribute). | -| onCellClick | (param: GridCellParams) => void | | Callback fired when a click event comes from a cell element. | -| onCellDoubleClick | (param: GridCellParams) => void | | Callback fired when a double click event comes from a cell element. | -| onCellOver | (param: GridCellParams) => void | | Callback fired when a mouse over event comes from a cell element. | -| onCellOut | (param: GridCellParams) => void | | Callback fired when a mouse out comes from a cell element. | -| onCellEnter | (param: GridCellParams) => void | | Callback fired when a mouse enter event comes from a cell element. | -| onCellLeave | (param: GridCellParams) => void | | Callback fired when a mouse leave event comes from a cell element. | +| onCellClick | (param: GridCellParams, event: React.MouseEvent) => void | | Callback fired when a click event comes from a cell element. | +| onCellDoubleClick | (param: GridCellParams, event: React.MouseEvent) => void | | Callback fired when a double click event comes from a cell element. | +| onCellOver | (param: GridCellParams, event: React.MouseEvent) => void | | Callback fired when a mouse over event comes from a cell element. | +| onCellOut | (param: GridCellParams, event: React.MouseEvent) => void | | Callback fired when a mouse out comes from a cell element. | +| 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) => void | | Callback fired when a click event comes from a column header element. | -| onColumnHeaderDoubleClick | (param: GridColParams) => void | | Callback fired when a double click event comes from a column header element. | -| onColumnHeaderOver | (param: GridColParams) => void | | Callback fired when a mouseover event comes from a column header element. | -| onColumnHeaderOut | (param: GridColParams) => void | | Callback fired when a mouseout event comes from a column header element. | -| onColumnHeaderEnter | (param: GridColParams) => void | | Callback fired when a mouse enter event comes from a column header element. | -| onColumnHeaderLeave | (param: GridColParams) => void | | Callback fired when a mouse leave event comes from a column header element. | +| 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. | | 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. | @@ -65,12 +65,12 @@ import { XGrid } from '@material-ui/x-grid'; | onFilterModelChange | (params: GridFilterModelParams) => void | | Callback fired when the Filter model changes before the filters are applied. | | onPageChange | (param: GridPageChangeParams) => void | | Callback fired when the current page has changed. | | onPageSizeChange | (param: GridPageChangeParams) => void | | Callback fired when the page size has changed. | -| onRowClick | (param: GridRowParams) => void | | Callback fired when a click event comes from a row container element. | -| onRowDoubleClick | (param: GridRowParams) => void | | Callback fired when a double click event comes from a row container element. | -| onRowOver | (param: GridRowParams) => void | | Callback fired when a mouse over comes from a row container element. | -| onRowOut | (param: GridRowParams) => void | | Callback fired when a mouse out comes from a row container element. | -| onRowEnter | (param: GridRowParams) => void | | Callback fired when a mouse enter comes from a row container element. | -| onRowLeave | (param: GridRowParams) => void | | Callback fired when a mouse leave event comes from a row container element. | +| onRowClick | (param: GridRowParams, event: React.MouseEvent) => void | | Callback fired when a click event comes from a row container element. | +| onRowDoubleClick | (param: GridRowParams, event: React.MouseEvent) => void | | Callback fired when a double click event comes from a row container element. | +| onRowOver | (param: GridRowParams, event: React.MouseEvent) => void | | Callback fired when a mouse over comes from a row container element. | +| onRowOut | (param: GridRowParams, event: React.MouseEvent) => void | | Callback fired when a mouse out comes from a row container element. | +| onRowEnter | (param: GridRowParams, event: React.MouseEvent) => void | | Callback fired when a mouse enter comes from a row container element. | +| onRowLeave | (param: GridRowParams, event: React.MouseEvent) => void | | Callback fired when a mouse leave event comes from a row container element. | | onRowSelected | (param: GridRowSelectedParams) => void | | Callback fired when one row is selected. | | onSelectionModelChange | (param: GridSelectionModelChangeParams) => void | | Callback fired when the selection state of one or multiple rows changes. | | onSortModelChange | (param: GridSortModelParams) => void | | Callback fired when the sort model changes before a column is sorted. | From 89db2a5226f853f6bb82c243ae89794217258063 Mon Sep 17 00:00:00 2001 From: damien Date: Wed, 10 Mar 2021 19:45:34 +0100 Subject: [PATCH 17/22] add more tests --- .../x-grid/src/tests/events.XGrid.test.tsx | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) 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 36b186460a142..7e8be4d332d26 100644 --- a/packages/grid/x-grid/src/tests/events.XGrid.test.tsx +++ b/packages/grid/x-grid/src/tests/events.XGrid.test.tsx @@ -206,5 +206,62 @@ describe(' - Events Params ', () => { fireEvent.click(cell22); expect(events).to.equal('cellClick, rowClick, '); }); + + it('should not bubble to the row if the column has disableEventBubbling', () => { + let events = ''; + const addEventName = (name: string) => () => { + events += `${name}, `; + }; + render( + ({ + ...col, + disableClickEventBubbling: true, + }))} + />, + ); + + const cell22 = getCell(1, 1); + fireEvent.click(cell22); + expect(events).to.equal('cellClick, '); + }); + it('should allow to stop propagation', () => { + let events = ''; + const addEventName = (name: string) => () => { + events += `${name}, `; + }; + const stopClick = (params, event) => { + event.stopPropagation(); + }; + render(); + + const cell22 = getCell(1, 1); + fireEvent.click(cell22); + expect(events).to.equal(''); + }); + it('should select a row by default', () => { + let events = ''; + const addEventName = (name: string) => () => { + events += `${name}, `; + }; + render(); + + const cell22 = getCell(1, 1); + fireEvent.click(cell22); + expect(events).to.equal('rowSelected, '); + }); + it('should not select a row if options.disableSelectionOnClick', () => { + let events = ''; + const addEventName = (name: string) => () => { + events += `${name}, `; + }; + render(); + + const cell22 = getCell(1, 1); + fireEvent.click(cell22); + expect(events).to.equal(''); + }); }); }); From 1e3b65239b645f7dd28dbd2f5faa6da0e6e0d88a Mon Sep 17 00:00:00 2001 From: damien Date: Thu, 11 Mar 2021 10:54:15 +0100 Subject: [PATCH 18/22] small refactoring on tests --- .../x-grid/src/tests/events.XGrid.test.tsx | 185 +++++++----------- 1 file changed, 72 insertions(+), 113 deletions(-) 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 7e8be4d332d26..1cff4ce5196ef 100644 --- a/packages/grid/x-grid/src/tests/events.XGrid.test.tsx +++ b/packages/grid/x-grid/src/tests/events.XGrid.test.tsx @@ -81,74 +81,70 @@ describe(' - Events Params ', () => { fireEvent.click(ageColumnElement); }); - it('should contains the column header element', () => { - expect(eventArgs!.params.element).to.equal(ageColumnElement); - }); - it('should contains the column def', () => { - expect(eventArgs!.params.colDef).to.equal(apiRef!.current.getColumnFromField('age')); - }); - it('should contains the column index', () => { - expect(eventArgs!.params.colIndex).to.equal(2); - }); - it('should contains the column field', () => { - expect(eventArgs!.params.field).to.equal('age'); - }); - it('should contains the api', () => { - expect(eventArgs!.params.api).to.equal(apiRef.current); + it('should include the correct params', () => { + expect(eventArgs!.params).to.deep.include({ + colDef: apiRef!.current.getColumnFromField('age'), + element: ageColumnElement, + colIndex: 2, + field: 'age', + api: apiRef.current, + }); }); }); describe('RowsParams', () => { let eventArgs: { params: GridRowParams; event: React.MouseEvent } | null = null; - let row2; + let row1; + beforeEach(() => { const handleClick = (params, event) => { eventArgs = { params, event }; }; render(); - row2 = getRow(1); - fireEvent.click(row2); + row1 = getRow(1); + fireEvent.click(row1); }); - it('should contains the row id', () => { - expect(eventArgs!.params.id).to.equal(2); - }); - it('should contains the element', () => { - expect(eventArgs!.params.element).to.equal(row2); - }); - it('should contains the row model', () => { - expect(eventArgs!.params.row).to.equal(baselineProps.rows[1]); - }); - it('should contains the row index', () => { - expect(eventArgs!.params.rowIndex).to.equal(1); - }); - it('should contains the columns', () => { - expect(eventArgs!.params.columns).to.equal(apiRef!.current.getAllColumns()); - }); - it('should contains the api', () => { - expect(eventArgs!.params.api).to.equal(apiRef.current); + it('should include the correct params', () => { + expect(eventArgs!.params).to.deep.include({ + id: 2, + element: row1, + row: baselineProps.rows[1], + rowIndex: 1, + columns: apiRef!.current.getAllColumns(), + api: apiRef.current, + }); }); }); describe('CellsParams', () => { let eventArgs: { params: GridCellParams; event: React.MouseEvent } | null = null; - let cell22; + let cell11; + beforeEach(() => { const handleClick = (params, event) => { eventArgs = { params, event }; }; render(); - cell22 = getCell(1, 1); - fireEvent.click(cell22); + cell11 = getCell(1, 1); + fireEvent.click(cell11); }); - it('should contains the cell id', () => { - expect(eventArgs!.params.id).to.equal(2); - }); - it('should contains the cell value', () => { - expect(eventArgs!.params.value).to.equal('Jack'); + it('should include the correct params', () => { + expect(eventArgs!.params).to.deep.include({ + id: 2, + value: 'Jack', + formattedValue: 'Jack', + isEditable: true, + element: cell11, + row: baselineProps.rows[1], + rowIndex: 1, + colDef: apiRef!.current.getColumnFromField('first'), + colIndex: 1, + api: apiRef.current, + }); }); it('should consider value getter', () => { @@ -157,65 +153,38 @@ describe(' - Events Params ', () => { expect(eventArgs!.params.value).to.equal('Jack_11'); }); + it('should consider value formatter', () => { const cellFirstAge = getCell(1, 3); fireEvent.click(cellFirstAge); expect(eventArgs!.params.formattedValue).to.equal('Jack_11 yrs'); }); - it('should contains the cell formattedValue', () => { - expect(eventArgs!.params.formattedValue).to.equal('Jack'); - }); - it('should contains the cell isEditable', () => { - expect(eventArgs!.params.isEditable).to.equal(true); - }); - it('should contains the element', () => { - expect(eventArgs!.params.element).to.equal(cell22); - }); - it('should contains the cell model', () => { - expect(eventArgs!.params.row).to.equal(baselineProps.rows[1]); - }); - it('should contains the cell index', () => { - expect(eventArgs!.params.rowIndex).to.equal(1); - }); - it('should contains the column', () => { - expect(eventArgs!.params.colDef).to.equal(apiRef!.current.getColumnFromField('first')); - }); - it('should contains the column index', () => { - expect(eventArgs!.params.colIndex).to.equal(1); - }); - it('should contains the api', () => { - expect(eventArgs!.params.api).to.equal(apiRef.current); - }); }); describe('onCellClick', () => { + let eventStack: string[] = []; + const push = (name: string) => () => { + eventStack.push(name); + }; + + beforeEach(() => { + eventStack = []; + }); + it('should bubble to the row', () => { - let events = ''; - const addEventName = (name: string) => () => { - events += `${name}, `; - }; - render( - , - ); + render(); - const cell22 = getCell(1, 1); - fireEvent.click(cell22); - expect(events).to.equal('cellClick, rowClick, '); + const cell11 = getCell(1, 1); + fireEvent.click(cell11); + expect(eventStack).to.deep.equal(['cellClick', 'rowClick']); }); it('should not bubble to the row if the column has disableEventBubbling', () => { - let events = ''; - const addEventName = (name: string) => () => { - events += `${name}, `; - }; render( ({ ...col, disableClickEventBubbling: true, @@ -223,45 +192,35 @@ describe(' - Events Params ', () => { />, ); - const cell22 = getCell(1, 1); - fireEvent.click(cell22); - expect(events).to.equal('cellClick, '); + const cell11 = getCell(1, 1); + fireEvent.click(cell11); + expect(eventStack).to.deep.equal(['cellClick']); }); + it('should allow to stop propagation', () => { - let events = ''; - const addEventName = (name: string) => () => { - events += `${name}, `; - }; const stopClick = (params, event) => { event.stopPropagation(); }; - render(); + render(); - const cell22 = getCell(1, 1); - fireEvent.click(cell22); - expect(events).to.equal(''); + const cell11 = getCell(1, 1); + fireEvent.click(cell11); + expect(eventStack).to.deep.equal([]); }); + it('should select a row by default', () => { - let events = ''; - const addEventName = (name: string) => () => { - events += `${name}, `; - }; - render(); + render(); - const cell22 = getCell(1, 1); - fireEvent.click(cell22); - expect(events).to.equal('rowSelected, '); + const cell11 = getCell(1, 1); + fireEvent.click(cell11); + expect(eventStack).to.deep.equal(['rowSelected']); }); - it('should not select a row if options.disableSelectionOnClick', () => { - let events = ''; - const addEventName = (name: string) => () => { - events += `${name}, `; - }; - render(); - const cell22 = getCell(1, 1); - fireEvent.click(cell22); - expect(events).to.equal(''); + it('should not select a row if options.disableSelectionOnClick', () => { + render(); + const cell11 = getCell(1, 1); + fireEvent.click(cell11); + expect(eventStack).to.deep.equal([]); }); }); }); From f2deb7a58eb7f62f4ebcfca992fdc0a757621ac6 Mon Sep 17 00:00:00 2001 From: damien Date: Thu, 11 Mar 2021 14:21:50 +0100 Subject: [PATCH 19/22] Add . at the end of desc Co-authored-by: Olivier Tassinari --- .../grid/_modules_/grid/models/api/gridParamsApi.ts | 10 +++++----- .../_modules_/grid/models/params/gridCellParams.ts | 2 +- .../grid/_modules_/grid/models/params/gridColParams.ts | 2 +- .../grid/_modules_/grid/models/params/gridRowParams.ts | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/grid/_modules_/grid/models/api/gridParamsApi.ts b/packages/grid/_modules_/grid/models/api/gridParamsApi.ts index d85b87d61881b..b88f57e0ad824 100644 --- a/packages/grid/_modules_/grid/models/api/gridParamsApi.ts +++ b/packages/grid/_modules_/grid/models/api/gridParamsApi.ts @@ -12,13 +12,13 @@ export interface GridParamsApi { */ getCellValue: (id: GridRowId, field: string) => GridCellValue; /** - * Get the cell DOM element + * Get the cell DOM element. * @param id * @param field */ getCellElement: (id: GridRowId, field: string) => HTMLDivElement | null; /** - * Get the cell params that are passed in events + * Get the cell params that are passed in events. * @param id * @param field */ @@ -30,18 +30,18 @@ export interface GridParamsApi { */ getRowParams: (id: GridRowId) => GridRowParams; /** - * Get the row DOM element + * Get the row DOM element. * @param id * @param field */ getRowElement: (id: GridRowId) => HTMLDivElement | null; /** - * Get the column header DOM element + * Get the column header DOM element. * @param field */ getColumnHeaderElement: (field: string) => HTMLDivElement | null; /** - * Get the header params that are passed in events + * Get the header params that are passed in events. * @param field */ getColumnHeaderParams: (field: string) => GridColParams; diff --git a/packages/grid/_modules_/grid/models/params/gridCellParams.ts b/packages/grid/_modules_/grid/models/params/gridCellParams.ts index 132ad09cb8aed..caede603f289a 100644 --- a/packages/grid/_modules_/grid/models/params/gridCellParams.ts +++ b/packages/grid/_modules_/grid/models/params/gridCellParams.ts @@ -10,7 +10,7 @@ export interface GridCellParams { */ id: GridRowId; /** - * The HTMLElement cell element + * The HTMLElement cell element. */ element?: HTMLElement | null; /** diff --git a/packages/grid/_modules_/grid/models/params/gridColParams.ts b/packages/grid/_modules_/grid/models/params/gridColParams.ts index d3a885e4c7ba3..67c1c3e982edd 100644 --- a/packages/grid/_modules_/grid/models/params/gridColParams.ts +++ b/packages/grid/_modules_/grid/models/params/gridColParams.ts @@ -3,7 +3,7 @@ */ export interface GridColParams { /** - * The HTMLElement column header element + * The HTMLElement column header element. */ element?: HTMLElement | null; /** diff --git a/packages/grid/_modules_/grid/models/params/gridRowParams.ts b/packages/grid/_modules_/grid/models/params/gridRowParams.ts index 8d005efd7a491..d733139176038 100644 --- a/packages/grid/_modules_/grid/models/params/gridRowParams.ts +++ b/packages/grid/_modules_/grid/models/params/gridRowParams.ts @@ -6,11 +6,11 @@ import { GridRowId, GridRowModel } from '../gridRows'; */ export interface GridRowParams { /** - * The grid row id + * The grid row id. */ id: GridRowId; /** - * The HTMLElement row element + * The HTMLElement row element. */ element?: HTMLElement | null; /** From af50f175535e29db56c7759742b52b515f17cb26 Mon Sep 17 00:00:00 2001 From: damien Date: Thu, 11 Mar 2021 14:22:16 +0100 Subject: [PATCH 20/22] Update packages/grid/_modules_/grid/models/api/gridParamsApi.ts Co-authored-by: Olivier Tassinari --- packages/grid/_modules_/grid/models/api/gridParamsApi.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/grid/_modules_/grid/models/api/gridParamsApi.ts b/packages/grid/_modules_/grid/models/api/gridParamsApi.ts index b88f57e0ad824..35095dc3d812c 100644 --- a/packages/grid/_modules_/grid/models/api/gridParamsApi.ts +++ b/packages/grid/_modules_/grid/models/api/gridParamsApi.ts @@ -24,7 +24,7 @@ export interface GridParamsApi { */ getCellParams: (id: GridRowId, field: string) => GridCellParams; /** - * Get the row params that are passed in events + * Get the row params that are passed in events. * @param id * @param field */ From be8b4774f74049c8e998c0552d42d16a94f2ec2c Mon Sep 17 00:00:00 2001 From: damien Date: Thu, 11 Mar 2021 14:22:27 +0100 Subject: [PATCH 21/22] Update packages/grid/_modules_/grid/models/params/gridCellParams.ts Co-authored-by: Olivier Tassinari --- packages/grid/_modules_/grid/models/params/gridCellParams.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/grid/_modules_/grid/models/params/gridCellParams.ts b/packages/grid/_modules_/grid/models/params/gridCellParams.ts index caede603f289a..096330a7ca421 100644 --- a/packages/grid/_modules_/grid/models/params/gridCellParams.ts +++ b/packages/grid/_modules_/grid/models/params/gridCellParams.ts @@ -6,7 +6,7 @@ import { GridRowId, GridRowModel } from '../gridRows'; */ export interface GridCellParams { /** - * The grid row id + * The grid row id. */ id: GridRowId; /** From a8f25de35389e0228ee34ce469604ca96ec749ed Mon Sep 17 00:00:00 2001 From: damien Date: Thu, 11 Mar 2021 14:36:31 +0100 Subject: [PATCH 22/22] small cleanup --- .../data-grid/overview/DataGridDemo.tsx | 4 ++-- .../rendering/ValueFormatterGrid.tsx | 8 +++++-- .../data-grid/rendering/ValueGetterGrid.tsx | 4 ++-- .../sorting/ComparatorSortingGrid.tsx | 4 ++-- .../hooks/features/rows/useGridParamsApi.ts | 4 ++-- .../grid/models/colDef/gridColDef.ts | 10 ++++++--- .../grid/models/params/gridCellParams.ts | 4 ++-- .../grid/_modules_/grid/utils/domUtils.ts | 4 +--- .../src/tests/layout.DataGrid.test.tsx | 4 ++-- .../x-grid/src/tests/events.XGrid.test.tsx | 22 +++++++------------ .../src/stories/grid-columns.stories.tsx | 6 ++--- .../stories/playground/RecipeReviewCard.tsx | 2 +- 12 files changed, 38 insertions(+), 38 deletions(-) diff --git a/docs/src/pages/components/data-grid/overview/DataGridDemo.tsx b/docs/src/pages/components/data-grid/overview/DataGridDemo.tsx index dea26492e138f..f4fa10db58e5b 100644 --- a/docs/src/pages/components/data-grid/overview/DataGridDemo.tsx +++ b/docs/src/pages/components/data-grid/overview/DataGridDemo.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { DataGrid, GridColDef, ValueGetterParams } from '@material-ui/data-grid'; +import { DataGrid, GridColDef, GridValueGetterParams } from '@material-ui/data-grid'; const columns: GridColDef[] = [ { field: 'id', headerName: 'ID', width: 70 }, @@ -17,7 +17,7 @@ const columns: GridColDef[] = [ description: 'This column has a value getter and is not sortable.', sortable: false, width: 160, - valueGetter: (params: ValueGetterParams) => + valueGetter: (params: GridValueGetterParams) => `${params.getValue('firstName') || ''} ${params.getValue('lastName') || ''}`, }, ]; diff --git a/docs/src/pages/components/data-grid/rendering/ValueFormatterGrid.tsx b/docs/src/pages/components/data-grid/rendering/ValueFormatterGrid.tsx index 5fb869f12b81e..07d7c704bd91f 100644 --- a/docs/src/pages/components/data-grid/rendering/ValueFormatterGrid.tsx +++ b/docs/src/pages/components/data-grid/rendering/ValueFormatterGrid.tsx @@ -1,11 +1,15 @@ import * as React from 'react'; -import { DataGrid, GridColDef, ValueFormatterParams } from '@material-ui/data-grid'; +import { + DataGrid, + GridColDef, + GridValueFormatterParams, +} from '@material-ui/data-grid'; const columns: GridColDef[] = [ { field: 'date', headerName: 'Year', - valueFormatter: (params: ValueFormatterParams) => + valueFormatter: (params: GridValueFormatterParams) => (params.value as Date).getFullYear(), }, ]; diff --git a/docs/src/pages/components/data-grid/rendering/ValueGetterGrid.tsx b/docs/src/pages/components/data-grid/rendering/ValueGetterGrid.tsx index 6140bb77d9cb9..7e810039f4ea1 100644 --- a/docs/src/pages/components/data-grid/rendering/ValueGetterGrid.tsx +++ b/docs/src/pages/components/data-grid/rendering/ValueGetterGrid.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; -import { DataGrid, GridColDef, ValueGetterParams } from '@material-ui/data-grid'; +import { DataGrid, GridColDef, GridValueGetterParams } from '@material-ui/data-grid'; -function getFullName(params: ValueGetterParams) { +function getFullName(params: GridValueGetterParams) { return `${params.getValue('firstName') || ''} ${ params.getValue('lastName') || '' }`; diff --git a/docs/src/pages/components/data-grid/sorting/ComparatorSortingGrid.tsx b/docs/src/pages/components/data-grid/sorting/ComparatorSortingGrid.tsx index 13416b60a4936..77de800d57aae 100644 --- a/docs/src/pages/components/data-grid/sorting/ComparatorSortingGrid.tsx +++ b/docs/src/pages/components/data-grid/sorting/ComparatorSortingGrid.tsx @@ -4,7 +4,7 @@ import { GridRowsProp, DataGrid, GridSortDirection, - ValueGetterParams, + GridValueGetterParams, } from '@material-ui/data-grid'; import { randomCreatedDate, @@ -16,7 +16,7 @@ const columns: GridColumns = [ { field: 'age', type: 'number' }, { field: 'username', - valueGetter: (params: ValueGetterParams) => + valueGetter: (params: GridValueGetterParams) => `${params.getValue('name') || 'unknown'} - ${params.getValue('age') || 'x'}`, sortComparator: (v1, v2, param1, param2) => param1.row.age - param2.row.age, width: 150, diff --git a/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts b/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts index c258b58b9b67d..4c533f6d3ff02 100644 --- a/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts +++ b/packages/grid/_modules_/grid/hooks/features/rows/useGridParamsApi.ts @@ -2,7 +2,7 @@ import * as React from 'react'; import { GridApiRef } from '../../../models/api/gridApiRef'; import { GridParamsApi } from '../../../models/api/gridParamsApi'; import { GridRowId } from '../../../models/gridRows'; -import { GridCellParams, ValueGetterParams } from '../../../models/params/gridCellParams'; +import { GridCellParams, GridValueGetterParams } from '../../../models/params/gridCellParams'; import { GridColParams } from '../../../models/params/gridColParams'; import { GridRowParams } from '../../../models/params/gridRowParams'; import { @@ -57,7 +57,7 @@ export function useGridParamsApi(apiRef: GridApiRef) { const element = apiRef.current.getCellElement(id, field); const row = apiRef.current.getRowFromId(id); - const params: ValueGetterParams = { + const params: GridValueGetterParams = { element, id, field, diff --git a/packages/grid/_modules_/grid/models/colDef/gridColDef.ts b/packages/grid/_modules_/grid/models/colDef/gridColDef.ts index 3bd0888cb2587..d947351afb99c 100644 --- a/packages/grid/_modules_/grid/models/colDef/gridColDef.ts +++ b/packages/grid/_modules_/grid/models/colDef/gridColDef.ts @@ -2,7 +2,11 @@ import * as React from 'react'; import { GridCellValue } from '../gridCell'; import { GridCellClassNamePropType, GridCellClassRules } from '../gridCellClass'; import { GridFilterOperator } from '../gridFilterOperator'; -import { GridCellParams, ValueFormatterParams, ValueGetterParams } from '../params/gridCellParams'; +import { + GridCellParams, + GridValueFormatterParams, + GridValueGetterParams, +} from '../params/gridCellParams'; import { GridColParams } from '../params/gridColParams'; import { GridComparatorFn } from '../gridSortModel'; import { GridColType, GridNativeColTypes } from './gridColType'; @@ -74,12 +78,12 @@ export interface GridColDef { * Function that allows to get a specific data instead of field to render in the cell. * @param params */ - valueGetter?: (params: ValueGetterParams) => GridCellValue; + valueGetter?: (params: GridValueGetterParams) => GridCellValue; /** * Function that allows to apply a formatter before rendering its value. * @param params */ - valueFormatter?: (params: ValueFormatterParams) => GridCellValue; + valueFormatter?: (params: GridValueFormatterParams) => GridCellValue; /** * Class name that will be added in cells for that column. */ diff --git a/packages/grid/_modules_/grid/models/params/gridCellParams.ts b/packages/grid/_modules_/grid/models/params/gridCellParams.ts index 096330a7ca421..9176c4423d547 100644 --- a/packages/grid/_modules_/grid/models/params/gridCellParams.ts +++ b/packages/grid/_modules_/grid/models/params/gridCellParams.ts @@ -59,9 +59,9 @@ export interface GridCellParams { /** * Alias of GridCellParams. */ -export type ValueGetterParams = Omit; +export type GridValueGetterParams = Omit; /** * Alias of GridCellParams. */ -export type ValueFormatterParams = Omit; +export type GridValueFormatterParams = Omit; diff --git a/packages/grid/_modules_/grid/utils/domUtils.ts b/packages/grid/_modules_/grid/utils/domUtils.ts index 89608aea8c2fa..06361cbface09 100644 --- a/packages/grid/_modules_/grid/utils/domUtils.ts +++ b/packages/grid/_modules_/grid/utils/domUtils.ts @@ -78,9 +78,7 @@ export function getGridCellElementFromIndexes( } export function getGridColumnHeaderElement(root: Element, field: string) { - return root.querySelector( - `:scope [role='columnheader'][data-field='${field}']`, - ) as HTMLDivElement; + return root.querySelector(`[role='columnheader'][data-field='${field}']`) as HTMLDivElement; } export function getGridRowElement(root: Element, id: GridRowId) { diff --git a/packages/grid/data-grid/src/tests/layout.DataGrid.test.tsx b/packages/grid/data-grid/src/tests/layout.DataGrid.test.tsx index a951b953f8337..4e24305ff7f56 100644 --- a/packages/grid/data-grid/src/tests/layout.DataGrid.test.tsx +++ b/packages/grid/data-grid/src/tests/layout.DataGrid.test.tsx @@ -7,7 +7,7 @@ import { } from 'test/utils'; import { useFakeTimers, stub } from 'sinon'; import { expect } from 'chai'; -import { DataGrid, ValueGetterParams, GridToolbar } from '@material-ui/data-grid'; +import { DataGrid, GridValueGetterParams, GridToolbar } from '@material-ui/data-grid'; import { getColumnValues, raf, sleep } from 'test/utils/helperFn'; describe(' - Layout & Warnings', () => { @@ -170,7 +170,7 @@ describe(' - Layout & Warnings', () => { { field: 'id', hide: true }, { field: 'fullName', - valueGetter: (params: ValueGetterParams) => params.getValue('age'), + valueGetter: (params: GridValueGetterParams) => params.getValue('age'), }, ]; expect(() => { 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 1cff4ce5196ef..d051946d3bd3d 100644 --- a/packages/grid/x-grid/src/tests/events.XGrid.test.tsx +++ b/packages/grid/x-grid/src/tests/events.XGrid.test.tsx @@ -69,19 +69,16 @@ describe(' - Events Params ', () => { }; describe('columnHeaderParams', () => { - let eventArgs: { params: GridColParams; event: React.MouseEvent } | null = null; - let ageColumnElement; - beforeEach(() => { + it('should include the correct params', () => { + let eventArgs: { params: GridColParams; event: React.MouseEvent } | null = null; const handleClick = (params, event) => { eventArgs = { params, event }; }; render(); - ageColumnElement = getColumnHeaderCell(3); + const ageColumnElement = getColumnHeaderCell(3); fireEvent.click(ageColumnElement); - }); - it('should include the correct params', () => { expect(eventArgs!.params).to.deep.include({ colDef: apiRef!.current.getColumnFromField('age'), element: ageColumnElement, @@ -93,20 +90,17 @@ describe(' - Events Params ', () => { }); describe('RowsParams', () => { - let eventArgs: { params: GridRowParams; event: React.MouseEvent } | null = null; - let row1; + it('should include the correct params', () => { + let eventArgs: { params: GridRowParams; event: React.MouseEvent } | null = null; - beforeEach(() => { const handleClick = (params, event) => { eventArgs = { params, event }; }; render(); - row1 = getRow(1); + const row1 = getRow(1); fireEvent.click(row1); - }); - it('should include the correct params', () => { expect(eventArgs!.params).to.deep.include({ id: 2, element: row1, @@ -127,12 +121,12 @@ describe(' - Events Params ', () => { eventArgs = { params, event }; }; render(); + }); + it('should include the correct params', () => { cell11 = getCell(1, 1); fireEvent.click(cell11); - }); - it('should include the correct params', () => { expect(eventArgs!.params).to.deep.include({ id: 2, value: 'Jack', diff --git a/packages/storybook/src/stories/grid-columns.stories.tsx b/packages/storybook/src/stories/grid-columns.stories.tsx index 5d25b93041b8c..783eee43028b9 100644 --- a/packages/storybook/src/stories/grid-columns.stories.tsx +++ b/packages/storybook/src/stories/grid-columns.stories.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { GridColDef, XGrid, GridColTypeDef, ValueGetterParams } from '@material-ui/x-grid'; +import { GridColDef, XGrid, GridColTypeDef, GridValueGetterParams } from '@material-ui/x-grid'; import CreateIcon from '@material-ui/icons/Create'; import Button from '@material-ui/core/Button'; import { useData } from '../hooks/useData'; @@ -298,12 +298,12 @@ export const ValueGetterAndFormatter = () => { { field: 'id', hide: true }, { field: 'firstAge', - valueGetter: (params: ValueGetterParams) => + valueGetter: (params: GridValueGetterParams) => `${params.getValue('first')}_${params.getValue('age')}`, }, { field: 'firstAgeFormatted', - valueGetter: (params: ValueGetterParams) => + valueGetter: (params: GridValueGetterParams) => `${params.getValue('first')}_${params.getValue('age')}`, valueFormatter: (params) => `${params.value} yrs`, }, diff --git a/packages/storybook/src/stories/playground/RecipeReviewCard.tsx b/packages/storybook/src/stories/playground/RecipeReviewCard.tsx index 14c9616a44f91..7d5fd56566b8f 100644 --- a/packages/storybook/src/stories/playground/RecipeReviewCard.tsx +++ b/packages/storybook/src/stories/playground/RecipeReviewCard.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import * as React from 'react'; import { makeStyles, Theme, createStyles } from '@material-ui/core/styles'; import clsx from 'clsx'; import Card from '@material-ui/core/Card';