Skip to content

Commit

Permalink
[DataGrid] Add slot typings (#11795)
Browse files Browse the repository at this point in the history
Co-authored-by: Andrew Cherniavskyi <[email protected]>
Co-authored-by: Bilal Shafi <[email protected]>
  • Loading branch information
3 people authored Feb 5, 2024
1 parent af04654 commit c5d5a17
Show file tree
Hide file tree
Showing 34 changed files with 208 additions and 150 deletions.
3 changes: 2 additions & 1 deletion docs/data/data-grid/components/CustomColumnMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
GridColumnMenuSortItem,
useGridApiRef,
DataGridPro,
GridSlots,
} from '@mui/x-data-grid-pro';
import StarOutlineIcon from '@mui/icons-material/StarOutline';

Expand Down Expand Up @@ -119,7 +120,7 @@ export default function CustomColumnMenu() {
},
]}
slots={{
columnMenu: CustomColumnMenuComponent,
columnMenu: CustomColumnMenuComponent as GridSlots['columnMenu'],
}}
slotProps={{
columnMenu: { color },
Expand Down
4 changes: 2 additions & 2 deletions docs/data/data-grid/components/CustomLoadingOverlayGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { DataGrid } from '@mui/x-data-grid';
import { DataGrid, GridSlots } from '@mui/x-data-grid';
import LinearProgress from '@mui/material/LinearProgress';
import { useDemoData } from '@mui/x-data-grid-generator';

Expand All @@ -14,7 +14,7 @@ export default function CustomLoadingOverlayGrid() {
<div style={{ height: 400, width: '100%' }}>
<DataGrid
slots={{
loadingOverlay: LinearProgress,
loadingOverlay: LinearProgress as GridSlots['loadingOverlay'],
}}
loading
{...data}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<DataGrid
slots={{
loadingOverlay: LinearProgress,
loadingOverlay: LinearProgress as GridSlots['loadingOverlay'],
}}
loading
{...data}
Expand Down
18 changes: 15 additions & 3 deletions docs/data/data-grid/components/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,35 @@ As part of the customization API, the Data Grid allows you to override internal
The prop accepts an object of type [`GridSlotsComponent`](/x/api/data-grid/data-grid/#slots).

If you wish to pass additional props in a component slot, you can do it using the `slotProps` prop.
This prop is of type `GridSlotsComponentsProps`.
This prop is of type `GridSlotsComponentsProps`. Note that if you do and you use typescript, you'll need to cast your custom component so it can fit in the slot type.

As an example, you could override the column menu and pass additional props as below.

```jsx
```tsx
<DataGrid
rows={rows}
columns={columns}
slots={{
columnMenu: MyCustomColumnMenu,
columnMenu: MyCustomColumnMenu as DataGridProps['slots']['columnMenu'],
}}
slotProps={{
columnMenu: { background: 'red', counter: rows.length },
}}
/>
```

If you want to ensure type safety, you can declare your component using the slot props typings:

```tsx
import { GridSlotProps } from '@mui/x-data-grid';

function MyCustomColumnMenu(
props: GridSlotProps['columnMenu'] & { background: string; counter: number },
) {
// ...
}
```

### Interacting with the data grid

The grid exposes two hooks to help you to access the data grid data while overriding component slots.
Expand Down
3 changes: 2 additions & 1 deletion docs/data/data-grid/editing/FullFeaturedCrudGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
GridRowId,
GridRowModel,
GridRowEditStopReasons,
GridSlots,
} from '@mui/x-data-grid';
import {
randomCreatedDate,
Expand Down Expand Up @@ -237,7 +238,7 @@ export default function FullFeaturedCrudGrid() {
onRowEditStop={handleRowEditStop}
processRowUpdate={processRowUpdate}
slots={{
toolbar: EditToolbar,
toolbar: EditToolbar as GridSlots['toolbar'],
}}
slotProps={{
toolbar: { setRows, setRowModesModel },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
onRowEditStop={handleRowEditStop}
processRowUpdate={processRowUpdate}
slots={{
toolbar: EditToolbar,
toolbar: EditToolbar as GridSlots['toolbar'],
}}
slotProps={{
toolbar: { setRows, setRowModesModel },
Expand Down
3 changes: 2 additions & 1 deletion docs/data/data-grid/editing/StartEditButtonGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
GridCellModes,
GridEventListener,
GridCellModesModel,
GridSlots,
} from '@mui/x-data-grid';
import {
randomCreatedDate,
Expand Down Expand Up @@ -147,7 +148,7 @@ export default function StartEditButtonGrid() {
onCellEditStop={handleCellEditStop}
onCellModesModelChange={(model) => setCellModesModel(model)}
slots={{
toolbar: EditToolbar,
toolbar: EditToolbar as GridSlots['toolbar'],
}}
slotProps={{
toolbar: {
Expand Down
3 changes: 2 additions & 1 deletion docs/data/data-grid/filtering/CustomFilterPanelPosition.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import {
DataGrid,
GridSlots,
GridToolbarContainer,
GridToolbarFilterButton,
} from '@mui/x-data-grid';
Expand Down Expand Up @@ -35,7 +36,7 @@ export default function CustomFilterPanelPosition() {
<DataGrid
{...data}
slots={{
toolbar: CustomToolbar,
toolbar: CustomToolbar as GridSlots['toolbar'],
}}
slotProps={{
panel: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<DataGrid
{...data}
slots={{
toolbar: CustomToolbar,
toolbar: CustomToolbar as GridSlots['toolbar'],
}}
slotProps={{
panel: {
Expand Down
4 changes: 2 additions & 2 deletions docs/data/data-grid/row-updates/InfiniteLoadingGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { DataGridPro, DataGridProProps } from '@mui/x-data-grid-pro';
import { DataGridPro, DataGridProProps, GridSlots } from '@mui/x-data-grid-pro';
import {
useDemoData,
getRealGridData,
Expand Down Expand Up @@ -61,7 +61,7 @@ export default function InfiniteLoadingGrid() {
hideFooterPagination
onRowsScrollEnd={handleOnRowsScrollEnd}
slots={{
loadingOverlay: LinearProgress,
loadingOverlay: LinearProgress as GridSlots['loadingOverlay'],
}}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
hideFooterPagination
onRowsScrollEnd={handleOnRowsScrollEnd}
slots={{
loadingOverlay: LinearProgress,
loadingOverlay: LinearProgress as GridSlots['loadingOverlay'],
}}
/>
3 changes: 2 additions & 1 deletion docs/data/data-grid/state/RestoreStateInitialState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Stack from '@mui/material/Stack';
import {
DataGridPro,
GridInitialState,
GridSlots,
GridToolbarContainer,
GridToolbarDensitySelector,
GridToolbarFilterButton,
Expand Down Expand Up @@ -62,7 +63,7 @@ export default function RestoreStateInitialState() {
<DataGridPro
{...data}
loading={loading}
slots={{ toolbar: GridCustomToolbar }}
slots={{ toolbar: GridCustomToolbar as GridSlots['toolbar'] }}
slotProps={{ toolbar: { syncState } }}
/>
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<DataGridPro
{...data}
loading={loading}
slots={{ toolbar: GridCustomToolbar }}
slots={{ toolbar: GridCustomToolbar as GridSlots['toolbar'] }}
slotProps={{ toolbar: { syncState } }}
/>
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -457,5 +457,6 @@ Here's the list of affected features, colDef flags and props to disable them and
- The slot `row` has had these props removed: `containerWidth`, `position`.
- The slot `row` has typed props now.
- The slot `headerFilterCell` has had these props removed: `filterOperators`.
- All slots are now strongly typed, previously were `React.JSXElementConstructor<any>`.
<!-- ### Rename `components` to `slots` -->
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import {
import { useDataGridPremiumProps } from './useDataGridPremiumProps';
import { getReleaseInfo } from '../utils/releaseInfo';

export type { GridPremiumSlotsComponent as GridSlots } from '../models';

const releaseInfo = getReleaseInfo();

const dataGridPremiumPropValidators: PropValidator<DataGridPremiumProcessedProps>[] = [
Expand Down
2 changes: 2 additions & 0 deletions packages/grid/x-data-grid-pro/src/DataGridPro/DataGridPro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { useDataGridProProps } from './useDataGridProProps';
import { getReleaseInfo } from '../utils/releaseInfo';
import { propValidatorsDataGridPro } from '../internals/propValidation';

export type { GridProSlotsComponent as GridSlots } from '../models';

const releaseInfo = getReleaseInfo();

const DataGridProRaw = React.forwardRef(function DataGridPro<R extends GridValidRowModel>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,16 @@ function GridHeaderFilterMenuContainer(props: {
return null;
}

const label = apiRef.current.getLocaleText('filterPanelOperator');
const labelString = label ? String(label) : undefined;

return (
<React.Fragment>
<rootProps.slots.baseIconButton
id={buttonId}
ref={buttonRef}
aria-label={apiRef.current.getLocaleText('filterPanelOperator')}
title={apiRef.current.getLocaleText('filterPanelOperator')}
aria-label={labelString}
title={labelString}
aria-controls={menuId}
aria-expanded={open ? 'true' : undefined}
aria-haspopup="true"
Expand Down
2 changes: 2 additions & 0 deletions packages/grid/x-data-grid/src/DataGrid/DataGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
validateProps,
} from '../internals/utils/propValidation';

export type { GridSlotsComponent as GridSlots } from '../models';

const propValidators: PropValidator<DataGridProcessedProps>[] = [
...propValidatorsDataGrid,
// Only validate in MIT version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const GridPaginationRoot = styled(TablePagination)(({ theme }) => ({
},
})) as typeof TablePagination;

export const GridPagination = React.forwardRef<HTMLDivElement, Partial<TablePaginationProps>>(
export const GridPagination = React.forwardRef<unknown, Partial<TablePaginationProps>>(
function GridPagination(props, ref) {
const apiRef = useGridApiContext();
const rootProps = useGridRootProps();
Expand Down
2 changes: 1 addition & 1 deletion packages/grid/x-data-grid/src/components/GridRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ const GridRow = React.forwardRef<HTMLDivElement, GridRowProps>(function GridRow(
width={width}
contentWidth={contentWidth}
field={column.field}
align={column.align}
align={column.align ?? 'left'}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ export function GridFooterPlaceholder() {
return null;
}

return <rootProps.slots.footer {...rootProps.slotProps?.footer} />;
return (
<rootProps.slots.footer {...(rootProps.slotProps?.footer as any) /* FIXME: typing error */} />
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const GridCellCheckboxForwardRef = React.forwardRef<HTMLInputElement, GridRender
const rootProps = useGridRootProps();
const ownerState = { classes: rootProps.classes };
const classes = useUtilityClasses(ownerState);
const checkboxElement = React.useRef<HTMLInputElement | null>(null);
const checkboxElement = React.useRef<HTMLElement>(null);

const rippleRef = React.useRef<TouchRippleActions>(null);
const handleRef = useForkRef(checkboxElement, ref);
Expand Down Expand Up @@ -104,7 +104,7 @@ const GridCellCheckboxForwardRef = React.forwardRef<HTMLInputElement, GridRender
inputProps={{ 'aria-label': label }}
onKeyDown={handleKeyDown}
disabled={!isSelectable}
touchRippleRef={rippleRef}
touchRippleRef={rippleRef as any /* FIXME: typing error */}
{...rootProps.slotProps?.baseCheckbox}
{...other}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const useUtilityClasses = (ownerState: OwnerState) => {
return composeClasses(slots, getDataGridUtilityClass, classes);
};

const GridHeaderCheckbox = React.forwardRef<HTMLInputElement, GridColumnHeaderParams>(
const GridHeaderCheckbox = React.forwardRef<HTMLButtonElement, GridColumnHeaderParams>(
function GridHeaderCheckbox(props, ref) {
const { field, colDef, ...other } = props;
const [, forceUpdate] = React.useState(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ const GridFilterForm = React.forwardRef<HTMLDivElement, GridFilterFormProps>(
}, [item, currentColumn]);

const changeColumn = React.useCallback(
(event: SelectChangeEvent) => {
(event: SelectChangeEvent<any>) => {
const field = event.target.value as string;
const column = apiRef.current.getColumn(field)!;

Expand Down Expand Up @@ -369,7 +369,7 @@ const GridFilterForm = React.forwardRef<HTMLDivElement, GridFilterFormProps>(
);

const changeOperator = React.useCallback(
(event: SelectChangeEvent) => {
(event: SelectChangeEvent<any>) => {
const operator = event.target.value as string;

const newOperator = currentColumn?.filterOperators!.find((op) => op.value === operator);
Expand All @@ -388,7 +388,7 @@ const GridFilterForm = React.forwardRef<HTMLDivElement, GridFilterFormProps>(
);

const changeLogicOperator = React.useCallback(
(event: SelectChangeEvent) => {
(event: SelectChangeEvent<any>) => {
const logicOperator =
(event.target.value as string) === GridLogicOperator.And.toString()
? GridLogicOperator.And
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ function GridFilterInputBoolean(props: GridFilterInputBooleanProps) {
native={isSelectNative}
displayEmpty
inputProps={{ ref: focusElementRef, tabIndex }}
{...others}
{
...(others as any) /* FIXME: typing error */
}
{...baseSelectProps}
>
<rootProps.slots.baseSelectOption
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ function GridFilterInputSingleSelect(props: GridFilterInputSingleSelectProps) {
}, [resolvedColumn]);

const onFilterChange = React.useCallback(
(event: SelectChangeEvent) => {
(event: SelectChangeEvent<any>) => {
let value = event.target.value;

// NativeSelect casts the value to a string.
Expand Down Expand Up @@ -146,7 +146,9 @@ function GridFilterInputSingleSelect(props: GridFilterInputSingleSelectProps) {
placeholder: placeholder ?? apiRef.current.getLocaleText('filterPanelInputPlaceholder'),
}}
native={isSelectNative}
{...others}
{
...(others as any) /* FIXME: typing error */
}
{...rootProps.slotProps?.baseSelect}
>
{renderSingleSelectOptions({
Expand Down
Loading

0 comments on commit c5d5a17

Please sign in to comment.