diff --git a/docs/data/data-grid/column-header/column-header.md b/docs/data/data-grid/column-header/column-header.md index 01bfdaf93e76..332ece76cfd9 100644 --- a/docs/data/data-grid/column-header/column-header.md +++ b/docs/data/data-grid/column-header/column-header.md @@ -38,12 +38,6 @@ const columns: GridColDef[] = [ You can check the [styling header](/x/react-data-grid/style/#styling-column-headers) section for more information. -## Column menu - -By default, each column header displays a column menu. The column menu allows actions to be performed in the context of the target column, e.g. filtering. To disable the column menu, set the prop `disableColumnMenu={true}`. - -{{"demo": "ColumnMenuGrid.js", "bg": "inline"}} - ## API - [DataGrid](/x/api/data-grid/data-grid/) diff --git a/docs/data/data-grid/column-menu/AddNewColumnMenuGrid.js b/docs/data/data-grid/column-menu/AddNewColumnMenuGrid.js new file mode 100644 index 000000000000..d1748e056971 --- /dev/null +++ b/docs/data/data-grid/column-menu/AddNewColumnMenuGrid.js @@ -0,0 +1,54 @@ +import * as React from 'react'; +import MenuItem from '@mui/material/MenuItem'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import SettingsApplicationsIcon from '@mui/icons-material/SettingsApplications'; +import { DataGrid, GridColumnMenu } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; + +function CustomUserItem(props) { + const { myCustomHandler, myCustomValue } = props; + return ( + + + + + {myCustomValue} + + ); +} + +function CustomColumnMenu(props) { + return ( + alert('Custom handler fired'), + }, + }} + /> + ); +} + +export default function AddNewColumnMenuGrid() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 20, + maxColumns: 5, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/column-menu/AddNewColumnMenuGrid.tsx b/docs/data/data-grid/column-menu/AddNewColumnMenuGrid.tsx new file mode 100644 index 000000000000..325d01ae5c31 --- /dev/null +++ b/docs/data/data-grid/column-menu/AddNewColumnMenuGrid.tsx @@ -0,0 +1,59 @@ +import * as React from 'react'; +import MenuItem from '@mui/material/MenuItem'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import SettingsApplicationsIcon from '@mui/icons-material/SettingsApplications'; +import { + DataGrid, + GridColumnMenu, + GridColumnMenuProps, + GridColumnMenuItemProps, +} from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; + +function CustomUserItem(props: GridColumnMenuItemProps) { + const { myCustomHandler, myCustomValue } = props; + return ( + + + + + {myCustomValue} + + ); +} + +function CustomColumnMenu(props: GridColumnMenuProps) { + return ( + alert('Custom handler fired'), + }, + }} + /> + ); +} + +export default function AddNewColumnMenuGrid() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 20, + maxColumns: 5, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/column-menu/AddNewColumnMenuGrid.tsx.preview b/docs/data/data-grid/column-menu/AddNewColumnMenuGrid.tsx.preview new file mode 100644 index 000000000000..9112f9e6ce3e --- /dev/null +++ b/docs/data/data-grid/column-menu/AddNewColumnMenuGrid.tsx.preview @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/column-header/ColumnMenuGrid.js b/docs/data/data-grid/column-menu/ColumnMenuGrid.js similarity index 88% rename from docs/data/data-grid/column-header/ColumnMenuGrid.js rename to docs/data/data-grid/column-menu/ColumnMenuGrid.js index ed82e19e0b43..2a353c33dca2 100644 --- a/docs/data/data-grid/column-header/ColumnMenuGrid.js +++ b/docs/data/data-grid/column-menu/ColumnMenuGrid.js @@ -11,7 +11,7 @@ export default function ColumnMenuGrid() { return (
- +
); } diff --git a/docs/data/data-grid/column-header/ColumnMenuGrid.tsx b/docs/data/data-grid/column-menu/ColumnMenuGrid.tsx similarity index 88% rename from docs/data/data-grid/column-header/ColumnMenuGrid.tsx rename to docs/data/data-grid/column-menu/ColumnMenuGrid.tsx index ed82e19e0b43..2a353c33dca2 100644 --- a/docs/data/data-grid/column-header/ColumnMenuGrid.tsx +++ b/docs/data/data-grid/column-menu/ColumnMenuGrid.tsx @@ -11,7 +11,7 @@ export default function ColumnMenuGrid() { return (
- +
); } diff --git a/docs/data/data-grid/column-menu/ColumnMenuGrid.tsx.preview b/docs/data/data-grid/column-menu/ColumnMenuGrid.tsx.preview new file mode 100644 index 000000000000..4eba0f23a52f --- /dev/null +++ b/docs/data/data-grid/column-menu/ColumnMenuGrid.tsx.preview @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/column-menu/ColumnMenuGridPremium.js b/docs/data/data-grid/column-menu/ColumnMenuGridPremium.js new file mode 100644 index 000000000000..230df4949647 --- /dev/null +++ b/docs/data/data-grid/column-menu/ColumnMenuGridPremium.js @@ -0,0 +1,45 @@ +import * as React from 'react'; +import { + DataGridPremium, + useGridApiRef, + useKeepGroupedColumnsHidden, +} from '@mui/x-data-grid-premium'; +import { useMovieData } from '@mui/x-data-grid-generator'; + +export default function ColumnMenuGridPremium() { + const apiRef = useGridApiRef(); + const data = useMovieData(); + + const initialState = useKeepGroupedColumnsHidden({ + apiRef, + initialState: { + aggregation: { + model: { + gross: 'avg', + }, + }, + columns: { + columnVisibilityModel: { + cinematicUniverse: false, + title: false, + }, + }, + rowGrouping: { + model: ['company'], + }, + }, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/column-menu/ColumnMenuGridPremium.tsx b/docs/data/data-grid/column-menu/ColumnMenuGridPremium.tsx new file mode 100644 index 000000000000..230df4949647 --- /dev/null +++ b/docs/data/data-grid/column-menu/ColumnMenuGridPremium.tsx @@ -0,0 +1,45 @@ +import * as React from 'react'; +import { + DataGridPremium, + useGridApiRef, + useKeepGroupedColumnsHidden, +} from '@mui/x-data-grid-premium'; +import { useMovieData } from '@mui/x-data-grid-generator'; + +export default function ColumnMenuGridPremium() { + const apiRef = useGridApiRef(); + const data = useMovieData(); + + const initialState = useKeepGroupedColumnsHidden({ + apiRef, + initialState: { + aggregation: { + model: { + gross: 'avg', + }, + }, + columns: { + columnVisibilityModel: { + cinematicUniverse: false, + title: false, + }, + }, + rowGrouping: { + model: ['company'], + }, + }, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/column-menu/ColumnMenuGridPremium.tsx.preview b/docs/data/data-grid/column-menu/ColumnMenuGridPremium.tsx.preview new file mode 100644 index 000000000000..a7085f34d5ec --- /dev/null +++ b/docs/data/data-grid/column-menu/ColumnMenuGridPremium.tsx.preview @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/column-menu/ColumnMenuGridReferences.js b/docs/data/data-grid/column-menu/ColumnMenuGridReferences.js new file mode 100644 index 000000000000..3bac84a36954 --- /dev/null +++ b/docs/data/data-grid/column-menu/ColumnMenuGridReferences.js @@ -0,0 +1,154 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import { DataGridPremium } from '@mui/x-data-grid-premium'; +import Stack from '@mui/material/Stack'; +import Typography from '@mui/material/Typography'; + +const getPlanProps = (plan) => { + switch (plan.toLowerCase()) { + case 'premium': + return { + href: '/x/introduction/licensing/#premium-plan', + className: 'plan-premium', + title: 'Premium plan', + }; + case 'pro': + return { + href: '/x/introduction/licensing/#pro-plan', + className: 'plan-pro', + title: 'Pro plan', + }; + default: + return null; + } +}; + +function PlanIcon(props) { + if (!props.plan) { + return null; + } + const planProps = getPlanProps(props.plan); + if (!planProps) { + return null; + } + return ( + + + + ); +} + +PlanIcon.propTypes = { + plan: PropTypes.string, +}; + +function ComponentTag(props) { + if (!props.value) { + return null; + } + const components = props.value.split(','); + return ( + + {components.map((c, key) => ( +
+ + {c} + + +
+ ))} +
+ ); +} + +ComponentTag.propTypes = { + plan: PropTypes.string, + value: PropTypes.string, +}; + +const columns = [ + { + field: 'slot', + headerName: 'Component', + width: 240, + renderCell: (params) => ( + + ), + }, + { + field: 'defaultComponent', + headerName: 'Default Component', + width: 300, + renderCell: (params) => , + }, + { field: 'displayOrder', headerName: 'Display Order', width: 140, type: 'number' }, +]; + +const rows = [ + { + id: 1, + slot: 'ColumnMenuSortItem', + defaultComponent: 'GridColumnMenuSortItem', + displayOrder: 10, + plan: 'Community', + }, + { + id: 3, + slot: 'ColumnMenuFilterItem', + defaultComponent: 'GridColumnMenuFilterItem', + displayOrder: 20, + plan: 'Community', + }, + { + id: 7, + slot: 'ColumnMenuColumnsItem', + defaultComponent: 'GridColumnMenuColumnsItem', + displayOrder: 30, + plan: 'Community', + }, + { + id: 9, + slot: 'ColumnMenuPinningItem', + defaultComponent: 'GridColumnMenuPinningItem', + displayOrder: 15, + plan: 'Pro', + }, + { + id: 11, + slot: 'ColumnMenuAggregationItem', + defaultComponent: 'GridColumnMenuAggregationItem', + displayOrder: 23, + plan: 'Premium', + }, + { + id: 13, + slot: 'ColumnMenuGroupingItem', + defaultComponent: 'GridColumnMenuGroupingItem', + displayOrder: 27, + plan: 'Premium', + }, +]; + +export default function ColumnMenuGridReferences() { + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/column-menu/ColumnMenuGridReferences.tsx b/docs/data/data-grid/column-menu/ColumnMenuGridReferences.tsx new file mode 100644 index 000000000000..19d82cf6737c --- /dev/null +++ b/docs/data/data-grid/column-menu/ColumnMenuGridReferences.tsx @@ -0,0 +1,146 @@ +import * as React from 'react'; +import { DataGridPremium, GridRenderCellParams } from '@mui/x-data-grid-premium'; +import Stack from '@mui/material/Stack'; +import Typography from '@mui/material/Typography'; + +const getPlanProps = (plan: string) => { + switch (plan.toLowerCase()) { + case 'premium': + return { + href: '/x/introduction/licensing/#premium-plan', + className: 'plan-premium', + title: 'Premium plan', + }; + case 'pro': + return { + href: '/x/introduction/licensing/#pro-plan', + className: 'plan-pro', + title: 'Pro plan', + }; + default: + return null; + } +}; + +function PlanIcon(props: { plan?: string }) { + if (!props.plan) { + return null; + } + const planProps = getPlanProps(props.plan); + if (!planProps) { + return null; + } + return ( + + + + ); +} + +function ComponentTag(props: { value?: string; plan?: string }) { + if (!props.value) { + return null; + } + const components = props.value.split(','); + return ( + + {components.map((c, key) => ( +
+ + {c} + + +
+ ))} +
+ ); +} + +const columns = [ + { + field: 'slot', + headerName: 'Component', + width: 240, + renderCell: (params: GridRenderCellParams) => ( + + ), + }, + { + field: 'defaultComponent', + headerName: 'Default Component', + width: 300, + renderCell: (params: GridRenderCellParams) => ( + + ), + }, + { field: 'displayOrder', headerName: 'Display Order', width: 140, type: 'number' }, +]; + +const rows = [ + { + id: 1, + slot: 'ColumnMenuSortItem', + defaultComponent: 'GridColumnMenuSortItem', + displayOrder: 10, + plan: 'Community', + }, + { + id: 3, + slot: 'ColumnMenuFilterItem', + defaultComponent: 'GridColumnMenuFilterItem', + displayOrder: 20, + plan: 'Community', + }, + { + id: 7, + slot: 'ColumnMenuColumnsItem', + defaultComponent: 'GridColumnMenuColumnsItem', + displayOrder: 30, + plan: 'Community', + }, + { + id: 9, + slot: 'ColumnMenuPinningItem', + defaultComponent: 'GridColumnMenuPinningItem', + displayOrder: 15, + plan: 'Pro', + }, + { + id: 11, + slot: 'ColumnMenuAggregationItem', + defaultComponent: 'GridColumnMenuAggregationItem', + displayOrder: 23, + plan: 'Premium', + }, + { + id: 13, + slot: 'ColumnMenuGroupingItem', + defaultComponent: 'GridColumnMenuGroupingItem', + displayOrder: 27, + plan: 'Premium', + }, +]; + +export default function ColumnMenuGridReferences() { + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/column-menu/ColumnMenuGridReferences.tsx.preview b/docs/data/data-grid/column-menu/ColumnMenuGridReferences.tsx.preview new file mode 100644 index 000000000000..de54ebdeb5d5 --- /dev/null +++ b/docs/data/data-grid/column-menu/ColumnMenuGridReferences.tsx.preview @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/column-menu/CustomColumnMenuGrid.js b/docs/data/data-grid/column-menu/CustomColumnMenuGrid.js new file mode 100644 index 000000000000..8b551b1c6bd7 --- /dev/null +++ b/docs/data/data-grid/column-menu/CustomColumnMenuGrid.js @@ -0,0 +1,71 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import { + DataGrid, + GridColumnMenuFilterItem, + GridColumnMenuSortItem, + GridColumnMenuColumnsItem, +} from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; +import Stack from '@mui/material/Stack'; +import Button from '@mui/material/Button'; +import Divider from '@mui/material/Divider'; + +function MenuCloseComponent(props) { + return ( + + ); +} + +MenuCloseComponent.propTypes = { + onClick: PropTypes.func.isRequired, +}; + +function CustomColumnMenu(props) { + const itemProps = { + colDef: props.colDef, + onClick: props.hideMenu, + }; + return ( + + + + {/* Only provide filtering on desk */} + {itemProps.colDef.field === 'desk' ? ( + + ) : null} + + + + + + + + ); +} + +CustomColumnMenu.propTypes = { + colDef: PropTypes.object.isRequired, + hideMenu: PropTypes.func.isRequired, +}; + +export default function CustomColumnMenuGrid() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 20, + maxColumns: 5, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/column-menu/CustomColumnMenuGrid.tsx b/docs/data/data-grid/column-menu/CustomColumnMenuGrid.tsx new file mode 100644 index 000000000000..bb40e473f1ae --- /dev/null +++ b/docs/data/data-grid/column-menu/CustomColumnMenuGrid.tsx @@ -0,0 +1,63 @@ +import * as React from 'react'; +import { + DataGrid, + GridColumnMenuFilterItem, + GridColumnMenuSortItem, + GridColumnMenuColumnsItem, + GridColumnMenuItemProps, + GridColumnMenuProps, +} from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; +import Stack from '@mui/material/Stack'; +import Button from '@mui/material/Button'; +import Divider from '@mui/material/Divider'; + +function MenuCloseComponent(props: GridColumnMenuItemProps) { + return ( + + ); +} + +function CustomColumnMenu(props: GridColumnMenuProps) { + const itemProps = { + colDef: props.colDef, + onClick: props.hideMenu, + }; + return ( + + + + {/* Only provide filtering on desk */} + {itemProps.colDef.field === 'desk' ? ( + + ) : null} + + + + + + + + ); +} + +export default function CustomColumnMenuGrid() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 20, + maxColumns: 5, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/column-menu/CustomColumnMenuGrid.tsx.preview b/docs/data/data-grid/column-menu/CustomColumnMenuGrid.tsx.preview new file mode 100644 index 000000000000..7583bcf20a33 --- /dev/null +++ b/docs/data/data-grid/column-menu/CustomColumnMenuGrid.tsx.preview @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/column-menu/DisabledColumnMenuGrid.js b/docs/data/data-grid/column-menu/DisabledColumnMenuGrid.js new file mode 100644 index 000000000000..78e9bef9de9c --- /dev/null +++ b/docs/data/data-grid/column-menu/DisabledColumnMenuGrid.js @@ -0,0 +1,17 @@ +import * as React from 'react'; +import { DataGrid } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; + +export default function DisabledColumnMenuGrid() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 20, + maxColumns: 5, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/column-menu/DisabledColumnMenuGrid.tsx b/docs/data/data-grid/column-menu/DisabledColumnMenuGrid.tsx new file mode 100644 index 000000000000..78e9bef9de9c --- /dev/null +++ b/docs/data/data-grid/column-menu/DisabledColumnMenuGrid.tsx @@ -0,0 +1,17 @@ +import * as React from 'react'; +import { DataGrid } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; + +export default function DisabledColumnMenuGrid() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 20, + maxColumns: 5, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/column-header/ColumnMenuGrid.tsx.preview b/docs/data/data-grid/column-menu/DisabledColumnMenuGrid.tsx.preview similarity index 100% rename from docs/data/data-grid/column-header/ColumnMenuGrid.tsx.preview rename to docs/data/data-grid/column-menu/DisabledColumnMenuGrid.tsx.preview diff --git a/docs/data/data-grid/column-menu/HideColumnMenuGrid.js b/docs/data/data-grid/column-menu/HideColumnMenuGrid.js new file mode 100644 index 000000000000..01a0a856607a --- /dev/null +++ b/docs/data/data-grid/column-menu/HideColumnMenuGrid.js @@ -0,0 +1,29 @@ +import * as React from 'react'; +import { DataGrid, GridColumnMenu } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; + +function CustomColumnMenu(props) { + return ( + + ); +} + +export default function HideColumnMenuGrid() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 20, + maxColumns: 5, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/column-menu/HideColumnMenuGrid.tsx b/docs/data/data-grid/column-menu/HideColumnMenuGrid.tsx new file mode 100644 index 000000000000..6ba81e4d7338 --- /dev/null +++ b/docs/data/data-grid/column-menu/HideColumnMenuGrid.tsx @@ -0,0 +1,29 @@ +import * as React from 'react'; +import { DataGrid, GridColumnMenu, GridColumnMenuProps } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; + +function CustomColumnMenu(props: GridColumnMenuProps) { + return ( + + ); +} + +export default function HideColumnMenuGrid() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 20, + maxColumns: 5, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/column-menu/HideColumnMenuGrid.tsx.preview b/docs/data/data-grid/column-menu/HideColumnMenuGrid.tsx.preview new file mode 100644 index 000000000000..9112f9e6ce3e --- /dev/null +++ b/docs/data/data-grid/column-menu/HideColumnMenuGrid.tsx.preview @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/column-menu/OverrideColumnMenuGrid.js b/docs/data/data-grid/column-menu/OverrideColumnMenuGrid.js new file mode 100644 index 000000000000..bddbd2710da0 --- /dev/null +++ b/docs/data/data-grid/column-menu/OverrideColumnMenuGrid.js @@ -0,0 +1,60 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import MenuItem from '@mui/material/MenuItem'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import IconFilter from '@mui/icons-material/FilterAlt'; +import { DataGrid, GridColumnMenu, useGridApiContext } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; + +function CustomFilterItem(props) { + const { onClick, colDef } = props; + const apiRef = useGridApiContext(); + const handleClick = React.useCallback( + (event) => { + apiRef.current.showFilterPanel(colDef.field); + onClick(event); + }, + [apiRef, colDef.field, onClick], + ); + + return ( + + + + + Show Filters + + ); +} + +CustomFilterItem.propTypes = { + colDef: PropTypes.object.isRequired, + onClick: PropTypes.func.isRequired, +}; + +function CustomColumnMenu(props) { + return ( + + ); +} + +export default function OverrideColumnMenuGrid() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 20, + maxColumns: 5, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/column-menu/OverrideColumnMenuGrid.tsx b/docs/data/data-grid/column-menu/OverrideColumnMenuGrid.tsx new file mode 100644 index 000000000000..d89dba00880c --- /dev/null +++ b/docs/data/data-grid/column-menu/OverrideColumnMenuGrid.tsx @@ -0,0 +1,59 @@ +import * as React from 'react'; +import MenuItem from '@mui/material/MenuItem'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import IconFilter from '@mui/icons-material/FilterAlt'; +import { + DataGrid, + GridColumnMenu, + GridColumnMenuProps, + GridColumnMenuItemProps, + useGridApiContext, +} from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; + +function CustomFilterItem(props: GridColumnMenuItemProps) { + const { onClick, colDef } = props; + const apiRef = useGridApiContext(); + const handleClick = React.useCallback( + (event: React.MouseEvent) => { + apiRef.current.showFilterPanel(colDef.field); + onClick(event); + }, + [apiRef, colDef.field, onClick], + ); + return ( + + + + + Show Filters + + ); +} + +function CustomColumnMenu(props: GridColumnMenuProps) { + return ( + + ); +} + +export default function OverrideColumnMenuGrid() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 20, + maxColumns: 5, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/column-menu/OverrideColumnMenuGrid.tsx.preview b/docs/data/data-grid/column-menu/OverrideColumnMenuGrid.tsx.preview new file mode 100644 index 000000000000..9112f9e6ce3e --- /dev/null +++ b/docs/data/data-grid/column-menu/OverrideColumnMenuGrid.tsx.preview @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/column-menu/ReorderColumnMenuGrid.js b/docs/data/data-grid/column-menu/ReorderColumnMenuGrid.js new file mode 100644 index 000000000000..14267cbdb0c5 --- /dev/null +++ b/docs/data/data-grid/column-menu/ReorderColumnMenuGrid.js @@ -0,0 +1,34 @@ +import * as React from 'react'; +import { DataGrid, GridColumnMenu } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; + +function CustomColumnMenu(props) { + return ( + + ); +} + +export default function ReorderColumnMenuGrid() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 20, + maxColumns: 5, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/column-menu/ReorderColumnMenuGrid.tsx b/docs/data/data-grid/column-menu/ReorderColumnMenuGrid.tsx new file mode 100644 index 000000000000..bbcedfadc194 --- /dev/null +++ b/docs/data/data-grid/column-menu/ReorderColumnMenuGrid.tsx @@ -0,0 +1,34 @@ +import * as React from 'react'; +import { DataGrid, GridColumnMenu, GridColumnMenuProps } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; + +function CustomColumnMenu(props: GridColumnMenuProps) { + return ( + + ); +} + +export default function ReorderColumnMenuGrid() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 20, + maxColumns: 5, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/column-menu/ReorderColumnMenuGrid.tsx.preview b/docs/data/data-grid/column-menu/ReorderColumnMenuGrid.tsx.preview new file mode 100644 index 000000000000..9112f9e6ce3e --- /dev/null +++ b/docs/data/data-grid/column-menu/ReorderColumnMenuGrid.tsx.preview @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/column-menu/column-menu.md b/docs/data/data-grid/column-menu/column-menu.md new file mode 100644 index 000000000000..1a9b2ed338f9 --- /dev/null +++ b/docs/data/data-grid/column-menu/column-menu.md @@ -0,0 +1,161 @@ +--- +title: Data Grid - Column menu +--- + +# Data grid - Column menu + +

Customize your columns menu.

+ +## Column menu + +Each column header comes with a column menu with quickly accessible grid features like column visibility, sorting, filtering, and others. + +It can be accessed by clicking on the 3-dots icon that appears on hover on a header cell or when focusing on a column header and pressing Ctrl+Enter (or ⌘ Command+Enter on macOS). + +{{"demo": "ColumnMenuGrid.js", "bg": "inline"}} + +## Customize column menu items + +You can customize the column menu items by passing the `components` and `componentsProps` props to the `` component: + +- `components` - use this prop to override default column menu components or add new components. +- `componentsProps` - use this prop to override or pass [`displayOrder`](/x/react-data-grid/column-menu/#reordering-menu-items) for column menu items. You can also use this to pass extra props to custom column menu components. + +:::warning +The `components` prop uses pascal case (`ColumnMenuFilterItem`), while `componentsProps` uses camel case (`columnMenuFilterItem`). +::: + +### Adding a menu item + +To add a new menu item, create a new item slot and pass it to the `components` prop. In the example below, the new slot is called `ColumnMenuUserItem` but you can choose any name and it'll be added to the menu automatically. +You can also set the `displayOrder` (default `100`) or pass new props to the components using `componentsProps` prop. + +```tsx +function CustomColumnMenu(props: GridColumnMenuProps) { + return ( + alert('Custom handler fired'), + }, + }} + /> + ); +} +``` + +{{"demo": "AddNewColumnMenuGrid.js", "bg": "inline"}} + +### Overriding default menu items + +Use the `components` prop to override default menu items. +Check [this table](/x/react-data-grid/column-menu/#default-column-menu-items) to know the overridable slot name for each menu item. + +```tsx +function CustomColumnMenu(props: GridColumnMenuProps) { + return ( + + ); +} +``` + +{{"demo": "OverrideColumnMenuGrid.js", "bg": "inline"}} + +### Hiding a menu item + +To hide a menu item, you can set its respective slot in `components` to `null`. +Check [this table](/x/react-data-grid/column-menu/#default-column-menu-items) to know the slot name for each menu item. + +```tsx +function CustomColumnMenu(props: GridColumnMenuProps) { + return ( + + ); +} +``` + +{{"demo": "HideColumnMenuGrid.js", "bg": "inline"}} + +### Reordering menu items + +Every item is assigned a `displayOrder` based on which it is shown before or after other items. It works in ascending order; the smaller the number is, the earlier it is displayed on the list. For new items default value for `displayOrder` is **100**. + +You can override `displayOrder` for the default or new items in `componentsProps`. + +Check [this table](/x/react-data-grid/column-menu/#default-column-menu-items) to see default `displayOrder` for each menu item. + +```tsx +function CustomColumnMenu(props: GridColumnMenuProps) { + return ( + + ); +} +``` + +{{"demo": "ReorderColumnMenuGrid.js", "bg": "inline"}} + +### Default column menu items + +As a reference, here are the column menu `components` along with the default item components and `displayOrder`. + +{{"demo": "ColumnMenuGridReferences.js", "bg": "inline", "hideToolbar": true}} + +## Custom menu component + +You can also customize and replace the column menu by [passing a fully custom component](/x/react-data-grid/components/#overriding-components) to the `ColumnMenu` slot of the Data Grid. If you want to add some of the default menu items to your custom component, you can import and re-use them. + +{{"demo": "CustomColumnMenuGrid.js", "bg": "inline"}} + +:::info +Tip: The `ColumnMenu` component and its components slots receive the `colDef` prop corresponding to the current column; you can use this to conditionally render some items or change some logic. +::: + +## Disable column menu + +By default, each column header has the column menu enabled. To disable the column menu, set the prop `disableColumnMenu={true}`. + +{{"demo": "DisabledColumnMenuGrid.js", "bg": "inline"}} + +## Column menu with Pro/Premium features [](/x/introduction/licensing/#pro-plan)[](/x/introduction/licensing/#premium-plan) + +In the following demo, in addition to data grid MIT features, you can see commercial features like [grouping](/x/react-data-grid/row-grouping/), and [aggregation](/x/react-data-grid/aggregation/) in action. Try tweaking the values from respective column menu items. + +{{"demo": "ColumnMenuGridPremium.js", "bg": "inline"}} + +## API + +- [DataGrid](/x/api/data-grid/data-grid/) +- [DataGridPro](/x/api/data-grid/data-grid-pro/) +- [DataGridPremium](/x/api/data-grid/data-grid-premium/) diff --git a/docs/data/data-grid/column-pinning/DisableColumnPinningButtons.js b/docs/data/data-grid/column-pinning/DisableColumnPinningButtons.js index 0141adb23a4a..487426855e09 100644 --- a/docs/data/data-grid/column-pinning/DisableColumnPinningButtons.js +++ b/docs/data/data-grid/column-pinning/DisableColumnPinningButtons.js @@ -3,10 +3,10 @@ import PropTypes from 'prop-types'; import { DataGridPro, GridColumnMenuContainer, - SortGridMenuItems, - HideGridColMenuItem, - GridColumnsMenuItem, - GridFilterMenuItem, + GridColumnMenuSortItem, + GridColumnMenuHideItem, + GridColumnMenuColumnsItem, + GridColumnMenuFilterItem, } from '@mui/x-data-grid-pro'; import { randomCreatedDate, @@ -16,25 +16,21 @@ import { } from '@mui/x-data-grid-generator'; function CustomColumnMenu(props) { - const { hideMenu, currentColumn, color, ...other } = props; + const { hideMenu, colDef, color, ...other } = props; return ( - - - - - + + + + + ); } CustomColumnMenu.propTypes = { + colDef: PropTypes.object.isRequired, color: PropTypes.string, - currentColumn: PropTypes.object.isRequired, hideMenu: PropTypes.func.isRequired, }; diff --git a/docs/data/data-grid/column-pinning/DisableColumnPinningButtons.tsx b/docs/data/data-grid/column-pinning/DisableColumnPinningButtons.tsx index 91c656fab06a..de712645e63b 100644 --- a/docs/data/data-grid/column-pinning/DisableColumnPinningButtons.tsx +++ b/docs/data/data-grid/column-pinning/DisableColumnPinningButtons.tsx @@ -4,10 +4,10 @@ import { GridColumns, GridRowsProp, GridColumnMenuContainer, - SortGridMenuItems, - HideGridColMenuItem, - GridColumnsMenuItem, - GridFilterMenuItem, + GridColumnMenuSortItem, + GridColumnMenuHideItem, + GridColumnMenuColumnsItem, + GridColumnMenuFilterItem, GridColumnMenuProps, } from '@mui/x-data-grid-pro'; import { @@ -18,18 +18,14 @@ import { } from '@mui/x-data-grid-generator'; export function CustomColumnMenu(props: GridColumnMenuProps) { - const { hideMenu, currentColumn, color, ...other } = props; + const { hideMenu, colDef, color, ...other } = props; return ( - - - - - + + + + + ); } diff --git a/docs/data/data-grid/components/CustomColumnMenu.js b/docs/data/data-grid/components/CustomColumnMenu.js index 37ebd7d1fa90..fa757b3d25a3 100644 --- a/docs/data/data-grid/components/CustomColumnMenu.js +++ b/docs/data/data-grid/components/CustomColumnMenu.js @@ -6,8 +6,8 @@ import Button from '@mui/material/Button'; import { GridColumnMenu, GridColumnMenuContainer, - GridFilterMenuItem, - SortGridMenuItems, + GridColumnMenuFilterItem, + GridColumnMenuSortItem, useGridApiRef, DataGridPro, } from '@mui/x-data-grid-pro'; @@ -16,36 +16,34 @@ import StarOutlineIcon from '@mui/icons-material/StarOutline'; const StyledGridColumnMenuContainer = styled(GridColumnMenuContainer)( ({ theme, ownerState }) => ({ background: theme.palette[ownerState.color].main, - color: theme.palette[ownerState.color].contrastText, }), ); const StyledGridColumnMenu = styled(GridColumnMenu)(({ theme, ownerState }) => ({ background: theme.palette[ownerState.color].main, - color: theme.palette[ownerState.color].contrastText, })); function CustomColumnMenuComponent(props) { - const { hideMenu, currentColumn, color, ...other } = props; + const { hideMenu, colDef, color, ...other } = props; - if (currentColumn.field === 'name') { + if (colDef.field === 'name') { return ( - - + + ); } - if (currentColumn.field === 'stars') { + if (colDef.field === 'stars') { return ( @@ -67,7 +65,7 @@ function CustomColumnMenuComponent(props) { return ( @@ -75,8 +73,8 @@ function CustomColumnMenuComponent(props) { } CustomColumnMenuComponent.propTypes = { + colDef: PropTypes.object.isRequired, color: PropTypes.oneOf(['primary', 'secondary']).isRequired, - currentColumn: PropTypes.object.isRequired, hideMenu: PropTypes.func.isRequired, }; diff --git a/docs/data/data-grid/components/CustomColumnMenu.tsx b/docs/data/data-grid/components/CustomColumnMenu.tsx index f63eced58617..7f807d2cdaec 100644 --- a/docs/data/data-grid/components/CustomColumnMenu.tsx +++ b/docs/data/data-grid/components/CustomColumnMenu.tsx @@ -6,8 +6,8 @@ import { GridColumnMenu, GridColumnMenuContainer, GridColumnMenuProps, - GridFilterMenuItem, - SortGridMenuItems, + GridColumnMenuFilterItem, + GridColumnMenuSortItem, useGridApiRef, DataGridPro, } from '@mui/x-data-grid-pro'; @@ -22,37 +22,35 @@ const StyledGridColumnMenuContainer = styled(GridColumnMenuContainer)<{ ownerState: OwnerState; }>(({ theme, ownerState }: { theme: Theme; ownerState: OwnerState }) => ({ background: theme.palette[ownerState.color].main, - color: theme.palette[ownerState.color].contrastText, })); const StyledGridColumnMenu = styled(GridColumnMenu)<{ ownerState: OwnerState; }>(({ theme, ownerState }: { theme: Theme; ownerState: OwnerState }) => ({ background: theme.palette[ownerState.color].main, - color: theme.palette[ownerState.color].contrastText, })); export function CustomColumnMenuComponent(props: GridColumnMenuProps & OwnerState) { - const { hideMenu, currentColumn, color, ...other } = props; + const { hideMenu, colDef, color, ...other } = props; - if (currentColumn.field === 'name') { + if (colDef.field === 'name') { return ( - - + + ); } - if (currentColumn.field === 'stars') { + if (colDef.field === 'stars') { return ( @@ -74,7 +72,7 @@ export function CustomColumnMenuComponent(props: GridColumnMenuProps & OwnerStat return ( diff --git a/docs/data/data-grid/components/components.md b/docs/data/data-grid/components/components.md index a0fb1adbac15..70a3e904d83c 100644 --- a/docs/data/data-grid/components/components.md +++ b/docs/data/data-grid/components/components.md @@ -71,14 +71,13 @@ export const GridColumnMenu = React.forwardRef< HTMLUListElement, GridColumnMenuProps >(function GridColumnMenu(props: GridColumnMenuProps, ref) { - const { hideMenu, currentColumn } = props; + const { hideMenu, colDef } = props; return ( - - - - + + + ); }); diff --git a/docs/data/data-grid/localization/data.json b/docs/data/data-grid/localization/data.json index a65fbcc5c9aa..ff42f2e3d390 100644 --- a/docs/data/data-grid/localization/data.json +++ b/docs/data/data-grid/localization/data.json @@ -3,224 +3,224 @@ "languageTag": "ar-SD", "importName": "arSD", "localeName": "Arabic (Sudan)", - "missingKeysCount": 13, - "totalKeysCount": 93, + "missingKeysCount": 14, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/arSD.ts/" }, { "languageTag": "bg-BG", "importName": "bgBG", "localeName": "Bulgarian", - "missingKeysCount": 13, - "totalKeysCount": 93, + "missingKeysCount": 14, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/bgBG.ts/" }, { "languageTag": "zh-CN", "importName": "zhCN", "localeName": "Chinese (Simplified)", - "missingKeysCount": 0, - "totalKeysCount": 93, + "missingKeysCount": 1, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/zhCN.ts/" }, { "languageTag": "zh-TW", "importName": "zhTW", "localeName": "Chinese (Taiwan)", - "missingKeysCount": 6, - "totalKeysCount": 93, + "missingKeysCount": 7, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/zhTW.ts/" }, { "languageTag": "cs-CZ", "importName": "csCZ", "localeName": "Czech", - "missingKeysCount": 20, - "totalKeysCount": 93, + "missingKeysCount": 21, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/csCZ.ts/" }, { "languageTag": "da-DK", "importName": "daDK", "localeName": "Danish", - "missingKeysCount": 13, - "totalKeysCount": 93, + "missingKeysCount": 14, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/daDK.ts/" }, { "languageTag": "nl-NL", "importName": "nlNL", "localeName": "Dutch", - "missingKeysCount": 7, - "totalKeysCount": 93, + "missingKeysCount": 8, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/nlNL.ts/" }, { "languageTag": "fi-FI", "importName": "fiFI", "localeName": "Finnish", - "missingKeysCount": 0, - "totalKeysCount": 93, + "missingKeysCount": 1, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/fiFI.ts/" }, { "languageTag": "fr-FR", "importName": "frFR", "localeName": "French", - "missingKeysCount": 6, - "totalKeysCount": 93, + "missingKeysCount": 7, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/frFR.ts/" }, { "languageTag": "de-DE", "importName": "deDE", "localeName": "German", - "missingKeysCount": 0, - "totalKeysCount": 93, + "missingKeysCount": 1, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/deDE.ts/" }, { "languageTag": "el-GR", "importName": "elGR", "localeName": "Greek", - "missingKeysCount": 36, - "totalKeysCount": 93, + "missingKeysCount": 37, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/elGR.ts/" }, { "languageTag": "he-IL", "importName": "heIL", "localeName": "Hebrew", - "missingKeysCount": 7, - "totalKeysCount": 93, + "missingKeysCount": 9, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/heIL.ts/" }, { "languageTag": "hu-HU", "importName": "huHU", "localeName": "Hungarian", - "missingKeysCount": 12, - "totalKeysCount": 93, + "missingKeysCount": 13, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/huHU.ts/" }, { "languageTag": "it-IT", "importName": "itIT", "localeName": "Italian", - "missingKeysCount": 6, - "totalKeysCount": 93, + "missingKeysCount": 7, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/itIT.ts/" }, { "languageTag": "ja-JP", "importName": "jaJP", "localeName": "Japanese", - "missingKeysCount": 12, - "totalKeysCount": 93, + "missingKeysCount": 13, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/jaJP.ts/" }, { "languageTag": "ko-KR", "importName": "koKR", "localeName": "Korean", - "missingKeysCount": 0, - "totalKeysCount": 93, + "missingKeysCount": 1, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/koKR.ts/" }, { "languageTag": "nb-NO", "importName": "nbNO", "localeName": "Norwegian (bokmål)", - "missingKeysCount": 7, - "totalKeysCount": 93, + "missingKeysCount": 8, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/nbNO.ts/" }, { "languageTag": "fa-IR", "importName": "faIR", "localeName": "Persian", - "missingKeysCount": 0, - "totalKeysCount": 93, + "missingKeysCount": 1, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/faIR.ts/" }, { "languageTag": "pl-PL", "importName": "plPL", "localeName": "Polish", - "missingKeysCount": 7, - "totalKeysCount": 93, + "missingKeysCount": 8, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/plPL.ts/" }, { "languageTag": "pt-BR", "importName": "ptBR", "localeName": "Portuguese (Brazil)", - "missingKeysCount": 6, - "totalKeysCount": 93, + "missingKeysCount": 7, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/ptBR.ts/" }, { "languageTag": "ro-RO", "importName": "roRO", "localeName": "Romanian", - "missingKeysCount": 6, - "totalKeysCount": 93, + "missingKeysCount": 7, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/roRO.ts/" }, { "languageTag": "ru-RU", "importName": "ruRU", "localeName": "Russian", - "missingKeysCount": 0, - "totalKeysCount": 93, + "missingKeysCount": 1, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/ruRU.ts/" }, { "languageTag": "sk-SK", "importName": "skSK", "localeName": "Slovak", - "missingKeysCount": 6, - "totalKeysCount": 93, + "missingKeysCount": 7, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/skSK.ts/" }, { "languageTag": "es-ES", "importName": "esES", "localeName": "Spanish", - "missingKeysCount": 37, - "totalKeysCount": 93, + "missingKeysCount": 38, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/esES.ts/" }, { "languageTag": "sv-SE", "importName": "svSE", "localeName": "Swedish", - "missingKeysCount": 7, - "totalKeysCount": 93, + "missingKeysCount": 8, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/svSE.ts/" }, { "languageTag": "tr-TR", "importName": "trTR", "localeName": "Turkish", - "missingKeysCount": 0, - "totalKeysCount": 93, + "missingKeysCount": 1, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/trTR.ts/" }, { "languageTag": "uk-UA", "importName": "ukUA", "localeName": "Ukrainian", - "missingKeysCount": 5, - "totalKeysCount": 93, + "missingKeysCount": 6, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/ukUA.ts/" }, { "languageTag": "vi-VN", "importName": "viVN", "localeName": "Vietnamese", - "missingKeysCount": 23, - "totalKeysCount": 93, + "missingKeysCount": 24, + "totalKeysCount": 94, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/grid/x-data-grid/src/locales/viVN.ts/" } ] diff --git a/docs/data/migration/migration-data-grid-v5/migration-data-grid-v5.md b/docs/data/migration/migration-data-grid-v5/migration-data-grid-v5.md index aec2c8be0606..9630d4ac763b 100644 --- a/docs/data/migration/migration-data-grid-v5/migration-data-grid-v5.md +++ b/docs/data/migration/migration-data-grid-v5/migration-data-grid-v5.md @@ -85,6 +85,23 @@ The minimum supported Node.js version has been changed from 12.0.0 to 14.0.0, si } ``` +### Column menu + +- The column menu components have been renamed or merged with the new design for consistency and API improvement, the new components are following: + + | Old name | New name | + | ------------------------------------------------------------------- | ------------------------------- | + | `GridFilterMenuItem` | `GridColumnMenuFilterItem` | + | `HideGridColMenuItem` | `GridColumnMenuHideItem` | + | `GridColumnsMenuItem` | `GridColumnMenuColumnsItem` | + | `SortGridMenuItems` | `GridColumnMenuSortItem` | + | `GridColumnPinningMenuItems` | `GridColumnMenuPinningItem` | + | `GridAggregationColumnMenuItem` | `GridColumnMenuAggregationItem` | + | `GridRowGroupingColumnMenuItems`, `GridRowGroupableColumnMenuItems` | `GridColumnMenuGroupingItem` | + +- `GridFilterItemProps` has been renamed to `GridColumnMenuItemProps`. +- Props `column` and `currentColumn` passed to `GridColumnMenu` and column menu items have been renamed to `colDef` + ### Rows - The `GridRowParams['getValue']` property was removed. Use `params.row` instead. @@ -161,6 +178,7 @@ The minimum supported Node.js version has been changed from 12.0.0 to 14.0.0, si - The `GridRowData` type was removed. Use `GridRowModel` instead. - The `filterPanelOperators` translation key was renamed to `filterPanelOperator` - The `MAX_PAGE_SIZE` constant was removed. +- The `DATA_GRID_DEFAULT_SLOTS_COMPONENTS` export was removed. - The `useGridScrollFn` hook was removed. ### CSS classes diff --git a/docs/data/pages.ts b/docs/data/pages.ts index 3fdcfea2225f..032f86e681bb 100644 --- a/docs/data/pages.ts +++ b/docs/data/pages.ts @@ -31,6 +31,7 @@ const pages: MuiPage[] = [ { pathname: '/x/react-data-grid/column-dimensions' }, { pathname: '/x/react-data-grid/column-visibility' }, { pathname: '/x/react-data-grid/column-header' }, + { pathname: '/x/react-data-grid/column-menu' }, { pathname: '/x/react-data-grid/column-ordering', plan: 'pro' }, { pathname: '/x/react-data-grid/column-pinning', plan: 'pro' }, { pathname: '/x/react-data-grid/column-spanning' }, diff --git a/docs/pages/x/api/data-grid/data-grid-premium.json b/docs/pages/x/api/data-grid/data-grid-premium.json index 846e69196e48..fce29d19a312 100644 --- a/docs/pages/x/api/data-grid/data-grid-premium.json +++ b/docs/pages/x/api/data-grid/data-grid-premium.json @@ -270,10 +270,39 @@ "type": { "name": "elementType" } }, "ColumnMenu": { "default": "GridColumnMenu", "type": { "name": "elementType" } }, + "ColumnMenuAggregationIcon": { + "default": "GridFunctionsIcon", + "type": { "name": "elementType" } + }, + "ColumnMenuClearIcon": { "default": "GridClearIcon", "type": { "name": "elementType" } }, + "ColumnMenuFilterIcon": { "default": "GridFilterAltIcon", "type": { "name": "elementType" } }, + "ColumnMenuGroupIcon": { "default": "GridGroupWorkIcon", "type": { "name": "elementType" } }, + "ColumnMenuHideIcon": { "default": "GridVisibilityOffIcon", "type": { "name": "elementType" } }, "ColumnMenuIcon": { "default": "GridTripleDotsVerticalIcon", "type": { "name": "elementType" } }, + "ColumnMenuManageColumnsIcon": { + "default": "GridViewColumnIcon", + "type": { "name": "elementType" } + }, + "ColumnMenuPinLeftIcon": { + "default": "GridPushPinLeftIcon", + "type": { "name": "elementType" } + }, + "ColumnMenuPinRightIcon": { + "default": "GridPushPinRightIcon", + "type": { "name": "elementType" } + }, + "ColumnMenuSortAscendingIcon": { + "default": "GridArrowUpwardIcon", + "type": { "name": "elementType" } + }, + "ColumnMenuSortDescendingIcon": { + "default": "GridArrowDownwardIcon", + "type": { "name": "elementType" } + }, + "ColumnMenuUngroupIcon": { "default": "GridWorkspacesIcon", "type": { "name": "elementType" } }, "ColumnResizeIcon": { "default": "GridSeparatorIcon", "type": { "name": "elementType" } }, "ColumnSelectorIcon": { "default": "GridColumnIcon", "type": { "name": "elementType" } }, "ColumnSortedAscendingIcon": { diff --git a/docs/pages/x/api/data-grid/data-grid-pro.json b/docs/pages/x/api/data-grid/data-grid-pro.json index ea9b14600801..4456b18b40a2 100644 --- a/docs/pages/x/api/data-grid/data-grid-pro.json +++ b/docs/pages/x/api/data-grid/data-grid-pro.json @@ -245,10 +245,33 @@ "type": { "name": "elementType" } }, "ColumnMenu": { "default": "GridColumnMenu", "type": { "name": "elementType" } }, + "ColumnMenuClearIcon": { "default": "GridClearIcon", "type": { "name": "elementType" } }, + "ColumnMenuFilterIcon": { "default": "GridFilterAltIcon", "type": { "name": "elementType" } }, + "ColumnMenuHideIcon": { "default": "GridVisibilityOffIcon", "type": { "name": "elementType" } }, "ColumnMenuIcon": { "default": "GridTripleDotsVerticalIcon", "type": { "name": "elementType" } }, + "ColumnMenuManageColumnsIcon": { + "default": "GridViewColumnIcon", + "type": { "name": "elementType" } + }, + "ColumnMenuPinLeftIcon": { + "default": "GridPushPinLeftIcon", + "type": { "name": "elementType" } + }, + "ColumnMenuPinRightIcon": { + "default": "GridPushPinRightIcon", + "type": { "name": "elementType" } + }, + "ColumnMenuSortAscendingIcon": { + "default": "GridArrowUpwardIcon", + "type": { "name": "elementType" } + }, + "ColumnMenuSortDescendingIcon": { + "default": "GridArrowDownwardIcon", + "type": { "name": "elementType" } + }, "ColumnResizeIcon": { "default": "GridSeparatorIcon", "type": { "name": "elementType" } }, "ColumnSelectorIcon": { "default": "GridColumnIcon", "type": { "name": "elementType" } }, "ColumnSortedAscendingIcon": { diff --git a/docs/pages/x/api/data-grid/data-grid.json b/docs/pages/x/api/data-grid/data-grid.json index 51e059bf916a..73f2ddede161 100644 --- a/docs/pages/x/api/data-grid/data-grid.json +++ b/docs/pages/x/api/data-grid/data-grid.json @@ -190,10 +190,25 @@ "type": { "name": "elementType" } }, "ColumnMenu": { "default": "GridColumnMenu", "type": { "name": "elementType" } }, + "ColumnMenuClearIcon": { "default": "GridClearIcon", "type": { "name": "elementType" } }, + "ColumnMenuFilterIcon": { "default": "GridFilterAltIcon", "type": { "name": "elementType" } }, + "ColumnMenuHideIcon": { "default": "GridVisibilityOffIcon", "type": { "name": "elementType" } }, "ColumnMenuIcon": { "default": "GridTripleDotsVerticalIcon", "type": { "name": "elementType" } }, + "ColumnMenuManageColumnsIcon": { + "default": "GridViewColumnIcon", + "type": { "name": "elementType" } + }, + "ColumnMenuSortAscendingIcon": { + "default": "GridArrowUpwardIcon", + "type": { "name": "elementType" } + }, + "ColumnMenuSortDescendingIcon": { + "default": "GridArrowDownwardIcon", + "type": { "name": "elementType" } + }, "ColumnResizeIcon": { "default": "GridSeparatorIcon", "type": { "name": "elementType" } }, "ColumnSelectorIcon": { "default": "GridColumnIcon", "type": { "name": "elementType" } }, "ColumnSortedAscendingIcon": { diff --git a/docs/pages/x/react-data-grid/column-menu.js b/docs/pages/x/react-data-grid/column-menu.js new file mode 100644 index 000000000000..293f6c798aca --- /dev/null +++ b/docs/pages/x/react-data-grid/column-menu.js @@ -0,0 +1,7 @@ +import * as React from 'react'; +import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; +import * as pageProps from 'docsx/data/data-grid/column-menu/column-menu.md?@mui/markdown'; + +export default function Page() { + return ; +} diff --git a/docs/translations/api-docs/data-grid/data-grid-premium-pt.json b/docs/translations/api-docs/data-grid/data-grid-premium-pt.json index 159c0a2172fa..61b54bb4ace2 100644 --- a/docs/translations/api-docs/data-grid/data-grid-premium-pt.json +++ b/docs/translations/api-docs/data-grid/data-grid-premium-pt.json @@ -741,6 +741,17 @@ "FilterPanelDeleteIcon": "Icon displayed for deleting the filter from filter Panel.", "RowReorderIcon": "Icon displayed on the reorder column type to reorder a row.", "QuickFilterIcon": "Icon displayed on the quick filter input.", - "QuickFilterClearIcon": "Icon displayed on the quick filter reset input." + "QuickFilterClearIcon": "Icon displayed on the quick filter reset input.", + "ColumnMenuHideIcon": "Icon displayed in column menu for hiding column", + "ColumnMenuSortAscendingIcon": "Icon displayed in column menu for ascending sort", + "ColumnMenuSortDescendingIcon": "Icon displayed in column menu for descending sort", + "ColumnMenuFilterIcon": "Icon displayed in column menu for filter", + "ColumnMenuManageColumnsIcon": "Icon displayed in column menu for showing all columns", + "ColumnMenuClearIcon": "Icon displayed in column menu for clearing values", + "ColumnMenuPinLeftIcon": "Icon displayed in column menu for left pinning", + "ColumnMenuPinRightIcon": "Icon displayed in column menu for right pinning", + "ColumnMenuUngroupIcon": "Icon displayed in column menu for ungrouping", + "ColumnMenuGroupIcon": "Icon displayed in column menu for grouping", + "ColumnMenuAggregationIcon": "Icon displayed in column menu for aggregation" } } diff --git a/docs/translations/api-docs/data-grid/data-grid-premium-zh.json b/docs/translations/api-docs/data-grid/data-grid-premium-zh.json index 159c0a2172fa..61b54bb4ace2 100644 --- a/docs/translations/api-docs/data-grid/data-grid-premium-zh.json +++ b/docs/translations/api-docs/data-grid/data-grid-premium-zh.json @@ -741,6 +741,17 @@ "FilterPanelDeleteIcon": "Icon displayed for deleting the filter from filter Panel.", "RowReorderIcon": "Icon displayed on the reorder column type to reorder a row.", "QuickFilterIcon": "Icon displayed on the quick filter input.", - "QuickFilterClearIcon": "Icon displayed on the quick filter reset input." + "QuickFilterClearIcon": "Icon displayed on the quick filter reset input.", + "ColumnMenuHideIcon": "Icon displayed in column menu for hiding column", + "ColumnMenuSortAscendingIcon": "Icon displayed in column menu for ascending sort", + "ColumnMenuSortDescendingIcon": "Icon displayed in column menu for descending sort", + "ColumnMenuFilterIcon": "Icon displayed in column menu for filter", + "ColumnMenuManageColumnsIcon": "Icon displayed in column menu for showing all columns", + "ColumnMenuClearIcon": "Icon displayed in column menu for clearing values", + "ColumnMenuPinLeftIcon": "Icon displayed in column menu for left pinning", + "ColumnMenuPinRightIcon": "Icon displayed in column menu for right pinning", + "ColumnMenuUngroupIcon": "Icon displayed in column menu for ungrouping", + "ColumnMenuGroupIcon": "Icon displayed in column menu for grouping", + "ColumnMenuAggregationIcon": "Icon displayed in column menu for aggregation" } } diff --git a/docs/translations/api-docs/data-grid/data-grid-premium.json b/docs/translations/api-docs/data-grid/data-grid-premium.json index 159c0a2172fa..61b54bb4ace2 100644 --- a/docs/translations/api-docs/data-grid/data-grid-premium.json +++ b/docs/translations/api-docs/data-grid/data-grid-premium.json @@ -741,6 +741,17 @@ "FilterPanelDeleteIcon": "Icon displayed for deleting the filter from filter Panel.", "RowReorderIcon": "Icon displayed on the reorder column type to reorder a row.", "QuickFilterIcon": "Icon displayed on the quick filter input.", - "QuickFilterClearIcon": "Icon displayed on the quick filter reset input." + "QuickFilterClearIcon": "Icon displayed on the quick filter reset input.", + "ColumnMenuHideIcon": "Icon displayed in column menu for hiding column", + "ColumnMenuSortAscendingIcon": "Icon displayed in column menu for ascending sort", + "ColumnMenuSortDescendingIcon": "Icon displayed in column menu for descending sort", + "ColumnMenuFilterIcon": "Icon displayed in column menu for filter", + "ColumnMenuManageColumnsIcon": "Icon displayed in column menu for showing all columns", + "ColumnMenuClearIcon": "Icon displayed in column menu for clearing values", + "ColumnMenuPinLeftIcon": "Icon displayed in column menu for left pinning", + "ColumnMenuPinRightIcon": "Icon displayed in column menu for right pinning", + "ColumnMenuUngroupIcon": "Icon displayed in column menu for ungrouping", + "ColumnMenuGroupIcon": "Icon displayed in column menu for grouping", + "ColumnMenuAggregationIcon": "Icon displayed in column menu for aggregation" } } diff --git a/docs/translations/api-docs/data-grid/data-grid-pro-pt.json b/docs/translations/api-docs/data-grid/data-grid-pro-pt.json index 301c93f8e510..162e09a2efee 100644 --- a/docs/translations/api-docs/data-grid/data-grid-pro-pt.json +++ b/docs/translations/api-docs/data-grid/data-grid-pro-pt.json @@ -728,6 +728,14 @@ "FilterPanelDeleteIcon": "Icon displayed for deleting the filter from filter Panel.", "RowReorderIcon": "Icon displayed on the reorder column type to reorder a row.", "QuickFilterIcon": "Icon displayed on the quick filter input.", - "QuickFilterClearIcon": "Icon displayed on the quick filter reset input." + "QuickFilterClearIcon": "Icon displayed on the quick filter reset input.", + "ColumnMenuHideIcon": "Icon displayed in column menu for hiding column", + "ColumnMenuSortAscendingIcon": "Icon displayed in column menu for ascending sort", + "ColumnMenuSortDescendingIcon": "Icon displayed in column menu for descending sort", + "ColumnMenuFilterIcon": "Icon displayed in column menu for filter", + "ColumnMenuManageColumnsIcon": "Icon displayed in column menu for showing all columns", + "ColumnMenuClearIcon": "Icon displayed in column menu for clearing values", + "ColumnMenuPinLeftIcon": "Icon displayed in column menu for left pinning", + "ColumnMenuPinRightIcon": "Icon displayed in column menu for right pinning" } } diff --git a/docs/translations/api-docs/data-grid/data-grid-pro-zh.json b/docs/translations/api-docs/data-grid/data-grid-pro-zh.json index 301c93f8e510..162e09a2efee 100644 --- a/docs/translations/api-docs/data-grid/data-grid-pro-zh.json +++ b/docs/translations/api-docs/data-grid/data-grid-pro-zh.json @@ -728,6 +728,14 @@ "FilterPanelDeleteIcon": "Icon displayed for deleting the filter from filter Panel.", "RowReorderIcon": "Icon displayed on the reorder column type to reorder a row.", "QuickFilterIcon": "Icon displayed on the quick filter input.", - "QuickFilterClearIcon": "Icon displayed on the quick filter reset input." + "QuickFilterClearIcon": "Icon displayed on the quick filter reset input.", + "ColumnMenuHideIcon": "Icon displayed in column menu for hiding column", + "ColumnMenuSortAscendingIcon": "Icon displayed in column menu for ascending sort", + "ColumnMenuSortDescendingIcon": "Icon displayed in column menu for descending sort", + "ColumnMenuFilterIcon": "Icon displayed in column menu for filter", + "ColumnMenuManageColumnsIcon": "Icon displayed in column menu for showing all columns", + "ColumnMenuClearIcon": "Icon displayed in column menu for clearing values", + "ColumnMenuPinLeftIcon": "Icon displayed in column menu for left pinning", + "ColumnMenuPinRightIcon": "Icon displayed in column menu for right pinning" } } diff --git a/docs/translations/api-docs/data-grid/data-grid-pro.json b/docs/translations/api-docs/data-grid/data-grid-pro.json index 301c93f8e510..162e09a2efee 100644 --- a/docs/translations/api-docs/data-grid/data-grid-pro.json +++ b/docs/translations/api-docs/data-grid/data-grid-pro.json @@ -728,6 +728,14 @@ "FilterPanelDeleteIcon": "Icon displayed for deleting the filter from filter Panel.", "RowReorderIcon": "Icon displayed on the reorder column type to reorder a row.", "QuickFilterIcon": "Icon displayed on the quick filter input.", - "QuickFilterClearIcon": "Icon displayed on the quick filter reset input." + "QuickFilterClearIcon": "Icon displayed on the quick filter reset input.", + "ColumnMenuHideIcon": "Icon displayed in column menu for hiding column", + "ColumnMenuSortAscendingIcon": "Icon displayed in column menu for ascending sort", + "ColumnMenuSortDescendingIcon": "Icon displayed in column menu for descending sort", + "ColumnMenuFilterIcon": "Icon displayed in column menu for filter", + "ColumnMenuManageColumnsIcon": "Icon displayed in column menu for showing all columns", + "ColumnMenuClearIcon": "Icon displayed in column menu for clearing values", + "ColumnMenuPinLeftIcon": "Icon displayed in column menu for left pinning", + "ColumnMenuPinRightIcon": "Icon displayed in column menu for right pinning" } } diff --git a/docs/translations/api-docs/data-grid/data-grid-pt.json b/docs/translations/api-docs/data-grid/data-grid-pt.json index 97d2b21fb03f..58dd715f23ec 100644 --- a/docs/translations/api-docs/data-grid/data-grid-pt.json +++ b/docs/translations/api-docs/data-grid/data-grid-pt.json @@ -696,6 +696,12 @@ "FilterPanelDeleteIcon": "Icon displayed for deleting the filter from filter Panel.", "RowReorderIcon": "Icon displayed on the reorder column type to reorder a row.", "QuickFilterIcon": "Icon displayed on the quick filter input.", - "QuickFilterClearIcon": "Icon displayed on the quick filter reset input." + "QuickFilterClearIcon": "Icon displayed on the quick filter reset input.", + "ColumnMenuHideIcon": "Icon displayed in column menu for hiding column", + "ColumnMenuSortAscendingIcon": "Icon displayed in column menu for ascending sort", + "ColumnMenuSortDescendingIcon": "Icon displayed in column menu for descending sort", + "ColumnMenuFilterIcon": "Icon displayed in column menu for filter", + "ColumnMenuManageColumnsIcon": "Icon displayed in column menu for showing all columns", + "ColumnMenuClearIcon": "Icon displayed in column menu for clearing values" } } diff --git a/docs/translations/api-docs/data-grid/data-grid-zh.json b/docs/translations/api-docs/data-grid/data-grid-zh.json index 97d2b21fb03f..58dd715f23ec 100644 --- a/docs/translations/api-docs/data-grid/data-grid-zh.json +++ b/docs/translations/api-docs/data-grid/data-grid-zh.json @@ -696,6 +696,12 @@ "FilterPanelDeleteIcon": "Icon displayed for deleting the filter from filter Panel.", "RowReorderIcon": "Icon displayed on the reorder column type to reorder a row.", "QuickFilterIcon": "Icon displayed on the quick filter input.", - "QuickFilterClearIcon": "Icon displayed on the quick filter reset input." + "QuickFilterClearIcon": "Icon displayed on the quick filter reset input.", + "ColumnMenuHideIcon": "Icon displayed in column menu for hiding column", + "ColumnMenuSortAscendingIcon": "Icon displayed in column menu for ascending sort", + "ColumnMenuSortDescendingIcon": "Icon displayed in column menu for descending sort", + "ColumnMenuFilterIcon": "Icon displayed in column menu for filter", + "ColumnMenuManageColumnsIcon": "Icon displayed in column menu for showing all columns", + "ColumnMenuClearIcon": "Icon displayed in column menu for clearing values" } } diff --git a/docs/translations/api-docs/data-grid/data-grid.json b/docs/translations/api-docs/data-grid/data-grid.json index 97d2b21fb03f..58dd715f23ec 100644 --- a/docs/translations/api-docs/data-grid/data-grid.json +++ b/docs/translations/api-docs/data-grid/data-grid.json @@ -696,6 +696,12 @@ "FilterPanelDeleteIcon": "Icon displayed for deleting the filter from filter Panel.", "RowReorderIcon": "Icon displayed on the reorder column type to reorder a row.", "QuickFilterIcon": "Icon displayed on the quick filter input.", - "QuickFilterClearIcon": "Icon displayed on the quick filter reset input." + "QuickFilterClearIcon": "Icon displayed on the quick filter reset input.", + "ColumnMenuHideIcon": "Icon displayed in column menu for hiding column", + "ColumnMenuSortAscendingIcon": "Icon displayed in column menu for ascending sort", + "ColumnMenuSortDescendingIcon": "Icon displayed in column menu for descending sort", + "ColumnMenuFilterIcon": "Icon displayed in column menu for filter", + "ColumnMenuManageColumnsIcon": "Icon displayed in column menu for showing all columns", + "ColumnMenuClearIcon": "Icon displayed in column menu for clearing values" } } diff --git a/docsTech/README.md b/docsTech/README.md index 5ebbf937a50e..005337f752ad 100644 --- a/docsTech/README.md +++ b/docsTech/README.md @@ -13,7 +13,7 @@ Here we will discuss how the code is structured, to simplify codebase navigation In folder `packages` you will find one subfolder per exported package (`@mui/x-data-grid`, `@mui/x-data-grid-pro`, ...) -Since `@mui/x-data-grid-pro` is an extension of `@mui/x-data-grid`, it imports all the common features from `@mui/x-data-grid` and the internal logic are imported from `@mui/x-data-grid/internals` which is defined in `x-data-grid/src/internals/index.ts`. +Since `@mui/x-data-grid-pro` is an extension of `@mui/x-data-grid`, it imports all the common features from `@mui/x-data-grid` and the internal logic are imported from `@mui/x-data-grid/internals` which is defined in `x-data-grid/src/internals/index.ts`. And `@mui/x-data-grid-premium` is a further extension of `@mui/x-data-grid-pro`, it imports all the common features from both `@mui/x-data-grid` and `@mui/x-data-grid-pro` and adds some new features on top of that. In each package, the most used folders are: @@ -22,7 +22,7 @@ In each package, the most used folders are: - `hooks/core` defines logics for developers: initialization of the grid, error handling, translations, ... - `hooks/utils` defines logics for contributors: manipulating the state, managing events, ... - `hooks/features` defines logics for end-users: selection, filtering, editing, ... -- `DataGrid[Pro]/useDataGrid[Pro]Component.tsx` is the file in which all the hooks are added to the grid +- `DataGrid[Pro|Premium]/useDataGrid[Pro|Premium]Component.tsx` is the file in which all the hooks are added to the grid - `colDef` contains the default values for each [column type](https://mui.com/x/react-data-grid/column-definition/#column-types): rendering cell, filter operators, sorting method, ... - `models` define the typescript interfaces of the gird @@ -68,7 +68,7 @@ Notice that all the events do not have an associated prop `on` Here you will find more precision about how some features are designed. -- [filtering](./filtering) -- [virtualization](./virtualization) -- [processing](./processing) +- [filtering](./filtering.md) +- [virtualization](./virtualization.md) +- [processing](./processing.md) - print (TODO) diff --git a/docsTech/filtering.md b/docsTech/filtering.md index 2ef57ecb183c..a2ffe20db17f 100644 --- a/docsTech/filtering.md +++ b/docsTech/filtering.md @@ -4,7 +4,7 @@ ### Data -First, let's see how the filtering is saved in the state. Here are the types of the [filter model](https://mui.com/x/api/data-grid/grid-filter-model/). It is made of a `linkOperator`, and a list of [items](https://mui.com/x/api/data-grid/grid-filter-item/). Each item corresponds to a line in the filtering panel. Each item corresponds to a line in the filter panel. +First, let's see how the filtering is saved in the state. Here are the types of the [filter model](https://mui.com/x/api/data-grid/grid-filter-model/). It is made of a `linkOperator`, and a list of [items](https://mui.com/x/api/data-grid/grid-filter-item/). Each item corresponds to a line in the filtering panel. ```ts interface GridFilterModel { diff --git a/docsTech/processing.md b/docsTech/processing.md index 6d8e51ede1ed..6f8819bfede7 100644 --- a/docsTech/processing.md +++ b/docsTech/processing.md @@ -35,7 +35,12 @@ We can classify the pipe-processing into several categories: **Publisher**: `useGridColumns` plugin before updating `state.columns`. -**Why register to this processing**: Add some columns (eg: processor of the Selection plugin) or re-order the columns (eg: processor of the Column Pinning plugin). +**Why register to this processing** + +A few possible reasons could be to: + +- Add some columns (eg: processor of the Selection plugin) +- Re-order the columns (eg: processor of the Column Pinning plugin). **Example**: @@ -61,17 +66,19 @@ const addCustomFeatureColumn = React.useCallback> [apiRef, customFeatureHeightLookup], ); -useGridRegisterPipeProcessor(apiRef, 'rowHeight', addDetailHeight); +useGridRegisterPipeProcessor(apiRef, 'rowHeight', addCustomFeatureHeight); ``` ##### `'hydrateRows'` diff --git a/packages/grid/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumProps.ts b/packages/grid/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumProps.ts index 0d21c974dc65..bfec78850bbd 100644 --- a/packages/grid/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumProps.ts +++ b/packages/grid/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumProps.ts @@ -1,17 +1,14 @@ import * as React from 'react'; import { useThemeProps } from '@mui/material/styles'; -import { - DATA_GRID_PRO_PROPS_DEFAULT_VALUES, - DATA_GRID_DEFAULT_SLOTS_COMPONENTS, - GRID_DEFAULT_LOCALE_TEXT, - GridSlotsComponent, -} from '@mui/x-data-grid-pro'; +import { DATA_GRID_PRO_PROPS_DEFAULT_VALUES, GRID_DEFAULT_LOCALE_TEXT } from '@mui/x-data-grid-pro'; import { DataGridPremiumProps, DataGridPremiumProcessedProps, DataGridPremiumPropsWithDefaultValue, } from '../models/dataGridPremiumProps'; +import { GridPremiumSlotsComponent } from '../models'; import { GRID_AGGREGATION_FUNCTIONS } from '../hooks/features/aggregation'; +import { DATA_GRID_PREMIUM_DEFAULT_SLOTS_COMPONENTS } from '../constants/dataGridPremiumDefaultSlotsComponents'; /** * The default values of `DataGridPremiumPropsWithDefaultValue` to inject in the props of DataGridPremium. @@ -35,20 +32,24 @@ export const useDataGridPremiumProps = (inProps: DataGridPremiumProps) => { [themedProps.localeText], ); - const components = React.useMemo(() => { + const components = React.useMemo(() => { const overrides = themedProps.components; if (!overrides) { - return { ...DATA_GRID_DEFAULT_SLOTS_COMPONENTS }; + return { ...DATA_GRID_PREMIUM_DEFAULT_SLOTS_COMPONENTS }; } - const mergedComponents = {} as GridSlotsComponent; + const mergedComponents = {} as GridPremiumSlotsComponent; - type GridSlots = keyof GridSlotsComponent; - Object.entries(DATA_GRID_DEFAULT_SLOTS_COMPONENTS).forEach(([key, defaultComponent]) => { - mergedComponents[key as GridSlots] = - overrides[key as GridSlots] === undefined ? defaultComponent : overrides[key as GridSlots]; - }); + type GridSlots = keyof GridPremiumSlotsComponent; + Object.entries(DATA_GRID_PREMIUM_DEFAULT_SLOTS_COMPONENTS).forEach( + ([key, defaultComponent]) => { + mergedComponents[key as GridSlots] = + overrides[key as GridSlots] === undefined + ? defaultComponent + : overrides[key as GridSlots]; + }, + ); return mergedComponents; }, [themedProps.components]); diff --git a/packages/grid/x-data-grid-premium/src/components/GridAggregationColumnMenuItem.tsx b/packages/grid/x-data-grid-premium/src/components/GridAggregationColumnMenuItem.tsx deleted file mode 100644 index b37a8ecd96fc..000000000000 --- a/packages/grid/x-data-grid-premium/src/components/GridAggregationColumnMenuItem.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import * as React from 'react'; -import { GridColDef, useGridSelector } from '@mui/x-data-grid-pro'; -import MenuItem from '@mui/material/MenuItem'; -import FormControl from '@mui/material/FormControl'; -import InputLabel from '@mui/material/InputLabel'; -import { unstable_useId as useId } from '@mui/utils'; -import Select, { SelectChangeEvent } from '@mui/material/Select'; -import { useGridApiContext } from '../hooks/utils/useGridApiContext'; -import { useGridRootProps } from '../hooks/utils/useGridRootProps'; -import { - canColumnHaveAggregationFunction, - getAggregationFunctionLabel, -} from '../hooks/features/aggregation/gridAggregationUtils'; -import { gridAggregationModelSelector } from '../hooks/features/aggregation/gridAggregationSelectors'; -import { GridAggregationModel } from '../hooks/features/aggregation/gridAggregationInterfaces'; - -interface GridAggregationColumnMenuItemsProps { - column: GridColDef; - label: string; - availableAggregationFunctions: string[]; -} - -export function GridAggregationColumnMenuItem(props: GridAggregationColumnMenuItemsProps) { - const { column, label, availableAggregationFunctions } = props; - const apiRef = useGridApiContext(); - const rootProps = useGridRootProps(); - const id = useId(); - const aggregationModel = useGridSelector(apiRef, gridAggregationModelSelector); - - const selectedAggregationRule = React.useMemo(() => { - if (!column || !aggregationModel[column.field]) { - return ''; - } - - const aggregationFunctionName = aggregationModel[column.field]; - if ( - canColumnHaveAggregationFunction({ - column, - aggregationFunctionName, - aggregationFunction: rootProps.aggregationFunctions[aggregationFunctionName], - }) - ) { - return aggregationFunctionName; - } - - return ''; - }, [rootProps.aggregationFunctions, aggregationModel, column]); - - const handleAggregationItemChange = (event: SelectChangeEvent) => { - const newAggregationItem = event.target.value || undefined; - const currentModel = gridAggregationModelSelector(apiRef); - const { [column.field]: columnItem, ...otherColumnItems } = currentModel; - const newModel: GridAggregationModel = - newAggregationItem == null - ? otherColumnItems - : { ...otherColumnItems, [column.field]: newAggregationItem }; - - apiRef.current.setAggregationModel(newModel); - apiRef.current.hideColumnMenu(); - }; - - return ( - - - {label} - - - - ); -} diff --git a/packages/grid/x-data-grid-premium/src/components/GridColumnMenuAggregationItem.tsx b/packages/grid/x-data-grid-premium/src/components/GridColumnMenuAggregationItem.tsx new file mode 100644 index 000000000000..6fdce377dddd --- /dev/null +++ b/packages/grid/x-data-grid-premium/src/components/GridColumnMenuAggregationItem.tsx @@ -0,0 +1,117 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import { GridColumnMenuItemProps, useGridSelector } from '@mui/x-data-grid-pro'; +import MenuItem from '@mui/material/MenuItem'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import FormControl from '@mui/material/FormControl'; +import InputLabel from '@mui/material/InputLabel'; +import { unstable_useId as useId } from '@mui/utils'; +import Select, { SelectChangeEvent } from '@mui/material/Select'; +import { useGridApiContext } from '../hooks/utils/useGridApiContext'; +import { useGridRootProps } from '../hooks/utils/useGridRootProps'; +import { + canColumnHaveAggregationFunction, + getAggregationFunctionLabel, + getAvailableAggregationFunctions, +} from '../hooks/features/aggregation/gridAggregationUtils'; +import { gridAggregationModelSelector } from '../hooks/features/aggregation/gridAggregationSelectors'; +import { GridAggregationModel } from '../hooks/features/aggregation/gridAggregationInterfaces'; + +function GridColumnMenuAggregationItem(props: GridColumnMenuItemProps) { + const { colDef } = props; + const apiRef = useGridApiContext(); + const rootProps = useGridRootProps(); + const id = useId(); + const aggregationModel = useGridSelector(apiRef, gridAggregationModelSelector); + + const availableAggregationFunctions = React.useMemo( + () => + getAvailableAggregationFunctions({ + aggregationFunctions: rootProps.aggregationFunctions, + colDef, + }), + [colDef, rootProps.aggregationFunctions], + ); + + const selectedAggregationRule = React.useMemo(() => { + if (!colDef || !aggregationModel[colDef.field]) { + return ''; + } + + const aggregationFunctionName = aggregationModel[colDef.field]; + if ( + canColumnHaveAggregationFunction({ + colDef, + aggregationFunctionName, + aggregationFunction: rootProps.aggregationFunctions[aggregationFunctionName], + }) + ) { + return aggregationFunctionName; + } + + return ''; + }, [rootProps.aggregationFunctions, aggregationModel, colDef]); + + const handleAggregationItemChange = (event: SelectChangeEvent) => { + const newAggregationItem = event.target?.value || undefined; + const currentModel = gridAggregationModelSelector(apiRef); + const { [colDef.field]: columnItem, ...otherColumnItems } = currentModel; + const newModel: GridAggregationModel = + newAggregationItem == null + ? otherColumnItems + : { ...otherColumnItems, [colDef?.field]: newAggregationItem }; + + apiRef.current.setAggregationModel(newModel); + apiRef.current.hideColumnMenu(); + }; + + const label = apiRef.current.getLocaleText('aggregationMenuItemHeader'); + + return ( + + + + + + + {label} + + + + + ); +} + +GridColumnMenuAggregationItem.propTypes = { + // ----------------------------- Warning -------------------------------- + // | These PropTypes are generated from the TypeScript type definitions | + // | To update them edit the TypeScript types and run "yarn proptypes" | + // ---------------------------------------------------------------------- + colDef: PropTypes.object.isRequired, + onClick: PropTypes.func.isRequired, +} as any; + +export { GridColumnMenuAggregationItem }; diff --git a/packages/grid/x-data-grid-premium/src/components/GridRowGroupingColumnMenuItems.tsx b/packages/grid/x-data-grid-premium/src/components/GridColumnMenuRowGroupItem.tsx similarity index 61% rename from packages/grid/x-data-grid-premium/src/components/GridRowGroupingColumnMenuItems.tsx rename to packages/grid/x-data-grid-premium/src/components/GridColumnMenuRowGroupItem.tsx index f5557d8dd46d..e9405a18e337 100644 --- a/packages/grid/x-data-grid-premium/src/components/GridRowGroupingColumnMenuItems.tsx +++ b/packages/grid/x-data-grid-premium/src/components/GridColumnMenuRowGroupItem.tsx @@ -1,7 +1,13 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import MenuItem from '@mui/material/MenuItem'; -import { useGridSelector, gridColumnLookupSelector, GridColDef } from '@mui/x-data-grid-pro'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import { + useGridSelector, + gridColumnLookupSelector, + GridColumnMenuItemProps, +} from '@mui/x-data-grid-pro'; import { useGridApiContext } from '../hooks/utils/useGridApiContext'; import { gridRowGroupingSanitizedModelSelector } from '../hooks/features/rowGrouping/gridRowGroupingSelector'; import { @@ -9,53 +15,50 @@ import { GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, isGroupingColumn, } from '../hooks/features/rowGrouping/gridRowGroupingUtils'; +import { useGridRootProps } from '../hooks/utils/useGridRootProps'; -interface GridRowGroupingColumnMenuItemsProps { - column?: GridColDef; - onClick?: (event: React.MouseEvent) => void; -} - -function GridRowGroupingColumnMenuItems(props: GridRowGroupingColumnMenuItemsProps) { - const { column, onClick } = props; +function GridColumnMenuRowGroupItem(props: GridColumnMenuItemProps) { + const { colDef, onClick } = props; const apiRef = useGridApiContext(); const rowGroupingModel = useGridSelector(apiRef, gridRowGroupingSanitizedModelSelector); const columnsLookup = useGridSelector(apiRef, gridColumnLookupSelector); + const rootProps = useGridRootProps(); const renderUnGroupingMenuItem = (field: string) => { const ungroupColumn = (event: React.MouseEvent) => { apiRef.current.removeRowGroupingCriteria(field); - if (onClick) { - onClick(event); - } + onClick(event); }; const name = columnsLookup[field].headerName ?? field; - return ( - {apiRef.current.getLocaleText('unGroupColumn')(name)} + + + + {apiRef.current.getLocaleText('unGroupColumn')(name)} ); }; - if (!column || !isGroupingColumn(column.field)) { + if (!colDef || !isGroupingColumn(colDef.field)) { return null; } - if (column.field === GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD) { + if (colDef.field === GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD) { return {rowGroupingModel.map(renderUnGroupingMenuItem)}; } - return renderUnGroupingMenuItem(getRowGroupingCriteriaFromGroupingField(column.field)!); + return renderUnGroupingMenuItem(getRowGroupingCriteriaFromGroupingField(colDef.field)!); } -GridRowGroupingColumnMenuItems.propTypes = { +GridColumnMenuRowGroupItem.propTypes = { // ----------------------------- Warning -------------------------------- // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "yarn proptypes" | // ---------------------------------------------------------------------- - column: PropTypes.object, - onClick: PropTypes.func, + colDef: PropTypes.object.isRequired, + onClick: PropTypes.func.isRequired, } as any; -export { GridRowGroupingColumnMenuItems }; +export { GridColumnMenuRowGroupItem }; diff --git a/packages/grid/x-data-grid-premium/src/components/GridColumnMenuRowUngroupItem.tsx b/packages/grid/x-data-grid-premium/src/components/GridColumnMenuRowUngroupItem.tsx new file mode 100644 index 000000000000..5fd45e9b3187 --- /dev/null +++ b/packages/grid/x-data-grid-premium/src/components/GridColumnMenuRowUngroupItem.tsx @@ -0,0 +1,68 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import MenuItem from '@mui/material/MenuItem'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import { + gridColumnLookupSelector, + useGridSelector, + GridColumnMenuItemProps, +} from '@mui/x-data-grid-pro'; +import { useGridApiContext } from '../hooks/utils/useGridApiContext'; +import { gridRowGroupingSanitizedModelSelector } from '../hooks/features/rowGrouping/gridRowGroupingSelector'; +import { useGridRootProps } from '../hooks/utils/useGridRootProps'; + +function GridColumnMenuRowUngroupItem(props: GridColumnMenuItemProps) { + const { colDef, onClick } = props; + const apiRef = useGridApiContext(); + const rowGroupingModel = useGridSelector(apiRef, gridRowGroupingSanitizedModelSelector); + const columnsLookup = useGridSelector(apiRef, gridColumnLookupSelector); + const rootProps = useGridRootProps(); + + if (!colDef.groupable) { + return null; + } + + const ungroupColumn = (event: React.MouseEvent) => { + apiRef.current.removeRowGroupingCriteria(colDef.field); + onClick(event); + }; + + const groupColumn = (event: React.MouseEvent) => { + apiRef.current.addRowGroupingCriteria(colDef.field); + onClick(event); + }; + + const name = columnsLookup[colDef.field].headerName ?? colDef.field; + + if (rowGroupingModel.includes(colDef.field)) { + return ( + + + + + {apiRef.current.getLocaleText('unGroupColumn')(name)} + + ); + } + + return ( + + + + + {apiRef.current.getLocaleText('groupColumn')(name)} + + ); +} + +GridColumnMenuRowUngroupItem.propTypes = { + // ----------------------------- Warning -------------------------------- + // | These PropTypes are generated from the TypeScript type definitions | + // | To update them edit the TypeScript types and run "yarn proptypes" | + // ---------------------------------------------------------------------- + colDef: PropTypes.object.isRequired, + onClick: PropTypes.func.isRequired, +} as any; + +export { GridColumnMenuRowUngroupItem }; diff --git a/packages/grid/x-data-grid-premium/src/components/GridPremiumColumnMenu.tsx b/packages/grid/x-data-grid-premium/src/components/GridPremiumColumnMenu.tsx new file mode 100644 index 000000000000..2c4595f6f8a8 --- /dev/null +++ b/packages/grid/x-data-grid-premium/src/components/GridPremiumColumnMenu.tsx @@ -0,0 +1,61 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import { + GridGenericColumnMenu, + GridColumnMenuProps, + GRID_COLUMN_MENU_COMPONENTS, + GRID_COLUMN_MENU_COMPONENTS_PROPS, + GridColumnMenuItemProps, +} from '@mui/x-data-grid-pro'; +import { GridColumnMenuAggregationItem } from './GridColumnMenuAggregationItem'; +import { isGroupingColumn } from '../hooks/features/rowGrouping'; +import { GridColumnMenuRowGroupItem } from './GridColumnMenuRowGroupItem'; +import { GridColumnMenuRowUngroupItem } from './GridColumnMenuRowUngroupItem'; + +export function GridColumnMenuGroupingItem(props: GridColumnMenuItemProps) { + const { colDef } = props; + if (isGroupingColumn(colDef.field)) { + return ; + } + if (colDef.groupable) { + return ; + } + return null; +} + +export const GRID_COLUMN_MENU_COMPONENTS_PREMIUM = { + ...GRID_COLUMN_MENU_COMPONENTS, + ColumnMenuAggregationItem: GridColumnMenuAggregationItem, + ColumnMenuGroupingItem: GridColumnMenuGroupingItem, +}; + +export const GRID_COLUMN_MENU_COMPONENTS_PROPS_PREMIUM = { + ...GRID_COLUMN_MENU_COMPONENTS_PROPS, + columnMenuAggregationItem: { displayOrder: 23 }, + columnMenuGroupingItem: { displayOrder: 27 }, +}; + +const GridPremiumColumnMenu = React.forwardRef( + function GridPremiumColumnMenuSimple(props, ref) { + return ( + + ); + }, +); + +GridPremiumColumnMenu.propTypes = { + // ----------------------------- Warning -------------------------------- + // | These PropTypes are generated from the TypeScript type definitions | + // | To update them edit the TypeScript types and run "yarn proptypes" | + // ---------------------------------------------------------------------- + colDef: PropTypes.object.isRequired, + hideMenu: PropTypes.func.isRequired, + open: PropTypes.bool.isRequired, +} as any; + +export { GridPremiumColumnMenu }; diff --git a/packages/grid/x-data-grid-premium/src/components/GridRowGroupableColumnMenuItems.tsx b/packages/grid/x-data-grid-premium/src/components/GridRowGroupableColumnMenuItems.tsx deleted file mode 100644 index f62449cd2fb9..000000000000 --- a/packages/grid/x-data-grid-premium/src/components/GridRowGroupableColumnMenuItems.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import MenuItem from '@mui/material/MenuItem'; -import { gridColumnLookupSelector, useGridSelector, GridColDef } from '@mui/x-data-grid-pro'; -import { useGridApiContext } from '../hooks/utils/useGridApiContext'; -import { gridRowGroupingSanitizedModelSelector } from '../hooks/features/rowGrouping/gridRowGroupingSelector'; - -interface GridRowGroupableColumnMenuItemsProps { - column?: GridColDef; - onClick?: (event: React.MouseEvent) => void; -} - -function GridRowGroupableColumnMenuItems(props: GridRowGroupableColumnMenuItemsProps) { - const { column, onClick } = props; - const apiRef = useGridApiContext(); - const rowGroupingModel = useGridSelector(apiRef, gridRowGroupingSanitizedModelSelector); - const columnsLookup = useGridSelector(apiRef, gridColumnLookupSelector); - - if (!column?.groupable) { - return null; - } - - const ungroupColumn = (event: React.MouseEvent) => { - apiRef.current.removeRowGroupingCriteria(column.field); - if (onClick) { - onClick(event); - } - }; - - const groupColumn = (event: React.MouseEvent) => { - apiRef.current.addRowGroupingCriteria(column.field); - if (onClick) { - onClick(event); - } - }; - - const name = columnsLookup[column.field].headerName ?? column.field; - - if (rowGroupingModel.includes(column.field)) { - return ( - - {apiRef.current.getLocaleText('unGroupColumn')(name)} - - ); - } - - return ( - {apiRef.current.getLocaleText('groupColumn')(name)} - ); -} - -GridRowGroupableColumnMenuItems.propTypes = { - // ----------------------------- Warning -------------------------------- - // | These PropTypes are generated from the TypeScript type definitions | - // | To update them edit the TypeScript types and run "yarn proptypes" | - // ---------------------------------------------------------------------- - column: PropTypes.object, - onClick: PropTypes.func, -} as any; - -export { GridRowGroupableColumnMenuItems }; diff --git a/packages/grid/x-data-grid-premium/src/components/icons.tsx b/packages/grid/x-data-grid-premium/src/components/icons.tsx new file mode 100644 index 000000000000..92fff6f8518b --- /dev/null +++ b/packages/grid/x-data-grid-premium/src/components/icons.tsx @@ -0,0 +1,19 @@ +import * as React from 'react'; +import { createSvgIcon } from '@mui/material/utils'; + +export const GridWorkspacesIcon = createSvgIcon( + + + , + 'Workspaces', +); + +export const GridGroupWorkIcon = createSvgIcon( + , + 'GroupWork', +); + +export const GridFunctionsIcon = createSvgIcon( + , + 'Functions', +); diff --git a/packages/grid/x-data-grid-premium/src/components/index.ts b/packages/grid/x-data-grid-premium/src/components/index.ts index 29256c8c750c..8f90ed2753f6 100644 --- a/packages/grid/x-data-grid-premium/src/components/index.ts +++ b/packages/grid/x-data-grid-premium/src/components/index.ts @@ -1 +1,4 @@ export * from './GridExcelExportMenuItem'; +export * from './icons'; +export * from './GridColumnMenuAggregationItem'; +export { GridColumnMenuGroupingItem } from './GridPremiumColumnMenu'; diff --git a/packages/grid/x-data-grid-premium/src/components/reexports.ts b/packages/grid/x-data-grid-premium/src/components/reexports.ts new file mode 100644 index 000000000000..f4df5a2daef7 --- /dev/null +++ b/packages/grid/x-data-grid-premium/src/components/reexports.ts @@ -0,0 +1,5 @@ +export { + GridPremiumColumnMenu as GridColumnMenu, + GRID_COLUMN_MENU_COMPONENTS_PREMIUM as GRID_COLUMN_MENU_COMPONENTS, + GRID_COLUMN_MENU_COMPONENTS_PROPS_PREMIUM as GRID_COLUMN_MENU_COMPONENTS_PROPS, +} from './GridPremiumColumnMenu'; diff --git a/packages/grid/x-data-grid-premium/src/constants/dataGridPremiumDefaultSlotsComponents.ts b/packages/grid/x-data-grid-premium/src/constants/dataGridPremiumDefaultSlotsComponents.ts new file mode 100644 index 000000000000..2d06a03f5912 --- /dev/null +++ b/packages/grid/x-data-grid-premium/src/constants/dataGridPremiumDefaultSlotsComponents.ts @@ -0,0 +1,16 @@ +import { DATA_GRID_PRO_DEFAULT_SLOTS_COMPONENTS } from '@mui/x-data-grid-pro/internals'; +import { GridPremiumSlotsComponent, GridPremiumIconSlotsComponent } from '../models'; +import { GridWorkspacesIcon, GridGroupWorkIcon, GridFunctionsIcon } from '../components'; +import { GridPremiumColumnMenu } from '../components/GridPremiumColumnMenu'; + +export const DEFAULT_GRID_PREMIUM_ICON_SLOTS_COMPONENTS: GridPremiumIconSlotsComponent = { + ColumnMenuUngroupIcon: GridWorkspacesIcon, + ColumnMenuGroupIcon: GridGroupWorkIcon, + ColumnMenuAggregationIcon: GridFunctionsIcon, +}; + +export const DATA_GRID_PREMIUM_DEFAULT_SLOTS_COMPONENTS: GridPremiumSlotsComponent = { + ...DATA_GRID_PRO_DEFAULT_SLOTS_COMPONENTS, + ...DEFAULT_GRID_PREMIUM_ICON_SLOTS_COMPONENTS, + ColumnMenu: GridPremiumColumnMenu, +}; diff --git a/packages/grid/x-data-grid-premium/src/hooks/features/aggregation/gridAggregationUtils.ts b/packages/grid/x-data-grid-premium/src/hooks/features/aggregation/gridAggregationUtils.ts index 59455ccba0b2..fc8c246f1a1d 100644 --- a/packages/grid/x-data-grid-premium/src/hooks/features/aggregation/gridAggregationUtils.ts +++ b/packages/grid/x-data-grid-premium/src/hooks/features/aggregation/gridAggregationUtils.ts @@ -36,15 +36,15 @@ export const getAggregationFooterRowIdFromGroupId = (groupId: GridRowId | null) }; export const canColumnHaveAggregationFunction = ({ - column, + colDef, aggregationFunctionName, aggregationFunction, }: { - column: GridColDef | undefined; + colDef: GridColDef | undefined; aggregationFunctionName: string; aggregationFunction: GridAggregationFunction | undefined; }): boolean => { - if (!column || !column.aggregable) { + if (!colDef || !colDef.aggregable) { return false; } @@ -52,27 +52,27 @@ export const canColumnHaveAggregationFunction = ({ return false; } - if (column.availableAggregationFunctions != null) { - return column.availableAggregationFunctions.includes(aggregationFunctionName); + if (colDef.availableAggregationFunctions != null) { + return colDef.availableAggregationFunctions.includes(aggregationFunctionName); } if (!aggregationFunction.columnTypes) { return true; } - return aggregationFunction.columnTypes.includes(column.type!); + return aggregationFunction.columnTypes.includes(colDef.type!); }; export const getAvailableAggregationFunctions = ({ aggregationFunctions, - column, + colDef, }: { aggregationFunctions: Record; - column: GridColDef; + colDef: GridColDef; }) => Object.keys(aggregationFunctions).filter((aggregationFunctionName) => canColumnHaveAggregationFunction({ - column, + colDef, aggregationFunctionName, aggregationFunction: aggregationFunctions[aggregationFunctionName], }), @@ -100,7 +100,7 @@ export const getAggregationRules = ({ if ( columnsLookup[field] && canColumnHaveAggregationFunction({ - column: columnsLookup[field], + colDef: columnsLookup[field], aggregationFunctionName: columnItem, aggregationFunction: aggregationFunctions[columnItem], }) diff --git a/packages/grid/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregationPreProcessors.tsx b/packages/grid/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregationPreProcessors.tsx index b306ec4648f8..58705460b321 100644 --- a/packages/grid/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregationPreProcessors.tsx +++ b/packages/grid/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregationPreProcessors.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import MuiDivider from '@mui/material/Divider'; import { gridColumnLookupSelector } from '@mui/x-data-grid-pro'; import { GridPipeProcessor, @@ -18,20 +17,19 @@ import { unwrapColumnFromAggregation, } from './wrapColumnWithAggregation'; import { DataGridPremiumProcessedProps } from '../../../models/dataGridPremiumProps'; -import { GridAggregationColumnMenuItem } from '../../../components/GridAggregationColumnMenuItem'; import { gridAggregationModelSelector } from './gridAggregationSelectors'; import { GridInitialStatePremium } from '../../../models/gridStatePremium'; import { GridAggregationRules } from './gridAggregationInterfaces'; -function Divider() { - return event.stopPropagation()} />; -} - export const useGridAggregationPreProcessors = ( apiRef: React.MutableRefObject, props: Pick< DataGridPremiumProcessedProps, - 'aggregationFunctions' | 'disableAggregation' | 'getAggregationPosition' + | 'aggregationFunctions' + | 'disableAggregation' + | 'getAggregationPosition' + | 'componentsProps' + | 'components' >, ) => { // apiRef.current.caches.aggregation.rulesOnLastColumnHydration is not used because by the time @@ -112,31 +110,23 @@ export const useGridAggregationPreProcessors = ( ); const addColumnMenuButtons = React.useCallback>( - (initialValue, column) => { + (columnMenuItems, colDef) => { if (props.disableAggregation) { - return initialValue; + return columnMenuItems; } const availableAggregationFunctions = getAvailableAggregationFunctions({ aggregationFunctions: props.aggregationFunctions, - column, + colDef, }); if (availableAggregationFunctions.length === 0) { - return initialValue; + return columnMenuItems; } - return [ - ...initialValue, - , - , - ]; + return [...columnMenuItems, 'ColumnMenuAggregationItem']; }, - [apiRef, props.aggregationFunctions, props.disableAggregation], + [props.aggregationFunctions, props.disableAggregation], ); const stateExportPreProcessing = React.useCallback>( diff --git a/packages/grid/x-data-grid-premium/src/hooks/features/rowGrouping/index.ts b/packages/grid/x-data-grid-premium/src/hooks/features/rowGrouping/index.ts index 4a716de78898..1896d1be8042 100644 --- a/packages/grid/x-data-grid-premium/src/hooks/features/rowGrouping/index.ts +++ b/packages/grid/x-data-grid-premium/src/hooks/features/rowGrouping/index.ts @@ -3,4 +3,5 @@ export * from './gridRowGroupingInterfaces'; export { GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, getRowGroupingFieldFromGroupingCriteria, + isGroupingColumn, } from './gridRowGroupingUtils'; diff --git a/packages/grid/x-data-grid-premium/src/hooks/features/rowGrouping/useGridRowGrouping.tsx b/packages/grid/x-data-grid-premium/src/hooks/features/rowGrouping/useGridRowGrouping.tsx index 0b4e15f26e99..fa3e9dfc867e 100644 --- a/packages/grid/x-data-grid-premium/src/hooks/features/rowGrouping/useGridRowGrouping.tsx +++ b/packages/grid/x-data-grid-premium/src/hooks/features/rowGrouping/useGridRowGrouping.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import MuiDivider from '@mui/material/Divider'; import { GridEventListener, useGridApiEventHandler, @@ -28,14 +27,8 @@ import { areGroupingRulesEqual, } from './gridRowGroupingUtils'; import { GridRowGroupingApi } from './gridRowGroupingInterfaces'; -import { GridRowGroupableColumnMenuItems } from '../../../components/GridRowGroupableColumnMenuItems'; -import { GridRowGroupingColumnMenuItems } from '../../../components/GridRowGroupingColumnMenuItems'; import { GridInitialStatePremium } from '../../../models/gridStatePremium'; -function Divider() { - return event.stopPropagation()} />; -} - export const rowGroupingStateInitializer: GridStateInitializer< Pick > = (state, props, apiRef) => { @@ -68,6 +61,8 @@ export const useGridRowGrouping = ( | 'groupingColDef' | 'rowGroupingColumnMode' | 'disableRowGrouping' + | 'componentsProps' + | 'components' >, ) => { apiRef.current.registerControlState({ @@ -158,25 +153,14 @@ export const useGridRowGrouping = ( * PRE-PROCESSING */ const addColumnMenuButtons = React.useCallback>( - (initialValue, column) => { + (columnMenuItems, colDef) => { if (props.disableRowGrouping) { - return initialValue; + return columnMenuItems; } - - let menuItems: React.ReactNode; - if (isGroupingColumn(column.field)) { - menuItems = ; - } else if (column.groupable) { - menuItems = ; - } else { - menuItems = null; + if (isGroupingColumn(colDef.field) || colDef.groupable) { + return [...columnMenuItems, 'ColumnMenuGroupingItem']; } - - if (menuItems == null) { - return initialValue; - } - - return [...initialValue, , menuItems]; + return columnMenuItems; }, [props.disableRowGrouping], ); diff --git a/packages/grid/x-data-grid-premium/src/index.ts b/packages/grid/x-data-grid-premium/src/index.ts index 904ab8c7a375..d134ceb28bd6 100644 --- a/packages/grid/x-data-grid-premium/src/index.ts +++ b/packages/grid/x-data-grid-premium/src/index.ts @@ -26,3 +26,9 @@ export type { export { useGridApiContext, useGridApiRef, useGridRootProps } from './typeOverloads/reexports'; export type { GridApi, GridInitialState, GridState } from './typeOverloads/reexports'; + +export { + GridColumnMenu, + GRID_COLUMN_MENU_COMPONENTS, + GRID_COLUMN_MENU_COMPONENTS_PROPS, +} from './components/reexports'; diff --git a/packages/grid/x-data-grid-premium/src/models/dataGridPremiumProps.ts b/packages/grid/x-data-grid-premium/src/models/dataGridPremiumProps.ts index 8399c3cc707a..3cd389e1c535 100644 --- a/packages/grid/x-data-grid-premium/src/models/dataGridPremiumProps.ts +++ b/packages/grid/x-data-grid-premium/src/models/dataGridPremiumProps.ts @@ -13,19 +13,28 @@ import type { GridAggregationFunction, GridAggregationPosition, } from '../hooks/features/aggregation'; +import { GridPremiumSlotsComponent } from './gridPremiumSlotsComponent'; import { GridInitialStatePremium } from './gridStatePremium'; import { GridApiPremium } from './gridApiPremium'; import { GridCellSelectionModel } from '../hooks/features/cellSelection'; export interface GridExperimentalPremiumFeatures extends GridExperimentalProFeatures {} +export interface DataGridPremiumPropsWithComplexDefaultValueBeforeProcessing + extends Pick { + /** + * Overrideable components. + */ + components?: Partial; +} + /** - * The props users can give to the `DataGridProProps` component. + * The props users can give to the `DataGridPremiumProps` component. */ export interface DataGridPremiumProps extends Omit< Partial & - DataGridPropsWithComplexDefaultValueBeforeProcessing & + DataGridPremiumPropsWithComplexDefaultValueBeforeProcessing & DataGridPremiumPropsWithoutDefaultValue, DataGridPremiumForcedPropsKey > { @@ -36,12 +45,17 @@ export interface DataGridPremiumProps experimentalFeatures?: Partial; } +export interface DataGridPremiumPropsWithComplexDefaultValueAfterProcessing + extends Pick { + components: GridPremiumSlotsComponent; +} + /** * The props of the `DataGridPremium` component after the pre-processing phase. */ export interface DataGridPremiumProcessedProps extends DataGridPremiumPropsWithDefaultValue, - DataGridPropsWithComplexDefaultValueAfterProcessing, + DataGridPremiumPropsWithComplexDefaultValueAfterProcessing, DataGridPremiumPropsWithoutDefaultValue {} export type DataGridPremiumForcedPropsKey = 'signature'; diff --git a/packages/grid/x-data-grid-premium/src/models/gridPremiumIconSlotsComponent.ts b/packages/grid/x-data-grid-premium/src/models/gridPremiumIconSlotsComponent.ts new file mode 100644 index 000000000000..f09b91fbc559 --- /dev/null +++ b/packages/grid/x-data-grid-premium/src/models/gridPremiumIconSlotsComponent.ts @@ -0,0 +1,19 @@ +import * as React from 'react'; + +export interface GridPremiumIconSlotsComponent { + /** + * Icon displayed in column menu for ungrouping + * @default GridWorkspacesIcon + */ + ColumnMenuUngroupIcon: React.JSXElementConstructor; + /** + * Icon displayed in column menu for grouping + * @default GridGroupWorkIcon + */ + ColumnMenuGroupIcon: React.JSXElementConstructor; + /** + * Icon displayed in column menu for aggregation + * @default GridFunctionsIcon + */ + ColumnMenuAggregationIcon: React.JSXElementConstructor; +} diff --git a/packages/grid/x-data-grid-premium/src/models/gridPremiumSlotsComponent.ts b/packages/grid/x-data-grid-premium/src/models/gridPremiumSlotsComponent.ts new file mode 100644 index 000000000000..b9e307b89652 --- /dev/null +++ b/packages/grid/x-data-grid-premium/src/models/gridPremiumSlotsComponent.ts @@ -0,0 +1,10 @@ +import { GridProSlotsComponent } from '@mui/x-data-grid-pro'; +import { GridPremiumIconSlotsComponent } from './gridPremiumIconSlotsComponent'; + +/** + * Grid components React prop interface containing all the overridable components + * for Premium package + */ +export interface GridPremiumSlotsComponent + extends GridProSlotsComponent, + GridPremiumIconSlotsComponent {} diff --git a/packages/grid/x-data-grid-premium/src/models/index.ts b/packages/grid/x-data-grid-premium/src/models/index.ts index 1caadc53e7dc..03a21344b06b 100644 --- a/packages/grid/x-data-grid-premium/src/models/index.ts +++ b/packages/grid/x-data-grid-premium/src/models/index.ts @@ -1 +1,3 @@ export * from './gridGroupingValueGetterParams'; +export * from './gridPremiumIconSlotsComponent'; +export * from './gridPremiumSlotsComponent'; diff --git a/packages/grid/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx b/packages/grid/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx index 28989b3be52e..f8eeef31a1d5 100644 --- a/packages/grid/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx +++ b/packages/grid/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx @@ -1661,7 +1661,7 @@ describe(' - Row Grouping', () => { expect(apiRef.current.state.rowGrouping.model).to.deep.equal([]); }); - it('should add a "Stop grouping {field} menu item for each grouping criteria on the grouping column when prop.rowGroupingColumnMode = "single"', () => { + it('should add a "Stop grouping {field}" menu item for each grouping criteria on the grouping column when prop.rowGroupingColumnMode = "single"', () => { render( (inProps: DataGr [themedProps.localeText], ); - const components = React.useMemo(() => { + const components = React.useMemo(() => { const overrides = themedProps.components; if (!overrides) { - return { ...DATA_GRID_DEFAULT_SLOTS_COMPONENTS }; + return { ...DATA_GRID_PRO_DEFAULT_SLOTS_COMPONENTS }; } - const mergedComponents = {} as GridSlotsComponent; + const mergedComponents = {} as GridProSlotsComponent; - type GridSlots = keyof GridSlotsComponent; - Object.entries(DATA_GRID_DEFAULT_SLOTS_COMPONENTS).forEach(([key, defaultComponent]) => { + type GridSlots = keyof GridProSlotsComponent; + Object.entries(DATA_GRID_PRO_DEFAULT_SLOTS_COMPONENTS).forEach(([key, defaultComponent]) => { mergedComponents[key as GridSlots] = overrides[key as GridSlots] === undefined ? defaultComponent : overrides[key as GridSlots]; }); diff --git a/packages/grid/x-data-grid-pro/src/components/GridColumnMenuPinningItem.tsx b/packages/grid/x-data-grid-pro/src/components/GridColumnMenuPinningItem.tsx new file mode 100644 index 000000000000..0c20fb19575b --- /dev/null +++ b/packages/grid/x-data-grid-pro/src/components/GridColumnMenuPinningItem.tsx @@ -0,0 +1,83 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import MenuItem from '@mui/material/MenuItem'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import { GridColumnMenuItemProps } from '@mui/x-data-grid'; +import { GridPinnedPosition } from '../hooks/features/columnPinning'; +import { useGridApiContext } from '../hooks/utils/useGridApiContext'; +import { useGridRootProps } from '../hooks/utils/useGridRootProps'; + +function GridColumnMenuPinningItem(props: GridColumnMenuItemProps) { + const { colDef, onClick } = props; + const apiRef = useGridApiContext(); + const rootProps = useGridRootProps(); + + const pinColumn = (side: GridPinnedPosition) => (event: React.MouseEvent) => { + apiRef.current.pinColumn(colDef.field, side); + onClick(event); + }; + + const unpinColumn = (event: React.MouseEvent) => { + apiRef.current.unpinColumn(colDef.field); + onClick(event); + }; + + if (!colDef) { + return null; + } + + const side = apiRef.current.isColumnPinned(colDef.field); + + if (side) { + const otherSide = + side === GridPinnedPosition.right ? GridPinnedPosition.left : GridPinnedPosition.right; + const label = otherSide === GridPinnedPosition.right ? 'pinToRight' : 'pinToLeft'; + const Icon = + side === GridPinnedPosition.right + ? rootProps.components.ColumnMenuPinLeftIcon + : rootProps.components.ColumnMenuPinRightIcon; + return ( + + + + + + {apiRef.current.getLocaleText(label)} + + + + {apiRef.current.getLocaleText('unpin')} + + + ); + } + + return ( + + + + + + {apiRef.current.getLocaleText('pinToLeft')} + + + + + + {apiRef.current.getLocaleText('pinToRight')} + + + ); +} + +GridColumnMenuPinningItem.propTypes = { + // ----------------------------- Warning -------------------------------- + // | These PropTypes are generated from the TypeScript type definitions | + // | To update them edit the TypeScript types and run "yarn proptypes" | + // ---------------------------------------------------------------------- + colDef: PropTypes.object.isRequired, + onClick: PropTypes.func.isRequired, +} as any; + +export { GridColumnMenuPinningItem }; diff --git a/packages/grid/x-data-grid-pro/src/components/GridColumnPinningMenuItems.tsx b/packages/grid/x-data-grid-pro/src/components/GridColumnPinningMenuItems.tsx deleted file mode 100644 index 9861ee22873c..000000000000 --- a/packages/grid/x-data-grid-pro/src/components/GridColumnPinningMenuItems.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import MenuItem from '@mui/material/MenuItem'; -import { GridColDef } from '@mui/x-data-grid'; -import { GridPinnedPosition } from '../hooks/features/columnPinning'; -import { useGridApiContext } from '../hooks/utils/useGridApiContext'; - -interface GridColumnPinningMenuItemsProps { - column?: GridColDef; - onClick?: (event: React.MouseEvent) => void; -} - -function GridColumnPinningMenuItems(props: GridColumnPinningMenuItemsProps) { - const { column, onClick } = props; - const apiRef = useGridApiContext(); - - const pinColumn = (side: GridPinnedPosition) => (event: React.MouseEvent) => { - apiRef.current.pinColumn(column!.field, side); - - if (onClick) { - onClick(event); - } - }; - - const unpinColumn = (event: React.MouseEvent) => { - apiRef.current.unpinColumn(column!.field); - - if (onClick) { - onClick(event); - } - }; - - if (!column) { - return null; - } - - const side = apiRef.current.isColumnPinned(column.field); - - if (side) { - const otherSide = - side === GridPinnedPosition.right ? GridPinnedPosition.left : GridPinnedPosition.right; - const label = otherSide === GridPinnedPosition.right ? 'pinToRight' : 'pinToLeft'; - - return ( - - {apiRef.current.getLocaleText(label)} - {apiRef.current.getLocaleText('unpin')} - - ); - } - - return ( - - - {apiRef.current.getLocaleText('pinToLeft')} - - - {apiRef.current.getLocaleText('pinToRight')} - - - ); -} - -GridColumnPinningMenuItems.propTypes = { - // ----------------------------- Warning -------------------------------- - // | These PropTypes are generated from the TypeScript type definitions | - // | To update them edit the TypeScript types and run "yarn proptypes" | - // ---------------------------------------------------------------------- - column: PropTypes.object, - onClick: PropTypes.func, -} as any; - -export { GridColumnPinningMenuItems }; diff --git a/packages/grid/x-data-grid-pro/src/components/GridProColumnMenu.tsx b/packages/grid/x-data-grid-pro/src/components/GridProColumnMenu.tsx new file mode 100644 index 000000000000..058235332070 --- /dev/null +++ b/packages/grid/x-data-grid-pro/src/components/GridProColumnMenu.tsx @@ -0,0 +1,46 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import { + GridGenericColumnMenu, + GridColumnMenuProps, + GRID_COLUMN_MENU_COMPONENTS, + GRID_COLUMN_MENU_COMPONENTS_PROPS, +} from '@mui/x-data-grid'; +import { GridColumnMenuPinningItem } from './GridColumnMenuPinningItem'; + +export const GRID_COLUMN_MENU_COMPONENTS_PRO = { + ...GRID_COLUMN_MENU_COMPONENTS, + ColumnMenuPinningItem: GridColumnMenuPinningItem, +}; + +export const GRID_COLUMN_MENU_COMPONENTS_PROPS_PRO = { + ...GRID_COLUMN_MENU_COMPONENTS_PROPS, + columnMenuPinningItem: { + displayOrder: 15, + }, +}; + +const GridProColumnMenu = React.forwardRef( + function GridProColumnMenu(props, ref) { + return ( + + ); + }, +); + +GridProColumnMenu.propTypes = { + // ----------------------------- Warning -------------------------------- + // | These PropTypes are generated from the TypeScript type definitions | + // | To update them edit the TypeScript types and run "yarn proptypes" | + // ---------------------------------------------------------------------- + colDef: PropTypes.object.isRequired, + hideMenu: PropTypes.func.isRequired, + open: PropTypes.bool.isRequired, +} as any; + +export { GridProColumnMenu }; diff --git a/packages/grid/x-data-grid-pro/src/components/icons.tsx b/packages/grid/x-data-grid-pro/src/components/icons.tsx new file mode 100644 index 000000000000..f3b00c071306 --- /dev/null +++ b/packages/grid/x-data-grid-pro/src/components/icons.tsx @@ -0,0 +1,22 @@ +import * as React from 'react'; +import { createSvgIcon } from '@mui/material/utils'; + +export const GridPushPinRightIcon = createSvgIcon( + + + , + 'PushPinRight', +); + +export const GridPushPinLeftIcon = createSvgIcon( + + + , + 'PushPinLeft', +); diff --git a/packages/grid/x-data-grid-pro/src/components/index.ts b/packages/grid/x-data-grid-pro/src/components/index.ts index b3301a1fe59f..de99e186c04a 100644 --- a/packages/grid/x-data-grid-pro/src/components/index.ts +++ b/packages/grid/x-data-grid-pro/src/components/index.ts @@ -1,4 +1,5 @@ // Only export the variable and types that should be publicly exposed and re-exported from `@mui/x-data-grid-pro` export * from './GridTreeDataGroupingCell'; -export * from './GridColumnPinningMenuItems'; +export * from './GridColumnMenuPinningItem'; export * from './GridDetailPanelToggleCell'; +export * from './icons'; diff --git a/packages/grid/x-data-grid-pro/src/components/reexports.ts b/packages/grid/x-data-grid-pro/src/components/reexports.ts new file mode 100644 index 000000000000..efb1b4c9dd75 --- /dev/null +++ b/packages/grid/x-data-grid-pro/src/components/reexports.ts @@ -0,0 +1,5 @@ +export { + GridProColumnMenu as GridColumnMenu, + GRID_COLUMN_MENU_COMPONENTS_PRO as GRID_COLUMN_MENU_COMPONENTS, + GRID_COLUMN_MENU_COMPONENTS_PROPS_PRO as GRID_COLUMN_MENU_COMPONENTS_PROPS, +} from './GridProColumnMenu'; diff --git a/packages/grid/x-data-grid-pro/src/constants/dataGridProDefaultSlotsComponents.ts b/packages/grid/x-data-grid-pro/src/constants/dataGridProDefaultSlotsComponents.ts new file mode 100644 index 000000000000..9f48894e56ba --- /dev/null +++ b/packages/grid/x-data-grid-pro/src/constants/dataGridProDefaultSlotsComponents.ts @@ -0,0 +1,15 @@ +import { DATA_GRID_DEFAULT_SLOTS_COMPONENTS } from '@mui/x-data-grid/internals'; +import { GridProSlotsComponent, GridProIconSlotsComponent } from '../models'; +import { GridPushPinRightIcon, GridPushPinLeftIcon } from '../components'; +import { GridProColumnMenu } from '../components/GridProColumnMenu'; + +export const DEFAULT_GRID_PRO_ICON_SLOTS_COMPONENTS: GridProIconSlotsComponent = { + ColumnMenuPinRightIcon: GridPushPinRightIcon, + ColumnMenuPinLeftIcon: GridPushPinLeftIcon, +}; + +export const DATA_GRID_PRO_DEFAULT_SLOTS_COMPONENTS: GridProSlotsComponent = { + ...DATA_GRID_DEFAULT_SLOTS_COMPONENTS, + ...DEFAULT_GRID_PRO_ICON_SLOTS_COMPONENTS, + ColumnMenu: GridProColumnMenu, +}; diff --git a/packages/grid/x-data-grid-pro/src/hooks/features/columnPinning/useGridColumnPinning.tsx b/packages/grid/x-data-grid-pro/src/hooks/features/columnPinning/useGridColumnPinning.tsx index a8af6c01a0ac..a12c43b2dbe9 100644 --- a/packages/grid/x-data-grid-pro/src/hooks/features/columnPinning/useGridColumnPinning.tsx +++ b/packages/grid/x-data-grid-pro/src/hooks/features/columnPinning/useGridColumnPinning.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import MuiDivider from '@mui/material/Divider'; import { useGridSelector, gridVisibleColumnDefinitionsSelector, @@ -21,7 +20,6 @@ import { import { GridPrivateApiPro } from '../../../models/gridApiPro'; import { GridInitialStatePro, GridStatePro } from '../../../models/gridStatePro'; import { DataGridProProcessedProps } from '../../../models/dataGridProProps'; -import { GridColumnPinningMenuItems } from '../../../components/GridColumnPinningMenuItems'; import { GridColumnPinningApi, GridPinnedPosition, @@ -30,10 +28,6 @@ import { import { gridPinnedColumnsSelector } from './gridColumnPinningSelector'; import { filterColumns } from '../../../components/DataGridProVirtualScroller'; -function Divider() { - return event.stopPropagation()} />; -} - export const columnPinningStateInitializer: GridStateInitializer< Pick > = (state, props, apiRef) => { @@ -66,7 +60,12 @@ export const useGridColumnPinning = ( apiRef: React.MutableRefObject, props: Pick< DataGridProProcessedProps, - 'disableColumnPinning' | 'initialState' | 'pinnedColumns' | 'onPinnedColumnsChange' + | 'disableColumnPinning' + | 'initialState' + | 'pinnedColumns' + | 'onPinnedColumnsChange' + | 'componentsProps' + | 'components' >, ): void => { const pinnedColumns = useGridSelector(apiRef, gridPinnedColumnsSelector); @@ -175,17 +174,17 @@ export const useGridColumnPinning = ( [apiRef, pinnedColumns, props.disableColumnPinning], ); - const addColumnMenuButtons = React.useCallback>( - (initialValue, column) => { + const addColumnMenuItems = React.useCallback>( + (columnMenuItems, colDef) => { if (props.disableColumnPinning) { - return initialValue; + return columnMenuItems; } - if (column.pinnable === false) { - return initialValue; + if (colDef.pinnable === false) { + return columnMenuItems; } - return [...initialValue, , ]; + return [...columnMenuItems, 'ColumnMenuPinningItem']; }, [props.disableColumnPinning], ); @@ -257,7 +256,7 @@ export const useGridColumnPinning = ( ); useGridRegisterPipeProcessor(apiRef, 'scrollToIndexes', calculateScrollLeft); - useGridRegisterPipeProcessor(apiRef, 'columnMenu', addColumnMenuButtons); + useGridRegisterPipeProcessor(apiRef, 'columnMenu', addColumnMenuItems); useGridRegisterPipeProcessor(apiRef, 'canBeReordered', checkIfCanBeReordered); useGridRegisterPipeProcessor(apiRef, 'exportState', stateExportPreProcessing); useGridRegisterPipeProcessor(apiRef, 'restoreState', stateRestorePreProcessing); diff --git a/packages/grid/x-data-grid-pro/src/index.ts b/packages/grid/x-data-grid-pro/src/index.ts index ac239a836d14..4e445d67ce86 100644 --- a/packages/grid/x-data-grid-pro/src/index.ts +++ b/packages/grid/x-data-grid-pro/src/index.ts @@ -25,3 +25,9 @@ export type { DataGridProProps, GridExperimentalProFeatures } from './models/dat export { useGridApiContext, useGridApiRef, useGridRootProps } from './typeOverloads/reexports'; export type { GridApi, GridInitialState, GridState } from './typeOverloads/reexports'; + +export { + GridColumnMenu, + GRID_COLUMN_MENU_COMPONENTS, + GRID_COLUMN_MENU_COMPONENTS_PROPS, +} from './components/reexports'; diff --git a/packages/grid/x-data-grid-pro/src/internals/index.ts b/packages/grid/x-data-grid-pro/src/internals/index.ts index 86d3ca0ace19..1a4ff446992c 100644 --- a/packages/grid/x-data-grid-pro/src/internals/index.ts +++ b/packages/grid/x-data-grid-pro/src/internals/index.ts @@ -2,6 +2,7 @@ export * from '@mui/x-data-grid/internals'; export { DataGridProVirtualScroller } from '../components/DataGridProVirtualScroller'; export { DataGridProColumnHeaders } from '../components/DataGridProColumnHeaders'; +export { DATA_GRID_PRO_DEFAULT_SLOTS_COMPONENTS } from '../constants/dataGridProDefaultSlotsComponents'; export { useGridColumnResize, diff --git a/packages/grid/x-data-grid-pro/src/models/dataGridProProps.ts b/packages/grid/x-data-grid-pro/src/models/dataGridProProps.ts index becf77ffdfc2..9e9bb85d41fa 100644 --- a/packages/grid/x-data-grid-pro/src/models/dataGridProProps.ts +++ b/packages/grid/x-data-grid-pro/src/models/dataGridProProps.ts @@ -23,6 +23,7 @@ import { GridGroupingColDefOverrideParams, } from './gridGroupingColDefOverride'; import { GridInitialStatePro } from './gridStatePro'; +import { GridProSlotsComponent } from './gridProSlotsComponent'; export interface GridExperimentalProFeatures extends GridExperimentalFeatures { /** @@ -35,23 +36,36 @@ export interface GridExperimentalProFeatures extends GridExperimentalFeatures { rowPinning: boolean; } +interface DataGridProPropsWithComplexDefaultValueBeforeProcessing + extends Omit { + /** + * Overrideable components. + */ + components?: Partial; +} + /** * The props users can give to the `DataGridProProps` component. */ export interface DataGridProProps extends Omit< Partial & - DataGridPropsWithComplexDefaultValueBeforeProcessing & + DataGridProPropsWithComplexDefaultValueBeforeProcessing & DataGridProPropsWithoutDefaultValue, DataGridProForcedPropsKey > {} +interface DataGridProPropsWithComplexDefaultValueAfterProcessing + extends Omit { + components: GridProSlotsComponent; +} + /** * The props of the `DataGridPro` component after the pre-processing phase. */ export interface DataGridProProcessedProps extends DataGridProPropsWithDefaultValue, - DataGridPropsWithComplexDefaultValueAfterProcessing, + DataGridProPropsWithComplexDefaultValueAfterProcessing, DataGridProPropsWithoutDefaultValue {} export type DataGridProForcedPropsKey = 'signature'; diff --git a/packages/grid/x-data-grid-pro/src/models/gridProIconSlotsComponent.ts b/packages/grid/x-data-grid-pro/src/models/gridProIconSlotsComponent.ts new file mode 100644 index 000000000000..634bb5645548 --- /dev/null +++ b/packages/grid/x-data-grid-pro/src/models/gridProIconSlotsComponent.ts @@ -0,0 +1,14 @@ +import * as React from 'react'; + +export interface GridProIconSlotsComponent { + /** + * Icon displayed in column menu for left pinning + * @default GridPushPinLeftIcon + */ + ColumnMenuPinLeftIcon: React.JSXElementConstructor; + /** + * Icon displayed in column menu for right pinning + * @default GridPushPinRightIcon + */ + ColumnMenuPinRightIcon: React.JSXElementConstructor; +} diff --git a/packages/grid/x-data-grid-pro/src/models/gridProSlotsComponent.ts b/packages/grid/x-data-grid-pro/src/models/gridProSlotsComponent.ts new file mode 100644 index 000000000000..6c14dfd9f2c9 --- /dev/null +++ b/packages/grid/x-data-grid-pro/src/models/gridProSlotsComponent.ts @@ -0,0 +1,8 @@ +import { GridSlotsComponent } from '@mui/x-data-grid'; +import { GridProIconSlotsComponent } from './gridProIconSlotsComponent'; + +/** + * Grid components React prop interface containing all the overridable components + * for Pro package + */ +export interface GridProSlotsComponent extends GridSlotsComponent, GridProIconSlotsComponent {} diff --git a/packages/grid/x-data-grid-pro/src/models/index.ts b/packages/grid/x-data-grid-pro/src/models/index.ts index 43bbe4ae8279..58cfd0bf2f8e 100644 --- a/packages/grid/x-data-grid-pro/src/models/index.ts +++ b/packages/grid/x-data-grid-pro/src/models/index.ts @@ -2,3 +2,5 @@ export * from './gridGroupingColDefOverride'; export * from './gridRowScrollEndParams'; export * from './gridRowOrderChangeParams'; export * from './gridFetchRowsParams'; +export * from './gridProSlotsComponent'; +export * from './gridProIconSlotsComponent'; diff --git a/packages/grid/x-data-grid-pro/src/tests/columnHeaders.DataGridPro.test.tsx b/packages/grid/x-data-grid-pro/src/tests/columnHeaders.DataGridPro.test.tsx index 0b88f04ff3e6..663053cf652f 100644 --- a/packages/grid/x-data-grid-pro/src/tests/columnHeaders.DataGridPro.test.tsx +++ b/packages/grid/x-data-grid-pro/src/tests/columnHeaders.DataGridPro.test.tsx @@ -235,13 +235,12 @@ describe(' - Column Headers', () => { clock.runToLast(); const menu = screen.queryByRole('menu'); - const unsortMenuitem = screen.queryByRole('menuitem', { name: /unsort/i }); + const descMenuitem = screen.queryByRole('menuitem', { name: /sort by desc/i }); expect(menu).toHaveFocus(); fireEvent.keyDown(menu, { key: 'ArrowDown' }); - expect(unsortMenuitem).toHaveFocus(); - fireEvent.keyDown(unsortMenuitem, { key: 'Enter' }); - + expect(descMenuitem).toHaveFocus(); + fireEvent.keyDown(descMenuitem, { key: 'Enter' }); expect(columnCell).toHaveFocus(); }); diff --git a/packages/grid/x-data-grid-pro/src/tests/columnPinning.DataGridPro.test.tsx b/packages/grid/x-data-grid-pro/src/tests/columnPinning.DataGridPro.test.tsx index b2ac1b01f1b0..69b8da79aafd 100644 --- a/packages/grid/x-data-grid-pro/src/tests/columnPinning.DataGridPro.test.tsx +++ b/packages/grid/x-data-grid-pro/src/tests/columnPinning.DataGridPro.test.tsx @@ -603,7 +603,7 @@ describe(' - Column pinning', () => { }); describe('column menu', () => { - it('should pin the column to the left when clicking the "Pin to left" button', () => { + it('should pin the column to the left when clicking the "Pin to left" pinning button', () => { render(); const columnCell = document.querySelector('[role="columnheader"][data-field="id"]')!; const menuIconButton = columnCell.querySelector('button[aria-label="Menu"]'); @@ -614,7 +614,7 @@ describe(' - Column pinning', () => { ).not.to.equal(null); }); - it('should pin the column to the right when clicking the "Pin to right" button', () => { + it('should pin the column to the right when clicking the "Pin to right" pinning button', () => { render(); const columnCell = document.querySelector('[role="columnheader"][data-field="id"]')!; const menuIconButton = columnCell.querySelector('button[aria-label="Menu"]'); @@ -625,7 +625,7 @@ describe(' - Column pinning', () => { ).not.to.equal(null); }); - it('should allow to invert the side when clicking on "Pin to right" on a left pinned column', () => { + it('should allow to invert the side when clicking on "Pin to right" pinning button on a left pinned column', () => { render(); const columnCell = document.querySelector('[role="columnheader"][data-field="id"]')!; const menuIconButton = columnCell.querySelector('button[aria-label="Menu"]'); @@ -639,7 +639,7 @@ describe(' - Column pinning', () => { ).not.to.equal(null); }); - it('should allow to invert the side when clicking on "Pin to left" on a right pinned column', () => { + it('should allow to invert the side when clicking on "Pin to left" pinning button on a right pinned column', () => { render(); const columnCell = document.querySelector('[role="columnheader"][data-field="id"]')!; const menuIconButton = columnCell.querySelector('button[aria-label="Menu"]'); @@ -653,7 +653,7 @@ describe(' - Column pinning', () => { ).not.to.equal(null); }); - it('should allow to unpin a pinned column when clicking "Unpin"', () => { + it('should allow to unpin a pinned left column when clicking "Unpin" pinning button', () => { render(); const columnCell = document.querySelector('[role="columnheader"][data-field="id"]')!; const menuIconButton = columnCell.querySelector('button[aria-label="Menu"]'); diff --git a/packages/grid/x-data-grid/src/DataGrid/useDataGridProps.ts b/packages/grid/x-data-grid/src/DataGrid/useDataGridProps.ts index 4b04655007cb..792b14c10a8a 100644 --- a/packages/grid/x-data-grid/src/DataGrid/useDataGridProps.ts +++ b/packages/grid/x-data-grid/src/DataGrid/useDataGridProps.ts @@ -6,7 +6,8 @@ import { DataGridForcedPropsKey, DataGridPropsWithDefaultValues, } from '../models/props/DataGridProps'; -import { DATA_GRID_DEFAULT_SLOTS_COMPONENTS, GRID_DEFAULT_LOCALE_TEXT } from '../constants'; +import { GRID_DEFAULT_LOCALE_TEXT } from '../constants'; +import { DATA_GRID_DEFAULT_SLOTS_COMPONENTS } from '../constants/defaultGridSlotsComponents'; import { GridDensityTypes, GridEditModes, GridSlotsComponent, GridValidRowModel } from '../models'; const DATA_GRID_FORCED_PROPS: { [key in DataGridForcedPropsKey]?: DataGridProcessedProps[key] } = { diff --git a/packages/grid/x-data-grid/src/components/columnHeaders/ColumnHeaderMenuIcon.tsx b/packages/grid/x-data-grid/src/components/columnHeaders/ColumnHeaderMenuIcon.tsx index ce8c27f373cf..c3a0fb488403 100644 --- a/packages/grid/x-data-grid/src/components/columnHeaders/ColumnHeaderMenuIcon.tsx +++ b/packages/grid/x-data-grid/src/components/columnHeaders/ColumnHeaderMenuIcon.tsx @@ -8,7 +8,7 @@ import { useGridRootProps } from '../../hooks/utils/useGridRootProps'; import { DataGridProcessedProps } from '../../models/props/DataGridProps'; export interface ColumnHeaderMenuIconProps { - column: GridStateColDef; + colDef: GridStateColDef; columnMenuId: string; columnMenuButtonId: string; open: boolean; @@ -31,7 +31,7 @@ const useUtilityClasses = (ownerState: OwnerState) => { }; export const ColumnHeaderMenuIcon = React.memo((props: ColumnHeaderMenuIconProps) => { - const { column, open, columnMenuId, columnMenuButtonId, iconButtonRef } = props; + const { colDef, open, columnMenuId, columnMenuButtonId, iconButtonRef } = props; const apiRef = useGridApiContext(); const rootProps = useGridRootProps(); const ownerState = { ...props, classes: rootProps.classes }; @@ -41,9 +41,9 @@ export const ColumnHeaderMenuIcon = React.memo((props: ColumnHeaderMenuIconProps (event: React.MouseEvent) => { event.preventDefault(); event.stopPropagation(); - apiRef.current.toggleColumnMenu(column.field); + apiRef.current.toggleColumnMenu(colDef.field); }, - [apiRef, column.field], + [apiRef, colDef.field], ); return ( diff --git a/packages/grid/x-data-grid/src/components/columnHeaders/GridColumnHeaderItem.tsx b/packages/grid/x-data-grid/src/components/columnHeaders/GridColumnHeaderItem.tsx index f036d9f83f8e..3b332ce96080 100644 --- a/packages/grid/x-data-grid/src/components/columnHeaders/GridColumnHeaderItem.tsx +++ b/packages/grid/x-data-grid/src/components/columnHeaders/GridColumnHeaderItem.tsx @@ -16,7 +16,7 @@ import { GridColumnHeaderEventLookup } from '../../models/events'; interface GridColumnHeaderItemProps { colIndex: number; - column: GridStateColDef; + colDef: GridStateColDef; columnMenuOpen: boolean; headerHeight: number; isDragging: boolean; @@ -38,21 +38,21 @@ type OwnerState = GridColumnHeaderItemProps & { }; const useUtilityClasses = (ownerState: OwnerState) => { - const { column, classes, isDragging, sortDirection, showRightBorder, filterItemsCounter } = + const { colDef, classes, isDragging, sortDirection, showRightBorder, filterItemsCounter } = ownerState; const isColumnSorted = sortDirection != null; const isColumnFiltered = filterItemsCounter != null && filterItemsCounter > 0; // todo refactor to a prop on col isNumeric or ?? ie: coltype===price wont work - const isColumnNumeric = column.type === 'number'; + const isColumnNumeric = colDef.type === 'number'; const slots = { root: [ 'columnHeader', - column.headerAlign === 'left' && 'columnHeader--alignLeft', - column.headerAlign === 'center' && 'columnHeader--alignCenter', - column.headerAlign === 'right' && 'columnHeader--alignRight', - column.sortable && 'columnHeader--sortable', + colDef.headerAlign === 'left' && 'columnHeader--alignLeft', + colDef.headerAlign === 'center' && 'columnHeader--alignCenter', + colDef.headerAlign === 'right' && 'columnHeader--alignRight', + colDef.sortable && 'columnHeader--sortable', isDragging && 'columnHeader--moving', isColumnSorted && 'columnHeader--sorted', isColumnFiltered && 'columnHeader--filtered', @@ -70,7 +70,7 @@ const useUtilityClasses = (ownerState: OwnerState) => { function GridColumnHeaderItem(props: GridColumnHeaderItemProps) { const { - column, + colDef, columnMenuOpen, colIndex, headerHeight, @@ -98,13 +98,13 @@ function GridColumnHeaderItem(props: GridColumnHeaderItemProps) { }; const isDraggable = React.useMemo( - () => !rootProps.disableColumnReorder && !disableReorder && !column.disableReorder, - [rootProps.disableColumnReorder, disableReorder, column.disableReorder], + () => !rootProps.disableColumnReorder && !disableReorder && !colDef.disableReorder, + [rootProps.disableColumnReorder, disableReorder, colDef.disableReorder], ); let headerComponent: React.ReactNode; - if (column.renderHeader) { - headerComponent = column.renderHeader(apiRef.current.getColumnHeaderParams(column.field)); + if (colDef.renderHeader) { + headerComponent = colDef.renderHeader(apiRef.current.getColumnHeaderParams(colDef.field)); } const removeLastBorderRight = isLastColumn && hasScrollX && !hasScrollY; @@ -129,11 +129,11 @@ function GridColumnHeaderItem(props: GridColumnHeaderItemProps) { } apiRef.current.publishEvent( eventName, - apiRef.current.getColumnHeaderParams(column.field), + apiRef.current.getColumnHeaderParams(colDef.field), event as any, ); }, - [apiRef, column.field], + [apiRef, colDef.field], ); const mouseEventsHandlers = React.useMemo( @@ -179,9 +179,9 @@ function GridColumnHeaderItem(props: GridColumnHeaderItemProps) { setShowColumnMenuIcon(false); }, []); - const columnMenuIconButton = !rootProps.disableColumnMenu && !column.disableColumnMenu && ( + const columnMenuIconButton = !rootProps.disableColumnMenu && !colDef.disableColumnMenu && ( ); - const sortingOrder: GridSortDirection[] = column.sortingOrder ?? rootProps.sortingOrder; + const sortingOrder: GridSortDirection[] = colDef.sortingOrder ?? rootProps.sortingOrder; const columnTitleIconButtons = ( {!rootProps.disableColumnFilter && ( )} - {column.sortable && !column.hideSortIcons && ( + {colDef.sortable && !colDef.hideSortIcons && ( , 'MoreVert', ); + +export const GridVisibilityOffIcon = createSvgIcon( + , + 'VisibilityOff', +); + +export const GridViewColumnIcon = createSvgIcon( + + + , + 'ViewColumn', +); + +export const GridClearIcon = createSvgIcon( + , + 'Clear', +); diff --git a/packages/grid/x-data-grid/src/components/menu/GridMenu.tsx b/packages/grid/x-data-grid/src/components/menu/GridMenu.tsx index e9f6e705d2f2..1ccb2352887c 100644 --- a/packages/grid/x-data-grid/src/components/menu/GridMenu.tsx +++ b/packages/grid/x-data-grid/src/components/menu/GridMenu.tsx @@ -42,7 +42,7 @@ const useUtilityClasses = (ownerState: OwnerState) => { const GridMenuRoot = styled(Popper, { name: 'MuiDataGrid', slot: 'Menu', - overridesResolver: (props, styles) => styles.menu, + overridesResolver: (_, styles) => styles.menu, })(({ theme }) => ({ zIndex: theme.zIndex.modal, [`& .${gridClasses.menuList}`]: { @@ -67,23 +67,14 @@ const transformOrigin = { function GridMenu(props: GridMenuProps) { const { open, target, onClickAway, children, position, className, onExited, ...other } = props; const apiRef = useGridApiContext(); - const prevTarget = React.useRef(target); - const prevOpen = React.useRef(open); const rootProps = useGridRootProps(); const ownerState = { classes: rootProps.classes }; const classes = useUtilityClasses(ownerState); React.useEffect(() => { - if (prevOpen.current && prevTarget.current) { - (prevTarget.current as HTMLElement).focus(); - } - // Emit menuOpen or menuClose events const eventName = open ? 'menuOpen' : 'menuClose'; apiRef.current.publishEvent(eventName, { target }); - - prevOpen.current = open; - prevTarget.current = target; }, [apiRef, open, target]); const handleExited = (popperOnExited: (() => {}) | undefined) => (node: HTMLElement) => { diff --git a/packages/grid/x-data-grid/src/components/menu/columnMenu/GridColumnHeaderMenu.tsx b/packages/grid/x-data-grid/src/components/menu/columnMenu/GridColumnHeaderMenu.tsx index 728d1fff7fe9..45977b180993 100644 --- a/packages/grid/x-data-grid/src/components/menu/columnMenu/GridColumnHeaderMenu.tsx +++ b/packages/grid/x-data-grid/src/components/menu/columnMenu/GridColumnHeaderMenu.tsx @@ -26,7 +26,7 @@ function GridColumnHeaderMenu({ onExited, }: GridColumnHeaderMenuProps) { const apiRef = useGridApiContext(); - const currentColumn = apiRef.current.getColumn(field); + const colDef = apiRef.current.getColumn(field); const hideMenu = React.useCallback( (event: MouseEvent | TouchEvent) => { @@ -43,14 +43,14 @@ function GridColumnHeaderMenu({ return ( ( - function GridColumnMenu(props: GridColumnMenuProps, ref) { - const { hideMenu, currentColumn } = props; - const apiRef = useGridApiContext(); - - const defaultButtons = [ - , // TODO update types to allow `onClick` and `column` to be optional - , - , - , - ]; - - const preProcessedButtons = apiRef.current.unstable_applyPipeProcessors( - 'columnMenu', - defaultButtons, - currentColumn, - ); +export const GRID_COLUMN_MENU_COMPONENTS = { + ColumnMenuSortItem: GridColumnMenuSortItem, + ColumnMenuFilterItem: GridColumnMenuFilterItem, + ColumnMenuColumnsItem: GridColumnMenuColumnsItem, +}; + +export const GRID_COLUMN_MENU_COMPONENTS_PROPS = { + columnMenuSortItem: { displayOrder: 10 }, + columnMenuFilterItem: { displayOrder: 20 }, + columnMenuColumnsItem: { displayOrder: 30 }, +}; + +const GridGenericColumnMenu = React.forwardRef( + function GridGenericColumnMenu(props, ref) { + const { defaultComponents, defaultComponentsProps, components, componentsProps, ...other } = + props; + + const orderedComponents = useGridColumnMenuComponents({ + ...other, + defaultComponents, + defaultComponentsProps, + components, + componentsProps, + }); return ( - - {preProcessedButtons.map((button: any, index: number) => - React.cloneElement(button, { key: index, onClick: hideMenu, column: currentColumn }), - )} + + {orderedComponents.map(([Component, componentProps], index) => ( + + ))} ); }, ); +const GridColumnMenu = React.forwardRef( + function GridColumnMenu(props, ref) { + return ( + + ); + }, +); + GridColumnMenu.propTypes = { // ----------------------------- Warning -------------------------------- // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "yarn proptypes" | // ---------------------------------------------------------------------- - currentColumn: PropTypes.object.isRequired, + colDef: PropTypes.object.isRequired, + /** + * `components` could be used to add new and (or) override default column menu items + * If you register a nee component you must pass it's `displayOrder` in `componentsProps` + * or it will be placed in the end of the list + */ + components: PropTypes.object, + /** + * Could be used to pass new props or override props specific to a column menu component + * e.g. `displayOrder` + */ + componentsProps: PropTypes.object, hideMenu: PropTypes.func.isRequired, id: PropTypes.string, labelledby: PropTypes.string, open: PropTypes.bool.isRequired, } as any; -export { GridColumnMenu }; +export { GridColumnMenu, GridGenericColumnMenu }; diff --git a/packages/grid/x-data-grid/src/components/menu/columnMenu/GridColumnMenuContainer.tsx b/packages/grid/x-data-grid/src/components/menu/columnMenu/GridColumnMenuContainer.tsx index e8995bcdffbb..fdb51803c566 100644 --- a/packages/grid/x-data-grid/src/components/menu/columnMenu/GridColumnMenuContainer.tsx +++ b/packages/grid/x-data-grid/src/components/menu/columnMenu/GridColumnMenuContainer.tsx @@ -2,13 +2,19 @@ import clsx from 'clsx'; import PropTypes from 'prop-types'; import * as React from 'react'; import MenuList from '@mui/material/MenuList'; +import { styled } from '@mui/material/styles'; + import { isHideMenuKey, isTabKey } from '../../../utils/keyboardUtils'; -import { GridColumnMenuProps } from './GridColumnMenuProps'; +import { GridColumnMenuContainerProps } from './GridColumnMenuProps'; import { gridClasses } from '../../../constants/gridClasses'; -const GridColumnMenuContainer = React.forwardRef( - function GridColumnMenuContainer(props: GridColumnMenuProps, ref) { - const { hideMenu, currentColumn, open, id, labelledby, className, children, ...other } = props; +const StyledMenuList = styled(MenuList)(() => ({ + minWidth: 248, +})); + +const GridColumnMenuContainer = React.forwardRef( + function GridColumnMenuContainer(props, ref) { + const { hideMenu, colDef, id, labelledby, className, children, open, ...other } = props; const handleListKeyDown = React.useCallback( (event: React.KeyboardEvent) => { @@ -23,7 +29,7 @@ const GridColumnMenuContainer = React.forwardRef {children} - + ); }, ); @@ -43,7 +49,7 @@ GridColumnMenuContainer.propTypes = { // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "yarn proptypes" | // ---------------------------------------------------------------------- - currentColumn: PropTypes.object.isRequired, + colDef: PropTypes.object.isRequired, hideMenu: PropTypes.func.isRequired, id: PropTypes.string, labelledby: PropTypes.string, diff --git a/packages/grid/x-data-grid/src/components/menu/columnMenu/GridFilterItemProps.ts b/packages/grid/x-data-grid/src/components/menu/columnMenu/GridColumnMenuItemProps.ts similarity index 55% rename from packages/grid/x-data-grid/src/components/menu/columnMenu/GridFilterItemProps.ts rename to packages/grid/x-data-grid/src/components/menu/columnMenu/GridColumnMenuItemProps.ts index 2ecdfe35b278..64c4da14e8b8 100644 --- a/packages/grid/x-data-grid/src/components/menu/columnMenu/GridFilterItemProps.ts +++ b/packages/grid/x-data-grid/src/components/menu/columnMenu/GridColumnMenuItemProps.ts @@ -1,7 +1,10 @@ import * as React from 'react'; import { GridColDef } from '../../../models/colDef/gridColDef'; -export interface GridFilterItemProps { - column: GridColDef; +export interface GridColumnMenuItemProps { + // Native Props + colDef: GridColDef; onClick: (event: React.MouseEvent) => void; + // User Props + [key: string]: any; } diff --git a/packages/grid/x-data-grid/src/components/menu/columnMenu/GridColumnMenuProps.ts b/packages/grid/x-data-grid/src/components/menu/columnMenu/GridColumnMenuProps.ts index 4d99a4d8a4a3..b87a5d6d385e 100644 --- a/packages/grid/x-data-grid/src/components/menu/columnMenu/GridColumnMenuProps.ts +++ b/packages/grid/x-data-grid/src/components/menu/columnMenu/GridColumnMenuProps.ts @@ -1,10 +1,18 @@ import * as React from 'react'; import { GridColDef } from '../../../models/colDef/gridColDef'; +import { GridColumnMenuRootProps } from '../../../hooks/features/columnMenu'; -export interface GridColumnMenuProps extends React.HTMLAttributes { +export interface GridColumnMenuContainerProps extends React.HTMLAttributes { hideMenu: (event: React.SyntheticEvent) => void; - currentColumn: GridColDef; + colDef: GridColDef; open: boolean; id?: string; labelledby?: string; } + +export interface GridGenericColumnMenuProps + extends GridColumnMenuRootProps, + GridColumnMenuContainerProps {} + +export interface GridColumnMenuProps + extends Omit {} diff --git a/packages/grid/x-data-grid/src/components/menu/columnMenu/GridFilterMenuItem.tsx b/packages/grid/x-data-grid/src/components/menu/columnMenu/GridFilterMenuItem.tsx deleted file mode 100644 index 785e17fc1958..000000000000 --- a/packages/grid/x-data-grid/src/components/menu/columnMenu/GridFilterMenuItem.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import MenuItem from '@mui/material/MenuItem'; -import { useGridApiContext } from '../../../hooks/utils/useGridApiContext'; -import { GridFilterItemProps } from './GridFilterItemProps'; -import { useGridRootProps } from '../../../hooks/utils/useGridRootProps'; - -function GridFilterMenuItem(props: GridFilterItemProps) { - const { column, onClick } = props; - const apiRef = useGridApiContext(); - const rootProps = useGridRootProps(); - - const showFilter = React.useCallback( - (event: React.MouseEvent) => { - onClick(event); - apiRef.current.showFilterPanel(column?.field); - }, - [apiRef, column?.field, onClick], - ); - - if (rootProps.disableColumnFilter || !column?.filterable) { - return null; - } - - return ( - {apiRef.current.getLocaleText('columnMenuFilter')} - ); -} - -GridFilterMenuItem.propTypes = { - // ----------------------------- Warning -------------------------------- - // | These PropTypes are generated from the TypeScript type definitions | - // | To update them edit the TypeScript types and run "yarn proptypes" | - // ---------------------------------------------------------------------- - column: PropTypes.object.isRequired, - onClick: PropTypes.func.isRequired, -} as any; - -export { GridFilterMenuItem }; diff --git a/packages/grid/x-data-grid/src/components/menu/columnMenu/SortGridMenuItems.tsx b/packages/grid/x-data-grid/src/components/menu/columnMenu/SortGridMenuItems.tsx deleted file mode 100644 index 62f2cd9a8879..000000000000 --- a/packages/grid/x-data-grid/src/components/menu/columnMenu/SortGridMenuItems.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import MenuItem from '@mui/material/MenuItem'; -import { useGridSelector } from '../../../hooks/utils/useGridSelector'; -import { gridSortModelSelector } from '../../../hooks/features/sorting/gridSortingSelector'; -import { GridSortDirection } from '../../../models/gridSortModel'; -import { useGridApiContext } from '../../../hooks/utils/useGridApiContext'; -import { GridFilterItemProps } from './GridFilterItemProps'; -import { useGridRootProps } from '../../../hooks/utils/useGridRootProps'; - -function SortGridMenuItems(props: GridFilterItemProps) { - const { column, onClick } = props; - const apiRef = useGridApiContext(); - const sortModel = useGridSelector(apiRef, gridSortModelSelector); - const rootProps = useGridRootProps(); - const sortingOrder: GridSortDirection[] = column.sortingOrder ?? rootProps.sortingOrder; - - const sortDirection = React.useMemo(() => { - if (!column) { - return null; - } - const sortItem = sortModel.find((item) => item.field === column.field); - return sortItem?.sort; - }, [column, sortModel]); - - const onSortMenuItemClick = React.useCallback( - (event: React.MouseEvent) => { - onClick(event); - const direction = event.currentTarget.getAttribute('data-value') || null; - apiRef.current.sortColumn(column!, direction as GridSortDirection); - }, - [apiRef, column, onClick], - ); - - if (!column || !column.sortable) { - return null; - } - - return ( - - {sortingOrder.includes(null) ? ( - - {apiRef.current.getLocaleText('columnMenuUnsort')} - - ) : null} - {sortingOrder.includes('asc') ? ( - - {apiRef.current.getLocaleText('columnMenuSortAsc')} - - ) : null} - {sortingOrder.includes('desc') ? ( - - {apiRef.current.getLocaleText('columnMenuSortDesc')} - - ) : null} - - ); -} - -SortGridMenuItems.propTypes = { - // ----------------------------- Warning -------------------------------- - // | These PropTypes are generated from the TypeScript type definitions | - // | To update them edit the TypeScript types and run "yarn proptypes" | - // ---------------------------------------------------------------------- - column: PropTypes.object.isRequired, - onClick: PropTypes.func.isRequired, -} as any; - -export { SortGridMenuItems }; diff --git a/packages/grid/x-data-grid/src/components/menu/columnMenu/index.ts b/packages/grid/x-data-grid/src/components/menu/columnMenu/index.ts index 595ecb7bedd1..d05e447ba695 100644 --- a/packages/grid/x-data-grid/src/components/menu/columnMenu/index.ts +++ b/packages/grid/x-data-grid/src/components/menu/columnMenu/index.ts @@ -1,9 +1,9 @@ -export * from './GridColumnsMenuItem'; -export * from './GridFilterItemProps'; -export * from './GridFilterMenuItem'; +// shared modules export * from './GridColumnHeaderMenu'; -export * from './GridColumnMenu'; -export * from './HideGridColMenuItem'; -export * from './SortGridMenuItems'; -export * from './GridColumnMenuContainer'; export * from './GridColumnMenuProps'; +export * from './GridColumnMenuItemProps'; +export * from './GridColumnMenuContainer'; +export { GridGenericColumnMenu } from './GridColumnMenu'; + +// items +export * from './menuItems'; diff --git a/packages/grid/x-data-grid/src/components/menu/columnMenu/menuItems/GridColumnMenuColumnsItem.tsx b/packages/grid/x-data-grid/src/components/menu/columnMenu/menuItems/GridColumnMenuColumnsItem.tsx new file mode 100644 index 000000000000..5cf4355d3a43 --- /dev/null +++ b/packages/grid/x-data-grid/src/components/menu/columnMenu/menuItems/GridColumnMenuColumnsItem.tsx @@ -0,0 +1,25 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import { GridColumnMenuItemProps } from '../GridColumnMenuItemProps'; +import { GridColumnMenuHideItem } from './GridColumnMenuHideItem'; +import { GridColumnMenuManageItem } from './GridColumnMenuManageItem'; + +function GridColumnMenuColumnsItem(props: GridColumnMenuItemProps) { + return ( + + + + + ); +} + +GridColumnMenuColumnsItem.propTypes = { + // ----------------------------- Warning -------------------------------- + // | These PropTypes are generated from the TypeScript type definitions | + // | To update them edit the TypeScript types and run "yarn proptypes" | + // ---------------------------------------------------------------------- + colDef: PropTypes.object.isRequired, + onClick: PropTypes.func.isRequired, +} as any; + +export { GridColumnMenuColumnsItem }; diff --git a/packages/grid/x-data-grid/src/components/menu/columnMenu/menuItems/GridColumnMenuFilterItem.tsx b/packages/grid/x-data-grid/src/components/menu/columnMenu/menuItems/GridColumnMenuFilterItem.tsx new file mode 100644 index 000000000000..9691bd6d97a8 --- /dev/null +++ b/packages/grid/x-data-grid/src/components/menu/columnMenu/menuItems/GridColumnMenuFilterItem.tsx @@ -0,0 +1,46 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import MenuItem from '@mui/material/MenuItem'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import { useGridApiContext } from '../../../../hooks/utils/useGridApiContext'; +import { GridColumnMenuItemProps } from '../GridColumnMenuItemProps'; +import { useGridRootProps } from '../../../../hooks/utils/useGridRootProps'; + +function GridColumnMenuFilterItem(props: GridColumnMenuItemProps) { + const { colDef, onClick } = props; + const apiRef = useGridApiContext(); + const rootProps = useGridRootProps(); + + const showFilter = React.useCallback( + (event: React.MouseEvent) => { + onClick(event); + apiRef.current.showFilterPanel(colDef.field); + }, + [apiRef, colDef.field, onClick], + ); + + if (rootProps.disableColumnFilter || !colDef.filterable) { + return null; + } + + return ( + + + + + {apiRef.current.getLocaleText('columnMenuFilter')} + + ); +} + +GridColumnMenuFilterItem.propTypes = { + // ----------------------------- Warning -------------------------------- + // | These PropTypes are generated from the TypeScript type definitions | + // | To update them edit the TypeScript types and run "yarn proptypes" | + // ---------------------------------------------------------------------- + colDef: PropTypes.object.isRequired, + onClick: PropTypes.func.isRequired, +} as any; + +export { GridColumnMenuFilterItem }; diff --git a/packages/grid/x-data-grid/src/components/menu/columnMenu/HideGridColMenuItem.tsx b/packages/grid/x-data-grid/src/components/menu/columnMenu/menuItems/GridColumnMenuHideItem.tsx similarity index 57% rename from packages/grid/x-data-grid/src/components/menu/columnMenu/HideGridColMenuItem.tsx rename to packages/grid/x-data-grid/src/components/menu/columnMenu/menuItems/GridColumnMenuHideItem.tsx index fcde932ad24a..f883640e3009 100644 --- a/packages/grid/x-data-grid/src/components/menu/columnMenu/HideGridColMenuItem.tsx +++ b/packages/grid/x-data-grid/src/components/menu/columnMenu/menuItems/GridColumnMenuHideItem.tsx @@ -1,16 +1,17 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import MenuItem from '@mui/material/MenuItem'; -import { GridFilterItemProps } from './GridFilterItemProps'; -import { useGridApiContext } from '../../../hooks/utils/useGridApiContext'; -import { useGridRootProps } from '../../../hooks/utils/useGridRootProps'; -import { gridVisibleColumnDefinitionsSelector } from '../../../hooks/features/columns'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import { GridColumnMenuItemProps } from '../GridColumnMenuItemProps'; +import { useGridApiContext } from '../../../../hooks/utils/useGridApiContext'; +import { useGridRootProps } from '../../../../hooks/utils/useGridRootProps'; +import { gridVisibleColumnDefinitionsSelector } from '../../../../hooks/features/columns'; -function HideGridColMenuItem(props: GridFilterItemProps) { - const { column, onClick } = props; +function GridColumnMenuHideItem(props: GridColumnMenuItemProps) { + const { colDef, onClick } = props; const apiRef = useGridApiContext(); const rootProps = useGridRootProps(); - const timeoutRef = React.useRef(); const visibleColumns = gridVisibleColumnDefinitionsSelector(apiRef); const columnsWithMenu = visibleColumns.filter((col) => col.disableColumnMenu !== true); @@ -27,41 +28,37 @@ function HideGridColMenuItem(props: GridFilterItemProps) { if (disabled) { return; } + apiRef.current.setColumnVisibility(colDef.field, false); onClick(event); - // time for the transition - timeoutRef.current = setTimeout(() => { - apiRef.current.setColumnVisibility(column?.field, false); - }, 100); }, - [apiRef, column?.field, onClick, disabled], + [apiRef, colDef.field, onClick, disabled], ); - React.useEffect(() => { - return () => clearTimeout(timeoutRef.current); - }, []); - if (rootProps.disableColumnSelector) { return null; } - if (column.hideable === false) { + if (colDef.hideable === false) { return null; } return ( - {apiRef.current.getLocaleText('columnMenuHideColumn')} + + + + {apiRef.current.getLocaleText('columnMenuHideColumn')} ); } -HideGridColMenuItem.propTypes = { +GridColumnMenuHideItem.propTypes = { // ----------------------------- Warning -------------------------------- // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "yarn proptypes" | // ---------------------------------------------------------------------- - column: PropTypes.object.isRequired, + colDef: PropTypes.object.isRequired, onClick: PropTypes.func.isRequired, } as any; -export { HideGridColMenuItem }; +export { GridColumnMenuHideItem }; diff --git a/packages/grid/x-data-grid/src/components/menu/columnMenu/GridColumnsMenuItem.tsx b/packages/grid/x-data-grid/src/components/menu/columnMenu/menuItems/GridColumnMenuManageItem.tsx similarity index 50% rename from packages/grid/x-data-grid/src/components/menu/columnMenu/GridColumnsMenuItem.tsx rename to packages/grid/x-data-grid/src/components/menu/columnMenu/menuItems/GridColumnMenuManageItem.tsx index dcb0dd6ba7a9..609837dbe56f 100644 --- a/packages/grid/x-data-grid/src/components/menu/columnMenu/GridColumnsMenuItem.tsx +++ b/packages/grid/x-data-grid/src/components/menu/columnMenu/menuItems/GridColumnMenuManageItem.tsx @@ -1,19 +1,21 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import MenuItem from '@mui/material/MenuItem'; -import { GridPreferencePanelsValue } from '../../../hooks/features/preferencesPanel/gridPreferencePanelsValue'; -import { useGridApiContext } from '../../../hooks/utils/useGridApiContext'; -import { GridFilterItemProps } from './GridFilterItemProps'; -import { useGridRootProps } from '../../../hooks/utils/useGridRootProps'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import { GridPreferencePanelsValue } from '../../../../hooks/features/preferencesPanel/gridPreferencePanelsValue'; +import { useGridApiContext } from '../../../../hooks/utils/useGridApiContext'; +import { GridColumnMenuItemProps } from '../GridColumnMenuItemProps'; +import { useGridRootProps } from '../../../../hooks/utils/useGridRootProps'; -function GridColumnsMenuItem(props: GridFilterItemProps) { +function GridColumnMenuManageItem(props: GridColumnMenuItemProps) { const { onClick } = props; const apiRef = useGridApiContext(); const rootProps = useGridRootProps(); const showColumns = React.useCallback( (event: React.MouseEvent) => { - onClick(event); + onClick(event); // hide column menu apiRef.current.showPreferences(GridPreferencePanelsValue.columns); }, [apiRef, onClick], @@ -25,18 +27,21 @@ function GridColumnsMenuItem(props: GridFilterItemProps) { return ( - {apiRef.current.getLocaleText('columnMenuShowColumns')} + + + + {apiRef.current.getLocaleText('columnMenuManageColumns')} ); } -GridColumnsMenuItem.propTypes = { +GridColumnMenuManageItem.propTypes = { // ----------------------------- Warning -------------------------------- // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "yarn proptypes" | // ---------------------------------------------------------------------- - column: PropTypes.object.isRequired, + colDef: PropTypes.object.isRequired, onClick: PropTypes.func.isRequired, } as any; -export { GridColumnsMenuItem }; +export { GridColumnMenuManageItem }; diff --git a/packages/grid/x-data-grid/src/components/menu/columnMenu/menuItems/GridColumnMenuSortItem.tsx b/packages/grid/x-data-grid/src/components/menu/columnMenu/menuItems/GridColumnMenuSortItem.tsx new file mode 100644 index 000000000000..586ce05ce6aa --- /dev/null +++ b/packages/grid/x-data-grid/src/components/menu/columnMenu/menuItems/GridColumnMenuSortItem.tsx @@ -0,0 +1,82 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import MenuItem from '@mui/material/MenuItem'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import { useGridSelector } from '../../../../hooks/utils/useGridSelector'; +import { gridSortModelSelector } from '../../../../hooks/features/sorting/gridSortingSelector'; +import { GridSortDirection } from '../../../../models/gridSortModel'; +import { useGridApiContext } from '../../../../hooks/utils/useGridApiContext'; +import { GridColumnMenuItemProps } from '../GridColumnMenuItemProps'; +import { useGridRootProps } from '../../../../hooks/utils/useGridRootProps'; + +function GridColumnMenuSortItem(props: GridColumnMenuItemProps) { + const { colDef, onClick } = props; + const apiRef = useGridApiContext(); + const sortModel = useGridSelector(apiRef, gridSortModelSelector); + const rootProps = useGridRootProps(); + + const sortDirection = React.useMemo(() => { + if (!colDef) { + return null; + } + const sortItem = sortModel.find((item) => item.field === colDef.field); + return sortItem?.sort; + }, [colDef, sortModel]); + + const sortingOrder: GridSortDirection[] = colDef.sortingOrder ?? rootProps.sortingOrder; + + const onSortMenuItemClick = React.useCallback( + (event: React.MouseEvent) => { + onClick(event); + const direction = event.currentTarget.getAttribute('data-value') || null; + apiRef.current.sortColumn( + colDef!, + (direction === sortDirection ? null : direction) as GridSortDirection, + ); + }, + [apiRef, colDef, onClick, sortDirection], + ); + + if (!colDef || !colDef.sortable || !sortingOrder.some((item) => !!item)) { + return null; + } + + return ( + + {sortingOrder.includes('asc') && sortDirection !== 'asc' ? ( + + + + + {apiRef.current.getLocaleText('columnMenuSortAsc')} + + ) : null} + {sortingOrder.includes('desc') && sortDirection !== 'desc' ? ( + + + + + {apiRef.current.getLocaleText('columnMenuSortDesc')} + + ) : null} + {sortingOrder.includes(null) && sortDirection != null ? ( + + + {apiRef.current.getLocaleText('columnMenuUnsort')} + + ) : null} + + ); +} + +GridColumnMenuSortItem.propTypes = { + // ----------------------------- Warning -------------------------------- + // | These PropTypes are generated from the TypeScript type definitions | + // | To update them edit the TypeScript types and run "yarn proptypes" | + // ---------------------------------------------------------------------- + colDef: PropTypes.object.isRequired, + onClick: PropTypes.func.isRequired, +} as any; + +export { GridColumnMenuSortItem }; diff --git a/packages/grid/x-data-grid/src/components/menu/columnMenu/menuItems/index.ts b/packages/grid/x-data-grid/src/components/menu/columnMenu/menuItems/index.ts new file mode 100644 index 000000000000..5b5ce5e88c53 --- /dev/null +++ b/packages/grid/x-data-grid/src/components/menu/columnMenu/menuItems/index.ts @@ -0,0 +1,5 @@ +export * from './GridColumnMenuColumnsItem'; +export * from './GridColumnMenuManageItem'; +export * from './GridColumnMenuFilterItem'; +export * from './GridColumnMenuHideItem'; +export * from './GridColumnMenuSortItem'; diff --git a/packages/grid/x-data-grid/src/components/reexportable.ts b/packages/grid/x-data-grid/src/components/reexportable.ts new file mode 100644 index 000000000000..6732f3187ce2 --- /dev/null +++ b/packages/grid/x-data-grid/src/components/reexportable.ts @@ -0,0 +1,5 @@ +export { + GridColumnMenu, + GRID_COLUMN_MENU_COMPONENTS, + GRID_COLUMN_MENU_COMPONENTS_PROPS, +} from './menu/columnMenu/GridColumnMenu'; diff --git a/packages/grid/x-data-grid/src/constants/defaultGridSlotsComponents.ts b/packages/grid/x-data-grid/src/constants/defaultGridSlotsComponents.ts index dadcedad4235..710f8b87ff71 100644 --- a/packages/grid/x-data-grid/src/constants/defaultGridSlotsComponents.ts +++ b/packages/grid/x-data-grid/src/constants/defaultGridSlotsComponents.ts @@ -15,7 +15,6 @@ import { GridCheckIcon, GridCloseIcon, GridColumnIcon, - GridColumnMenu, GridColumnsPanel, GridFilterAltIcon, GridFilterListIcon, @@ -41,7 +40,11 @@ import { GridDragIcon, GridColumnHeaderFilterIconButton, GridSearchIcon, + GridVisibilityOffIcon, + GridViewColumnIcon, + GridClearIcon, } from '../components'; +import { GridColumnMenu } from '../components/menu/columnMenu/GridColumnMenu'; import { GridColumnUnsortedIcon } from '../components/columnHeaders/GridColumnUnsortedIcon'; import { GridErrorOverlay } from '../components/GridErrorOverlay'; import { GridNoResultsOverlay } from '../components/GridNoResultsOverlay'; @@ -72,11 +75,14 @@ const DEFAULT_GRID_ICON_SLOTS_COMPONENTS: GridIconSlotsComponent = { RowReorderIcon: GridDragIcon, QuickFilterIcon: GridSearchIcon, QuickFilterClearIcon: GridCloseIcon, + ColumnMenuHideIcon: GridVisibilityOffIcon, + ColumnMenuSortAscendingIcon: GridArrowUpwardIcon, + ColumnMenuSortDescendingIcon: GridArrowDownwardIcon, + ColumnMenuFilterIcon: GridFilterAltIcon, + ColumnMenuManageColumnsIcon: GridViewColumnIcon, + ColumnMenuClearIcon: GridClearIcon, }; -/** - * TODO: Differentiate community and pro value and interface - */ export const DATA_GRID_DEFAULT_SLOTS_COMPONENTS: GridSlotsComponent = { ...DEFAULT_GRID_ICON_SLOTS_COMPONENTS, BaseCheckbox: MUICheckbox, diff --git a/packages/grid/x-data-grid/src/constants/index.ts b/packages/grid/x-data-grid/src/constants/index.ts index ca413cdb79b7..667fc4d02d8c 100644 --- a/packages/grid/x-data-grid/src/constants/index.ts +++ b/packages/grid/x-data-grid/src/constants/index.ts @@ -1,4 +1,3 @@ export * from './envConstants'; export * from './localeTextConstants'; -export * from './defaultGridSlotsComponents'; export * from './gridClasses'; diff --git a/packages/grid/x-data-grid/src/constants/localeTextConstants.ts b/packages/grid/x-data-grid/src/constants/localeTextConstants.ts index 35b73120fb31..63bb9d4367c0 100644 --- a/packages/grid/x-data-grid/src/constants/localeTextConstants.ts +++ b/packages/grid/x-data-grid/src/constants/localeTextConstants.ts @@ -78,8 +78,9 @@ export const GRID_DEFAULT_LOCALE_TEXT: GridLocaleText = { // Column menu text columnMenuLabel: 'Menu', columnMenuShowColumns: 'Show columns', + columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Filter', - columnMenuHideColumn: 'Hide', + columnMenuHideColumn: 'Hide column', columnMenuUnsort: 'Unsort', columnMenuSortAsc: 'Sort by ASC', columnMenuSortDesc: 'Sort by DESC', diff --git a/packages/grid/x-data-grid/src/hooks/core/pipeProcessing/gridPipeProcessingApi.ts b/packages/grid/x-data-grid/src/hooks/core/pipeProcessing/gridPipeProcessingApi.ts index a940b44cdddb..0be5ef5668c5 100644 --- a/packages/grid/x-data-grid/src/hooks/core/pipeProcessing/gridPipeProcessingApi.ts +++ b/packages/grid/x-data-grid/src/hooks/core/pipeProcessing/gridPipeProcessingApi.ts @@ -19,7 +19,10 @@ import { GridPreferencePanelsValue } from '../../features/preferencesPanel'; export type GridPipeProcessorGroup = keyof GridPipeProcessingLookup; export interface GridPipeProcessingLookup { - columnMenu: { value: React.ReactNode[]; context: GridColDef }; + columnMenu: { + value: Array; + context: GridColDef; + }; exportState: { value: GridInitialStateCommunity; context: GridExportStateParams }; hydrateColumns: { value: GridHydrateColumnsValue; diff --git a/packages/grid/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx b/packages/grid/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx index 6a758fc85376..ee1dc4b992f1 100644 --- a/packages/grid/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx +++ b/packages/grid/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx @@ -294,7 +294,7 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => { const columns: JSX.Element[] = []; for (let i = 0; i < renderedColumns.length; i += 1) { - const column = renderedColumns[i]; + const colDef = renderedColumns[i]; const columnIndex = firstColumnToRender + i; const isFirstColumn = columnIndex === 0; @@ -304,26 +304,26 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => { cellTabIndexState === null ); const tabIndex = - (columnHeaderTabIndexState !== null && columnHeaderTabIndexState.field === column.field) || + (columnHeaderTabIndexState !== null && columnHeaderTabIndexState.field === colDef.field) || (isFirstColumn && !hasTabbableElement) ? 0 : -1; - const hasFocus = columnHeaderFocus !== null && columnHeaderFocus.field === column.field; - const open = columnMenuState.open && columnMenuState.field === column.field; + const hasFocus = columnHeaderFocus !== null && columnHeaderFocus.field === colDef.field; + const open = columnMenuState.open && columnMenuState.field === colDef.field; columns.push( }; + /** + * Initial `componentsProps` - it is internal, to be overrriden by Pro or Premium packages + * @ignore - do not document. + */ + defaultComponentsProps: { [key: string]: GridColumnMenuComponentProps }; + /** + * `components` could be used to add new and (or) override default column menu items + * If you register a nee component you must pass it's `displayOrder` in `componentsProps` + * or it will be placed in the end of the list + */ + components?: { [key: string]: React.JSXElementConstructor | null }; + /** + * Could be used to pass new props or override props specific to a column menu component + * e.g. `displayOrder` + */ + componentsProps?: { [key: string]: GridColumnMenuComponentProps }; +} diff --git a/packages/grid/x-data-grid/src/hooks/features/columnMenu/columnMenuState.ts b/packages/grid/x-data-grid/src/hooks/features/columnMenu/columnMenuState.ts deleted file mode 100644 index b2d79f3af283..000000000000 --- a/packages/grid/x-data-grid/src/hooks/features/columnMenu/columnMenuState.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface GridColumnMenuState { - open: boolean; - field?: string; -} diff --git a/packages/grid/x-data-grid/src/hooks/features/columnMenu/index.ts b/packages/grid/x-data-grid/src/hooks/features/columnMenu/index.ts index e80f9ef66585..f2947dbc1803 100644 --- a/packages/grid/x-data-grid/src/hooks/features/columnMenu/index.ts +++ b/packages/grid/x-data-grid/src/hooks/features/columnMenu/index.ts @@ -1,2 +1,2 @@ -export * from './columnMenuState'; +export * from './columnMenuInterfaces'; export * from './columnMenuSelector'; diff --git a/packages/grid/x-data-grid/src/hooks/features/columnMenu/useGridColumnMenu.ts b/packages/grid/x-data-grid/src/hooks/features/columnMenu/useGridColumnMenu.ts index 931d2bb41cee..5aa5b38b16c2 100644 --- a/packages/grid/x-data-grid/src/hooks/features/columnMenu/useGridColumnMenu.ts +++ b/packages/grid/x-data-grid/src/hooks/features/columnMenu/useGridColumnMenu.ts @@ -2,9 +2,13 @@ import * as React from 'react'; import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity'; import { useGridLogger, useGridApiMethod, useGridApiEventHandler } from '../../utils'; import { gridColumnMenuSelector } from './columnMenuSelector'; -import { GridColumnMenuApi, GridEventListener } from '../../../models'; +import { GridColumnMenuApi } from '../../../models'; import { GridStateInitializer } from '../../utils/useGridInitializeState'; -import { gridClasses } from '../../../constants/gridClasses'; +import { + gridColumnLookupSelector, + gridColumnVisibilityModelSelector, + gridColumnFieldsSelector, +} from '../columns/gridColumnsSelector'; export const columnMenuStateInitializer: GridStateInitializer = (state) => ({ ...state, @@ -47,6 +51,34 @@ export const useGridColumnMenu = ( ); const hideColumnMenu = React.useCallback(() => { + const columnMenuState = gridColumnMenuSelector(apiRef.current.state); + + if (columnMenuState.field) { + const columnLookup = gridColumnLookupSelector(apiRef); + const columnVisibilityModel = gridColumnVisibilityModelSelector(apiRef); + const orderedFields = gridColumnFieldsSelector(apiRef); + let fieldToFocus = columnMenuState.field; + + // If the column was removed from the grid, we need to find the closest visible field + if (!columnLookup[fieldToFocus]) { + fieldToFocus = orderedFields[0]; + } + + // If the field to focus is hidden, we need to find the closest visible field + if (columnVisibilityModel[fieldToFocus] === false) { + // contains visible column fields + the field that was just hidden + const visibleOrderedFields = orderedFields.filter((field) => { + if (field === fieldToFocus) { + return true; + } + return columnVisibilityModel[field] !== false; + }); + const fieldIndex = visibleOrderedFields.indexOf(fieldToFocus); + fieldToFocus = visibleOrderedFields[fieldIndex + 1] || visibleOrderedFields[fieldIndex - 1]; + } + apiRef.current.setColumnHeaderFocus(fieldToFocus); + } + const shouldUpdate = apiRef.current.setState((state) => { if (!state.columnMenu.open && state.columnMenu.field === undefined) { return state; @@ -86,35 +118,7 @@ export const useGridColumnMenu = ( useGridApiMethod(apiRef, columnMenuApi, 'public'); - /** - * EVENTS - */ - const handleColumnHeaderFocus = React.useCallback>( - (params, event) => { - // Check if the column menu button received focus - if (!event.target.classList.contains(gridClasses.menuIconButton)) { - return; - } - - // Check if there's an element which lost focus - if (!event.relatedTarget) { - return; - } - - // `true` if the focus was on the column menu itself, not on any item - const columnMenuLostFocus = event.relatedTarget.classList.contains(gridClasses.menuList); - // `true` if the focus was on an item from the column menu - const columnMenuItemLostFocus = event.relatedTarget.getAttribute('role') === 'menuitem'; - - if (columnMenuLostFocus || columnMenuItemLostFocus) { - apiRef.current.setColumnHeaderFocus(params.field); - } - }, - [apiRef], - ); - useGridApiEventHandler(apiRef, 'columnResizeStart', hideColumnMenu); - useGridApiEventHandler(apiRef, 'columnHeaderFocus', handleColumnHeaderFocus); useGridApiEventHandler(apiRef, 'virtualScrollerWheel', apiRef.current.hideColumnMenu); useGridApiEventHandler(apiRef, 'virtualScrollerTouchMove', apiRef.current.hideColumnMenu); }; diff --git a/packages/grid/x-data-grid/src/hooks/features/columnMenu/useGridColumnMenuComponents.ts b/packages/grid/x-data-grid/src/hooks/features/columnMenu/useGridColumnMenuComponents.ts new file mode 100644 index 000000000000..849c84672e90 --- /dev/null +++ b/packages/grid/x-data-grid/src/hooks/features/columnMenu/useGridColumnMenuComponents.ts @@ -0,0 +1,94 @@ +import * as React from 'react'; +import Divider from '@mui/material/Divider'; +import { GridColumnMenuRootProps } from './columnMenuInterfaces'; +import { GridColDef } from '../../../models/colDef/gridColDef'; +import { useGridPrivateApiContext } from '../../utils/useGridPrivateApiContext'; + +interface UseGridColumnMenuComponentsProps extends GridColumnMenuRootProps { + colDef: GridColDef; + hideMenu: (event: React.SyntheticEvent) => void; + addDividers?: boolean; +} + +type UseGridColumnMenuComponentsResponse = Array< + [React.JSXElementConstructor, { [key: string]: any }] +>; + +const camelize = (pascalCase: string) => { + const camelCase = pascalCase.split(''); + camelCase[0] = camelCase[0].toLowerCase(); + return camelCase.join(''); +}; + +const useGridColumnMenuComponents = (props: UseGridColumnMenuComponentsProps) => { + const apiRef = useGridPrivateApiContext(); + const { + defaultComponents, + defaultComponentsProps, + components = {}, + componentsProps = {}, + hideMenu, + colDef, + addDividers = true, + } = props; + + const processedComponents = React.useMemo( + () => ({ ...defaultComponents, ...components }), + [defaultComponents, components], + ); + + const processedComponentsProps = React.useMemo(() => { + if (!componentsProps || Object.keys(componentsProps).length === 0) { + return defaultComponentsProps; + } + const mergedProps = { ...componentsProps } as typeof defaultComponentsProps; + Object.entries(defaultComponentsProps).forEach(([key, currentComponentProps]) => { + mergedProps[key] = { ...currentComponentProps, ...(componentsProps[key] || {}) }; + }); + return mergedProps; + }, [defaultComponentsProps, componentsProps]); + + const defaultItems = apiRef.current.unstable_applyPipeProcessors('columnMenu', [], props.colDef); + + const userItems = React.useMemo(() => { + const defaultComponentKeys = Object.keys(defaultComponents); + return Object.keys(components).filter((key) => !defaultComponentKeys.includes(key)); + }, [components, defaultComponents]); + + return React.useMemo(() => { + const uniqueItems = Array.from(new Set([...defaultItems, ...userItems])); + const cleansedItems = uniqueItems.filter((key) => processedComponents[key] != null); + const sorted = cleansedItems.sort((a, b) => { + const leftItemProps = processedComponentsProps[camelize(a)]; + const rightItemProps = processedComponentsProps[camelize(b)]; + const leftDisplayOrder = Number.isFinite(leftItemProps?.displayOrder) + ? leftItemProps.displayOrder + : 100; + const rightDisplayOrder = Number.isFinite(rightItemProps?.displayOrder) + ? rightItemProps.displayOrder + : 100; + return leftDisplayOrder! - rightDisplayOrder!; + }); + return sorted.reduce((acc, key, index) => { + let itemProps = { colDef, onClick: hideMenu }; + const processedComponentProps = processedComponentsProps[camelize(key)]; + if (processedComponentProps) { + const { displayOrder, ...customProps } = processedComponentProps; + itemProps = { ...itemProps, ...customProps }; + } + return addDividers && index !== sorted.length - 1 + ? [...acc, [processedComponents[key]!, itemProps], [Divider, {}]] + : [...acc, [processedComponents[key]!, itemProps]]; + }, []); + }, [ + addDividers, + colDef, + defaultItems, + hideMenu, + processedComponents, + processedComponentsProps, + userItems, + ]); +}; + +export { useGridColumnMenuComponents }; diff --git a/packages/grid/x-data-grid/src/hooks/features/columns/useGridColumns.tsx b/packages/grid/x-data-grid/src/hooks/features/columns/useGridColumns.tsx index 4a0c22d9634a..f4573cb5742b 100644 --- a/packages/grid/x-data-grid/src/hooks/features/columns/useGridColumns.tsx +++ b/packages/grid/x-data-grid/src/hooks/features/columns/useGridColumns.tsx @@ -74,6 +74,7 @@ export function useGridColumns( | 'columnTypes' | 'components' | 'componentsProps' + | 'disableColumnSelector' | 'signature' >, ): void { @@ -354,6 +355,18 @@ export function useGridColumns( [props.components.ColumnsPanel, props.componentsProps?.columnsPanel], ); + const addColumnMenuItems = React.useCallback>( + (columnMenuItems) => { + if (props.disableColumnSelector) { + return columnMenuItems; + } + + return [...columnMenuItems, 'ColumnMenuColumnsItem']; + }, + [props.disableColumnSelector], + ); + + useGridRegisterPipeProcessor(apiRef, 'columnMenu', addColumnMenuItems); useGridRegisterPipeProcessor(apiRef, 'exportState', stateExportPreProcessing); useGridRegisterPipeProcessor(apiRef, 'restoreState', stateRestorePreProcessing); useGridRegisterPipeProcessor(apiRef, 'preferencePanel', preferencePanelPreProcessing); diff --git a/packages/grid/x-data-grid/src/hooks/features/filter/useGridFilter.tsx b/packages/grid/x-data-grid/src/hooks/features/filter/useGridFilter.tsx index 71003b80f604..8d016a1a1c41 100644 --- a/packages/grid/x-data-grid/src/hooks/features/filter/useGridFilter.tsx +++ b/packages/grid/x-data-grid/src/hooks/features/filter/useGridFilter.tsx @@ -62,6 +62,7 @@ export const useGridFilter = ( | 'disableMultipleColumnsFiltering' | 'components' | 'componentsProps' + | 'disableColumnFilter' >, ): void => { const logger = useGridLogger(apiRef, 'useGridFilter'); @@ -96,6 +97,17 @@ export const useGridFilter = ( apiRef.current.publishEvent('filteredRowsSet'); }, [props.filterMode, apiRef]); + const addColumnMenuItem = React.useCallback>( + (columnMenuItems, colDef) => { + if (colDef == null || colDef.filterable === false || props.disableColumnFilter) { + return columnMenuItems; + } + + return [...columnMenuItems, 'ColumnMenuFilterItem']; + }, + [props.disableColumnFilter], + ); + /** * API METHODS */ @@ -389,6 +401,7 @@ export const useGridFilter = ( [apiRef, props.filterMode], ); + useGridRegisterPipeProcessor(apiRef, 'columnMenu', addColumnMenuItem); useGridRegisterPipeProcessor(apiRef, 'exportState', stateExportPreProcessing); useGridRegisterPipeProcessor(apiRef, 'restoreState', stateRestorePreProcessing); useGridRegisterPipeProcessor(apiRef, 'preferencePanel', preferencePanelPreProcessing); diff --git a/packages/grid/x-data-grid/src/hooks/features/sorting/useGridSorting.ts b/packages/grid/x-data-grid/src/hooks/features/sorting/useGridSorting.ts index 8ad4ba7c0f3f..ea98de7a848b 100644 --- a/packages/grid/x-data-grid/src/hooks/features/sorting/useGridSorting.ts +++ b/packages/grid/x-data-grid/src/hooks/features/sorting/useGridSorting.ts @@ -116,6 +116,23 @@ export const useGridSorting = ( [apiRef, props.sortingOrder], ); + const addColumnMenuItem = React.useCallback>( + (columnMenuItems, colDef) => { + if (colDef == null || colDef.sortable === false) { + return columnMenuItems; + } + + const sortingOrder = colDef.sortingOrder || props.sortingOrder; + + if (sortingOrder.some((item) => !!item)) { + return [...columnMenuItems, 'ColumnMenuSortItem']; + } + + return columnMenuItems; + }, + [props.sortingOrder], + ); + /** * API METHODS */ @@ -331,6 +348,8 @@ export const useGridSorting = ( [apiRef], ); + useGridRegisterPipeProcessor(apiRef, 'columnMenu', addColumnMenuItem); + useGridApiEventHandler(apiRef, 'columnHeaderClick', handleColumnHeaderClick); useGridApiEventHandler(apiRef, 'columnHeaderKeyDown', handleColumnHeaderKeyDown); useGridApiEventHandler(apiRef, 'rowsSet', apiRef.current.applySorting); diff --git a/packages/grid/x-data-grid/src/index.ts b/packages/grid/x-data-grid/src/index.ts index ca9c0514a38f..a27b06080794 100644 --- a/packages/grid/x-data-grid/src/index.ts +++ b/packages/grid/x-data-grid/src/index.ts @@ -20,6 +20,15 @@ export type { DataGridProps, GridExperimentalFeatures } from './models/props/Dat export type { GridToolbarExportProps } from './components/toolbar/GridToolbarExport'; export type { GridExportFormat, GridExportExtension } from './models/gridExport'; +/** + * Reexportable components. + */ +export { + GridColumnMenu, + GRID_COLUMN_MENU_COMPONENTS, + GRID_COLUMN_MENU_COMPONENTS_PROPS, +} from './components/reexportable'; + /** * The full grid API. */ diff --git a/packages/grid/x-data-grid/src/internals/index.ts b/packages/grid/x-data-grid/src/internals/index.ts index 44a7ee3d2d91..92b1efd9ff8f 100644 --- a/packages/grid/x-data-grid/src/internals/index.ts +++ b/packages/grid/x-data-grid/src/internals/index.ts @@ -3,6 +3,7 @@ export { GridVirtualScrollerContent } from '../components/virtualization/GridVir export { GridVirtualScrollerRenderZone } from '../components/virtualization/GridVirtualScrollerRenderZone'; export { GridColumnHeaders } from '../components/columnHeaders/GridColumnHeaders'; export { GridColumnHeadersInner } from '../components/columnHeaders/GridColumnHeadersInner'; +export { DATA_GRID_DEFAULT_SLOTS_COMPONENTS } from '../constants/defaultGridSlotsComponents'; export { useGridRegisterPipeProcessor } from '../hooks/core/pipeProcessing'; export type { GridPipeProcessor } from '../hooks/core/pipeProcessing'; diff --git a/packages/grid/x-data-grid/src/locales/arSD.ts b/packages/grid/x-data-grid/src/locales/arSD.ts index 6f101a32b29a..227677a518b4 100644 --- a/packages/grid/x-data-grid/src/locales/arSD.ts +++ b/packages/grid/x-data-grid/src/locales/arSD.ts @@ -80,6 +80,7 @@ const arSDGrid: Partial = { // Column menu text columnMenuLabel: 'القائمة', columnMenuShowColumns: 'إظهار الأعمدة', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'المرشِح', columnMenuHideColumn: 'إخفاء', columnMenuUnsort: 'الغاء الفرز', diff --git a/packages/grid/x-data-grid/src/locales/bgBG.ts b/packages/grid/x-data-grid/src/locales/bgBG.ts index 7ab2e7686b18..aa99eed5e755 100644 --- a/packages/grid/x-data-grid/src/locales/bgBG.ts +++ b/packages/grid/x-data-grid/src/locales/bgBG.ts @@ -79,6 +79,7 @@ const bgBGGrid: Partial = { // Column menu text columnMenuLabel: 'Меню', columnMenuShowColumns: 'Покажи колоните', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Филтри', columnMenuHideColumn: 'Скрий', columnMenuUnsort: 'Отмени сортирането', diff --git a/packages/grid/x-data-grid/src/locales/csCZ.ts b/packages/grid/x-data-grid/src/locales/csCZ.ts index 28df55b258f8..d179f2606c2f 100644 --- a/packages/grid/x-data-grid/src/locales/csCZ.ts +++ b/packages/grid/x-data-grid/src/locales/csCZ.ts @@ -87,6 +87,7 @@ const csCZGrid: Partial = { // Column menu text columnMenuLabel: 'Menu', columnMenuShowColumns: 'Zobrazit sloupce', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Filtr', columnMenuHideColumn: 'Skrýt', columnMenuUnsort: 'Zrušit filtry', diff --git a/packages/grid/x-data-grid/src/locales/daDK.ts b/packages/grid/x-data-grid/src/locales/daDK.ts index 14790da3a807..fca32161d18f 100644 --- a/packages/grid/x-data-grid/src/locales/daDK.ts +++ b/packages/grid/x-data-grid/src/locales/daDK.ts @@ -80,6 +80,7 @@ const daDKGrid: Partial = { // Column menu text columnMenuLabel: 'Menu', columnMenuShowColumns: 'Vis Kolonner', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Filtre', columnMenuHideColumn: 'Skjul', columnMenuUnsort: 'Fjern sortering', diff --git a/packages/grid/x-data-grid/src/locales/deDE.ts b/packages/grid/x-data-grid/src/locales/deDE.ts index 290d22a489aa..73717fddd31f 100644 --- a/packages/grid/x-data-grid/src/locales/deDE.ts +++ b/packages/grid/x-data-grid/src/locales/deDE.ts @@ -80,6 +80,7 @@ const deDEGrid: Partial = { // Column menu text columnMenuLabel: 'Menü', columnMenuShowColumns: 'Zeige alle Spalten', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Filter', columnMenuHideColumn: 'Verbergen', columnMenuUnsort: 'Sortierung deaktivieren', diff --git a/packages/grid/x-data-grid/src/locales/elGR.ts b/packages/grid/x-data-grid/src/locales/elGR.ts index de28a75a8371..7968cc883c21 100644 --- a/packages/grid/x-data-grid/src/locales/elGR.ts +++ b/packages/grid/x-data-grid/src/locales/elGR.ts @@ -79,6 +79,7 @@ const elGRGrid: Partial = { // Column menu text columnMenuLabel: 'Μενού', columnMenuShowColumns: 'Εμφάνιση στηλών', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Φίλτρο', columnMenuHideColumn: 'Απόκρυψη', columnMenuUnsort: 'Απενεργοποίηση ταξινόμησης', diff --git a/packages/grid/x-data-grid/src/locales/esES.ts b/packages/grid/x-data-grid/src/locales/esES.ts index 704ea4f15133..ec081c7bd7a5 100644 --- a/packages/grid/x-data-grid/src/locales/esES.ts +++ b/packages/grid/x-data-grid/src/locales/esES.ts @@ -80,6 +80,7 @@ const esESGrid: Partial = { // Column menu text columnMenuLabel: 'Menú', columnMenuShowColumns: 'Mostrar columnas', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Filtro', columnMenuHideColumn: 'Ocultar', columnMenuUnsort: 'Desordenar', diff --git a/packages/grid/x-data-grid/src/locales/faIR.ts b/packages/grid/x-data-grid/src/locales/faIR.ts index 4bd62bb27e1c..11d4b39768f5 100644 --- a/packages/grid/x-data-grid/src/locales/faIR.ts +++ b/packages/grid/x-data-grid/src/locales/faIR.ts @@ -80,6 +80,7 @@ const faIRGrid: Partial = { // Column menu text columnMenuLabel: 'فهرست', columnMenuShowColumns: 'نمایش ستون‌ها', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'فیلتر', columnMenuHideColumn: 'مخفی', columnMenuUnsort: 'نامرتب‌کردن', diff --git a/packages/grid/x-data-grid/src/locales/fiFI.ts b/packages/grid/x-data-grid/src/locales/fiFI.ts index 4178bb0924b3..139a942aa72e 100644 --- a/packages/grid/x-data-grid/src/locales/fiFI.ts +++ b/packages/grid/x-data-grid/src/locales/fiFI.ts @@ -80,6 +80,7 @@ const fiFIGrid: Partial = { // Column menu text columnMenuLabel: 'Valikko', columnMenuShowColumns: 'Näytä sarakkeet', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Suodata', columnMenuHideColumn: 'Piilota', columnMenuUnsort: 'Poista järjestys', diff --git a/packages/grid/x-data-grid/src/locales/frFR.ts b/packages/grid/x-data-grid/src/locales/frFR.ts index 06f1300557ce..dba693b3635a 100644 --- a/packages/grid/x-data-grid/src/locales/frFR.ts +++ b/packages/grid/x-data-grid/src/locales/frFR.ts @@ -80,6 +80,7 @@ const frFRGrid: Partial = { // Column menu text columnMenuLabel: 'Menu', columnMenuShowColumns: 'Afficher les colonnes', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Filtrer', columnMenuHideColumn: 'Cacher', columnMenuUnsort: 'Annuler le tri', diff --git a/packages/grid/x-data-grid/src/locales/heIL.ts b/packages/grid/x-data-grid/src/locales/heIL.ts index 2ef50c0ea2ba..af507541f3af 100644 --- a/packages/grid/x-data-grid/src/locales/heIL.ts +++ b/packages/grid/x-data-grid/src/locales/heIL.ts @@ -80,6 +80,7 @@ const heILGrid: Partial = { // Column menu text columnMenuLabel: 'תפריט', columnMenuShowColumns: 'הצג עמודות', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'סנן', columnMenuHideColumn: 'הסתר', columnMenuUnsort: 'בטל מיון', @@ -120,7 +121,7 @@ const heILGrid: Partial = { // Column pinning text pinToLeft: 'נעץ משמאל', pinToRight: 'נעץ מימין', - unpin: 'בטל נעיצה', + // unpin: 'Unpin', // Tree Data treeDataGroupingHeaderName: 'קבוצה', diff --git a/packages/grid/x-data-grid/src/locales/huHU.ts b/packages/grid/x-data-grid/src/locales/huHU.ts index 6ae99146d144..4ef3fc512538 100644 --- a/packages/grid/x-data-grid/src/locales/huHU.ts +++ b/packages/grid/x-data-grid/src/locales/huHU.ts @@ -79,6 +79,7 @@ const huHUGrid: Partial = { // Column menu text columnMenuLabel: 'Menü', columnMenuShowColumns: 'Oszlopok megjelenítése', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Szűrők', columnMenuHideColumn: 'Elrejtés', columnMenuUnsort: 'Sorrend visszaállítása', diff --git a/packages/grid/x-data-grid/src/locales/itIT.ts b/packages/grid/x-data-grid/src/locales/itIT.ts index 5fadba485b9a..77ab02c846fd 100644 --- a/packages/grid/x-data-grid/src/locales/itIT.ts +++ b/packages/grid/x-data-grid/src/locales/itIT.ts @@ -80,6 +80,7 @@ const itITGrid: Partial = { // Column menu text columnMenuLabel: 'Menu', columnMenuShowColumns: 'Mostra le colonne', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Filtra', columnMenuHideColumn: 'Nascondi', columnMenuUnsort: "Annulla l'ordinamento", diff --git a/packages/grid/x-data-grid/src/locales/jaJP.ts b/packages/grid/x-data-grid/src/locales/jaJP.ts index 0ab8ea1d9830..e690147299b5 100644 --- a/packages/grid/x-data-grid/src/locales/jaJP.ts +++ b/packages/grid/x-data-grid/src/locales/jaJP.ts @@ -79,6 +79,7 @@ const jaJPGrid: Partial = { // Column menu text columnMenuLabel: 'メニュー', columnMenuShowColumns: '列表示', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'フィルター', columnMenuHideColumn: '列非表示', columnMenuUnsort: 'ソート解除', diff --git a/packages/grid/x-data-grid/src/locales/koKR.ts b/packages/grid/x-data-grid/src/locales/koKR.ts index 4d97c6c34016..b3a58be12da1 100644 --- a/packages/grid/x-data-grid/src/locales/koKR.ts +++ b/packages/grid/x-data-grid/src/locales/koKR.ts @@ -79,6 +79,7 @@ const koKRGrid: Partial = { // Column menu text columnMenuLabel: '메뉴', columnMenuShowColumns: '열 표시', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: '필터', columnMenuHideColumn: '열 숨기기', columnMenuUnsort: '정렬 해제', diff --git a/packages/grid/x-data-grid/src/locales/nbNO.ts b/packages/grid/x-data-grid/src/locales/nbNO.ts index edb3b0948300..ed0d531c1104 100644 --- a/packages/grid/x-data-grid/src/locales/nbNO.ts +++ b/packages/grid/x-data-grid/src/locales/nbNO.ts @@ -80,6 +80,7 @@ const nbNOGrid: Partial = { // Column menu text columnMenuLabel: 'Meny', columnMenuShowColumns: 'Vis kolonner', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Filter', columnMenuHideColumn: 'Skjul', columnMenuUnsort: 'Usorter', diff --git a/packages/grid/x-data-grid/src/locales/nlNL.ts b/packages/grid/x-data-grid/src/locales/nlNL.ts index 3f8aff5e04e7..d983ce5b8bde 100644 --- a/packages/grid/x-data-grid/src/locales/nlNL.ts +++ b/packages/grid/x-data-grid/src/locales/nlNL.ts @@ -80,6 +80,7 @@ const nlNLGrid: Partial = { // Column menu text columnMenuLabel: 'Menu', columnMenuShowColumns: 'Toon kolommen', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Filteren', columnMenuHideColumn: 'Verbergen', columnMenuUnsort: 'Annuleer sortering', diff --git a/packages/grid/x-data-grid/src/locales/plPL.ts b/packages/grid/x-data-grid/src/locales/plPL.ts index 3db2157e4688..af67426f9b45 100644 --- a/packages/grid/x-data-grid/src/locales/plPL.ts +++ b/packages/grid/x-data-grid/src/locales/plPL.ts @@ -79,6 +79,7 @@ const plPLGrid: Partial = { // Column menu text columnMenuLabel: 'Menu', columnMenuShowColumns: 'Pokaż wszystkie kolumny', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Filtr', columnMenuHideColumn: 'Ukryj', columnMenuUnsort: 'Anuluj sortowanie', diff --git a/packages/grid/x-data-grid/src/locales/ptBR.ts b/packages/grid/x-data-grid/src/locales/ptBR.ts index b937ec9d1811..cd9ed9bc2e77 100644 --- a/packages/grid/x-data-grid/src/locales/ptBR.ts +++ b/packages/grid/x-data-grid/src/locales/ptBR.ts @@ -80,6 +80,7 @@ const ptBRGrid: Partial = { // Column menu text columnMenuLabel: 'Menu', columnMenuShowColumns: 'Exibir colunas', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Filtrar', columnMenuHideColumn: 'Ocultar', columnMenuUnsort: 'Desfazer ordenação', diff --git a/packages/grid/x-data-grid/src/locales/roRO.ts b/packages/grid/x-data-grid/src/locales/roRO.ts index a0b7ecd44d90..06fc91302536 100644 --- a/packages/grid/x-data-grid/src/locales/roRO.ts +++ b/packages/grid/x-data-grid/src/locales/roRO.ts @@ -80,6 +80,7 @@ const roROGrid: Partial = { // Column menu text columnMenuLabel: 'Meniu', columnMenuShowColumns: 'Afișează toate coloanele', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Filtru', columnMenuHideColumn: 'Ascunde', columnMenuUnsort: 'Dezactivare sortare', diff --git a/packages/grid/x-data-grid/src/locales/ruRU.ts b/packages/grid/x-data-grid/src/locales/ruRU.ts index 6daa585eccf5..eb2b67416b07 100644 --- a/packages/grid/x-data-grid/src/locales/ruRU.ts +++ b/packages/grid/x-data-grid/src/locales/ruRU.ts @@ -88,6 +88,7 @@ const ruRUGrid: Partial = { // Column menu text columnMenuLabel: 'Меню', columnMenuShowColumns: 'Показать столбцы', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Фильтр', columnMenuHideColumn: 'Скрыть', columnMenuUnsort: 'Отменить сортировку', diff --git a/packages/grid/x-data-grid/src/locales/skSK.ts b/packages/grid/x-data-grid/src/locales/skSK.ts index 881850c44c6e..7a07d5139459 100644 --- a/packages/grid/x-data-grid/src/locales/skSK.ts +++ b/packages/grid/x-data-grid/src/locales/skSK.ts @@ -87,6 +87,7 @@ const skSKGrid: Partial = { // Column menu text columnMenuLabel: 'Menu', columnMenuShowColumns: 'Zobraziť stĺpce', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Filter', columnMenuHideColumn: 'Skryť', columnMenuUnsort: 'Zrušiť filtre', diff --git a/packages/grid/x-data-grid/src/locales/svSE.ts b/packages/grid/x-data-grid/src/locales/svSE.ts index 8bc7b652aa0a..8b5c77973261 100644 --- a/packages/grid/x-data-grid/src/locales/svSE.ts +++ b/packages/grid/x-data-grid/src/locales/svSE.ts @@ -80,6 +80,7 @@ const svSEGrid: Partial = { // Column menu text columnMenuLabel: 'Meny', columnMenuShowColumns: 'Visa kolumner', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Filtrera', columnMenuHideColumn: 'Dölj', columnMenuUnsort: 'Osortera', diff --git a/packages/grid/x-data-grid/src/locales/trTR.ts b/packages/grid/x-data-grid/src/locales/trTR.ts index cc684e7ee29a..37155b81ae7d 100644 --- a/packages/grid/x-data-grid/src/locales/trTR.ts +++ b/packages/grid/x-data-grid/src/locales/trTR.ts @@ -79,6 +79,7 @@ const trTRGrid: Partial = { // Column menu text columnMenuLabel: 'Menü', columnMenuShowColumns: 'Sütunları göster', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Filtre uygula', columnMenuHideColumn: 'Gizle', columnMenuUnsort: 'Sıralama', diff --git a/packages/grid/x-data-grid/src/locales/ukUA.ts b/packages/grid/x-data-grid/src/locales/ukUA.ts index fd765c3af8de..a800d3226f19 100644 --- a/packages/grid/x-data-grid/src/locales/ukUA.ts +++ b/packages/grid/x-data-grid/src/locales/ukUA.ts @@ -103,6 +103,7 @@ const ukUAGrid: Partial = { // Column menu text columnMenuLabel: 'Меню', columnMenuShowColumns: 'Показати стовпці', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Фільтр', columnMenuHideColumn: 'Приховати', columnMenuUnsort: 'Скасувати сортування', diff --git a/packages/grid/x-data-grid/src/locales/viVN.ts b/packages/grid/x-data-grid/src/locales/viVN.ts index e30f19dbc583..a45673755e9e 100644 --- a/packages/grid/x-data-grid/src/locales/viVN.ts +++ b/packages/grid/x-data-grid/src/locales/viVN.ts @@ -80,6 +80,7 @@ const viVNGrid: Partial = { // Column menu text columnMenuLabel: 'Danh mục', columnMenuShowColumns: 'Danh sách cột', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: 'Bộ lọc', columnMenuHideColumn: 'Ẩn cột', columnMenuUnsort: 'Bỏ sắp xếp', diff --git a/packages/grid/x-data-grid/src/locales/zhCN.ts b/packages/grid/x-data-grid/src/locales/zhCN.ts index e63046ae7708..9646c15c383b 100644 --- a/packages/grid/x-data-grid/src/locales/zhCN.ts +++ b/packages/grid/x-data-grid/src/locales/zhCN.ts @@ -79,6 +79,7 @@ const zhCNGrid: Partial = { // Column menu text columnMenuLabel: '菜单', columnMenuShowColumns: '显示', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: '筛选器', columnMenuHideColumn: '隐藏', columnMenuUnsort: '恢复默认', diff --git a/packages/grid/x-data-grid/src/locales/zhTW.ts b/packages/grid/x-data-grid/src/locales/zhTW.ts index 51f55515b045..50ce12d219da 100644 --- a/packages/grid/x-data-grid/src/locales/zhTW.ts +++ b/packages/grid/x-data-grid/src/locales/zhTW.ts @@ -79,6 +79,7 @@ const zhTWGrid: Partial = { // Column menu text columnMenuLabel: '選單', columnMenuShowColumns: '顯示欄位', + // columnMenuManageColumns: 'Manage columns', columnMenuFilter: '篩選器', columnMenuHideColumn: '隱藏', columnMenuUnsort: '預設排序', diff --git a/packages/grid/x-data-grid/src/models/api/gridLocaleTextApi.ts b/packages/grid/x-data-grid/src/models/api/gridLocaleTextApi.ts index c81d9729e15c..10a2fa931083 100644 --- a/packages/grid/x-data-grid/src/models/api/gridLocaleTextApi.ts +++ b/packages/grid/x-data-grid/src/models/api/gridLocaleTextApi.ts @@ -81,6 +81,7 @@ export interface GridLocaleText { // Column menu text columnMenuLabel: string; columnMenuShowColumns: React.ReactNode; + columnMenuManageColumns: React.ReactNode; columnMenuFilter: React.ReactNode; columnMenuHideColumn: React.ReactNode; columnMenuUnsort: React.ReactNode; diff --git a/packages/grid/x-data-grid/src/models/gridIconSlotsComponent.ts b/packages/grid/x-data-grid/src/models/gridIconSlotsComponent.ts index 69d7ebdf2506..14e4e0f6661b 100644 --- a/packages/grid/x-data-grid/src/models/gridIconSlotsComponent.ts +++ b/packages/grid/x-data-grid/src/models/gridIconSlotsComponent.ts @@ -130,4 +130,34 @@ export interface GridIconSlotsComponent { * @default GridCloseIcon */ QuickFilterClearIcon: React.JSXElementConstructor; + /** + * Icon displayed in column menu for hiding column + * @default GridVisibilityOffIcon + */ + ColumnMenuHideIcon: React.JSXElementConstructor; + /** + * Icon displayed in column menu for ascending sort + * @default GridArrowUpwardIcon + */ + ColumnMenuSortAscendingIcon: React.JSXElementConstructor; + /** + * Icon displayed in column menu for descending sort + * @default GridArrowDownwardIcon + */ + ColumnMenuSortDescendingIcon: React.JSXElementConstructor; + /** + * Icon displayed in column menu for filter + * @default GridFilterAltIcon + */ + ColumnMenuFilterIcon: React.JSXElementConstructor; + /** + * Icon displayed in column menu for showing all columns + * @default GridViewColumnIcon + */ + ColumnMenuManageColumnsIcon: React.JSXElementConstructor; + /** + * Icon displayed in column menu for clearing values + * @default GridClearIcon + */ + ColumnMenuClearIcon: React.JSXElementConstructor; } diff --git a/packages/grid/x-data-grid/src/tests/columnHeaders.DataGrid.test.tsx b/packages/grid/x-data-grid/src/tests/columnHeaders.DataGrid.test.tsx index 5798a70caaba..5a4ce7cb466a 100644 --- a/packages/grid/x-data-grid/src/tests/columnHeaders.DataGrid.test.tsx +++ b/packages/grid/x-data-grid/src/tests/columnHeaders.DataGrid.test.tsx @@ -65,7 +65,7 @@ describe(' - Column Headers', () => { expect(getColumnHeadersTextContent()).to.deep.equal(['id', 'brand']); fireEvent.click(within(getColumnHeaderCell(0)).getByLabelText('Menu')); - fireEvent.click(screen.getByRole('menuitem', { name: 'Hide' })); + fireEvent.click(screen.getByRole('menuitem', { name: 'Hide column' })); clock.runToLast(); expect(getColumnHeadersTextContent()).to.deep.equal(['brand']); @@ -89,7 +89,7 @@ describe(' - Column Headers', () => { expect(getColumnHeadersTextContent()).to.deep.equal(['id']); fireEvent.click(within(getColumnHeaderCell(0)).getByLabelText('Menu')); - fireEvent.click(screen.getByRole('menuitem', { name: 'Hide' })); + fireEvent.click(screen.getByRole('menuitem', { name: 'Hide column' })); clock.runToLast(); expect(getColumnHeadersTextContent()).to.deep.equal(['id']); @@ -111,7 +111,7 @@ describe(' - Column Headers', () => { expect(getColumnHeadersTextContent()).to.deep.equal(['id', 'brand']); fireEvent.click(within(getColumnHeaderCell(1)).getByLabelText('Menu')); - fireEvent.click(screen.getByRole('menuitem', { name: 'Hide' })); + fireEvent.click(screen.getByRole('menuitem', { name: 'Hide column' })); clock.runToLast(); expect(getColumnHeadersTextContent()).to.deep.equal(['id', 'brand']); diff --git a/packages/grid/x-data-grid/src/tests/columnSpanning.DataGrid.test.tsx b/packages/grid/x-data-grid/src/tests/columnSpanning.DataGrid.test.tsx index a3d666652902..2faecd7e1592 100644 --- a/packages/grid/x-data-grid/src/tests/columnSpanning.DataGrid.test.tsx +++ b/packages/grid/x-data-grid/src/tests/columnSpanning.DataGrid.test.tsx @@ -583,7 +583,7 @@ describe(' - Column Spanning', () => { // hide `category` column fireEvent.click(within(getColumnHeaderCell(1)).getByLabelText('Menu')); - fireEvent.click(screen.getByRole('menuitem', { name: 'Hide' })); + fireEvent.click(screen.getByRole('menuitem', { name: 'Hide column' })); clock.runToLast(); // Nike row diff --git a/scripts/x-data-grid-premium.exports.json b/scripts/x-data-grid-premium.exports.json index f37d3689462e..1692fd57633c 100644 --- a/scripts/x-data-grid-premium.exports.json +++ b/scripts/x-data-grid-premium.exports.json @@ -10,7 +10,6 @@ { "name": "csCZ", "kind": "Variable" }, { "name": "CursorCoordinates", "kind": "Interface" }, { "name": "daDK", "kind": "Variable" }, - { "name": "DATA_GRID_DEFAULT_SLOTS_COMPONENTS", "kind": "Variable" }, { "name": "DATA_GRID_PREMIUM_PROPS_DEFAULT_VALUES", "kind": "Variable" }, { "name": "DataGrid", "kind": "Function" }, { "name": "DataGridPremium", "kind": "Variable" }, @@ -49,6 +48,8 @@ { "name": "GRID_BOOLEAN_COL_DEF", "kind": "Variable" }, { "name": "GRID_CHECKBOX_SELECTION_COL_DEF", "kind": "Variable" }, { "name": "GRID_CHECKBOX_SELECTION_FIELD", "kind": "Variable" }, + { "name": "GRID_COLUMN_MENU_COMPONENTS", "kind": "Variable" }, + { "name": "GRID_COLUMN_MENU_COMPONENTS_PROPS", "kind": "Variable" }, { "name": "GRID_DATE_COL_DEF", "kind": "Variable" }, { "name": "GRID_DATETIME_COL_DEF", "kind": "Variable" }, { "name": "GRID_DEFAULT_LOCALE_TEXT", "kind": "Variable" }, @@ -122,6 +123,7 @@ { "name": "gridClasses", "kind": "Variable" }, { "name": "GridClasses", "kind": "Interface" }, { "name": "GridClassKey", "kind": "TypeAlias" }, + { "name": "GridClearIcon", "kind": "Variable" }, { "name": "GridClipboardApi", "kind": "Interface" }, { "name": "GridCloseIcon", "kind": "Variable" }, { "name": "GridColDef", "kind": "Interface" }, @@ -163,16 +165,27 @@ { "name": "GridColumnLookup", "kind": "TypeAlias" }, { "name": "gridColumnLookupSelector", "kind": "Variable" }, { "name": "GridColumnMenu", "kind": "Variable" }, + { "name": "GridColumnMenuAggregationItem", "kind": "Function" }, { "name": "GridColumnMenuApi", "kind": "Interface" }, + { "name": "GridColumnMenuColumnsItem", "kind": "Function" }, + { "name": "GridColumnMenuComponentProps", "kind": "Interface" }, { "name": "GridColumnMenuContainer", "kind": "Variable" }, + { "name": "GridColumnMenuContainerProps", "kind": "Interface" }, + { "name": "GridColumnMenuFilterItem", "kind": "Function" }, + { "name": "GridColumnMenuGroupingItem", "kind": "Function" }, + { "name": "GridColumnMenuHideItem", "kind": "Function" }, + { "name": "GridColumnMenuItemProps", "kind": "Interface" }, + { "name": "GridColumnMenuManageItem", "kind": "Function" }, + { "name": "GridColumnMenuPinningItem", "kind": "Function" }, { "name": "GridColumnMenuProps", "kind": "Interface" }, + { "name": "GridColumnMenuRootProps", "kind": "Interface" }, { "name": "gridColumnMenuSelector", "kind": "Variable" }, + { "name": "GridColumnMenuSortItem", "kind": "Function" }, { "name": "GridColumnMenuState", "kind": "Interface" }, { "name": "GridColumnNode", "kind": "TypeAlias" }, { "name": "GridColumnOrderChangeParams", "kind": "Interface" }, { "name": "GridColumnPinningApi", "kind": "Interface" }, { "name": "GridColumnPinningInternalCache", "kind": "Interface" }, - { "name": "GridColumnPinningMenuItems", "kind": "Function" }, { "name": "GridColumnPinningState", "kind": "TypeAlias" }, { "name": "gridColumnPositionsSelector", "kind": "Variable" }, { "name": "GridColumnReorderApi", "kind": "Interface" }, @@ -185,7 +198,6 @@ { "name": "GridColumns", "kind": "TypeAlias" }, { "name": "GridColumnsGroupingState", "kind": "Interface" }, { "name": "GridColumnsInitialState", "kind": "Interface" }, - { "name": "GridColumnsMenuItem", "kind": "Function" }, { "name": "GridColumnsMeta", "kind": "Interface" }, { "name": "GridColumnsPanel", "kind": "Function" }, { "name": "GridColumnsPanelProps", "kind": "Interface" }, @@ -297,9 +309,7 @@ { "name": "GridFilterInputValue", "kind": "Function" }, { "name": "GridFilterInputValueProps", "kind": "TypeAlias" }, { "name": "GridFilterItem", "kind": "Interface" }, - { "name": "GridFilterItemProps", "kind": "Interface" }, { "name": "GridFilterListIcon", "kind": "Variable" }, - { "name": "GridFilterMenuItem", "kind": "Function" }, { "name": "GridFilterModel", "kind": "Interface" }, { "name": "gridFilterModelSelector", "kind": "Variable" }, { "name": "GridFilterOperator", "kind": "Interface" }, @@ -316,6 +326,9 @@ { "name": "GridFooterContainerProps", "kind": "TypeAlias" }, { "name": "GridFooterNode", "kind": "Interface" }, { "name": "GridFooterPlaceholder", "kind": "Function" }, + { "name": "GridFunctionsIcon", "kind": "Variable" }, + { "name": "GridGenericColumnMenu", "kind": "Variable" }, + { "name": "GridGenericColumnMenuProps", "kind": "Interface" }, { "name": "GridGetRowsToExportParams", "kind": "Interface" }, { "name": "GridGroupingColDefOverride", "kind": "Interface" }, { "name": "GridGroupingColDefOverrideParams", "kind": "Interface" }, @@ -323,6 +336,7 @@ { "name": "GridGroupingRules", "kind": "TypeAlias" }, { "name": "GridGroupingValueGetterParams", "kind": "Interface" }, { "name": "GridGroupNode", "kind": "TypeAlias" }, + { "name": "GridGroupWorkIcon", "kind": "Variable" }, { "name": "GridHeader", "kind": "Variable" }, { "name": "GridHeaderCheckbox", "kind": "Variable" }, { "name": "GridHeaderSelectionCheckboxParams", "kind": "Interface" }, @@ -384,11 +398,17 @@ { "name": "GridPreferencePanelsValue", "kind": "Enum" }, { "name": "GridPreferencesPanel", "kind": "Variable" }, { "name": "GridPreferencesPanelApi", "kind": "Interface" }, + { "name": "GridPremiumIconSlotsComponent", "kind": "Interface" }, + { "name": "GridPremiumSlotsComponent", "kind": "Interface" }, { "name": "GridPreProcessEditCellProps", "kind": "Interface" }, { "name": "GridPrintExportApi", "kind": "Interface" }, { "name": "GridPrintExportMenuItem", "kind": "Function" }, { "name": "GridPrintExportMenuItemProps", "kind": "TypeAlias" }, { "name": "GridPrintExportOptions", "kind": "Interface" }, + { "name": "GridProIconSlotsComponent", "kind": "Interface" }, + { "name": "GridProSlotsComponent", "kind": "Interface" }, + { "name": "GridPushPinLeftIcon", "kind": "Variable" }, + { "name": "GridPushPinRightIcon", "kind": "Variable" }, { "name": "gridQuickFilterValuesSelector", "kind": "Variable" }, { "name": "GridRemoveIcon", "kind": "Variable" }, { "name": "GridRenderCellParams", "kind": "Interface" }, @@ -524,9 +544,11 @@ { "name": "GridValueGetterParams", "kind": "Interface" }, { "name": "GridValueOptionsParams", "kind": "Interface" }, { "name": "GridValueSetterParams", "kind": "Interface" }, + { "name": "GridViewColumnIcon", "kind": "Variable" }, { "name": "GridViewHeadlineIcon", "kind": "Variable" }, { "name": "GridViewStreamIcon", "kind": "Variable" }, { "name": "GridVirtualScrollerApi", "kind": "Interface" }, + { "name": "GridVisibilityOffIcon", "kind": "Variable" }, { "name": "gridVisibleColumnDefinitionsSelector", "kind": "Variable" }, { "name": "gridVisibleColumnFieldsSelector", "kind": "Variable" }, { "name": "gridVisibleRowCountSelector", "kind": "Variable" }, @@ -535,9 +557,10 @@ { "name": "gridVisibleSortedRowIdsSelector", "kind": "Variable" }, { "name": "gridVisibleSortedTopLevelRowEntriesSelector", "kind": "Variable" }, { "name": "gridVisibleTopLevelRowCountSelector", "kind": "Variable" }, + { "name": "GridWorkspacesIcon", "kind": "Variable" }, { "name": "heIL", "kind": "Variable" }, - { "name": "HideGridColMenuItem", "kind": "Function" }, { "name": "huHU", "kind": "Variable" }, + { "name": "isGroupingColumn", "kind": "Variable" }, { "name": "isLeaf", "kind": "Function" }, { "name": "itIT", "kind": "Variable" }, { "name": "jaJP", "kind": "Variable" }, @@ -563,7 +586,6 @@ { "name": "selectedGridRowsSelector", "kind": "Variable" }, { "name": "selectedIdsLookupSelector", "kind": "Variable" }, { "name": "skSK", "kind": "Variable" }, - { "name": "SortGridMenuItems", "kind": "Function" }, { "name": "SUBMIT_FILTER_DATE_STROKE_TIME", "kind": "Variable" }, { "name": "SUBMIT_FILTER_STROKE_TIME", "kind": "Variable" }, { "name": "svSE", "kind": "Variable" }, diff --git a/scripts/x-data-grid-pro.exports.json b/scripts/x-data-grid-pro.exports.json index d439e458e461..3ed08f726823 100644 --- a/scripts/x-data-grid-pro.exports.json +++ b/scripts/x-data-grid-pro.exports.json @@ -9,7 +9,6 @@ { "name": "csCZ", "kind": "Variable" }, { "name": "CursorCoordinates", "kind": "Interface" }, { "name": "daDK", "kind": "Variable" }, - { "name": "DATA_GRID_DEFAULT_SLOTS_COMPONENTS", "kind": "Variable" }, { "name": "DATA_GRID_PRO_PROPS_DEFAULT_VALUES", "kind": "Variable" }, { "name": "DataGrid", "kind": "Function" }, { "name": "DataGridPremium", "kind": "Function" }, @@ -44,6 +43,8 @@ { "name": "GRID_BOOLEAN_COL_DEF", "kind": "Variable" }, { "name": "GRID_CHECKBOX_SELECTION_COL_DEF", "kind": "Variable" }, { "name": "GRID_CHECKBOX_SELECTION_FIELD", "kind": "Variable" }, + { "name": "GRID_COLUMN_MENU_COMPONENTS", "kind": "Variable" }, + { "name": "GRID_COLUMN_MENU_COMPONENTS_PROPS", "kind": "Variable" }, { "name": "GRID_DATE_COL_DEF", "kind": "Variable" }, { "name": "GRID_DATETIME_COL_DEF", "kind": "Variable" }, { "name": "GRID_DEFAULT_LOCALE_TEXT", "kind": "Variable" }, @@ -98,6 +99,7 @@ { "name": "gridClasses", "kind": "Variable" }, { "name": "GridClasses", "kind": "Interface" }, { "name": "GridClassKey", "kind": "TypeAlias" }, + { "name": "GridClearIcon", "kind": "Variable" }, { "name": "GridClipboardApi", "kind": "Interface" }, { "name": "GridCloseIcon", "kind": "Variable" }, { "name": "GridColDef", "kind": "Interface" }, @@ -140,15 +142,24 @@ { "name": "gridColumnLookupSelector", "kind": "Variable" }, { "name": "GridColumnMenu", "kind": "Variable" }, { "name": "GridColumnMenuApi", "kind": "Interface" }, + { "name": "GridColumnMenuColumnsItem", "kind": "Function" }, + { "name": "GridColumnMenuComponentProps", "kind": "Interface" }, { "name": "GridColumnMenuContainer", "kind": "Variable" }, + { "name": "GridColumnMenuContainerProps", "kind": "Interface" }, + { "name": "GridColumnMenuFilterItem", "kind": "Function" }, + { "name": "GridColumnMenuHideItem", "kind": "Function" }, + { "name": "GridColumnMenuItemProps", "kind": "Interface" }, + { "name": "GridColumnMenuManageItem", "kind": "Function" }, + { "name": "GridColumnMenuPinningItem", "kind": "Function" }, { "name": "GridColumnMenuProps", "kind": "Interface" }, + { "name": "GridColumnMenuRootProps", "kind": "Interface" }, { "name": "gridColumnMenuSelector", "kind": "Variable" }, + { "name": "GridColumnMenuSortItem", "kind": "Function" }, { "name": "GridColumnMenuState", "kind": "Interface" }, { "name": "GridColumnNode", "kind": "TypeAlias" }, { "name": "GridColumnOrderChangeParams", "kind": "Interface" }, { "name": "GridColumnPinningApi", "kind": "Interface" }, { "name": "GridColumnPinningInternalCache", "kind": "Interface" }, - { "name": "GridColumnPinningMenuItems", "kind": "Function" }, { "name": "GridColumnPinningState", "kind": "TypeAlias" }, { "name": "gridColumnPositionsSelector", "kind": "Variable" }, { "name": "GridColumnReorderApi", "kind": "Interface" }, @@ -161,7 +172,6 @@ { "name": "GridColumns", "kind": "TypeAlias" }, { "name": "GridColumnsGroupingState", "kind": "Interface" }, { "name": "GridColumnsInitialState", "kind": "Interface" }, - { "name": "GridColumnsMenuItem", "kind": "Function" }, { "name": "GridColumnsMeta", "kind": "Interface" }, { "name": "GridColumnsPanel", "kind": "Function" }, { "name": "GridColumnsPanelProps", "kind": "Interface" }, @@ -268,9 +278,7 @@ { "name": "GridFilterInputValue", "kind": "Function" }, { "name": "GridFilterInputValueProps", "kind": "TypeAlias" }, { "name": "GridFilterItem", "kind": "Interface" }, - { "name": "GridFilterItemProps", "kind": "Interface" }, { "name": "GridFilterListIcon", "kind": "Variable" }, - { "name": "GridFilterMenuItem", "kind": "Function" }, { "name": "GridFilterModel", "kind": "Interface" }, { "name": "gridFilterModelSelector", "kind": "Variable" }, { "name": "GridFilterOperator", "kind": "Interface" }, @@ -287,6 +295,8 @@ { "name": "GridFooterContainerProps", "kind": "TypeAlias" }, { "name": "GridFooterNode", "kind": "Interface" }, { "name": "GridFooterPlaceholder", "kind": "Function" }, + { "name": "GridGenericColumnMenu", "kind": "Variable" }, + { "name": "GridGenericColumnMenuProps", "kind": "Interface" }, { "name": "GridGetRowsToExportParams", "kind": "Interface" }, { "name": "GridGroupingColDefOverride", "kind": "Interface" }, { "name": "GridGroupingColDefOverrideParams", "kind": "Interface" }, @@ -357,6 +367,10 @@ { "name": "GridPrintExportMenuItem", "kind": "Function" }, { "name": "GridPrintExportMenuItemProps", "kind": "TypeAlias" }, { "name": "GridPrintExportOptions", "kind": "Interface" }, + { "name": "GridProIconSlotsComponent", "kind": "Interface" }, + { "name": "GridProSlotsComponent", "kind": "Interface" }, + { "name": "GridPushPinLeftIcon", "kind": "Variable" }, + { "name": "GridPushPinRightIcon", "kind": "Variable" }, { "name": "gridQuickFilterValuesSelector", "kind": "Variable" }, { "name": "GridRemoveIcon", "kind": "Variable" }, { "name": "GridRenderCellParams", "kind": "Interface" }, @@ -485,9 +499,11 @@ { "name": "GridValueGetterParams", "kind": "Interface" }, { "name": "GridValueOptionsParams", "kind": "Interface" }, { "name": "GridValueSetterParams", "kind": "Interface" }, + { "name": "GridViewColumnIcon", "kind": "Variable" }, { "name": "GridViewHeadlineIcon", "kind": "Variable" }, { "name": "GridViewStreamIcon", "kind": "Variable" }, { "name": "GridVirtualScrollerApi", "kind": "Interface" }, + { "name": "GridVisibilityOffIcon", "kind": "Variable" }, { "name": "gridVisibleColumnDefinitionsSelector", "kind": "Variable" }, { "name": "gridVisibleColumnFieldsSelector", "kind": "Variable" }, { "name": "gridVisibleRowCountSelector", "kind": "Variable" }, @@ -497,7 +513,6 @@ { "name": "gridVisibleSortedTopLevelRowEntriesSelector", "kind": "Variable" }, { "name": "gridVisibleTopLevelRowCountSelector", "kind": "Variable" }, { "name": "heIL", "kind": "Variable" }, - { "name": "HideGridColMenuItem", "kind": "Function" }, { "name": "huHU", "kind": "Variable" }, { "name": "isLeaf", "kind": "Function" }, { "name": "itIT", "kind": "Variable" }, @@ -524,7 +539,6 @@ { "name": "selectedGridRowsSelector", "kind": "Variable" }, { "name": "selectedIdsLookupSelector", "kind": "Variable" }, { "name": "skSK", "kind": "Variable" }, - { "name": "SortGridMenuItems", "kind": "Function" }, { "name": "SUBMIT_FILTER_DATE_STROKE_TIME", "kind": "Variable" }, { "name": "SUBMIT_FILTER_STROKE_TIME", "kind": "Variable" }, { "name": "svSE", "kind": "Variable" }, diff --git a/scripts/x-data-grid.exports.json b/scripts/x-data-grid.exports.json index a790f350d50d..feb78625b3f3 100644 --- a/scripts/x-data-grid.exports.json +++ b/scripts/x-data-grid.exports.json @@ -9,7 +9,6 @@ { "name": "csCZ", "kind": "Variable" }, { "name": "CursorCoordinates", "kind": "Interface" }, { "name": "daDK", "kind": "Variable" }, - { "name": "DATA_GRID_DEFAULT_SLOTS_COMPONENTS", "kind": "Variable" }, { "name": "DATA_GRID_PROPS_DEFAULT_VALUES", "kind": "Variable" }, { "name": "DataGrid", "kind": "Variable" }, { "name": "DataGridProps", "kind": "TypeAlias" }, @@ -41,6 +40,8 @@ { "name": "GRID_BOOLEAN_COL_DEF", "kind": "Variable" }, { "name": "GRID_CHECKBOX_SELECTION_COL_DEF", "kind": "Variable" }, { "name": "GRID_CHECKBOX_SELECTION_FIELD", "kind": "Variable" }, + { "name": "GRID_COLUMN_MENU_COMPONENTS", "kind": "Variable" }, + { "name": "GRID_COLUMN_MENU_COMPONENTS_PROPS", "kind": "Variable" }, { "name": "GRID_DATE_COL_DEF", "kind": "Variable" }, { "name": "GRID_DATETIME_COL_DEF", "kind": "Variable" }, { "name": "GRID_DEFAULT_LOCALE_TEXT", "kind": "Variable" }, @@ -91,6 +92,7 @@ { "name": "gridClasses", "kind": "Variable" }, { "name": "GridClasses", "kind": "Interface" }, { "name": "GridClassKey", "kind": "TypeAlias" }, + { "name": "GridClearIcon", "kind": "Variable" }, { "name": "GridClipboardApi", "kind": "Interface" }, { "name": "GridCloseIcon", "kind": "Variable" }, { "name": "GridColDef", "kind": "Interface" }, @@ -133,9 +135,18 @@ { "name": "gridColumnLookupSelector", "kind": "Variable" }, { "name": "GridColumnMenu", "kind": "Variable" }, { "name": "GridColumnMenuApi", "kind": "Interface" }, + { "name": "GridColumnMenuColumnsItem", "kind": "Function" }, + { "name": "GridColumnMenuComponentProps", "kind": "Interface" }, { "name": "GridColumnMenuContainer", "kind": "Variable" }, + { "name": "GridColumnMenuContainerProps", "kind": "Interface" }, + { "name": "GridColumnMenuFilterItem", "kind": "Function" }, + { "name": "GridColumnMenuHideItem", "kind": "Function" }, + { "name": "GridColumnMenuItemProps", "kind": "Interface" }, + { "name": "GridColumnMenuManageItem", "kind": "Function" }, { "name": "GridColumnMenuProps", "kind": "Interface" }, + { "name": "GridColumnMenuRootProps", "kind": "Interface" }, { "name": "gridColumnMenuSelector", "kind": "Variable" }, + { "name": "GridColumnMenuSortItem", "kind": "Function" }, { "name": "GridColumnMenuState", "kind": "Interface" }, { "name": "GridColumnNode", "kind": "TypeAlias" }, { "name": "GridColumnOrderChangeParams", "kind": "Interface" }, @@ -145,7 +156,6 @@ { "name": "GridColumns", "kind": "TypeAlias" }, { "name": "GridColumnsGroupingState", "kind": "Interface" }, { "name": "GridColumnsInitialState", "kind": "Interface" }, - { "name": "GridColumnsMenuItem", "kind": "Function" }, { "name": "GridColumnsMeta", "kind": "Interface" }, { "name": "GridColumnsPanel", "kind": "Function" }, { "name": "GridColumnsPanelProps", "kind": "Interface" }, @@ -243,9 +253,7 @@ { "name": "GridFilterInputValue", "kind": "Function" }, { "name": "GridFilterInputValueProps", "kind": "TypeAlias" }, { "name": "GridFilterItem", "kind": "Interface" }, - { "name": "GridFilterItemProps", "kind": "Interface" }, { "name": "GridFilterListIcon", "kind": "Variable" }, - { "name": "GridFilterMenuItem", "kind": "Function" }, { "name": "GridFilterModel", "kind": "Interface" }, { "name": "gridFilterModelSelector", "kind": "Variable" }, { "name": "GridFilterOperator", "kind": "Interface" }, @@ -262,6 +270,8 @@ { "name": "GridFooterContainerProps", "kind": "TypeAlias" }, { "name": "GridFooterNode", "kind": "Interface" }, { "name": "GridFooterPlaceholder", "kind": "Function" }, + { "name": "GridGenericColumnMenu", "kind": "Variable" }, + { "name": "GridGenericColumnMenuProps", "kind": "Interface" }, { "name": "GridGetRowsToExportParams", "kind": "Interface" }, { "name": "GridGroupNode", "kind": "TypeAlias" }, { "name": "GridHeader", "kind": "Variable" }, @@ -448,9 +458,11 @@ { "name": "GridValueGetterParams", "kind": "Interface" }, { "name": "GridValueOptionsParams", "kind": "Interface" }, { "name": "GridValueSetterParams", "kind": "Interface" }, + { "name": "GridViewColumnIcon", "kind": "Variable" }, { "name": "GridViewHeadlineIcon", "kind": "Variable" }, { "name": "GridViewStreamIcon", "kind": "Variable" }, { "name": "GridVirtualScrollerApi", "kind": "Interface" }, + { "name": "GridVisibilityOffIcon", "kind": "Variable" }, { "name": "gridVisibleColumnDefinitionsSelector", "kind": "Variable" }, { "name": "gridVisibleColumnFieldsSelector", "kind": "Variable" }, { "name": "gridVisibleRowCountSelector", "kind": "Variable" }, @@ -460,7 +472,6 @@ { "name": "gridVisibleSortedTopLevelRowEntriesSelector", "kind": "Variable" }, { "name": "gridVisibleTopLevelRowCountSelector", "kind": "Variable" }, { "name": "heIL", "kind": "Variable" }, - { "name": "HideGridColMenuItem", "kind": "Function" }, { "name": "huHU", "kind": "Variable" }, { "name": "isLeaf", "kind": "Function" }, { "name": "itIT", "kind": "Variable" }, @@ -486,7 +497,6 @@ { "name": "selectedGridRowsSelector", "kind": "Variable" }, { "name": "selectedIdsLookupSelector", "kind": "Variable" }, { "name": "skSK", "kind": "Variable" }, - { "name": "SortGridMenuItems", "kind": "Function" }, { "name": "SUBMIT_FILTER_DATE_STROKE_TIME", "kind": "Variable" }, { "name": "SUBMIT_FILTER_STROKE_TIME", "kind": "Variable" }, { "name": "svSE", "kind": "Variable" },