Skip to content

Commit

Permalink
Merge branch 'master' into tree-view-pigmentcss
Browse files Browse the repository at this point in the history
  • Loading branch information
flaviendelangle committed Jun 10, 2024
2 parents 5912816 + 2305117 commit b083d9a
Show file tree
Hide file tree
Showing 59 changed files with 874 additions and 493 deletions.
26 changes: 26 additions & 0 deletions docs/data/data-grid/master-detail/master-detail.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,31 @@ This approach can also be used to change the location of the toggle column, as s
As any ordinary cell renderer, the `value` prop is also available, and it corresponds to the state of the row: `true` when expanded and `false` when collapsed.
:::

## Custom header for detail panel column

To render a custom header for the detail panel column, use the [`renderHeader`](/x/react-data-grid/column-header/#custom-header-renderer) property in the column definition.
This property receives a `GridRenderHeaderParams` object that contains `colDef` (the column definition) and `field`.
The following example demonstrates how to render a custom header for the detail panel column:

```tsx
const columns = [
{
...GRID_DETAIL_PANEL_TOGGLE_COL_DEF,
renderHeader: (params) => (
<div>
<span>{params.colDef.headerName}</span>
<button onClick={() => console.log('Custom action')}>Custom action</button>
</div>
),
},
//... other columns
];
```

:::info
For a more advanced example check out the [Expand or collapse all detail panels](/x/react-data-grid/row-recipes/#expand-or-collapse-all-detail-panels) recipe.
:::

## Disable detail panel content scroll

By default, the detail panel has a width that is the sum of the widths of all columns.
Expand All @@ -153,6 +178,7 @@ Notice that the toggle column is pinned to make sure that it will always be visi
More examples of how to customize the detail panel:

- [One expanded detail panel at a time](/x/react-data-grid/row-recipes/#one-expanded-detail-panel-at-a-time)
- [Expand or collapse all detail panels](/x/react-data-grid/row-recipes/#expand-or-collapse-all-detail-panels)

## apiRef

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<DataGridPro
rows={rows}
columns={columns}
getDetailPanelContent={getDetailPanelContent}
getDetailPanelHeight={getDetailPanelHeight}
/>
134 changes: 134 additions & 0 deletions docs/data/data-grid/row-recipes/DetailPanelExpandCollapseAll.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import IconButton from '@mui/material/IconButton';
import UnfoldLessIcon from '@mui/icons-material/UnfoldLess';
import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore';
import {
DataGridPro,
useGridApiContext,
useGridSelector,
gridRowsLookupSelector,
gridDetailPanelExpandedRowIdsSelector,
gridDetailPanelExpandedRowsContentCacheSelector,
GRID_DETAIL_PANEL_TOGGLE_COL_DEF,
} from '@mui/x-data-grid-pro';
import {
randomCreatedDate,
randomCurrency,
randomEmail,
randomPrice,
} from '@mui/x-data-grid-generator';

export default function DetailPanelExpandCollapseAll() {
const getDetailPanelContent = React.useCallback(
({ row }) => <Box sx={{ p: 2 }}>{`Order #${row.id}`}</Box>,
[],
);

const getDetailPanelHeight = React.useCallback(() => 50, []);

return (
<div style={{ height: 400, width: '100%' }}>
<DataGridPro
rows={rows}
columns={columns}
getDetailPanelContent={getDetailPanelContent}
getDetailPanelHeight={getDetailPanelHeight}
/>
</div>
);
}

function CustomDetailPanelHeader() {
const apiRef = useGridApiContext();

const expandedRowIds = useGridSelector(
apiRef,
gridDetailPanelExpandedRowIdsSelector,
);
const rowsWithDetailPanels = useGridSelector(
apiRef,
gridDetailPanelExpandedRowsContentCacheSelector,
);

const noDetailPanelsOpen = expandedRowIds.length === 0;

const expandOrCollapseAll = () => {
const dataRowIdToModelLookup = gridRowsLookupSelector(apiRef);
const allRowIdsWithDetailPanels = Object.keys(rowsWithDetailPanels).map((key) =>
apiRef.current.getRowId(dataRowIdToModelLookup[key]),
);

apiRef.current.setExpandedDetailPanels(
noDetailPanelsOpen ? allRowIdsWithDetailPanels : [],
);
};

const Icon = noDetailPanelsOpen ? UnfoldMoreIcon : UnfoldLessIcon;

return (
<IconButton
size="small"
tabIndex={-1}
onClick={expandOrCollapseAll}
aria-label={noDetailPanelsOpen ? 'Expand All' : 'Collapse All'}
>
<Icon fontSize="inherit" />
</IconButton>
);
}

const columns = [
{
...GRID_DETAIL_PANEL_TOGGLE_COL_DEF,
renderHeader: () => <CustomDetailPanelHeader />,
},
{ field: 'id', headerName: 'Order ID' },
{ field: 'customer', headerName: 'Customer', width: 200 },
{ field: 'date', type: 'date', headerName: 'Placed at' },
{ field: 'currency', headerName: 'Currency' },
{ field: 'total', type: 'number', headerName: 'Total' },
];

const rows = [
{
id: 1,
customer: 'Matheus',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
{
id: 2,
customer: 'Olivier',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
{
id: 3,
customer: 'Flavien',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
{
id: 4,
customer: 'Danail',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
{
id: 5,
customer: 'Alexandre',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
];
138 changes: 138 additions & 0 deletions docs/data/data-grid/row-recipes/DetailPanelExpandCollapseAll.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import IconButton from '@mui/material/IconButton';
import UnfoldLessIcon from '@mui/icons-material/UnfoldLess';
import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore';
import {
DataGridPro,
GridColDef,
GridRowsProp,
GridRowParams,
useGridApiContext,
useGridSelector,
gridRowsLookupSelector,
gridDetailPanelExpandedRowIdsSelector,
gridDetailPanelExpandedRowsContentCacheSelector,
GRID_DETAIL_PANEL_TOGGLE_COL_DEF,
GridRowId,
} from '@mui/x-data-grid-pro';
import {
randomCreatedDate,
randomCurrency,
randomEmail,
randomPrice,
} from '@mui/x-data-grid-generator';

export default function DetailPanelExpandCollapseAll() {
const getDetailPanelContent = React.useCallback(
({ row }: GridRowParams) => <Box sx={{ p: 2 }}>{`Order #${row.id}`}</Box>,
[],
);

const getDetailPanelHeight = React.useCallback(() => 50, []);

return (
<div style={{ height: 400, width: '100%' }}>
<DataGridPro
rows={rows}
columns={columns}
getDetailPanelContent={getDetailPanelContent}
getDetailPanelHeight={getDetailPanelHeight}
/>
</div>
);
}

function CustomDetailPanelHeader() {
const apiRef = useGridApiContext();

const expandedRowIds = useGridSelector(
apiRef,
gridDetailPanelExpandedRowIdsSelector,
);
const rowsWithDetailPanels = useGridSelector(
apiRef,
gridDetailPanelExpandedRowsContentCacheSelector,
);

const noDetailPanelsOpen = expandedRowIds.length === 0;

const expandOrCollapseAll = () => {
const dataRowIdToModelLookup = gridRowsLookupSelector(apiRef);
const allRowIdsWithDetailPanels: GridRowId[] = Object.keys(
rowsWithDetailPanels,
).map((key) => apiRef.current.getRowId(dataRowIdToModelLookup[key]));

apiRef.current.setExpandedDetailPanels(
noDetailPanelsOpen ? allRowIdsWithDetailPanels : [],
);
};

const Icon = noDetailPanelsOpen ? UnfoldMoreIcon : UnfoldLessIcon;

return (
<IconButton
size="small"
tabIndex={-1}
onClick={expandOrCollapseAll}
aria-label={noDetailPanelsOpen ? 'Expand All' : 'Collapse All'}
>
<Icon fontSize="inherit" />
</IconButton>
);
}

const columns: GridColDef[] = [
{
...GRID_DETAIL_PANEL_TOGGLE_COL_DEF,
renderHeader: () => <CustomDetailPanelHeader />,
},
{ field: 'id', headerName: 'Order ID' },
{ field: 'customer', headerName: 'Customer', width: 200 },
{ field: 'date', type: 'date', headerName: 'Placed at' },
{ field: 'currency', headerName: 'Currency' },
{ field: 'total', type: 'number', headerName: 'Total' },
];

const rows: GridRowsProp = [
{
id: 1,
customer: 'Matheus',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
{
id: 2,
customer: 'Olivier',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
{
id: 3,
customer: 'Flavien',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
{
id: 4,
customer: 'Danail',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
{
id: 5,
customer: 'Alexandre',
email: randomEmail(),
date: randomCreatedDate(),
currency: randomCurrency(),
total: randomPrice(1, 1000),
},
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<DataGridPro
rows={rows}
columns={columns}
getDetailPanelContent={getDetailPanelContent}
getDetailPanelHeight={getDetailPanelHeight}
/>
12 changes: 12 additions & 0 deletions docs/data/data-grid/row-recipes/row-recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,15 @@ By default, the [Master detail <span class="plan-pro" />](/x/react-data-grid/mas
However, you can [control the expanded detail panels](/x/react-data-grid/master-detail/#controlling-expanded-detail-panels) to have only one detail panel expanded at a time.

{{"demo": "DetailPanelOneExpandedRow.js", "bg": "inline", "defaultCodeOpen": false}}

## Expand or collapse all detail panels

The following demo shows how to create a custom header element that expands or collapses all detail panels at once.

Here's how it works:

The custom header uses `gridRowsLookupSelector` to find all rows with a detail panel.
It checks the status of open panels using the [`useGridSelector` hook](/x/react-data-grid/state/#with-usegridselector) to access the grid's state.
When clicked, it uses [`setExpandedDetailPanels`](/x/api/data-grid/grid-api/#grid-api-prop-setExpandedDetailPanels) from the [Grid API](/x/react-data-grid/api-object/#how-to-use-the-api-object) to expand or collapse all detail panels.

{{"demo": "DetailPanelExpandCollapseAll.js", "bg": "inline", "defaultCodeOpen": false}}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
extractPluginParamsFromProps,
useTreeView,
TreeViewProvider,
ConvertPluginsIntoSignatures,
} from '@mui/x-tree-view/internals';

interface TreeViewLogExpandedParameters {
Expand Down Expand Up @@ -88,7 +89,7 @@ function TreeView<R extends {}, Multiple extends boolean | undefined>(
const ownerState = themeProps as TreeViewProps<any, any>;

const { pluginParams, otherProps } = extractPluginParamsFromProps<
typeof TREE_VIEW_PLUGINS,
ConvertPluginsIntoSignatures<typeof TREE_VIEW_PLUGINS>,
DefaultTreeViewPluginSlots,
DefaultTreeViewPluginSlotProps,
TreeViewProps<R, Multiple>
Expand Down
2 changes: 1 addition & 1 deletion docs/data/tree-view/rich-tree-view/headless/headless.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ function useTreeItemState(itemId: string) {
const {
customPlugin,
// ...other elements returned by the context
} = useTreeViewContext<DefaultTreeViewPlugins>();
} = useTreeViewContext<DefaultTreeViewPluginSignatures>();

// ...rest of the `useTreeItemState` hook content

Expand Down
Loading

0 comments on commit b083d9a

Please sign in to comment.