Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DataGrid] Add slot typings #11795

Merged
merged 17 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
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.

Check failure on line 11 in docs/data/data-grid/components/components.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Blog.NamingConventions] To be consistent with capitalization, consider using 'TypeScript' instead of 'typescript'. Raw Output: {"message": "[Blog.NamingConventions] To be consistent with capitalization, consider using 'TypeScript' instead of 'typescript'.", "location": {"path": "docs/data/data-grid/components/components.md", "range": {"start": {"line": 11, "column": 82}}}, "severity": "ERROR"}

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 @@ -375,5 +375,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 */} />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is interesting.
The reason it's failing without as any is this override in the docs examples:

declare module '@mui/x-data-grid' {
interface FooterPropsOverrides {
status: FooterStatus;
}
}

I there something we can do to isolate overrides in docs from the packages?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way it's setup, the docs is importing the grid through relative imports (behind aliased paths). If the docs were importing code as regular packages, then the skipLibCheck flag would do that iiuc, but it doesn't apply here since it's just regular files. I think it could probably be done, but I'm not sure how long it will take to setup, so I'd skip it for this PR.

);
}
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
Loading