diff --git a/.circleci/config.yml b/.circleci/config.yml
index 84d4e25c65e1..2d34f428caf5 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -189,7 +189,7 @@ jobs:
test_browser:
<<: *defaults
docker:
- - image: mcr.microsoft.com/playwright:v1.33.0-focal
+ - image: mcr.microsoft.com/playwright:v1.35.1-focal
environment:
NODE_ENV: development # Needed if playwright is in `devDependencies`
steps:
@@ -222,7 +222,7 @@ jobs:
test_e2e:
<<: *defaults
docker:
- - image: mcr.microsoft.com/playwright:v1.33.0-focal
+ - image: mcr.microsoft.com/playwright:v1.35.1-focal
environment:
NODE_ENV: development # Needed if playwright is in `devDependencies`
steps:
@@ -235,7 +235,7 @@ jobs:
test_e2e_website:
<<: *defaults
docker:
- - image: mcr.microsoft.com/playwright:v1.33.0-focal
+ - image: mcr.microsoft.com/playwright:v1.35.1-focal
environment:
NODE_ENV: development # Needed if playwright is in `devDependencies`
steps:
@@ -250,7 +250,7 @@ jobs:
test_regressions:
<<: *defaults
docker:
- - image: mcr.microsoft.com/playwright:v1.33.0-focal
+ - image: mcr.microsoft.com/playwright:v1.35.1-focal
environment:
NODE_ENV: development # Needed if playwright is in `devDependencies`
steps:
@@ -266,7 +266,7 @@ jobs:
test_performance:
<<: *defaults
docker:
- - image: mcr.microsoft.com/playwright:v1.33.0-focal
+ - image: mcr.microsoft.com/playwright:v1.35.1-focal
environment:
NODE_ENV: development # Needed if playwright is in `devDependencies`
steps:
diff --git a/.github/ISSUE_TEMPLATE/4.premium-support.yml b/.github/ISSUE_TEMPLATE/4.premium-support.yml
index 82e56d648cec..14820c37b7f1 100644
--- a/.github/ISSUE_TEMPLATE/4.premium-support.yml
+++ b/.github/ISSUE_TEMPLATE/4.premium-support.yml
@@ -12,7 +12,7 @@ body:
- type: input
id: contact
attributes:
- label: Order ID or Support key ๐ณ (optional)
+ label: Order ID
description: The order ID of the purchased Premium plan. Community users can [learn more about support](https://mui.com/getting-started/support/) in the documentation.
placeholder: 'e.g. 11111'
validations:
diff --git a/.github/ISSUE_TEMPLATE/5.priority-support.yml b/.github/ISSUE_TEMPLATE/5.priority-support.yml
new file mode 100644
index 000000000000..15643579fc14
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/5.priority-support.yml
@@ -0,0 +1,39 @@
+name: 'Priority support: SLA โฐ'
+description: I'm a Premium plan user and I have the priority support add-on, I can't find a solution to my problem with MUI X.
+title: '[question] '
+labels: ['status: needs triage', 'support: commercial', 'support: unknown']
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Please provide a searchable summary of the issue in the title above โฌ๏ธ.
+ - type: checkboxes
+ attributes:
+ label: Duplicates
+ description: Please [search the history](https://github.com/mui/mui-x/issues) to see if an issue already exists for the same problem.
+ options:
+ - label: I have searched the existing issues
+ required: true
+ - type: checkboxes
+ attributes:
+ label: Latest version
+ description: We roll bug fixes, performance enhancements, and other improvements into new releases.
+ options:
+ - label: I have tested the latest version
+ required: true
+ - type: textarea
+ attributes:
+ label: The problem in depth ๐
+ - type: textarea
+ attributes:
+ label: Your environment ๐
+ description: Run `npx @mui/envinfo` and post the results. If you encounter issues with TypeScript please include the used tsconfig.
+ value: |
+
+ `npx @mui/envinfo`
+
+ ```
+ Don't forget to mention which browser you used.
+ Output from `npx @mui/envinfo` goes here.
+ ```
+
diff --git a/.github/ISSUE_TEMPLATE/5.rfc.yml b/.github/ISSUE_TEMPLATE/7.rfc.yml
similarity index 100%
rename from .github/ISSUE_TEMPLATE/5.rfc.yml
rename to .github/ISSUE_TEMPLATE/7.rfc.yml
diff --git a/.github/workflows/priority-support-validation-prompt.yml b/.github/workflows/priority-support-validation-prompt.yml
new file mode 100644
index 000000000000..bdc45206a6e1
--- /dev/null
+++ b/.github/workflows/priority-support-validation-prompt.yml
@@ -0,0 +1,47 @@
+name: Priority Support Validation Prompt
+
+on:
+ issues:
+ types:
+ - labeled
+
+permissions: {}
+
+jobs:
+ comment:
+ name: Create or update comment
+ runs-on: ubuntu-latest
+ permissions:
+ issues: write
+
+ steps:
+ - name: Find Comment
+ uses: peter-evans/find-comment@v2 # v2.4.0
+ id: findComment
+ with:
+ issue-number: ${{ github.event.issue.number }}
+ comment-author: 'github-actions[bot]'
+ body-includes: You have created a priority support request
+
+ - name: Create comment
+ if: ${{ steps.findComment.outputs.comment-id == '' && contains(github.event.label.name, 'unknown') }}
+ uses: peter-evans/create-or-update-comment@5f728c3dae25f329afbe34ee4d08eef25569d79f # v3.0.2
+ with:
+ issue-number: ${{ github.event.issue.number }}
+ body: |
+ You have created a priority support request โฐ. Please validate your support key using the link below:
+
+ https://tools-public.mui.com/prod/pages/jyhs86t?repo=mui-x&issueId=${{ github.event.issue.number }}
+
+ Do not share you support key in this issue!
+
+ Priority support will only be provided to verified customers. Once you have verified your support key, we will remove the `support: unknown` label and add the `support: priority` label to this issue. Only then the time for the SLA will start counting.
+
+ - name: Update comment
+ if: ${{ steps.findComment.outputs.comment-id != '' && contains(github.event.label.name, 'priority') }}
+ uses: peter-evans/create-or-update-comment@5f728c3dae25f329afbe34ee4d08eef25569d79f # v3.0.2
+ with:
+ comment-id: ${{ steps.findComment.outputs.comment-id }}
+ body: |
+ Thank you for verifying your support key ๐, your SLA starts now.
+ edit-mode: replace
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 55d7165e34fb..a3074ca0943a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,77 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+## 6.9.0
+
+_Jun 22, 2023_
+
+We'd like to offer a big thanks to the 11 contributors who made this release possible. Here are some highlights โจ:
+
+- ๐ We released a new open-source package: `@mui/x-charts`. This package aims at simplifying the integration of charts into your dashboards. ๐
+
+
+
+ It already contains [line](https://mui.com/x/react-charts/lines/), [bar](https://mui.com/x/react-charts/bars/), and [scatter](https://mui.com/x/react-charts/scatter/) charts, with basic customization features. Check out the [documentation](https://mui.com/x/react-charts/) to see what it can do, and open issues to get the feature you need implemented.
+
+- ๐ Introducing UTC and timezone support for pickers.
+
+
+
+ Visit the [documentation](https://mui.com/x/react-date-pickers/timezone/) to learn how to use it.
+
+- ๐ Improve Brazilian Portuguese (pt-BR) on the data grid
+- ๐ Improve Czech (cs-CZ) locale on the pickers
+- ๐ Performance improvements
+- ๐ Bugfixes
+- ๐ Documentation improvements
+
+### `@mui/x-data-grid@v6.9.0` / `@mui/x-data-grid-pro@v6.9.0` / `@mui/x-data-grid-premium@v6.9.0`
+
+#### Changes
+
+- [DataGrid] Filtering performance: use unmemoized selectors by default (#9287) @romgrk
+- [DataGrid] Use container dimensions from `getComputedStyle` (#9236) @m4theushw
+- [l10n] Improve Brazilian Portuguese (pt-BR) locale (#9404) @julioAz
+
+### `@mui/x-date-pickers@v6.9.0` / `@mui/x-date-pickers-pro@v6.9.0`
+
+#### Changes
+
+- [fields] Ensure `minutesStep` is respected by fields arrows up/down (#9338) @alexfauquette
+- [fields] Reset internal state when `referenceValue` changes (#9390) @adrianmxb
+- [l10n] Improve Czech (cs-CZ) locale (#9397) @radimkafka
+- [pickers] Add proper support for UTC and timezones (#8261) @flaviendelangle
+- [pickers] Fix field section selection on `DateTimePicker` (#9342) @LukasTy
+- [pickers] Reduce date range calendar vertical border width (#9368) @oliviertassinari
+- [pickers] Reset fields internal state when pasting value (#9385) @alexfauquette
+
+### `@mui/x-charts@v6.0.0-alpha.0`
+
+#### Changes
+
+- [charts] Allow to customize colors based on the theme mode (#9006) @alexfauquette
+- [charts] Prepare the charts release (#9361) @alexfauquette
+- [charts] Various improvements of charts docs (#9341) @alexfauquette
+
+### Docs
+
+- [docs] Add examples of using different time view renderers (#9360) @LukasTy
+- [docs] Add recipe for single-click editing (#8365) @m4theushw
+- [docs] Fix Base UI references (#9349) @oliviertassinari
+- [docs] Fix random screenshot generation (#9364) @cherniavskii
+- [docs] Remove random generation from chart doc example (#9343) @flaviendelangle
+- [docs] Sync h1 with sidenav link (#9252) @oliviertassinari
+- [docs] Use the mui-x Stack Overflow tag (#9352) @oliviertassinari
+
+### Core
+
+- [core] Add PR template and update the contributions guide (#9329) @DanailH
+- [core] Bump monorepo (#9420) @LukasTy
+- [core] Fix file typo (#9421) @DanailH
+- [core] Fix proptypes (#9396) @LukasTy
+- [core] Move old release notes in `CHANGELOG.old.md` (#9269) @flaviendelangle
+- [core] Add priority support issue template (#8928) @DanailH
+
## 6.8.0
_Jun 16, 2023_
diff --git a/README.md b/README.md
index 7c597ed78116..97f1d8550d8b 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,7 @@ See the [Licensing page](https://mui.com/x/introduction/licensing/) for details.
- [Data Grid](https://mui.com/x/react-data-grid/)
- [Date and Time Pickers](https://mui.com/x/react-date-pickers/getting-started/)
+- [Charts](https://mui.com/x/react-charts/)
## Installation
@@ -30,6 +31,10 @@ Read the Data Grid [Installation instructions](https://mui.com/x/react-data-grid
Read the Date and Time Pickers [Installation instructions](https://mui.com/x/react-date-pickers/getting-started/#installation) in the MUI X docs.
+### Charts
+
+Read the Charts [Installation instructions](https://mui.com/x/react-charts/#getting-started) in the MUI X docs.
+
## MIT vs. commercial licenses
MUI has been building MIT-licensed React components since 2014, and we are committed to the continued advancement of the open-source libraries.
@@ -54,6 +59,7 @@ MIT licensed packages:
- [`@mui/x-data-grid`](https://www.npmjs.com/package/@mui/x-data-grid)
- [`@mui/x-date-pickers`](https://www.npmjs.com/package/@mui/x-date-pickers)
+- [`@mui/x-charts`](https://www.npmjs.com/package/@mui/x-charts)
### Pro Plan
diff --git a/benchmark/package.json b/benchmark/package.json
index 317a44c8c18c..7d627bde842b 100644
--- a/benchmark/package.json
+++ b/benchmark/package.json
@@ -10,14 +10,14 @@
"@emotion/styled": "^11.11.0",
"@material-ui/core": "^5.0.0-beta.5",
"@material-ui/icons": "^5.0.0-beta.5",
- "@mui/material": "^5.13.5",
+ "@mui/material": "^5.13.6",
"@mui/x-data-grid": "^4.0.0",
"ag-grid-community": "^29.3.5",
"ag-grid-react": "^29.3.5",
"css-loader": "^6.8.1",
"html-webpack-plugin": "^5.5.3",
"mui-plus": "^0.0.15",
- "playwright": "^1.33.0",
+ "playwright": "^1.35.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-spring": "^9.2.4",
diff --git a/docs/.link-check-errors.txt b/docs/.link-check-errors.txt
index 50db6973be54..485411067fe3 100644
--- a/docs/.link-check-errors.txt
+++ b/docs/.link-check-errors.txt
@@ -1,7 +1,7 @@
Broken links found by `yarn docs:link-check` that exist:
-- https://mui.com/base/api/portal/#props
+- https://mui.com/base-ui/react-autocomplete/hooks-api/#use-autocomplete
+- https://mui.com/base-ui/react-portal/components-api
- https://mui.com/blog/material-ui-v4-is-out/#premium-themes-store-โจ
- https://mui.com/size-snapshot
-- https://mui.com/x/react-data-grid/filtering/#quick-filter
- https://mui.com/x/react-data-grid/migration-v4
diff --git a/docs/data/charts/funnel/funnel.md b/docs/data/charts/funnel/funnel.md
index dfe5e3b671b0..0fb2bb3c6c0a 100644
--- a/docs/data/charts/funnel/funnel.md
+++ b/docs/data/charts/funnel/funnel.md
@@ -3,13 +3,14 @@ product: charts
title: Charts - Funnel
---
-# Charts - Funnel
+# Charts - Funnel ๐ง
Funnel charts allows to express quantity evolution along a process, such as audience engagement.
-> โ ๏ธ This feature isn't implemented yet. It's coming.
->
-> ๐ Upvote [issue #7929](https://github.com/mui/mui-x/issues/7929) if you want to see it land faster.
->
-> ๐ฌ To have a solution that meets your needs, leave a comment on the [same issue](https://github.com/mui/mui-x/issues/7929).
-> If you already have a use case for this component, or if you are facing a pain-point with your current solution.
+:::warning
+This feature isn't implemented yet. It's coming.
+
+๐ Upvote [issue #7929](https://github.com/mui/mui-x/issues/7929) if you want to see it land faster.
+
+Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution.
+:::
diff --git a/docs/data/charts/gantt/gantt.md b/docs/data/charts/gantt/gantt.md
index bf9963b1807d..422080cae61f 100644
--- a/docs/data/charts/gantt/gantt.md
+++ b/docs/data/charts/gantt/gantt.md
@@ -3,13 +3,14 @@ product: charts
title: Charts - Gantt
---
-# Charts - Sankey
+# Charts - Gantt ๐ง
Gantt charts can illustrate a product schedule and the relationships between its various activities.
-> โ ๏ธ This feature isn't implemented yet. It's coming.
->
-> ๐ Upvote [issue #8732](https://github.com/mui/mui-x/issues/8732) if you want to see it land faster.
->
-> ๐ฌ To have a solution that meets your needs, leave a comment on the [same issue](https://github.com/mui/mui-x/issues/8732).
-> If you already have a use case for this component, or if you are facing a pain-point with your current solution.
+:::warning
+This feature isn't implemented yet. It's coming.
+
+๐ Upvote [issue #8732](https://github.com/mui/mui-x/issues/8732) if you want to see it land faster.
+
+Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution.
+:::
diff --git a/docs/data/charts/heat-map/heat-map.md b/docs/data/charts/heat-map/heat-map.md
index a653ad5f107c..417de70b1aad 100644
--- a/docs/data/charts/heat-map/heat-map.md
+++ b/docs/data/charts/heat-map/heat-map.md
@@ -3,13 +3,14 @@ product: charts
title: Charts - Heat map
---
-# Charts - Heat map
+# Charts - Heat map ๐ง
Heat map charts allows to highlight correlation between categories.
-> โ ๏ธ This feature isn't implemented yet. It's coming.
->
-> ๐ Upvote [issue #7926](https://github.com/mui/mui-x/issues/7926) if you want to see it land faster.
->
-> ๐ฌ To have a solution that meets your needs, leave a comment on the [same issue](https://github.com/mui/mui-x/issues/7926).
-> If you already have a use case for this component, or if you are facing a pain-point with your current solution.
+:::warning
+This feature isn't implemented yet. It's coming.
+
+๐ Upvote [issue #7926](https://github.com/mui/mui-x/issues/7926) if you want to see it land faster.
+
+Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution.
+:::
diff --git a/docs/data/charts/overview/overview.md b/docs/data/charts/overview/overview.md
index bbc7e20550f7..ea2d22a1fb20 100644
--- a/docs/data/charts/overview/overview.md
+++ b/docs/data/charts/overview/overview.md
@@ -11,13 +11,13 @@ title: Charts - Overview
## Overview
-The `@mui-x/chars` is an MIT library to render charts.
+The `@mui/x-charts` is an MIT library to render charts.
It relies on D3.js for data manipulation and SVG for rendering.
Like other MUI X components, charts are built to be production-ready components with nice integration into your application for common use cases.
They also provide a high level of customization.
-To achieve this goal, the `@mui-x/chars` relies on three levels of customization:
+To achieve this goal, the `@mui/x-charts` relies on three levels of customization:
_single components_ with nice default, extensive _configuration props_, and subcomponents for _composition_.
To modify the styling of charts you can rely on all the MUI styling tools, such as the theme override, or the `sx` props.
diff --git a/docs/data/charts/pie/pie.md b/docs/data/charts/pie/pie.md
index 1f4e15529a01..c6e73ea0b633 100644
--- a/docs/data/charts/pie/pie.md
+++ b/docs/data/charts/pie/pie.md
@@ -3,13 +3,14 @@ product: charts
title: Charts - Pie
---
-# Charts - Pie
+# Charts - Pie ๐ง
Pie charts express portions of a whole, using arcs or angles within a circle.
-> โ ๏ธ This feature isn't implemented yet. It's coming.
->
-> ๐ Upvote [issue #7884](https://github.com/mui/mui-x/issues/7884) if you want to see it land faster.
->
-> ๐ฌ To have a solution that meets your needs, leave a comment on the [same issue](https://github.com/mui/mui-x/issues/7884).
-> If you already have a use case for this component, or if you are facing a pain-point with your current solution.
+:::warning
+This feature isn't implemented yet. It's coming.
+
+๐ Upvote [issue #7884](https://github.com/mui/mui-x/issues/7884) if you want to see it land faster.
+
+Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution.
+:::
diff --git a/docs/data/charts/radar/radar.md b/docs/data/charts/radar/radar.md
index f700ac33c235..81db26097fce 100644
--- a/docs/data/charts/radar/radar.md
+++ b/docs/data/charts/radar/radar.md
@@ -3,13 +3,14 @@ product: charts
title: Charts - Radar
---
-# Charts - Radar
+# Charts - Radar ๐ง
Radar allows to compare multivariate data in a 2D chart.
-> โ ๏ธ This feature isn't implemented yet. It's coming.
->
-> ๐ Upvote [issue #7925](https://github.com/mui/mui-x/issues/7925) if you want to see it land faster.
->
-> ๐ฌ To have a solution that meets your needs, leave a comment on the [same issue](https://github.com/mui/mui-x/issues/7925).
-> If you already have a use case for this component, or if you are facing a pain-point with your current solution.
+:::warning
+This feature isn't implemented yet. It's coming.
+
+๐ Upvote [issue #7925](https://github.com/mui/mui-x/issues/7925) if you want to see it land faster.
+
+Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution.
+:::
diff --git a/docs/data/charts/sankey/sankey.md b/docs/data/charts/sankey/sankey.md
index 1b5abcbe44b0..620fb05a223b 100644
--- a/docs/data/charts/sankey/sankey.md
+++ b/docs/data/charts/sankey/sankey.md
@@ -3,13 +3,14 @@ product: charts
title: Charts - Sankey
---
-# Charts - Sankey
+# Charts - Sankey ๐ง
Chart lines can express flows between different entities.
-> โ ๏ธ This feature isn't implemented yet. It's coming.
->
-> ๐ Upvote [issue #7930](https://github.com/mui/mui-x/issues/7930) if you want to see it land faster.
->
-> ๐ฌ To have a solution that meets your needs, leave a comment on the [same issue](https://github.com/mui/mui-x/issues/7930).
-> If you already have a use case for this component, or if you are facing a pain-point with your current solution.
+:::warning
+This feature isn't implemented yet. It's coming.
+
+๐ Upvote [issue #7930](https://github.com/mui/mui-x/issues/7930) if you want to see it land faster.
+
+Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution.
+:::
diff --git a/docs/data/charts/styling/MuiColorTemplate.js b/docs/data/charts/styling/MuiColorTemplate.js
index 269c21b2270d..a8cad965ec1f 100644
--- a/docs/data/charts/styling/MuiColorTemplate.js
+++ b/docs/data/charts/styling/MuiColorTemplate.js
@@ -9,7 +9,7 @@ import Button from '@mui/material/Button';
import Box from '@mui/material/Box';
import Brightness4Icon from '@mui/icons-material/Brightness4';
import Brightness7Icon from '@mui/icons-material/Brightness7';
-import globalChance from 'chance';
+import { Chance } from 'chance';
import { ScatterChart } from '@mui/x-charts/ScatterChart';
import {
@@ -18,7 +18,7 @@ import {
cheerfulFiestaPalette,
} from '@mui/x-charts/colorPalettes';
-const chance = globalChance();
+const chance = new Chance(42);
function getGaussianSeriesData(mean, stdev = [0.3, 0.4], N = 50) {
return [...Array(N)].map((_, i) => {
diff --git a/docs/data/charts/styling/MuiColorTemplate.tsx b/docs/data/charts/styling/MuiColorTemplate.tsx
index 4403734030b9..54ccc94b4795 100644
--- a/docs/data/charts/styling/MuiColorTemplate.tsx
+++ b/docs/data/charts/styling/MuiColorTemplate.tsx
@@ -9,7 +9,7 @@ import Button from '@mui/material/Button';
import Box from '@mui/material/Box';
import Brightness4Icon from '@mui/icons-material/Brightness4';
import Brightness7Icon from '@mui/icons-material/Brightness7';
-import globalChance from 'chance';
+import { Chance } from 'chance';
import { ScatterChart } from '@mui/x-charts/ScatterChart';
import { ScatterValueType } from '@mui/x-charts';
import {
@@ -18,7 +18,7 @@ import {
cheerfulFiestaPalette,
} from '@mui/x-charts/colorPalettes';
-const chance = globalChance();
+const chance = new Chance(42);
function getGaussianSeriesData(
mean: [number, number],
diff --git a/docs/data/charts/tree-map/tree-map.md b/docs/data/charts/tree-map/tree-map.md
index 5eee852e25b1..d1c6d8c8fd35 100644
--- a/docs/data/charts/tree-map/tree-map.md
+++ b/docs/data/charts/tree-map/tree-map.md
@@ -7,9 +7,10 @@ title: Charts - Tree map
Tree map allows to display data with a hierarchical structure.
-> โ ๏ธ This feature isn't implemented yet. It's coming.
->
-> ๐ Upvote [issue #7924(https://github.com/mui/mui-x/issues/7924 if you want to see it land faster.
->
-> ๐ฌ To have a solution that meets your needs, leave a comment on the [same issue](https://github.com/mui/mui-x/issues/7924.
-> If you already have a use case for this component, or if you are facing a pain-point with your current solution.
+:::warning
+This feature isn't implemented yet. It's coming.
+
+๐ Upvote [issue #7924](https://github.com/mui/mui-x/issues/7924) if you want to see it land faster.
+
+Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution.
+:::
diff --git a/docs/data/data-grid/column-groups/column-groups.md b/docs/data/data-grid/column-groups/column-groups.md
index d10eb7b71c64..2140041ad6e5 100644
--- a/docs/data/data-grid/column-groups/column-groups.md
+++ b/docs/data/data-grid/column-groups/column-groups.md
@@ -77,19 +77,27 @@ In the example below, the `Full name` column group can be divided, but not other
## Manage group visibility ๐ง
+The column group should allow to switch between an extended/collapsed view which hide/show some columns.
+
:::warning
This feature isn't implemented yet. It's coming.
+
+๐ Upvote [issue #6651](https://github.com/mui/mui-x/issues/6651) if you want to see it land faster.
+
+Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution.
:::
-The column group should allow to switch between an extended/collapsed view which hide/show some columns
+## Column group ordering [](/x/introduction/licensing/#pro-plan)๐ง
-## Reordering groups ๐ง[](/x/introduction/licensing/#pro-plan)
+Users could drag and drop group header to move all the group children at once, [like they can already do it with normal columns](/x/react-data-grid/column-ordering/).
:::warning
This feature isn't implemented yet. It's coming.
-:::
-Users could drag and drop group header to move all the group children at once
+๐ Upvote [issue #9448](https://github.com/mui/mui-x/issues/9448) if you want to see it land faster.
+
+Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution.
+:::
## API
diff --git a/docs/data/data-grid/demo/demo.md b/docs/data/data-grid/demo/demo.md
index 5853c48961a9..a102d86cd55d 100644
--- a/docs/data/data-grid/demo/demo.md
+++ b/docs/data/data-grid/demo/demo.md
@@ -8,7 +8,7 @@ We're using the Data Grid to display the following features' table.
Filtering, sorting, and grouping (by plan) are at your disposal to help you explore the list.
:::
-{{"demo": "PopularFeaturesDemo.tsx", "defaultCodeOpen": false, "bg": "inline", "hideToolbar": true}}
+{{"demo": "PopularFeaturesDemo.js", "defaultCodeOpen": false, "bg": "inline", "hideToolbar": true}}
## API
diff --git a/docs/data/data-grid/filtering/customization.md b/docs/data/data-grid/filtering/customization.md
index 182e05ba2067..0a610c5385d4 100644
--- a/docs/data/data-grid/filtering/customization.md
+++ b/docs/data/data-grid/filtering/customization.md
@@ -179,6 +179,38 @@ The demo below shows how to anchor the filter panel to the toolbar button instea
{{"demo": "CustomFilterPanelPosition.js", "bg": "inline", "defaultCodeOpen": false}}
+### Optimize performance
+
+There is a new set of APIs with a more efficient interface that are going to be used by default at the next major release, V7.
+
+You can use them right now to make your custom filters faster. Instead of receiving a `GridCellParams` argument, they receive the parameters listed below.
+
+```ts
+const noop = () => {};
+const operator: GridFilterOperator = {
+ /* ...other operator properties */
+ getApplyFilterFn: noop /* It is required to pass a noop function until V7 */,
+ getApplyFilterFnV7: (filterItem: GridFilterItem) => {
+ /* This example is our default string filter function for V7 */
+
+ if (!filterItem.value) {
+ return null;
+ }
+ const filterItemValue = disableTrim ? filterItem.value : filterItem.value.trim();
+ const filterRegex = new RegExp(escapeRegExp(filterItemValue), 'i');
+
+ return (
+ value: any,
+ row: GridValidRowModel,
+ column: GridColDef,
+ apiRef: React.MutableRefObject,
+ ): boolean => {
+ return value != null ? filterRegex.test(String(value)) : false;
+ };
+ },
+};
+```
+
## API
- [GridFilterOperator](/x/api/data-grid/grid-filter-operator/)
diff --git a/docs/data/data-grid/joy-ui/GridJoyUISlots.js b/docs/data/data-grid/joy-ui/GridJoyUISlots.js
index be5b71b98f56..7d88bad69902 100644
--- a/docs/data/data-grid/joy-ui/GridJoyUISlots.js
+++ b/docs/data/data-grid/joy-ui/GridJoyUISlots.js
@@ -70,9 +70,9 @@ const columns = [
},
];
-const rows = [];
+const initialRows = [];
for (let i = 0; i < 20; i += 1) {
- rows.push({
+ initialRows.push({
id: i,
name: randomCompanyName(),
number: randomRating(),
@@ -84,16 +84,29 @@ for (let i = 0; i < 20; i += 1) {
}
export default function GridJoyUISlots() {
+ const [rows, setRows] = React.useState([]);
+ const [loading, setLoading] = React.useState(true);
+
+ React.useEffect(() => {
+ setLoading(true);
+ const timeoutId = setTimeout(() => {
+ setRows(initialRows);
+ setLoading(false);
+ }, 800);
+ return () => clearTimeout(timeoutId);
+ }, []);
+
return (
-
+ ([]);
+ const [loading, setLoading] = React.useState(true);
+
+ React.useEffect(() => {
+ setLoading(true);
+ const timeoutId = setTimeout(() => {
+ setRows(initialRows);
+ setLoading(false);
+ }, 800);
+ return () => clearTimeout(timeoutId);
+ }, []);
+
return (
-
+
+
+
+ );
+}
+
+export default function PageSizeAutoPremium() {
+ return (
+
+ );
+}
diff --git a/docs/data/data-grid/pagination/PageSizeAutoPremium.tsx.preview b/docs/data/data-grid/pagination/PageSizeAutoPremium.tsx.preview
new file mode 100644
index 000000000000..8adee950a97c
--- /dev/null
+++ b/docs/data/data-grid/pagination/PageSizeAutoPremium.tsx.preview
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/docs/data/data-grid/pagination/pagination.md b/docs/data/data-grid/pagination/pagination.md
index 8248f826599c..e62934831518 100644
--- a/docs/data/data-grid/pagination/pagination.md
+++ b/docs/data/data-grid/pagination/pagination.md
@@ -2,14 +2,6 @@
Easily paginate your rows and only fetch what you need.
-:::warning
-The default pagination behavior depends on your plan.
-
-- On the `DataGrid`, pagination is enabled by default and can't be disabled
-- On the `DataGridPro`, pagination is disabled by default, use the `pagination` prop to enable it
-
-:::
-
## Size of the page
The `DataGrid` (MIT license) is limited to pages of up to 100 rows.
@@ -33,6 +25,20 @@ You can't use both the `autoPageSize` and `autoHeight` props at the same time be
{{"demo": "PageSizeAuto.js", "bg": "inline"}}
+## Pagination on Pro and Premium
+
+The default pagination behavior depends on your plan.
+
+- On the `DataGrid`, pagination is enabled by default and can't be disabled.
+- On the `DataGridPro` and `DataGridPremium`, pagination is disabled by default; use the `pagination` prop to enable it.
+
+The following example activates pagination on a `DataGridPremium` component.
+
+:::info
+On a side note, exported CSV and Excel files will contain the full data and disregard the pagination by default. To apply pagination on exported files, please check the available [row selectors](/x/react-data-grid/export/#exported-rows).
+:::
+{{"demo": "PageSizeAutoPremium.js", "bg": "inline"}}
+
## Pagination model
The pagination model is an object containing the current page and the size of the page. The default value is `{ page: 0, pageSize: 100 }`. To change the default value, make it controlled by `paginationModel` prop or initialize a custom value using `initialState.pagination.paginationModel`.
diff --git a/docs/data/data-grid/performance/performance.md b/docs/data/data-grid/performance/performance.md
index 1eaa98dcf03e..c616c2f294d0 100644
--- a/docs/data/data-grid/performance/performance.md
+++ b/docs/data/data-grid/performance/performance.md
@@ -48,6 +48,10 @@ shows you which cells re-render in reaction to your interaction with the grid.
{{"demo": "GridVisualization.js", "bg": "inline", "defaultCodeOpen": false}}
+## Filtering
+
+For filtering performance, see [the filter customization section](/x/react-data-grid/filtering/customization/#optimize-performance).
+
## API
- [DataGrid](/x/api/data-grid/data-grid/)
diff --git a/docs/data/data-grid/pivoting/pivoting.md b/docs/data/data-grid/pivoting/pivoting.md
index 2926f12b9f5a..7afb0589495f 100644
--- a/docs/data/data-grid/pivoting/pivoting.md
+++ b/docs/data/data-grid/pivoting/pivoting.md
@@ -2,7 +2,7 @@
title: Data Grid - Pivoting
---
-# Data Grid - Pivoting [](/x/introduction/licensing/#premium-plan)
+# Data Grid - Pivoting [](/x/introduction/licensing/#premium-plan)๐ง
Turn a column values into columns.
@@ -10,6 +10,8 @@ title: Data Grid - Pivoting
This feature isn't implemented yet. It's coming.
๐ Upvote [issue #214](https://github.com/mui/mui-x/issues/214) if you want to see it land faster.
+
+Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution.
:::
Pivoting will allow you to take a columns values and turn them into columns.
diff --git a/docs/data/data-grid/row-grouping/row-grouping.md b/docs/data/data-grid/row-grouping/row-grouping.md
index a937988dbc2c..8341c84600e6 100644
--- a/docs/data/data-grid/row-grouping/row-grouping.md
+++ b/docs/data/data-grid/row-grouping/row-grouping.md
@@ -316,12 +316,14 @@ const rows = apiRef.current.getRowGroupChildren({
{{"demo": "RowGroupingGetRowGroupChildren.js", "bg": "inline", "defaultCodeOpen": false}}
-## ๐ง Row group panel
+## Row group panel ๐ง
:::warning
This feature isn't implemented yet. It's coming.
๐ Upvote [issue #5235](https://github.com/mui/mui-x/issues/5235) if you want to see it land faster.
+
+Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution.
:::
With this panel, your users will be able to control which columns are used for grouping just by dragging them inside the panel.
diff --git a/docs/data/data-grid/row-ordering/row-ordering.md b/docs/data/data-grid/row-ordering/row-ordering.md
index 0d81a4b2c873..aff076e84744 100644
--- a/docs/data/data-grid/row-ordering/row-ordering.md
+++ b/docs/data/data-grid/row-ordering/row-ordering.md
@@ -83,6 +83,8 @@ For now, row reordering is disabled if sorting is applied to the data grid.
This feature isn't implemented yet. It's coming.
๐ Upvote [issue #4821](https://github.com/mui/mui-x/issues/4821) if you want to see it land faster.
+
+Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution.
:::
## Reordering rows with tree data ๐ง
@@ -91,6 +93,8 @@ This feature isn't implemented yet. It's coming.
This feature isn't implemented yet. It's coming.
๐ Upvote [issue #4821](https://github.com/mui/mui-x/issues/4821) if you want to see it land faster.
+
+Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution.
:::
## API
diff --git a/docs/data/data-grid/row-recipes/DetailPanelOneExpandedRow.js b/docs/data/data-grid/row-recipes/DetailPanelOneExpandedRow.js
new file mode 100644
index 000000000000..22070963b4fc
--- /dev/null
+++ b/docs/data/data-grid/row-recipes/DetailPanelOneExpandedRow.js
@@ -0,0 +1,90 @@
+import * as React from 'react';
+import Box from '@mui/material/Box';
+import { DataGridPro } from '@mui/x-data-grid-pro';
+import {
+ randomCreatedDate,
+ randomCurrency,
+ randomEmail,
+ randomPrice,
+} from '@mui/x-data-grid-generator';
+
+const getDetailPanelContent = ({ row }) => (
+ {`Order #${row.id}`}
+);
+const getDetailPanelHeight = () => 50;
+
+export default function DetailPanelOneExpandedRow() {
+ const [detailPanelExpandedRowIds, setDetailPanelExpandedRowIds] = React.useState(
+ [],
+ );
+
+ const handleDetailPanelExpandedRowIdsChange = React.useCallback((newIds) => {
+ setDetailPanelExpandedRowIds(
+ newIds.length > 1 ? [newIds[newIds.length - 1]] : newIds,
+ );
+ }, []);
+
+ return (
+
+
+
+ );
+}
+
+const columns = [
+ { field: 'id', headerName: 'Order ID' },
+ { field: 'customer', headerName: 'Customer', width: 200 },
+ { field: 'date', type: 'date', headerName: 'Placed at' },
+ { field: 'currency', headerName: 'Currency' },
+ { field: 'total', type: 'number', headerName: 'Total' },
+];
+
+const rows = [
+ {
+ id: 1,
+ customer: 'Matheus',
+ email: randomEmail(),
+ date: randomCreatedDate(),
+ currency: randomCurrency(),
+ total: randomPrice(1, 1000),
+ },
+ {
+ id: 2,
+ customer: 'Olivier',
+ email: randomEmail(),
+ date: randomCreatedDate(),
+ currency: randomCurrency(),
+ total: randomPrice(1, 1000),
+ },
+ {
+ id: 3,
+ customer: 'Flavien',
+ email: randomEmail(),
+ date: randomCreatedDate(),
+ currency: randomCurrency(),
+ total: randomPrice(1, 1000),
+ },
+ {
+ id: 4,
+ customer: 'Danail',
+ email: randomEmail(),
+ date: randomCreatedDate(),
+ currency: randomCurrency(),
+ total: randomPrice(1, 1000),
+ },
+ {
+ id: 5,
+ customer: 'Alexandre',
+ email: randomEmail(),
+ date: randomCreatedDate(),
+ currency: randomCurrency(),
+ total: randomPrice(1, 1000),
+ },
+];
diff --git a/docs/data/data-grid/row-recipes/DetailPanelOneExpandedRow.tsx b/docs/data/data-grid/row-recipes/DetailPanelOneExpandedRow.tsx
new file mode 100644
index 000000000000..79f15166d5bd
--- /dev/null
+++ b/docs/data/data-grid/row-recipes/DetailPanelOneExpandedRow.tsx
@@ -0,0 +1,99 @@
+import * as React from 'react';
+import Box from '@mui/material/Box';
+import {
+ DataGridPro,
+ DataGridProProps,
+ GridRowsProp,
+ GridRowId,
+ GridColDef,
+} from '@mui/x-data-grid-pro';
+import {
+ randomCreatedDate,
+ randomCurrency,
+ randomEmail,
+ randomPrice,
+} from '@mui/x-data-grid-generator';
+
+const getDetailPanelContent: DataGridProProps['getDetailPanelContent'] = ({
+ row,
+}) => {`Order #${row.id}`};
+const getDetailPanelHeight: DataGridProProps['getDetailPanelHeight'] = () => 50;
+
+export default function DetailPanelOneExpandedRow() {
+ const [detailPanelExpandedRowIds, setDetailPanelExpandedRowIds] = React.useState<
+ GridRowId[]
+ >([]);
+
+ const handleDetailPanelExpandedRowIdsChange = React.useCallback(
+ (newIds: GridRowId[]) => {
+ setDetailPanelExpandedRowIds(
+ newIds.length > 1 ? [newIds[newIds.length - 1]] : newIds,
+ );
+ },
+ [],
+ );
+
+ return (
+
+
+
+ );
+}
+
+const columns: GridColDef[] = [
+ { field: 'id', headerName: 'Order ID' },
+ { field: 'customer', headerName: 'Customer', width: 200 },
+ { field: 'date', type: 'date', headerName: 'Placed at' },
+ { field: 'currency', headerName: 'Currency' },
+ { field: 'total', type: 'number', headerName: 'Total' },
+];
+
+const rows: GridRowsProp = [
+ {
+ id: 1,
+ customer: 'Matheus',
+ email: randomEmail(),
+ date: randomCreatedDate(),
+ currency: randomCurrency(),
+ total: randomPrice(1, 1000),
+ },
+ {
+ id: 2,
+ customer: 'Olivier',
+ email: randomEmail(),
+ date: randomCreatedDate(),
+ currency: randomCurrency(),
+ total: randomPrice(1, 1000),
+ },
+ {
+ id: 3,
+ customer: 'Flavien',
+ email: randomEmail(),
+ date: randomCreatedDate(),
+ currency: randomCurrency(),
+ total: randomPrice(1, 1000),
+ },
+ {
+ id: 4,
+ customer: 'Danail',
+ email: randomEmail(),
+ date: randomCreatedDate(),
+ currency: randomCurrency(),
+ total: randomPrice(1, 1000),
+ },
+ {
+ id: 5,
+ customer: 'Alexandre',
+ email: randomEmail(),
+ date: randomCreatedDate(),
+ currency: randomCurrency(),
+ total: randomPrice(1, 1000),
+ },
+];
diff --git a/docs/data/data-grid/row-recipes/DetailPanelOneExpandedRow.tsx.preview b/docs/data/data-grid/row-recipes/DetailPanelOneExpandedRow.tsx.preview
new file mode 100644
index 000000000000..8bcb25776e47
--- /dev/null
+++ b/docs/data/data-grid/row-recipes/DetailPanelOneExpandedRow.tsx.preview
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/docs/data/data-grid/row-recipes/row-recipes.md b/docs/data/data-grid/row-recipes/row-recipes.md
new file mode 100644
index 000000000000..b032a14754a4
--- /dev/null
+++ b/docs/data/data-grid/row-recipes/row-recipes.md
@@ -0,0 +1,15 @@
+---
+title: Data Grid - Row customization recipes
+---
+
+# Data Grid - Row customization recipes
+
+
Advanced row customization recipes.
+
+## One expanded detail panel at a time
+
+By default, the [Master detail ](/x/react-data-grid/master-detail/) feature supports multiple expanded detail panels simultaneously.
+
+However, you can [control the expanded detail panels](/x/react-data-grid/master-detail/#controlling-expanded-detail-panels) to have only one detail panel expanded at a time.
+
+{{"demo": "DetailPanelOneExpandedRow.js", "bg": "inline", "defaultCodeOpen": false}}
diff --git a/docs/data/data-grid/row-spanning/row-spanning.md b/docs/data/data-grid/row-spanning/row-spanning.md
index e5331910b13f..7640695d86d6 100644
--- a/docs/data/data-grid/row-spanning/row-spanning.md
+++ b/docs/data/data-grid/row-spanning/row-spanning.md
@@ -1,4 +1,4 @@
-# Data Grid - Row spanning
+# Data Grid - Row spanning ๐ง
Span cells across several columns.
@@ -6,6 +6,8 @@
This feature isn't implemented yet. It's coming.
๐ Upvote [issue #207](https://github.com/mui/mui-x/issues/207) if you want to see it land faster.
+
+Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution.
:::
Each cell takes up the width of one row.
diff --git a/docs/data/data-grid/tree-data/tree-data.md b/docs/data/data-grid/tree-data/tree-data.md
index 06629f1e6435..d01012bb92cc 100644
--- a/docs/data/data-grid/tree-data/tree-data.md
+++ b/docs/data/data-grid/tree-data/tree-data.md
@@ -113,12 +113,14 @@ You can limit the sorting to the top-level rows with the `disableChildrenSorting
> const invalidRows = [{ path: ['A'] }, { path: ['B'] }, { path: ['A', 'A'] }];
> ```
-## Children lazy-loading
+## Children lazy-loading ๐ง
:::warning
This feature isn't implemented yet. It's coming.
๐ Upvote [issue #3377](https://github.com/mui/mui-x/issues/3377) if you want to see it land faster.
+
+Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution.
:::
Alternatively, you can achieve a similar behavior by implementing this feature outside the component as shown below.
diff --git a/docs/data/date-pickers/base-concepts/base-concepts.md b/docs/data/date-pickers/base-concepts/base-concepts.md
index 70615bfaddd5..c2e8522b9f76 100644
--- a/docs/data/date-pickers/base-concepts/base-concepts.md
+++ b/docs/data/date-pickers/base-concepts/base-concepts.md
@@ -81,7 +81,7 @@ Each _Picker_ is available in a responsive, desktop and mobile variant:
There are many components available, each fitting specific use cases. Use the form below to find the component you need:
-{{"demo": "ComponentExplorerNoSnap.tsx", "hideToolbar": true}}
+{{"demo": "ComponentExplorerNoSnap.js", "hideToolbar": true}}
## Accessibility
diff --git a/docs/data/date-pickers/custom-layout/custom-layout.md b/docs/data/date-pickers/custom-layout/custom-layout.md
index d1394d9138bc..f0838edd06bb 100644
--- a/docs/data/date-pickers/custom-layout/custom-layout.md
+++ b/docs/data/date-pickers/custom-layout/custom-layout.md
@@ -36,7 +36,7 @@ Here is a demonstration with the 3 main blocks outlined with color borders.
A `` wraps all the subcomponents to provide the structure.
By default it renders a `div` with `display: grid`.
-Such that all subcomponents are placed in a 3 by 3 [CSS grid](https://developer.mozilla.org/fr/docs/Web/CSS/CSS_Grid_Layout).
+Such that all subcomponents are placed in a 3 by 3 [CSS grid](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout).
```jsx
diff --git a/docs/data/date-pickers/date-range-picker/date-range-picker.md b/docs/data/date-pickers/date-range-picker/date-range-picker.md
index e8be8cbeb6fe..df44a71bd385 100644
--- a/docs/data/date-pickers/date-range-picker/date-range-picker.md
+++ b/docs/data/date-pickers/date-range-picker/date-range-picker.md
@@ -105,6 +105,8 @@ You can find the documentation in the [Validation page](/x/react-date-pickers/va
This feature isn't implemented yet. It's coming.
๐ Upvote [issue #4995](https://github.com/mui/mui-x/issues/4995) if you want to see it land faster.
+
+Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution.
:::
The Month Range Picker allows setting a range of months.
diff --git a/docs/data/date-pickers/date-time-range-picker/date-time-range-picker.md b/docs/data/date-pickers/date-time-range-picker/date-time-range-picker.md
index a17bcf9821ab..d70a20f953a9 100644
--- a/docs/data/date-pickers/date-time-range-picker/date-time-range-picker.md
+++ b/docs/data/date-pickers/date-time-range-picker/date-time-range-picker.md
@@ -6,10 +6,14 @@ packageName: '@mui/x-date-pickers-pro'
materialDesign: https://m2.material.io/components/date-pickers
---
-# Date Time Range Picker [](/x/introduction/licensing/#pro-plan)
+# Date Time Range Picker [](/x/introduction/licensing/#pro-plan)๐ง
The Date Time Range Picker let the user select a range of dates with an explicit starting and ending time.
-> โ ๏ธ This feature isn't implemented yet. It's coming.
->
-> ๐ Upvote [issue #4547](https://github.com/mui/mui-x/issues/4547) if you want to see it land faster.
+:::warning
+This feature isn't implemented yet. It's coming.
+
+๐ Upvote [issue #4547](https://github.com/mui/mui-x/issues/4547) if you want to see it land faster.
+
+Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution.
+:::
diff --git a/docs/data/date-pickers/localization/data.json b/docs/data/date-pickers/localization/data.json
index 3c2203b677b2..0624309e396a 100644
--- a/docs/data/date-pickers/localization/data.json
+++ b/docs/data/date-pickers/localization/data.json
@@ -15,6 +15,14 @@
"totalKeysCount": 36,
"githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/caES.ts"
},
+ {
+ "languageTag": "zh-HK",
+ "importName": "zhHK",
+ "localeName": "Chinese (Hong Kong)",
+ "missingKeysCount": 0,
+ "totalKeysCount": 36,
+ "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/zhHK.ts"
+ },
{
"languageTag": "zh-CN",
"importName": "zhCN",
@@ -171,7 +179,7 @@
"languageTag": "ro-RO",
"importName": "roRO",
"localeName": "Romanian",
- "missingKeysCount": 8,
+ "missingKeysCount": 1,
"totalKeysCount": 36,
"githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/roRO.ts"
},
diff --git a/docs/data/date-pickers/time-range-picker/time-range-picker.md b/docs/data/date-pickers/time-range-picker/time-range-picker.md
index 1b0692f84f91..b77147ce907a 100644
--- a/docs/data/date-pickers/time-range-picker/time-range-picker.md
+++ b/docs/data/date-pickers/time-range-picker/time-range-picker.md
@@ -6,10 +6,14 @@ packageName: '@mui/x-date-pickers-pro'
materialDesign: https://m2.material.io/components/date-pickers
---
-# Time Range Picker [](/x/introduction/licensing/#pro-plan)
+# Time Range Picker [](/x/introduction/licensing/#pro-plan)๐ง
The Time Range Picker let the user select a range of time.
-> โ ๏ธ This feature isn't implemented yet. It's coming.
->
-> ๐ Upvote [issue #4460](https://github.com/mui/mui-x/issues/4460) if you want to see it land faster.
+:::warning
+This feature isn't implemented yet. It's coming.
+
+๐ Upvote [issue #4460](https://github.com/mui/mui-x/issues/4460) if you want to see it land faster.
+
+Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution.
+:::
diff --git a/docs/data/pages.ts b/docs/data/pages.ts
index a8d7423029c7..f37c5214933b 100644
--- a/docs/data/pages.ts
+++ b/docs/data/pages.ts
@@ -7,10 +7,10 @@ import dataGridComponentApi from './data-grid-component-api-pages';
import pickersComponentApi from './date-pickers-component-api-pages';
import chartsComponentApi from './charts-component-api-pages';
-const isPreview =
- process.env.NODE_ENV === 'development' ||
- process.env.CONTEXT === 'deploy-preview' ||
- process.env.CONTEXT === 'branch-deploy';
+// const isPreview =
+// process.env.NODE_ENV === 'development' ||
+// process.env.CONTEXT === 'deploy-preview' ||
+// process.env.CONTEXT === 'branch-deploy';
const pages: MuiPage[] = [
{
@@ -63,6 +63,7 @@ const pages: MuiPage[] = [
{ pathname: '/x/react-data-grid/master-detail', plan: 'pro' },
{ pathname: '/x/react-data-grid/row-ordering', plan: 'pro' },
{ pathname: '/x/react-data-grid/row-pinning', plan: 'pro' },
+ { pathname: '/x/react-data-grid/row-recipes', title: 'Recipes' },
],
},
{ pathname: '/x/react-data-grid/editing' },
@@ -348,65 +349,61 @@ const pages: MuiPage[] = [
},
],
},
- ...(isPreview
- ? [
- {
- pathname: '/x/react-charts-group',
- title: 'Charts ๐ง',
- icon: ChartIcon,
- children: [
- { pathname: '/x/react-charts', title: 'Overview' },
- {
- pathname: '/x/react-charts-bars',
- title: 'Bars',
- children: [
- { pathname: '/x/react-charts/bars', title: 'Bars' },
- { pathname: '/x/react-charts/bar-demo', title: 'Demo' },
- ],
- },
- {
- pathname: '/x/react-charts-lines',
- title: 'Lines',
- children: [
- { pathname: '/x/react-charts/lines', title: 'Lines' },
- { pathname: '/x/react-charts/line-demo', title: 'Demo lines' },
- { pathname: '/x/react-charts/areas-demo', title: 'Demo area' },
- ],
- },
- {
- pathname: '/x/react-charts-scatter',
- title: 'Scatter',
- children: [
- { pathname: '/x/react-charts/scatter', title: 'Scatter' },
- { pathname: '/x/react-charts/scatter-demo', title: 'Demo' },
- ],
- },
- {
- pathname: '/x/react-charts-common-components',
- title: 'Common components',
- children: [
- { pathname: '/x/react-charts/axis', title: 'Axis' },
- { pathname: '/x/react-charts/tooltip', title: 'Tooltip' },
- { pathname: '/x/react-charts/legend', title: 'Legend' },
- { pathname: '/x/react-charts/styling', title: 'Styling' },
- { pathname: '/x/react-charts/stacking', title: 'Stacking' },
- ],
- },
- { pathname: '/x/react-charts/heat-map', title: '๐ง Heat map' },
- { pathname: '/x/react-charts/funnel', title: '๐ง Funnel' },
- { pathname: '/x/react-charts/gantt', title: '๐ง Gantt' },
- { pathname: '/x/react-charts/radar', title: '๐ง Radar' },
- { pathname: '/x/react-charts/sankey', title: '๐ง Sankey' },
- { pathname: '/x/react-charts/tree-map', title: '๐ง Tree map' },
- {
- pathname: '/x/api/charts-group',
- title: 'API Reference',
- children: [...chartsComponentApi],
- },
- ],
- },
- ]
- : []),
+ {
+ pathname: '/x/react-charts-group',
+ title: 'Charts ๐งช',
+ icon: ChartIcon,
+ children: [
+ { pathname: '/x/react-charts', title: 'Overview' },
+ {
+ pathname: '/x/react-charts-bars',
+ title: 'Bars',
+ children: [
+ { pathname: '/x/react-charts/bars', title: 'Bars' },
+ { pathname: '/x/react-charts/bar-demo', title: 'Demo' },
+ ],
+ },
+ {
+ pathname: '/x/react-charts-lines',
+ title: 'Lines',
+ children: [
+ { pathname: '/x/react-charts/lines', title: 'Lines' },
+ { pathname: '/x/react-charts/line-demo', title: 'Demo lines' },
+ { pathname: '/x/react-charts/areas-demo', title: 'Demo area' },
+ ],
+ },
+ {
+ pathname: '/x/react-charts-scatter',
+ title: 'Scatter',
+ children: [
+ { pathname: '/x/react-charts/scatter', title: 'Scatter' },
+ { pathname: '/x/react-charts/scatter-demo', title: 'Demo' },
+ ],
+ },
+ {
+ pathname: '/x/react-charts-common-components',
+ title: 'Common components',
+ children: [
+ { pathname: '/x/react-charts/axis', title: 'Axis' },
+ { pathname: '/x/react-charts/tooltip', title: 'Tooltip' },
+ { pathname: '/x/react-charts/legend', title: 'Legend' },
+ { pathname: '/x/react-charts/styling', title: 'Styling' },
+ { pathname: '/x/react-charts/stacking', title: 'Stacking' },
+ ],
+ },
+ { pathname: '/x/react-charts/heat-map', title: '๐ง Heat map' },
+ { pathname: '/x/react-charts/funnel', title: '๐ง Funnel' },
+ { pathname: '/x/react-charts/gantt', title: '๐ง Gantt' },
+ { pathname: '/x/react-charts/radar', title: '๐ง Radar' },
+ { pathname: '/x/react-charts/sankey', title: '๐ง Sankey' },
+ { pathname: '/x/react-charts/tree-map', title: '๐ง Tree map' },
+ {
+ pathname: '/x/api/charts-group',
+ title: 'API Reference',
+ children: [...chartsComponentApi],
+ },
+ ],
+ },
];
export default pages;
diff --git a/docs/next.config.js b/docs/next.config.js
index 18407eae7ec2..63b01f71c7a0 100644
--- a/docs/next.config.js
+++ b/docs/next.config.js
@@ -21,7 +21,7 @@ module.exports = withDocsInfra({
FEEDBACK_URL: process.env.FEEDBACK_URL,
CONTEXT: process.env.CONTEXT,
// #default-branch-switch
- SOURCE_CODE_ROOT_URL: 'https://github.com/mui/mui-x/blob/master',
+ SOURCE_GITHUB_BRANCH: 'master',
SOURCE_CODE_REPO: 'https://github.com/mui/mui-x',
GITHUB_TEMPLATE_DOCS_FEEDBACK: '6.docs-feedback.yml',
},
diff --git a/docs/package.json b/docs/package.json
index aba43ee8083d..da2bfab20a93 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -29,10 +29,10 @@
"@emotion/server": "^11.11.0",
"@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.11.16",
- "@mui/joy": "^5.0.0-alpha.84",
- "@mui/material": "^5.13.5",
+ "@mui/joy": "^5.0.0-alpha.85",
+ "@mui/material": "^5.13.6",
"@mui/styles": "^5.13.2",
- "@mui/utils": "^5.13.1",
+ "@mui/utils": "^5.13.6",
"@trendmicro/react-interpolate": "^0.5.5",
"@types/lodash": "^4.14.195",
"@types/moment-hijri": "^2.1.0",
@@ -62,10 +62,10 @@
"luxon": "^3.3.0",
"lz-string": "^1.5.0",
"markdown-to-jsx": "^7.2.1",
- "marked": "^4.3.0",
+ "marked": "^5.1.0",
"moment": "^2.29.4",
"moment-hijri": "^2.1.2",
- "moment-timezone": "^0.5.41",
+ "moment-timezone": "^0.5.43",
"next": "^13.4.6",
"nprogress": "^0.2.0",
"postcss": "^8.4.24",
diff --git a/docs/pages/_app.js b/docs/pages/_app.js
index 0ef4d568930d..eac16b93d257 100644
--- a/docs/pages/_app.js
+++ b/docs/pages/_app.js
@@ -18,6 +18,7 @@ import { pathnameToLanguage } from 'docs/src/modules/utils/helpers';
import createEmotionCache from 'docs/src/createEmotionCache';
import findActivePage from 'docs/src/modules/utils/findActivePage';
import { LicenseInfo } from '@mui/x-license-pro';
+import getProductInfoFromUrl from 'docs/src/modules/utils/getProductInfoFromUrl';
// Remove the license warning from demonstration purposes
LicenseInfo.setLicenseKey(process.env.NEXT_PUBLIC_MUI_LICENSE);
@@ -171,6 +172,18 @@ function AppWrapper(props) {
const { children, emotionCache, pageProps } = props;
const router = useRouter();
+ const { productId: productIdRaw, productCategoryId } = getProductInfoFromUrl(router.asPath);
+ const { canonicalAs } = pathnameToLanguage(router.asPath);
+ let productId = productIdRaw;
+
+ // Not respecting URL convention, ad-hoc workaround
+ if (canonicalAs.startsWith('/x/api/data-grid/')) {
+ productId = 'x-data-grid';
+ } else if (canonicalAs.startsWith('/x/api/date-pickers/')) {
+ productId = 'x-date-pickers';
+ } else if (canonicalAs.startsWith('/x/api/charts/')) {
+ productId = 'x-charts';
+ }
React.useEffect(() => {
loadDependencies();
@@ -184,17 +197,14 @@ function AppWrapper(props) {
}, []);
let fonts = [];
- if (router.pathname.match(/onepirate/)) {
+ if (pathnameToLanguage(router.asPath).canonicalAs.match(/onepirate/)) {
fonts = [
'https://fonts.googleapis.com/css?family=Roboto+Condensed:700|Work+Sans:300,400&display=swap',
];
}
- const { canonicalAs } = pathnameToLanguage(router.asPath);
-
const pageContextValue = React.useMemo(() => {
const { activePage, activePageParents } = findActivePage(pages, router.pathname);
-
const languagePrefix = pageProps.userLanguage === 'en' ? '' : `/${pageProps.userLanguage}`;
let productIdentifier = {
@@ -207,10 +217,7 @@ function AppWrapper(props) {
],
};
- if (
- canonicalAs.startsWith('/x/react-data-grid/') ||
- canonicalAs.startsWith('/x/api/data-grid/')
- ) {
+ if (productId === 'x-data-grid') {
productIdentifier = {
metadata: 'MUI X',
name: 'Data Grid',
@@ -220,10 +227,7 @@ function AppWrapper(props) {
{ text: 'v4', href: `https://v4.mui.com${languagePrefix}/components/data-grid/` },
],
};
- } else if (
- canonicalAs.startsWith('/x/react-date-pickers/') ||
- canonicalAs.startsWith('/x/api/date-pickers/')
- ) {
+ } else if (productId === 'x-date-pickers') {
productIdentifier = {
metadata: 'MUI X',
name: 'Date Pickers',
@@ -237,8 +241,14 @@ function AppWrapper(props) {
};
}
- return { activePage, activePageParents, pages, productIdentifier };
- }, [canonicalAs, pageProps.userLanguage, router.pathname]);
+ return {
+ activePage,
+ activePageParents,
+ pages,
+ productIdentifier,
+ productId,
+ };
+ }, [productId, pageProps.userLanguage, router.pathname]);
// Replicate change reverted in https://github.com/mui/material-ui/pull/35969/files#r1089572951
// Fixes playground styles in dark mode.
@@ -250,6 +260,8 @@ function AppWrapper(props) {
{fonts.map((font) => (
))}
+
+
diff --git a/docs/pages/x/api/data-grid/grid-actions-col-def.md b/docs/pages/x/api/data-grid/grid-actions-col-def.md
index d544255e109a..982145c83efd 100644
--- a/docs/pages/x/api/data-grid/grid-actions-col-def.md
+++ b/docs/pages/x/api/data-grid/grid-actions-col-def.md
@@ -23,47 +23,48 @@ import { GridActionsColDef } from '@mui/x-data-grid';
## Properties
-| Name | Type | Default | Description |
-| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| aggregable? [](/x/introduction/licensing/#premium-plan) | boolean | true | If `true`, the cells of the column can be aggregated based. |
-| align? | GridAlignment | | Allows to align the column values in cells. |
-| availableAggregationFunctions? [](/x/introduction/licensing/#premium-plan) | string[] | | Limit the aggregation function usable on this column. By default, the column will have all the aggregation functions that are compatible with its type. |
-| cellClassName? | GridCellClassNamePropType<R, V> | | Class name that will be added in cells for that column. |
-| colSpan? | number \| ((params: GridCellParams<R, V, F>) => number \| undefined) | 1 | Number of columns a cell should span. |
-| description? | string | | The description of the column rendered as tooltip if the column header name is not fully displayed. |
-| disableColumnMenu? | boolean | false | If `true`, the column menu is disabled for this column. |
-| disableExport? | boolean | false | If `true`, this column will not be included in exports. |
-| disableReorder? | boolean | false | If `true`, this column cannot be reordered. |
-| editable? | boolean | false | If `true`, the cells of the column are editable. |
-| field | string | | The column identifier. It's used to map with GridRowModel values. |
-| filterable? | boolean | true | If `true`, the column is filterable. |
-| filterOperators? | GridFilterOperator<R, V, F>[] | | Allows setting the filter operators for this column. |
-| flex? | number | | If set, it indicates that a column has fluid width. Range [0, โ). |
-| getActions | (params: GridRowParams<R>) => React.ReactElement<GridActionsCellItemProps>[] | | Function that returns the actions to be shown. |
-| getApplyQuickFilterFn? | (value: any, colDef: GridStateColDef, apiRef: React.MutableRefObject<GridApiCommunity>) => null \| ((params: GridCellParams<R, V, F>) => boolean) | | The callback that generates a filtering function for a given quick filter value. This function can return `null` to skip filtering for this value and column. |
-| groupable? | boolean | true | If `true`, the rows can be grouped based on this column values (pro-plan only). Only available in DataGridPremium. |
-| groupingValueGetter? [](/x/introduction/licensing/#premium-plan) | (params: GridGroupingValueGetterParams<R, V>) => GridKeyValue \| null \| undefined | | Function that transforms a complex cell value into a key that be used for grouping the rows. |
-| headerAlign? | GridAlignment | | Header cell element alignment. |
-| headerClassName? | GridColumnHeaderClassNamePropType | | Class name that will be added in the column header cell. |
-| headerName? | string | | The title of the column rendered in the column header cell. |
-| hideable? | boolean | true | If `false`, removes the buttons for hiding this column. |
-| hideSortIcons? | boolean | false | Toggle the visibility of the sort icons. |
-| maxWidth? | number | Infinity | Sets the maximum width of a column. |
-| minWidth? | number | 50 | Sets the minimum width of a column. |
-| pastedValueParser? [](/x/introduction/licensing/#premium-plan) | (value: string, params: GridCellParams<R, V, F>) => V \| undefined | | Function that takes the clipboard-pasted value and converts it to a value used internally. |
-| pinnable? | boolean | true | If `false`, the menu items for column pinning menu will not be rendered. Only available in DataGridPro. |
-| preProcessEditCellProps? | (params: GridPreProcessEditCellProps) => GridEditCellProps \| Promise<GridEditCellProps> | | Callback fired when the edit props of the cell changes. It allows to process the props that saved into the state. |
-| renderCell? | (params: GridRenderCellParams<R, V, F>) => React.ReactNode | | Allows to override the component rendered as cell for this column. |
-| renderEditCell? | (params: GridRenderEditCellParams<R, V, F>) => React.ReactNode | | Allows to override the component rendered in edit cell mode for this column. |
-| renderHeader? | (params: GridColumnHeaderParams<R, V, F>) => React.ReactNode | | Allows to render a component in the column header cell. |
-| renderHeaderFilter? [](/x/introduction/licensing/#pro-plan) | (params: GridHeaderFilterCellProps) => React.ReactNode | | Allows to render a component in the column header filter cell. |
-| resizable? | boolean | true | If `true`, the column is resizable. |
-| sortable? | boolean | true | If `true`, the column is sortable. |
-| sortComparator? | GridComparatorFn<V> | | A comparator function used to sort rows. |
-| sortingOrder? | GridSortDirection[] | | The order of the sorting sequence. |
-| type | 'actions' | 'actions' | The type of the column. |
-| valueFormatter? | (params: GridValueFormatterParams<V>) => F | | Function that allows to apply a formatter before rendering its value. |
-| valueGetter? | (params: GridValueGetterParams<R, any>) => V | | Function that allows to get a specific data instead of field to render in the cell. |
-| valueParser? | (value: F \| undefined, params?: GridCellParams<R, V, F>) => V | | Function that takes the user-entered value and converts it to a value used internally. |
-| valueSetter? | (params: GridValueSetterParams<R, V>) => R | | Function that allows to customize how the entered value is stored in the row. It only works with cell/row editing. |
-| width? | number | 100 | Set the width of the column. |
+| Name | Type | Default | Description |
+| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| aggregable? [](/x/introduction/licensing/#premium-plan) | boolean | true | If `true`, the cells of the column can be aggregated based. |
+| align? | GridAlignment | | Allows to align the column values in cells. |
+| availableAggregationFunctions? [](/x/introduction/licensing/#premium-plan) | string[] | | Limit the aggregation function usable on this column. By default, the column will have all the aggregation functions that are compatible with its type. |
+| cellClassName? | GridCellClassNamePropType<R, V> | | Class name that will be added in cells for that column. |
+| colSpan? | number \| ((params: GridCellParams<R, V, F>) => number \| undefined) | 1 | Number of columns a cell should span. |
+| description? | string | | The description of the column rendered as tooltip if the column header name is not fully displayed. |
+| disableColumnMenu? | boolean | false | If `true`, the column menu is disabled for this column. |
+| disableExport? | boolean | false | If `true`, this column will not be included in exports. |
+| disableReorder? | boolean | false | If `true`, this column cannot be reordered. |
+| editable? | boolean | false | If `true`, the cells of the column are editable. |
+| field | string | | The column identifier. It's used to map with GridRowModel values. |
+| filterable? | boolean | true | If `true`, the column is filterable. |
+| filterOperators? | GridFilterOperator<R, V, F>[] | | Allows setting the filter operators for this column. |
+| flex? | number | | If set, it indicates that a column has fluid width. Range [0, โ). |
+| getActions | (params: GridRowParams<R>) => React.ReactElement<GridActionsCellItemProps>[] | | Function that returns the actions to be shown. |
+| getApplyQuickFilterFn? | GetApplyQuickFilterFnLegacy<R, V, F> | | The callback that generates a filtering function for a given quick filter value. This function can return `null` to skip filtering for this value and column. |
+| getApplyQuickFilterFnV7? | GetApplyQuickFilterFnV7<R, V> | | The callback that generates a filtering function for a given quick filter value. This function can return `null` to skip filtering for this value and column. |
+| groupable? | boolean | true | If `true`, the rows can be grouped based on this column values (pro-plan only). Only available in DataGridPremium. |
+| groupingValueGetter? [](/x/introduction/licensing/#premium-plan) | (params: GridGroupingValueGetterParams<R, V>) => GridKeyValue \| null \| undefined | | Function that transforms a complex cell value into a key that be used for grouping the rows. |
+| headerAlign? | GridAlignment | | Header cell element alignment. |
+| headerClassName? | GridColumnHeaderClassNamePropType | | Class name that will be added in the column header cell. |
+| headerName? | string | | The title of the column rendered in the column header cell. |
+| hideable? | boolean | true | If `false`, removes the buttons for hiding this column. |
+| hideSortIcons? | boolean | false | Toggle the visibility of the sort icons. |
+| maxWidth? | number | Infinity | Sets the maximum width of a column. |
+| minWidth? | number | 50 | Sets the minimum width of a column. |
+| pastedValueParser? [](/x/introduction/licensing/#premium-plan) | (value: string, params: GridCellParams<R, V, F>) => V \| undefined | | Function that takes the clipboard-pasted value and converts it to a value used internally. |
+| pinnable? | boolean | true | If `false`, the menu items for column pinning menu will not be rendered. Only available in DataGridPro. |
+| preProcessEditCellProps? | (params: GridPreProcessEditCellProps) => GridEditCellProps \| Promise<GridEditCellProps> | | Callback fired when the edit props of the cell changes. It allows to process the props that saved into the state. |
+| renderCell? | (params: GridRenderCellParams<R, V, F>) => React.ReactNode | | Allows to override the component rendered as cell for this column. |
+| renderEditCell? | (params: GridRenderEditCellParams<R, V, F>) => React.ReactNode | | Allows to override the component rendered in edit cell mode for this column. |
+| renderHeader? | (params: GridColumnHeaderParams<R, V, F>) => React.ReactNode | | Allows to render a component in the column header cell. |
+| renderHeaderFilter? [](/x/introduction/licensing/#pro-plan) | (params: GridHeaderFilterCellProps) => React.ReactNode | | Allows to render a component in the column header filter cell. |
+| resizable? | boolean | true | If `true`, the column is resizable. |
+| sortable? | boolean | true | If `true`, the column is sortable. |
+| sortComparator? | GridComparatorFn<V> | | A comparator function used to sort rows. |
+| sortingOrder? | GridSortDirection[] | | The order of the sorting sequence. |
+| type | 'actions' | 'actions' | The type of the column. |
+| valueFormatter? | (params: GridValueFormatterParams<V>) => F | | Function that allows to apply a formatter before rendering its value. |
+| valueGetter? | (params: GridValueGetterParams<R, any>) => V | | Function that allows to get a specific data instead of field to render in the cell. |
+| valueParser? | (value: F \| undefined, params?: GridCellParams<R, V, F>) => V | | Function that takes the user-entered value and converts it to a value used internally. |
+| valueSetter? | (params: GridValueSetterParams<R, V>) => R | | Function that allows to customize how the entered value is stored in the row. It only works with cell/row editing. |
+| width? | number | 100 | Set the width of the column. |
diff --git a/docs/pages/x/api/data-grid/grid-col-def.md b/docs/pages/x/api/data-grid/grid-col-def.md
index dc588db4ac53..a63fffa486f5 100644
--- a/docs/pages/x/api/data-grid/grid-col-def.md
+++ b/docs/pages/x/api/data-grid/grid-col-def.md
@@ -23,46 +23,47 @@ import { GridColDef } from '@mui/x-data-grid';
## Properties
-| Name | Type | Default | Description |
-| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| aggregable? [](/x/introduction/licensing/#premium-plan) | boolean | true | If `true`, the cells of the column can be aggregated based. |
-| align? | GridAlignment | | Allows to align the column values in cells. |
-| availableAggregationFunctions? [](/x/introduction/licensing/#premium-plan) | string[] | | Limit the aggregation function usable on this column. By default, the column will have all the aggregation functions that are compatible with its type. |
-| cellClassName? | GridCellClassNamePropType<R, V> | | Class name that will be added in cells for that column. |
-| colSpan? | number \| ((params: GridCellParams<R, V, F>) => number \| undefined) | 1 | Number of columns a cell should span. |
-| description? | string | | The description of the column rendered as tooltip if the column header name is not fully displayed. |
-| disableColumnMenu? | boolean | false | If `true`, the column menu is disabled for this column. |
-| disableExport? | boolean | false | If `true`, this column will not be included in exports. |
-| disableReorder? | boolean | false | If `true`, this column cannot be reordered. |
-| editable? | boolean | false | If `true`, the cells of the column are editable. |
-| field | string | | The column identifier. It's used to map with GridRowModel values. |
-| filterable? | boolean | true | If `true`, the column is filterable. |
-| filterOperators? | GridFilterOperator<R, V, F>[] | | Allows setting the filter operators for this column. |
-| flex? | number | | If set, it indicates that a column has fluid width. Range [0, โ). |
-| getApplyQuickFilterFn? | (value: any, colDef: GridStateColDef, apiRef: React.MutableRefObject<GridApiCommunity>) => null \| ((params: GridCellParams<R, V, F>) => boolean) | | The callback that generates a filtering function for a given quick filter value. This function can return `null` to skip filtering for this value and column. |
-| groupable? | boolean | true | If `true`, the rows can be grouped based on this column values (pro-plan only). Only available in DataGridPremium. |
-| groupingValueGetter? [](/x/introduction/licensing/#premium-plan) | (params: GridGroupingValueGetterParams<R, V>) => GridKeyValue \| null \| undefined | | Function that transforms a complex cell value into a key that be used for grouping the rows. |
-| headerAlign? | GridAlignment | | Header cell element alignment. |
-| headerClassName? | GridColumnHeaderClassNamePropType | | Class name that will be added in the column header cell. |
-| headerName? | string | | The title of the column rendered in the column header cell. |
-| hideable? | boolean | true | If `false`, removes the buttons for hiding this column. |
-| hideSortIcons? | boolean | false | Toggle the visibility of the sort icons. |
-| maxWidth? | number | Infinity | Sets the maximum width of a column. |
-| minWidth? | number | 50 | Sets the minimum width of a column. |
-| pastedValueParser? [](/x/introduction/licensing/#premium-plan) | (value: string, params: GridCellParams<R, V, F>) => V \| undefined | | Function that takes the clipboard-pasted value and converts it to a value used internally. |
-| pinnable? | boolean | true | If `false`, the menu items for column pinning menu will not be rendered. Only available in DataGridPro. |
-| preProcessEditCellProps? | (params: GridPreProcessEditCellProps) => GridEditCellProps \| Promise<GridEditCellProps> | | Callback fired when the edit props of the cell changes. It allows to process the props that saved into the state. |
-| renderCell? | (params: GridRenderCellParams<R, V, F>) => React.ReactNode | | Allows to override the component rendered as cell for this column. |
-| renderEditCell? | (params: GridRenderEditCellParams<R, V, F>) => React.ReactNode | | Allows to override the component rendered in edit cell mode for this column. |
-| renderHeader? | (params: GridColumnHeaderParams<R, V, F>) => React.ReactNode | | Allows to render a component in the column header cell. |
-| renderHeaderFilter? [](/x/introduction/licensing/#pro-plan) | (params: GridHeaderFilterCellProps) => React.ReactNode | | Allows to render a component in the column header filter cell. |
-| resizable? | boolean | true | If `true`, the column is resizable. |
-| sortable? | boolean | true | If `true`, the column is sortable. |
-| sortComparator? | GridComparatorFn<V> | | A comparator function used to sort rows. |
-| sortingOrder? | GridSortDirection[] | | The order of the sorting sequence. |
-| type? | GridColType | 'singleSelect' | The type of the column. |
-| valueFormatter? | (params: GridValueFormatterParams<V>) => F | | Function that allows to apply a formatter before rendering its value. |
-| valueGetter? | (params: GridValueGetterParams<R, any>) => V | | Function that allows to get a specific data instead of field to render in the cell. |
-| valueParser? | (value: F \| undefined, params?: GridCellParams<R, V, F>) => V | | Function that takes the user-entered value and converts it to a value used internally. |
-| valueSetter? | (params: GridValueSetterParams<R, V>) => R | | Function that allows to customize how the entered value is stored in the row. It only works with cell/row editing. |
-| width? | number | 100 | Set the width of the column. |
+| Name | Type | Default | Description |
+| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| aggregable? [](/x/introduction/licensing/#premium-plan) | boolean | true | If `true`, the cells of the column can be aggregated based. |
+| align? | GridAlignment | | Allows to align the column values in cells. |
+| availableAggregationFunctions? [](/x/introduction/licensing/#premium-plan) | string[] | | Limit the aggregation function usable on this column. By default, the column will have all the aggregation functions that are compatible with its type. |
+| cellClassName? | GridCellClassNamePropType<R, V> | | Class name that will be added in cells for that column. |
+| colSpan? | number \| ((params: GridCellParams<R, V, F>) => number \| undefined) | 1 | Number of columns a cell should span. |
+| description? | string | | The description of the column rendered as tooltip if the column header name is not fully displayed. |
+| disableColumnMenu? | boolean | false | If `true`, the column menu is disabled for this column. |
+| disableExport? | boolean | false | If `true`, this column will not be included in exports. |
+| disableReorder? | boolean | false | If `true`, this column cannot be reordered. |
+| editable? | boolean | false | If `true`, the cells of the column are editable. |
+| field | string | | The column identifier. It's used to map with GridRowModel values. |
+| filterable? | boolean | true | If `true`, the column is filterable. |
+| filterOperators? | GridFilterOperator<R, V, F>[] | | Allows setting the filter operators for this column. |
+| flex? | number | | If set, it indicates that a column has fluid width. Range [0, โ). |
+| getApplyQuickFilterFn? | GetApplyQuickFilterFnLegacy<R, V, F> | | The callback that generates a filtering function for a given quick filter value. This function can return `null` to skip filtering for this value and column. |
+| getApplyQuickFilterFnV7? | GetApplyQuickFilterFnV7<R, V> | | The callback that generates a filtering function for a given quick filter value. This function can return `null` to skip filtering for this value and column. |
+| groupable? | boolean | true | If `true`, the rows can be grouped based on this column values (pro-plan only). Only available in DataGridPremium. |
+| groupingValueGetter? [](/x/introduction/licensing/#premium-plan) | (params: GridGroupingValueGetterParams<R, V>) => GridKeyValue \| null \| undefined | | Function that transforms a complex cell value into a key that be used for grouping the rows. |
+| headerAlign? | GridAlignment | | Header cell element alignment. |
+| headerClassName? | GridColumnHeaderClassNamePropType | | Class name that will be added in the column header cell. |
+| headerName? | string | | The title of the column rendered in the column header cell. |
+| hideable? | boolean | true | If `false`, removes the buttons for hiding this column. |
+| hideSortIcons? | boolean | false | Toggle the visibility of the sort icons. |
+| maxWidth? | number | Infinity | Sets the maximum width of a column. |
+| minWidth? | number | 50 | Sets the minimum width of a column. |
+| pastedValueParser? [](/x/introduction/licensing/#premium-plan) | (value: string, params: GridCellParams<R, V, F>) => V \| undefined | | Function that takes the clipboard-pasted value and converts it to a value used internally. |
+| pinnable? | boolean | true | If `false`, the menu items for column pinning menu will not be rendered. Only available in DataGridPro. |
+| preProcessEditCellProps? | (params: GridPreProcessEditCellProps) => GridEditCellProps \| Promise<GridEditCellProps> | | Callback fired when the edit props of the cell changes. It allows to process the props that saved into the state. |
+| renderCell? | (params: GridRenderCellParams<R, V, F>) => React.ReactNode | | Allows to override the component rendered as cell for this column. |
+| renderEditCell? | (params: GridRenderEditCellParams<R, V, F>) => React.ReactNode | | Allows to override the component rendered in edit cell mode for this column. |
+| renderHeader? | (params: GridColumnHeaderParams<R, V, F>) => React.ReactNode | | Allows to render a component in the column header cell. |
+| renderHeaderFilter? [](/x/introduction/licensing/#pro-plan) | (params: GridHeaderFilterCellProps) => React.ReactNode | | Allows to render a component in the column header filter cell. |
+| resizable? | boolean | true | If `true`, the column is resizable. |
+| sortable? | boolean | true | If `true`, the column is sortable. |
+| sortComparator? | GridComparatorFn<V> | | A comparator function used to sort rows. |
+| sortingOrder? | GridSortDirection[] | | The order of the sorting sequence. |
+| type? | GridColType | 'singleSelect' | The type of the column. |
+| valueFormatter? | (params: GridValueFormatterParams<V>) => F | | Function that allows to apply a formatter before rendering its value. |
+| valueGetter? | (params: GridValueGetterParams<R, any>) => V | | Function that allows to get a specific data instead of field to render in the cell. |
+| valueParser? | (value: F \| undefined, params?: GridCellParams<R, V, F>) => V | | Function that takes the user-entered value and converts it to a value used internally. |
+| valueSetter? | (params: GridValueSetterParams<R, V>) => R | | Function that allows to customize how the entered value is stored in the row. It only works with cell/row editing. |
+| width? | number | 100 | Set the width of the column. |
diff --git a/docs/pages/x/api/data-grid/grid-filter-operator.md b/docs/pages/x/api/data-grid/grid-filter-operator.md
index f6448f38ea51..a983cc37abb7 100644
--- a/docs/pages/x/api/data-grid/grid-filter-operator.md
+++ b/docs/pages/x/api/data-grid/grid-filter-operator.md
@@ -23,13 +23,14 @@ import { GridFilterOperator } from '@mui/x-data-grid';
## Properties
-| Name | Type | Default | Description |
-| :---------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| getApplyFilterFn | (filterItem: GridFilterItem, column: GridColDef<R, V, F>) => null \| ((params: GridCellParams<R, V, F>) => boolean) | | The callback that generates a filtering function for a given filter item and column. This function can return `null` to skip filtering for this item and column. |
-| getValueAsString? | (value: GridFilterItem['value']) => string | | Converts the value of a filter item to a human-readable form. |
-| headerLabel? | string | | The label of the filter shown in header filter row. |
-| InputComponent? | React.JSXElementConstructor<any> | | The input component to render in the filter panel for this filter operator. |
-| InputComponentProps? | Record<string, any> | | The props to pass to the input component in the filter panel for this filter operator. |
-| label? | string | | The label of the filter operator. |
-| requiresFilterValue? | boolean | true | If `false`, filter operator doesn't require user-entered value to work. Usually should be set to `false` for filter operators that don't have `InputComponent` (for example `isEmpty`) |
-| value | string | | The name of the filter operator. It will be matched with the `operator` property of the filter items. |
+| Name | Type | Default | Description |
+| :---------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------- | :------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| getApplyFilterFn | GetApplyFilterFnLegacy<R, V, F> | | The callback that generates a filtering function for a given filter item and column. This function can return `null` to skip filtering for this item and column. |
+| getApplyFilterFnV7? | GetApplyFilterFnV7<R, V, F> | | The callback that generates a filtering function for a given filter item and column. This function can return `null` to skip filtering for this item and column. This function uses the more performant V7 API. |
+| getValueAsString? | (value: GridFilterItem['value']) => string | | Converts the value of a filter item to a human-readable form. |
+| headerLabel? | string | | The label of the filter shown in header filter row. |
+| InputComponent? | React.JSXElementConstructor<any> | | The input component to render in the filter panel for this filter operator. |
+| InputComponentProps? | Record<string, any> | | The props to pass to the input component in the filter panel for this filter operator. |
+| label? | string | | The label of the filter operator. |
+| requiresFilterValue? | boolean | true | If `false`, filter operator doesn't require user-entered value to work. Usually should be set to `false` for filter operators that don't have `InputComponent` (for example `isEmpty`) |
+| value | string | | The name of the filter operator. It will be matched with the `operator` property of the filter items. |
diff --git a/docs/pages/x/api/data-grid/grid-single-select-col-def.md b/docs/pages/x/api/data-grid/grid-single-select-col-def.md
index e53dafa4246b..5919c1df9977 100644
--- a/docs/pages/x/api/data-grid/grid-single-select-col-def.md
+++ b/docs/pages/x/api/data-grid/grid-single-select-col-def.md
@@ -23,49 +23,50 @@ import { GridSingleSelectColDef } from '@mui/x-data-grid';
## Properties
-| Name | Type | Default | Description |
-| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| aggregable? [](/x/introduction/licensing/#premium-plan) | boolean | true | If `true`, the cells of the column can be aggregated based. |
-| align? | GridAlignment | | Allows to align the column values in cells. |
-| availableAggregationFunctions? [](/x/introduction/licensing/#premium-plan) | string[] | | Limit the aggregation function usable on this column. By default, the column will have all the aggregation functions that are compatible with its type. |
-| cellClassName? | GridCellClassNamePropType<R, V> | | Class name that will be added in cells for that column. |
-| colSpan? | number \| ((params: GridCellParams<R, V, F>) => number \| undefined) | 1 | Number of columns a cell should span. |
-| description? | string | | The description of the column rendered as tooltip if the column header name is not fully displayed. |
-| disableColumnMenu? | boolean | false | If `true`, the column menu is disabled for this column. |
-| disableExport? | boolean | false | If `true`, this column will not be included in exports. |
-| disableReorder? | boolean | false | If `true`, this column cannot be reordered. |
-| editable? | boolean | false | If `true`, the cells of the column are editable. |
-| field | string | | The column identifier. It's used to map with GridRowModel values. |
-| filterable? | boolean | true | If `true`, the column is filterable. |
-| filterOperators? | GridFilterOperator<R, V, F>[] | | Allows setting the filter operators for this column. |
-| flex? | number | | If set, it indicates that a column has fluid width. Range [0, โ). |
-| getApplyQuickFilterFn? | (value: any, colDef: GridStateColDef, apiRef: React.MutableRefObject<GridApiCommunity>) => null \| ((params: GridCellParams<R, V, F>) => boolean) | | The callback that generates a filtering function for a given quick filter value. This function can return `null` to skip filtering for this value and column. |
-| getOptionLabel? | (value: ValueOptions) => string | | Used to determine the label displayed for a given value option. |
-| getOptionValue? | (value: ValueOptions) => any | | Used to determine the value used for a value option. |
-| groupable? | boolean | true | If `true`, the rows can be grouped based on this column values (pro-plan only). Only available in DataGridPremium. |
-| groupingValueGetter? [](/x/introduction/licensing/#premium-plan) | (params: GridGroupingValueGetterParams<R, V>) => GridKeyValue \| null \| undefined | | Function that transforms a complex cell value into a key that be used for grouping the rows. |
-| headerAlign? | GridAlignment | | Header cell element alignment. |
-| headerClassName? | GridColumnHeaderClassNamePropType | | Class name that will be added in the column header cell. |
-| headerName? | string | | The title of the column rendered in the column header cell. |
-| hideable? | boolean | true | If `false`, removes the buttons for hiding this column. |
-| hideSortIcons? | boolean | false | Toggle the visibility of the sort icons. |
-| maxWidth? | number | Infinity | Sets the maximum width of a column. |
-| minWidth? | number | 50 | Sets the minimum width of a column. |
-| pastedValueParser? [](/x/introduction/licensing/#premium-plan) | (value: string, params: GridCellParams<R, V, F>) => V \| undefined | | Function that takes the clipboard-pasted value and converts it to a value used internally. |
-| pinnable? | boolean | true | If `false`, the menu items for column pinning menu will not be rendered. Only available in DataGridPro. |
-| preProcessEditCellProps? | (params: GridPreProcessEditCellProps) => GridEditCellProps \| Promise<GridEditCellProps> | | Callback fired when the edit props of the cell changes. It allows to process the props that saved into the state. |
-| renderCell? | (params: GridRenderCellParams<R, V, F>) => React.ReactNode | | Allows to override the component rendered as cell for this column. |
-| renderEditCell? | (params: GridRenderEditCellParams<R, V, F>) => React.ReactNode | | Allows to override the component rendered in edit cell mode for this column. |
-| renderHeader? | (params: GridColumnHeaderParams<R, V, F>) => React.ReactNode | | Allows to render a component in the column header cell. |
-| renderHeaderFilter? [](/x/introduction/licensing/#pro-plan) | (params: GridHeaderFilterCellProps) => React.ReactNode | | Allows to render a component in the column header filter cell. |
-| resizable? | boolean | true | If `true`, the column is resizable. |
-| sortable? | boolean | true | If `true`, the column is sortable. |
-| sortComparator? | GridComparatorFn<V> | | A comparator function used to sort rows. |
-| sortingOrder? | GridSortDirection[] | | The order of the sorting sequence. |
-| type | 'singleSelect' | 'singleSelect' | The type of the column. |
-| valueFormatter? | (params: GridValueFormatterParams<V>) => F | | Function that allows to apply a formatter before rendering its value. |
-| valueGetter? | (params: GridValueGetterParams<R, any>) => V | | Function that allows to get a specific data instead of field to render in the cell. |
-| valueOptions? | Array<ValueOptions> \| ((params: GridValueOptionsParams<R>) => Array<ValueOptions>) | | To be used in combination with `type: 'singleSelect'`. This is an array (or a function returning an array) of the possible cell values and labels. |
-| valueParser? | (value: F \| undefined, params?: GridCellParams<R, V, F>) => V | | Function that takes the user-entered value and converts it to a value used internally. |
-| valueSetter? | (params: GridValueSetterParams<R, V>) => R | | Function that allows to customize how the entered value is stored in the row. It only works with cell/row editing. |
-| width? | number | 100 | Set the width of the column. |
+| Name | Type | Default | Description |
+| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| aggregable? [](/x/introduction/licensing/#premium-plan) | boolean | true | If `true`, the cells of the column can be aggregated based. |
+| align? | GridAlignment | | Allows to align the column values in cells. |
+| availableAggregationFunctions? [](/x/introduction/licensing/#premium-plan) | string[] | | Limit the aggregation function usable on this column. By default, the column will have all the aggregation functions that are compatible with its type. |
+| cellClassName? | GridCellClassNamePropType<R, V> | | Class name that will be added in cells for that column. |
+| colSpan? | number \| ((params: GridCellParams<R, V, F>) => number \| undefined) | 1 | Number of columns a cell should span. |
+| description? | string | | The description of the column rendered as tooltip if the column header name is not fully displayed. |
+| disableColumnMenu? | boolean | false | If `true`, the column menu is disabled for this column. |
+| disableExport? | boolean | false | If `true`, this column will not be included in exports. |
+| disableReorder? | boolean | false | If `true`, this column cannot be reordered. |
+| editable? | boolean | false | If `true`, the cells of the column are editable. |
+| field | string | | The column identifier. It's used to map with GridRowModel values. |
+| filterable? | boolean | true | If `true`, the column is filterable. |
+| filterOperators? | GridFilterOperator<R, V, F>[] | | Allows setting the filter operators for this column. |
+| flex? | number | | If set, it indicates that a column has fluid width. Range [0, โ). |
+| getApplyQuickFilterFn? | GetApplyQuickFilterFnLegacy<R, V, F> | | The callback that generates a filtering function for a given quick filter value. This function can return `null` to skip filtering for this value and column. |
+| getApplyQuickFilterFnV7? | GetApplyQuickFilterFnV7<R, V> | | The callback that generates a filtering function for a given quick filter value. This function can return `null` to skip filtering for this value and column. |
+| getOptionLabel? | (value: ValueOptions) => string | | Used to determine the label displayed for a given value option. |
+| getOptionValue? | (value: ValueOptions) => any | | Used to determine the value used for a value option. |
+| groupable? | boolean | true | If `true`, the rows can be grouped based on this column values (pro-plan only). Only available in DataGridPremium. |
+| groupingValueGetter? [](/x/introduction/licensing/#premium-plan) | (params: GridGroupingValueGetterParams<R, V>) => GridKeyValue \| null \| undefined | | Function that transforms a complex cell value into a key that be used for grouping the rows. |
+| headerAlign? | GridAlignment | | Header cell element alignment. |
+| headerClassName? | GridColumnHeaderClassNamePropType | | Class name that will be added in the column header cell. |
+| headerName? | string | | The title of the column rendered in the column header cell. |
+| hideable? | boolean | true | If `false`, removes the buttons for hiding this column. |
+| hideSortIcons? | boolean | false | Toggle the visibility of the sort icons. |
+| maxWidth? | number | Infinity | Sets the maximum width of a column. |
+| minWidth? | number | 50 | Sets the minimum width of a column. |
+| pastedValueParser? [](/x/introduction/licensing/#premium-plan) | (value: string, params: GridCellParams<R, V, F>) => V \| undefined | | Function that takes the clipboard-pasted value and converts it to a value used internally. |
+| pinnable? | boolean | true | If `false`, the menu items for column pinning menu will not be rendered. Only available in DataGridPro. |
+| preProcessEditCellProps? | (params: GridPreProcessEditCellProps) => GridEditCellProps \| Promise<GridEditCellProps> | | Callback fired when the edit props of the cell changes. It allows to process the props that saved into the state. |
+| renderCell? | (params: GridRenderCellParams<R, V, F>) => React.ReactNode | | Allows to override the component rendered as cell for this column. |
+| renderEditCell? | (params: GridRenderEditCellParams<R, V, F>) => React.ReactNode | | Allows to override the component rendered in edit cell mode for this column. |
+| renderHeader? | (params: GridColumnHeaderParams<R, V, F>) => React.ReactNode | | Allows to render a component in the column header cell. |
+| renderHeaderFilter? [](/x/introduction/licensing/#pro-plan) | (params: GridHeaderFilterCellProps) => React.ReactNode | | Allows to render a component in the column header filter cell. |
+| resizable? | boolean | true | If `true`, the column is resizable. |
+| sortable? | boolean | true | If `true`, the column is sortable. |
+| sortComparator? | GridComparatorFn<V> | | A comparator function used to sort rows. |
+| sortingOrder? | GridSortDirection[] | | The order of the sorting sequence. |
+| type | 'singleSelect' | 'singleSelect' | The type of the column. |
+| valueFormatter? | (params: GridValueFormatterParams<V>) => F | | Function that allows to apply a formatter before rendering its value. |
+| valueGetter? | (params: GridValueGetterParams<R, any>) => V | | Function that allows to get a specific data instead of field to render in the cell. |
+| valueOptions? | Array<ValueOptions> \| ((params: GridValueOptionsParams<R>) => Array<ValueOptions>) | | To be used in combination with `type: 'singleSelect'`. This is an array (or a function returning an array) of the possible cell values and labels. |
+| valueParser? | (value: F \| undefined, params?: GridCellParams<R, V, F>) => V | | Function that takes the user-entered value and converts it to a value used internally. |
+| valueSetter? | (params: GridValueSetterParams<R, V>) => R | | Function that allows to customize how the entered value is stored in the row. It only works with cell/row editing. |
+| width? | number | 100 | Set the width of the column. |
diff --git a/docs/pages/x/react-data-grid/row-recipes.js b/docs/pages/x/react-data-grid/row-recipes.js
new file mode 100644
index 000000000000..8402f18c1315
--- /dev/null
+++ b/docs/pages/x/react-data-grid/row-recipes.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/row-recipes/row-recipes.md?@mui/markdown';
+
+export default function Page() {
+ return ;
+}
diff --git a/lerna.json b/lerna.json
index d8d73732c181..7c47fccf2869 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,6 +1,5 @@
{
"npmClient": "yarn",
- "useWorkspaces": true,
"version": "independent",
"useNx": false
}
diff --git a/package.json b/package.json
index 974d1c3b876a..543382c6acb5 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
{
- "version": "6.8.0",
+ "version": "6.9.0",
"private": true,
"scripts": {
"start": "yarn && yarn docs:dev",
@@ -89,12 +89,12 @@
"@emotion/styled": "^11.11.0",
"@mnajdova/enzyme-adapter-react-18": "^0.2.0",
"@mui/icons-material": "^5.11.16",
- "@mui/material": "^5.13.5",
+ "@mui/material": "^5.13.6",
"@mui/monorepo": "https://github.com/mui/material-ui.git#master",
- "@mui/utils": "^5.13.1",
+ "@mui/utils": "^5.13.6",
"@octokit/plugin-retry": "^5.0.4",
"@octokit/rest": "^19.0.13",
- "@playwright/test": "1.33.0",
+ "@playwright/test": "1.35.1",
"@testing-library/react": "^14.0.0",
"@types/babel__core": "^7.20.1",
"@types/chai": "^4.3.5",
@@ -103,15 +103,15 @@
"@types/mocha": "^10.0.1",
"@types/node": "^18.16.18",
"@types/prettier": "^2.7.3",
- "@types/react": "^18.2.13",
+ "@types/react": "^18.2.14",
"@types/react-dom": "^18.2.6",
"@types/react-test-renderer": "^18.0.0",
"@types/requestidlecallback": "^0.3.5",
"@types/sinon": "^10.0.15",
"@types/yargs": "^17.0.24",
- "@typescript-eslint/eslint-plugin": "^5.59.9",
- "@typescript-eslint/parser": "^5.59.9",
- "axe-core": "4.7.1",
+ "@typescript-eslint/eslint-plugin": "^5.60.0",
+ "@typescript-eslint/parser": "^5.60.0",
+ "axe-core": "4.7.2",
"babel-loader": "^9.1.2",
"babel-plugin-istanbul": "^6.1.1",
"babel-plugin-module-resolver": "^4.1.0",
@@ -154,12 +154,11 @@
"karma-mocha": "^2.0.1",
"karma-sourcemap-loader": "^0.4.0",
"karma-webpack": "^5.0.0",
- "lerna": "^6.6.2",
+ "lerna": "^7.1.1",
"markdownlint-cli2": "^0.8.1",
"mocha": "^10.2.0",
"nyc": "^15.1.0",
"patch-package": "^7.0.0",
- "playwright": "^1.33.0",
"postinstall-postinstall": "^2.1.0",
"prettier": "^2.8.8",
"pretty-quick": "^3.1.3",
@@ -167,7 +166,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"serve": "^14.2.0",
- "sinon": "^15.0.4",
+ "sinon": "^15.2.0",
"stream-browserify": "^3.0.0",
"string-replace-loader": "^3.1.0",
"typescript": "^5.1.3",
diff --git a/packages/eslint-plugin-material-ui/package.json b/packages/eslint-plugin-material-ui/package.json
index aa5dc46810b3..3f064c6afa6f 100644
--- a/packages/eslint-plugin-material-ui/package.json
+++ b/packages/eslint-plugin-material-ui/package.json
@@ -6,8 +6,8 @@
"main": "src/index.js",
"devDependencies": {
"@types/eslint": "^8.40.2",
- "@typescript-eslint/experimental-utils": "^5.59.9",
- "@typescript-eslint/parser": "^5.59.9"
+ "@typescript-eslint/experimental-utils": "^5.60.0",
+ "@typescript-eslint/parser": "^5.60.0"
},
"scripts": {
"test": "cd ../../ && cross-env NODE_ENV=test mocha 'packages/eslint-plugin-material-ui/**/*.test.js' --timeout 3000"
diff --git a/packages/grid/x-data-grid-generator/package.json b/packages/grid/x-data-grid-generator/package.json
index 4e880da0061c..0a9f7e8e5c6b 100644
--- a/packages/grid/x-data-grid-generator/package.json
+++ b/packages/grid/x-data-grid-generator/package.json
@@ -1,6 +1,6 @@
{
"name": "@mui/x-data-grid-generator",
- "version": "6.8.0",
+ "version": "6.9.0",
"description": "Generate fake data for demo purposes only.",
"author": "MUI Team",
"main": "src/index.ts",
@@ -31,8 +31,8 @@
},
"dependencies": {
"@babel/runtime": "^7.22.5",
- "@mui/base": "^5.0.0-beta.4",
- "@mui/x-data-grid-premium": "6.8.0",
+ "@mui/base": "^5.0.0-beta.5",
+ "@mui/x-data-grid-premium": "6.9.0",
"chance": "^1.1.11",
"clsx": "^1.2.1",
"lru-cache": "^7.18.3"
diff --git a/packages/grid/x-data-grid-premium/package.json b/packages/grid/x-data-grid-premium/package.json
index f6fb066d3e75..0d60b90d96f8 100644
--- a/packages/grid/x-data-grid-premium/package.json
+++ b/packages/grid/x-data-grid-premium/package.json
@@ -1,6 +1,6 @@
{
"name": "@mui/x-data-grid-premium",
- "version": "6.8.0",
+ "version": "6.9.0",
"description": "The Premium plan edition of the data grid component (MUI X).",
"author": "MUI Team",
"main": "src/index.ts",
@@ -43,10 +43,10 @@
},
"dependencies": {
"@babel/runtime": "^7.22.5",
- "@mui/utils": "^5.13.1",
- "@mui/x-data-grid": "6.8.0",
- "@mui/x-data-grid-pro": "6.8.0",
- "@mui/x-license-pro": "6.6.0",
+ "@mui/utils": "^5.13.6",
+ "@mui/x-data-grid": "6.9.0",
+ "@mui/x-data-grid-pro": "6.9.0",
+ "@mui/x-license-pro": "6.9.0",
"@types/format-util": "^1.0.2",
"clsx": "^1.2.1",
"exceljs": "^4.3.0",
diff --git a/packages/grid/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx b/packages/grid/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx
index 960bc5f166f2..4da70394a314 100644
--- a/packages/grid/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx
+++ b/packages/grid/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx
@@ -145,7 +145,7 @@ export const useDataGridPremiumComponent = (
useGridRowPinning(privateApiRef, props);
useGridColumns(privateApiRef, props);
useGridRows(privateApiRef, props);
- useGridParamsApi(privateApiRef);
+ useGridParamsApi(privateApiRef, props);
useGridDetailPanel(privateApiRef, props);
useGridColumnSpanning(privateApiRef);
useGridColumnGrouping(privateApiRef, props);
diff --git a/packages/grid/x-data-grid-premium/src/hooks/features/aggregation/wrapColumnWithAggregation.tsx b/packages/grid/x-data-grid-premium/src/hooks/features/aggregation/wrapColumnWithAggregation.tsx
index 5f40e81699b2..f08849fca532 100644
--- a/packages/grid/x-data-grid-premium/src/hooks/features/aggregation/wrapColumnWithAggregation.tsx
+++ b/packages/grid/x-data-grid-premium/src/hooks/features/aggregation/wrapColumnWithAggregation.tsx
@@ -1,6 +1,6 @@
import * as React from 'react';
-import { GridRowId } from '@mui/x-data-grid-pro';
-import { GridBaseColDef } from '@mui/x-data-grid-pro/internals';
+import { GridFilterOperator, GridRowId } from '@mui/x-data-grid-pro';
+import { GridBaseColDef, tagInternalFilter } from '@mui/x-data-grid-pro/internals';
import { GridApiPremium } from '../../../models/gridApiPremium';
import {
GridAggregationCellMeta,
@@ -131,23 +131,44 @@ const getWrappedFilterOperators: ColumnPropertyWrapper<'filterOperators'> = ({
getCellAggregationResult,
}) =>
filterOperators!.map((operator) => {
- return {
- ...operator,
- getApplyFilterFn: (filterItem, column) => {
- const originalFn = operator.getApplyFilterFn(filterItem, column);
- if (!originalFn) {
+ const baseGetApplyFilterFn = operator.getApplyFilterFn;
+ const baseGetApplyFilterFnV7 = operator.getApplyFilterFnV7;
+
+ const getApplyFilterFn: GridFilterOperator['getApplyFilterFn'] =
+ tagInternalFilter((filterItem, colDef) => {
+ const filterFn = baseGetApplyFilterFn(filterItem, colDef);
+ if (!filterFn) {
return null;
}
-
return (params) => {
if (getCellAggregationResult(params.id, params.field) != null) {
return true;
}
-
- return originalFn(params);
+ return filterFn(params);
};
- },
- };
+ });
+
+ const getApplyFilterFnV7: GridFilterOperator['getApplyFilterFnV7'] =
+ baseGetApplyFilterFnV7 === undefined
+ ? undefined
+ : tagInternalFilter((filterItem, colDef) => {
+ const filterFn = baseGetApplyFilterFnV7(filterItem, colDef);
+ if (!filterFn) {
+ return null;
+ }
+ return (value, row, column, api) => {
+ if (getCellAggregationResult(row.id, column.field) != null) {
+ return true;
+ }
+ return filterFn(value, row, column, api);
+ };
+ });
+
+ return {
+ ...operator,
+ getApplyFilterFn,
+ getApplyFilterFnV7,
+ } as GridFilterOperator;
});
/**
diff --git a/packages/grid/x-data-grid-premium/src/hooks/features/export/serializer/excelSerializer.ts b/packages/grid/x-data-grid-premium/src/hooks/features/export/serializer/excelSerializer.ts
index fb2ede0f4aed..3d816ef3577d 100644
--- a/packages/grid/x-data-grid-premium/src/hooks/features/export/serializer/excelSerializer.ts
+++ b/packages/grid/x-data-grid-premium/src/hooks/features/export/serializer/excelSerializer.ts
@@ -153,7 +153,7 @@ export const serializeRow = (
case 'dateTime': {
// Excel does not do any timezone conversion, so we create a date using UTC instead of local timezone
// Solution from: https://github.com/exceljs/exceljs/issues/486#issuecomment-432557582
- // About Date.UTC(): https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Date/UTC#exemples
+ // About Date.UTC(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/UTC#exemples
const value = api.getCellParams(id, column.field).value;
// value may be `undefined` in auto-generated grouping rows
if (!value) {
diff --git a/packages/grid/x-data-grid-premium/src/hooks/features/rowGrouping/createGroupingColDef.tsx b/packages/grid/x-data-grid-premium/src/hooks/features/rowGrouping/createGroupingColDef.tsx
index d5a771204862..68ba6eb242f1 100644
--- a/packages/grid/x-data-grid-premium/src/hooks/features/rowGrouping/createGroupingColDef.tsx
+++ b/packages/grid/x-data-grid-premium/src/hooks/features/rowGrouping/createGroupingColDef.tsx
@@ -67,19 +67,7 @@ const getLeafProperties = (leafColDef: GridColDef): Partial => ({
sortable: leafColDef.sortable,
filterable: leafColDef.filterable,
valueOptions: isSingleSelectColDef(leafColDef) ? leafColDef.valueOptions : undefined,
- filterOperators: leafColDef.filterOperators?.map((operator) => ({
- ...operator,
- getApplyFilterFn: (filterItem, column) => {
- const originalFn = operator.getApplyFilterFn(filterItem, column);
- if (!originalFn) {
- return null;
- }
-
- return (params) => {
- return originalFn(params);
- };
- },
- })),
+ filterOperators: leafColDef.filterOperators,
sortComparator: (v1, v2, cellParams1, cellParams2) => {
// We only want to sort the leaves
if (cellParams1.rowNode.type === 'leaf' && cellParams2.rowNode.type === 'leaf') {
@@ -108,19 +96,7 @@ const getGroupingCriteriaProperties = (groupedByColDef: GridColDef, applyHeaderN
return groupingFieldIndexComparator(v1, v2, cellParams1, cellParams2);
},
- filterOperators: groupedByColDef.filterOperators?.map((operator) => ({
- ...operator,
- getApplyFilterFn: (filterItem, column) => {
- const originalFn = operator.getApplyFilterFn(filterItem, column);
- if (!originalFn) {
- return null;
- }
-
- return (params) => {
- return originalFn(params);
- };
- },
- })),
+ filterOperators: groupedByColDef.filterOperators,
};
if (applyHeaderName) {
diff --git a/packages/grid/x-data-grid-premium/src/hooks/features/rowGrouping/gridRowGroupingUtils.ts b/packages/grid/x-data-grid-premium/src/hooks/features/rowGrouping/gridRowGroupingUtils.ts
index 74e08434b757..1979146222f9 100644
--- a/packages/grid/x-data-grid-premium/src/hooks/features/rowGrouping/gridRowGroupingUtils.ts
+++ b/packages/grid/x-data-grid-premium/src/hooks/features/rowGrouping/gridRowGroupingUtils.ts
@@ -13,6 +13,7 @@ import {
import {
passFilterLogic,
GridAggregatedFilterItemApplier,
+ GridAggregatedFilterItemApplierResult,
GridColumnRawLookup,
GridApiCommunity,
} from '@mui/x-data-grid-pro/internals';
@@ -82,7 +83,7 @@ const shouldApplyFilterItemOnGroup = (columnField: string, node: GridGroupNode)
export const filterRowTreeFromGroupingColumns = (
params: FilterRowTreeFromTreeDataParams,
): Omit => {
- const { rowTree, isRowMatchingFilters, filterModel } = params;
+ const { apiRef, rowTree, isRowMatchingFilters, filterModel } = params;
const filteredRowsLookup: Record = {};
const filteredDescendantCountLookup: Record = {};
const filterCache = {};
@@ -90,21 +91,23 @@ export const filterRowTreeFromGroupingColumns = (
const filterTreeNode = (
node: GridTreeNode,
areAncestorsExpanded: boolean,
- ancestorsResults: ReturnType[],
+ ancestorsResults: GridAggregatedFilterItemApplierResult[],
): number => {
- let isPassingFiltering = false;
- let filterResults: ReturnType = {
+ const filterResults: GridAggregatedFilterItemApplierResult = {
passingFilterItems: null,
passingQuickFilterValues: null,
};
+ let isPassingFiltering = false;
+
if (isRowMatchingFilters && node.type !== 'footer') {
const shouldApplyItem =
node.type === 'group' && node.isAutoGenerated
? (columnField: string) => shouldApplyFilterItemOnGroup(columnField, node)
: undefined;
- filterResults = isRowMatchingFilters(node.id, shouldApplyItem);
+ const row = apiRef.current.getRow(node.id);
+ isRowMatchingFilters(row, shouldApplyItem, filterResults);
} else {
isPassingFiltering = true;
}
@@ -115,7 +118,6 @@ export const filterRowTreeFromGroupingColumns = (
const childNode = rowTree[childId];
const childSubTreeSize = filterTreeNode(
childNode,
-
areAncestorsExpanded && !!node.childrenExpanded,
[...ancestorsResults, filterResults],
);
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 e8c152c297a3..2a03b49efffe 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
@@ -8,6 +8,7 @@ import {
waitFor,
} from '@mui/monorepo/test/utils';
import {
+ microtasks,
getColumnHeaderCell,
getColumnHeadersTextContent,
getColumnValues,
@@ -1802,7 +1803,7 @@ describe(' - Row Grouping', () => {
clock.withFakeTimers();
describe('prop: rowGroupingColumnMode = "single"', () => {
- it('should use the top level grouping criteria for sorting if mainGroupingCriteria and leafField are not defined', () => {
+ it('should use the top level grouping criteria for sorting if mainGroupingCriteria and leafField are not defined', async () => {
render(
- Row Grouping', () => {
defaultGroupingExpansionDepth={-1}
/>,
);
+ await microtasks();
expect(getColumnValues(0)).to.deep.equal([
'Cat B (2)',
diff --git a/packages/grid/x-data-grid-pro/package.json b/packages/grid/x-data-grid-pro/package.json
index ae316738ed20..39dba15618b7 100644
--- a/packages/grid/x-data-grid-pro/package.json
+++ b/packages/grid/x-data-grid-pro/package.json
@@ -1,6 +1,6 @@
{
"name": "@mui/x-data-grid-pro",
- "version": "6.8.0",
+ "version": "6.9.0",
"description": "The Pro plan edition of the data grid component (MUI X).",
"author": "MUI Team",
"main": "src/index.ts",
@@ -43,9 +43,9 @@
},
"dependencies": {
"@babel/runtime": "^7.22.5",
- "@mui/utils": "^5.13.1",
- "@mui/x-data-grid": "6.8.0",
- "@mui/x-license-pro": "6.6.0",
+ "@mui/utils": "^5.13.6",
+ "@mui/x-data-grid": "6.9.0",
+ "@mui/x-license-pro": "6.9.0",
"@types/format-util": "^1.0.2",
"clsx": "^1.2.1",
"prop-types": "^15.8.1",
diff --git a/packages/grid/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx b/packages/grid/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx
index 36ff4a78c824..e9077e1996b1 100644
--- a/packages/grid/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx
+++ b/packages/grid/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx
@@ -128,7 +128,7 @@ export const useDataGridProComponent = (
useGridRowPinning(apiRef, props);
useGridColumns(apiRef, props);
useGridRows(apiRef, props);
- useGridParamsApi(apiRef);
+ useGridParamsApi(apiRef, props);
useGridDetailPanel(apiRef, props);
useGridColumnSpanning(apiRef);
useGridColumnGrouping(apiRef, props);
diff --git a/packages/grid/x-data-grid-pro/src/components/headerFiltering/GridHeaderFilterCell.tsx b/packages/grid/x-data-grid-pro/src/components/headerFiltering/GridHeaderFilterCell.tsx
index 9ca96d882359..517ea8eb2e41 100644
--- a/packages/grid/x-data-grid-pro/src/components/headerFiltering/GridHeaderFilterCell.tsx
+++ b/packages/grid/x-data-grid-pro/src/components/headerFiltering/GridHeaderFilterCell.tsx
@@ -297,6 +297,7 @@ GridHeaderFilterCell.propTypes = {
filterOperators: PropTypes.arrayOf(
PropTypes.shape({
getApplyFilterFn: PropTypes.func.isRequired,
+ getApplyFilterFnV7: PropTypes.func,
getValueAsString: PropTypes.func,
headerLabel: PropTypes.string,
InputComponent: PropTypes.elementType,
diff --git a/packages/grid/x-data-grid-pro/src/components/headerFiltering/GridHeaderFilterMenu.tsx b/packages/grid/x-data-grid-pro/src/components/headerFiltering/GridHeaderFilterMenu.tsx
index 3595948f08c7..2766a0b2cae0 100644
--- a/packages/grid/x-data-grid-pro/src/components/headerFiltering/GridHeaderFilterMenu.tsx
+++ b/packages/grid/x-data-grid-pro/src/components/headerFiltering/GridHeaderFilterMenu.tsx
@@ -108,6 +108,7 @@ GridHeaderFilterMenu.propTypes = {
operators: PropTypes.arrayOf(
PropTypes.shape({
getApplyFilterFn: PropTypes.func.isRequired,
+ getApplyFilterFnV7: PropTypes.func,
getValueAsString: PropTypes.func,
headerLabel: PropTypes.string,
InputComponent: PropTypes.elementType,
diff --git a/packages/grid/x-data-grid-pro/src/components/headerFiltering/GridHeaderFilterMenuContainer.tsx b/packages/grid/x-data-grid-pro/src/components/headerFiltering/GridHeaderFilterMenuContainer.tsx
index 1f0545ab0f11..4dc67450637b 100644
--- a/packages/grid/x-data-grid-pro/src/components/headerFiltering/GridHeaderFilterMenuContainer.tsx
+++ b/packages/grid/x-data-grid-pro/src/components/headerFiltering/GridHeaderFilterMenuContainer.tsx
@@ -101,6 +101,7 @@ GridHeaderFilterMenuContainer.propTypes = {
operators: PropTypes.arrayOf(
PropTypes.shape({
getApplyFilterFn: PropTypes.func.isRequired,
+ getApplyFilterFnV7: PropTypes.func,
getValueAsString: PropTypes.func,
headerLabel: PropTypes.string,
InputComponent: PropTypes.elementType,
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 e71a812d9d97..47fd3d037b3c 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
@@ -92,8 +92,13 @@ export const useGridColumnPinning = (
return;
}
+ const rowContainer = apiRef.current.virtualScrollerRef!.current!;
+ if (!rowContainer) {
+ return;
+ }
+
const index = event.currentTarget.dataset.rowindex;
- const rowElements = apiRef.current.virtualScrollerRef!.current!.querySelectorAll(
+ const rowElements = rowContainer.querySelectorAll(
`.${gridClasses.row}[data-rowindex="${index}"]`,
);
rowElements.forEach((row) => {
diff --git a/packages/grid/x-data-grid-pro/src/hooks/features/treeData/gridTreeDataUtils.ts b/packages/grid/x-data-grid-pro/src/hooks/features/treeData/gridTreeDataUtils.ts
index cc3a716f98e2..291adc3f39d7 100644
--- a/packages/grid/x-data-grid-pro/src/hooks/features/treeData/gridTreeDataUtils.ts
+++ b/packages/grid/x-data-grid-pro/src/hooks/features/treeData/gridTreeDataUtils.ts
@@ -7,6 +7,7 @@ import {
} from '@mui/x-data-grid';
import {
GridAggregatedFilterItemApplier,
+ GridAggregatedFilterItemApplierResult,
GridApiCommunity,
passFilterLogic,
} from '@mui/x-data-grid/internals';
@@ -29,11 +30,16 @@ export const TREE_DATA_STRATEGY = 'tree-data';
export const filterRowTreeFromTreeData = (
params: FilterRowTreeFromTreeDataParams,
): Omit => {
- const { rowTree, disableChildrenFiltering, isRowMatchingFilters } = params;
+ const { apiRef, rowTree, disableChildrenFiltering, isRowMatchingFilters } = params;
const filteredRowsLookup: Record = {};
const filteredDescendantCountLookup: Record = {};
const filterCache = {};
+ const filterResults: GridAggregatedFilterItemApplierResult = {
+ passingFilterItems: null,
+ passingQuickFilterValues: null,
+ };
+
const filterTreeNode = (
node: GridTreeNode,
isParentMatchingFilters: boolean,
@@ -47,10 +53,11 @@ export const filterRowTreeFromTreeData = (
} else if (!isRowMatchingFilters || node.type === 'footer') {
isMatchingFilters = true;
} else {
- const { passingFilterItems, passingQuickFilterValues } = isRowMatchingFilters(node.id);
+ const row = apiRef.current.getRow(node.id);
+ isRowMatchingFilters(row, undefined, filterResults);
isMatchingFilters = passFilterLogic(
- [passingFilterItems],
- [passingQuickFilterValues],
+ [filterResults.passingFilterItems],
+ [filterResults.passingQuickFilterValues],
params.filterModel,
params.apiRef,
filterCache,
diff --git a/packages/grid/x-data-grid-pro/src/tests/rowPinning.DataGridPro.test.tsx b/packages/grid/x-data-grid-pro/src/tests/rowPinning.DataGridPro.test.tsx
index 37a28c963c73..bb80ce265f76 100644
--- a/packages/grid/x-data-grid-pro/src/tests/rowPinning.DataGridPro.test.tsx
+++ b/packages/grid/x-data-grid-pro/src/tests/rowPinning.DataGridPro.test.tsx
@@ -765,7 +765,11 @@ describe(' - Row pinning', () => {
expect(getRowById(1)!).to.have.class(className);
});
- it('should support cell editing', async () => {
+ it('should support cell editing', async function test() {
+ if (isJSDOM) {
+ // flaky in JSDOM
+ this.skip();
+ }
const processRowUpdate = spy((row) => ({ ...row, currencyPair: 'USD-GBP' }));
const columns: GridColDef[] = [{ field: 'id' }, { field: 'name', editable: true }];
render(
@@ -800,7 +804,11 @@ describe(' - Row pinning', () => {
expect(processRowUpdate.lastCall.args[0]).to.deep.equal({ id: 3, name: 'Marcus' });
});
- it('should support row editing', async () => {
+ it('should support row editing', async function test() {
+ if (isJSDOM) {
+ // flaky in JSDOM
+ this.skip();
+ }
const processRowUpdate = spy((row) => ({ ...row, currencyPair: 'USD-GBP' }));
const columns: GridColDef[] = [{ field: 'id' }, { field: 'name', editable: true }];
render(
diff --git a/packages/grid/x-data-grid-pro/src/tests/treeData.DataGridPro.test.tsx b/packages/grid/x-data-grid-pro/src/tests/treeData.DataGridPro.test.tsx
index 0dc533164747..f83c86ef62d7 100644
--- a/packages/grid/x-data-grid-pro/src/tests/treeData.DataGridPro.test.tsx
+++ b/packages/grid/x-data-grid-pro/src/tests/treeData.DataGridPro.test.tsx
@@ -702,4 +702,18 @@ describe(' - Tree Data', () => {
]);
});
});
+
+ describe('regressions', () => {
+ // See https://github.com/mui/mui-x/issues/9402
+ it('should not fail with checkboxSelection', () => {
+ const initialRows = rowsWithoutGap;
+ const { setProps } = render();
+
+ const newRows = [...initialRows];
+ newRows.splice(7, 1);
+ setProps({
+ rows: newRows,
+ });
+ });
+ });
});
diff --git a/packages/grid/x-data-grid/package.json b/packages/grid/x-data-grid/package.json
index 68670e5cfcf1..a2babe06a05d 100644
--- a/packages/grid/x-data-grid/package.json
+++ b/packages/grid/x-data-grid/package.json
@@ -1,6 +1,6 @@
{
"name": "@mui/x-data-grid",
- "version": "6.8.0",
+ "version": "6.9.0",
"description": "The community edition of the data grid component (MUI X).",
"author": "MUI Team",
"main": "src/index.ts",
@@ -47,7 +47,7 @@
},
"dependencies": {
"@babel/runtime": "^7.22.5",
- "@mui/utils": "^5.13.1",
+ "@mui/utils": "^5.13.6",
"clsx": "^1.2.1",
"prop-types": "^15.8.1",
"reselect": "^4.1.8"
diff --git a/packages/grid/x-data-grid/src/DataGrid/useDataGridComponent.tsx b/packages/grid/x-data-grid/src/DataGrid/useDataGridComponent.tsx
index a43203f3a9a6..2e0db8b05d20 100644
--- a/packages/grid/x-data-grid/src/DataGrid/useDataGridComponent.tsx
+++ b/packages/grid/x-data-grid/src/DataGrid/useDataGridComponent.tsx
@@ -79,7 +79,7 @@ export const useDataGridComponent = (
useGridRowSelection(privateApiRef, props);
useGridColumns(privateApiRef, props);
useGridRows(privateApiRef, props);
- useGridParamsApi(privateApiRef);
+ useGridParamsApi(privateApiRef, props);
useGridColumnSpanning(privateApiRef);
useGridColumnGrouping(privateApiRef, props);
useGridEditing(privateApiRef, props);
diff --git a/packages/grid/x-data-grid/src/colDef/gridActionsColDef.tsx b/packages/grid/x-data-grid/src/colDef/gridActionsColDef.tsx
index 5c27a57a0458..ad197534905b 100644
--- a/packages/grid/x-data-grid/src/colDef/gridActionsColDef.tsx
+++ b/packages/grid/x-data-grid/src/colDef/gridActionsColDef.tsx
@@ -18,4 +18,5 @@ export const GRID_ACTIONS_COL_DEF: GridColTypeDef = {
disableExport: true,
renderCell: renderActionsCell,
getApplyQuickFilterFn: undefined,
+ getApplyQuickFilterFnV7: undefined,
};
diff --git a/packages/grid/x-data-grid/src/colDef/gridBooleanColDef.tsx b/packages/grid/x-data-grid/src/colDef/gridBooleanColDef.tsx
index 7c2abdc9416e..c208d7822275 100644
--- a/packages/grid/x-data-grid/src/colDef/gridBooleanColDef.tsx
+++ b/packages/grid/x-data-grid/src/colDef/gridBooleanColDef.tsx
@@ -42,6 +42,7 @@ export const GRID_BOOLEAN_COL_DEF: GridColTypeDef = {
valueFormatter: gridBooleanFormatter,
filterOperators: getGridBooleanOperators(),
getApplyQuickFilterFn: undefined,
+ getApplyQuickFilterFnV7: undefined,
// @ts-ignore
aggregable: false,
// @ts-ignore
diff --git a/packages/grid/x-data-grid/src/colDef/gridBooleanOperators.ts b/packages/grid/x-data-grid/src/colDef/gridBooleanOperators.ts
index e702a0c0ef2f..9c93a623274d 100644
--- a/packages/grid/x-data-grid/src/colDef/gridBooleanOperators.ts
+++ b/packages/grid/x-data-grid/src/colDef/gridBooleanOperators.ts
@@ -1,20 +1,22 @@
import { GridFilterInputBoolean } from '../components/panel/filterPanel/GridFilterInputBoolean';
import { GridFilterItem } from '../models/gridFilterItem';
import { GridFilterOperator } from '../models/gridFilterOperator';
+import { convertLegacyOperators } from './utils';
-export const getGridBooleanOperators = (): GridFilterOperator[] => [
- {
- value: 'is',
- getApplyFilterFn: (filterItem: GridFilterItem) => {
- if (!filterItem.value) {
- return null;
- }
+export const getGridBooleanOperators = (): GridFilterOperator[] =>
+ convertLegacyOperators([
+ {
+ value: 'is',
+ getApplyFilterFnV7: (filterItem: GridFilterItem) => {
+ if (!filterItem.value) {
+ return null;
+ }
- const valueAsBoolean = filterItem.value === 'true';
- return ({ value }): boolean => {
- return Boolean(value) === valueAsBoolean;
- };
+ const valueAsBoolean = filterItem.value === 'true';
+ return (value): boolean => {
+ return Boolean(value) === valueAsBoolean;
+ };
+ },
+ InputComponent: GridFilterInputBoolean,
},
- InputComponent: GridFilterInputBoolean,
- },
-];
+ ]);
diff --git a/packages/grid/x-data-grid/src/colDef/gridCheckboxSelectionColDef.tsx b/packages/grid/x-data-grid/src/colDef/gridCheckboxSelectionColDef.tsx
index f036ca4082ad..662782884b53 100644
--- a/packages/grid/x-data-grid/src/colDef/gridCheckboxSelectionColDef.tsx
+++ b/packages/grid/x-data-grid/src/colDef/gridCheckboxSelectionColDef.tsx
@@ -21,6 +21,7 @@ export const GRID_CHECKBOX_SELECTION_COL_DEF: GridColDef = {
disableReorder: true,
disableExport: true,
getApplyQuickFilterFn: undefined,
+ getApplyQuickFilterFnV7: undefined,
valueGetter: (params) => {
const selectionLookup = selectedIdsLookupSelector(params.api.state, params.api.instanceId);
return selectionLookup[params.id] !== undefined;
diff --git a/packages/grid/x-data-grid/src/colDef/gridDateColDef.ts b/packages/grid/x-data-grid/src/colDef/gridDateColDef.ts
index 891f09620bf6..cb09fa6d40cd 100644
--- a/packages/grid/x-data-grid/src/colDef/gridDateColDef.ts
+++ b/packages/grid/x-data-grid/src/colDef/gridDateColDef.ts
@@ -51,6 +51,7 @@ export const GRID_DATE_COL_DEF: GridColTypeDef = {
filterOperators: getGridDateOperators(),
renderEditCell: renderEditDateCell,
getApplyQuickFilterFn: undefined,
+ getApplyQuickFilterFnV7: undefined,
// @ts-ignore
pastedValueParser: (value) => new Date(value),
};
@@ -63,6 +64,7 @@ export const GRID_DATETIME_COL_DEF: GridColTypeDef = {
filterOperators: getGridDateOperators(true),
renderEditCell: renderEditDateCell,
getApplyQuickFilterFn: undefined,
+ getApplyQuickFilterFnV7: undefined,
// @ts-ignore
pastedValueParser: (value) => new Date(value),
};
diff --git a/packages/grid/x-data-grid/src/colDef/gridDateOperators.ts b/packages/grid/x-data-grid/src/colDef/gridDateOperators.ts
index c3473599576e..ddfd18ec5fc9 100644
--- a/packages/grid/x-data-grid/src/colDef/gridDateOperators.ts
+++ b/packages/grid/x-data-grid/src/colDef/gridDateOperators.ts
@@ -1,7 +1,7 @@
import { GridFilterInputDate } from '../components/panel/filterPanel/GridFilterInputDate';
import { GridFilterItem } from '../models/gridFilterItem';
-import { GridFilterOperator } from '../models/gridFilterOperator';
-import { GridCellParams } from '../models/params/gridCellParams';
+import { GridFilterOperator, GetApplyFilterFnV7 } from '../models/gridFilterOperator';
+import { convertLegacyOperators } from './utils';
const dateRegex = /(\d+)-(\d+)-(\d+)/;
const dateTimeRegex = /(\d+)-(\d+)-(\d+)T(\d+):(\d+)/;
@@ -11,7 +11,7 @@ function buildApplyFilterFn(
compareFn: (value1: number, value2: number) => boolean,
showTime?: boolean,
keepHours?: boolean,
-) {
+): ReturnType {
if (!filterItem.value) {
return null;
}
@@ -23,7 +23,7 @@ function buildApplyFilterFn(
const time = new Date(year, month - 1, day, hour || 0, minute || 0).getTime();
- return ({ value }: GridCellParams): boolean => {
+ return (value): boolean => {
if (!value) {
return false;
}
@@ -44,76 +44,77 @@ function buildApplyFilterFn(
};
}
-export const getGridDateOperators = (showTime?: boolean): GridFilterOperator[] => [
- {
- value: 'is',
- getApplyFilterFn: (filterItem) => {
- return buildApplyFilterFn(filterItem, (value1, value2) => value1 === value2, showTime);
+export const getGridDateOperators = (showTime?: boolean): GridFilterOperator[] =>
+ convertLegacyOperators([
+ {
+ value: 'is',
+ getApplyFilterFnV7: (filterItem) => {
+ return buildApplyFilterFn(filterItem, (value1, value2) => value1 === value2, showTime);
+ },
+ InputComponent: GridFilterInputDate,
+ InputComponentProps: { type: showTime ? 'datetime-local' : 'date' },
},
- InputComponent: GridFilterInputDate,
- InputComponentProps: { type: showTime ? 'datetime-local' : 'date' },
- },
- {
- value: 'not',
- getApplyFilterFn: (filterItem) => {
- return buildApplyFilterFn(filterItem, (value1, value2) => value1 !== value2, showTime);
+ {
+ value: 'not',
+ getApplyFilterFnV7: (filterItem) => {
+ return buildApplyFilterFn(filterItem, (value1, value2) => value1 !== value2, showTime);
+ },
+ InputComponent: GridFilterInputDate,
+ InputComponentProps: { type: showTime ? 'datetime-local' : 'date' },
},
- InputComponent: GridFilterInputDate,
- InputComponentProps: { type: showTime ? 'datetime-local' : 'date' },
- },
- {
- value: 'after',
- getApplyFilterFn: (filterItem) => {
- return buildApplyFilterFn(filterItem, (value1, value2) => value1 > value2, showTime);
+ {
+ value: 'after',
+ getApplyFilterFnV7: (filterItem) => {
+ return buildApplyFilterFn(filterItem, (value1, value2) => value1 > value2, showTime);
+ },
+ InputComponent: GridFilterInputDate,
+ InputComponentProps: { type: showTime ? 'datetime-local' : 'date' },
},
- InputComponent: GridFilterInputDate,
- InputComponentProps: { type: showTime ? 'datetime-local' : 'date' },
- },
- {
- value: 'onOrAfter',
- getApplyFilterFn: (filterItem) => {
- return buildApplyFilterFn(filterItem, (value1, value2) => value1 >= value2, showTime);
+ {
+ value: 'onOrAfter',
+ getApplyFilterFnV7: (filterItem) => {
+ return buildApplyFilterFn(filterItem, (value1, value2) => value1 >= value2, showTime);
+ },
+ InputComponent: GridFilterInputDate,
+ InputComponentProps: { type: showTime ? 'datetime-local' : 'date' },
},
- InputComponent: GridFilterInputDate,
- InputComponentProps: { type: showTime ? 'datetime-local' : 'date' },
- },
- {
- value: 'before',
- getApplyFilterFn: (filterItem) => {
- return buildApplyFilterFn(
- filterItem,
- (value1, value2) => value1 < value2,
- showTime,
- !showTime,
- );
+ {
+ value: 'before',
+ getApplyFilterFnV7: (filterItem) => {
+ return buildApplyFilterFn(
+ filterItem,
+ (value1, value2) => value1 < value2,
+ showTime,
+ !showTime,
+ );
+ },
+ InputComponent: GridFilterInputDate,
+ InputComponentProps: { type: showTime ? 'datetime-local' : 'date' },
},
- InputComponent: GridFilterInputDate,
- InputComponentProps: { type: showTime ? 'datetime-local' : 'date' },
- },
- {
- value: 'onOrBefore',
- getApplyFilterFn: (filterItem) => {
- return buildApplyFilterFn(filterItem, (value1, value2) => value1 <= value2, showTime);
+ {
+ value: 'onOrBefore',
+ getApplyFilterFnV7: (filterItem) => {
+ return buildApplyFilterFn(filterItem, (value1, value2) => value1 <= value2, showTime);
+ },
+ InputComponent: GridFilterInputDate,
+ InputComponentProps: { type: showTime ? 'datetime-local' : 'date' },
},
- InputComponent: GridFilterInputDate,
- InputComponentProps: { type: showTime ? 'datetime-local' : 'date' },
- },
- {
- value: 'isEmpty',
- getApplyFilterFn: () => {
- return ({ value }): boolean => {
- return value == null;
- };
+ {
+ value: 'isEmpty',
+ getApplyFilterFnV7: () => {
+ return (value): boolean => {
+ return value == null;
+ };
+ },
+ requiresFilterValue: false,
},
- requiresFilterValue: false,
- },
- {
- value: 'isNotEmpty',
- getApplyFilterFn: () => {
- return ({ value }): boolean => {
- return value != null;
- };
+ {
+ value: 'isNotEmpty',
+ getApplyFilterFnV7: () => {
+ return (value): boolean => {
+ return value != null;
+ };
+ },
+ requiresFilterValue: false,
},
- requiresFilterValue: false,
- },
-];
+ ]);
diff --git a/packages/grid/x-data-grid/src/colDef/gridNumericColDef.ts b/packages/grid/x-data-grid/src/colDef/gridNumericColDef.ts
index cca2a740ff04..46c1fc55bde4 100644
--- a/packages/grid/x-data-grid/src/colDef/gridNumericColDef.ts
+++ b/packages/grid/x-data-grid/src/colDef/gridNumericColDef.ts
@@ -3,6 +3,7 @@ import { isNumber } from '../utils/utils';
import { getGridNumericOperators, getGridNumericQuickFilterFn } from './gridNumericOperators';
import { GRID_STRING_COL_DEF } from './gridStringColDef';
import { GridColTypeDef } from '../models/colDef/gridColDef';
+import { convertQuickFilterV7ToLegacy } from './utils';
export const GRID_NUMERIC_COL_DEF: GridColTypeDef = {
...GRID_STRING_COL_DEF,
@@ -13,5 +14,6 @@ export const GRID_NUMERIC_COL_DEF: GridColTypeDef (value === '' ? null : Number(value)),
valueFormatter: ({ value }) => (isNumber(value) ? value.toLocaleString() : value || ''),
filterOperators: getGridNumericOperators(),
- getApplyQuickFilterFn: getGridNumericQuickFilterFn,
+ getApplyQuickFilterFn: convertQuickFilterV7ToLegacy(getGridNumericQuickFilterFn),
+ getApplyQuickFilterFnV7: getGridNumericQuickFilterFn,
};
diff --git a/packages/grid/x-data-grid/src/colDef/gridNumericOperators.ts b/packages/grid/x-data-grid/src/colDef/gridNumericOperators.ts
index 182b839e6f2c..22147e4ea448 100644
--- a/packages/grid/x-data-grid/src/colDef/gridNumericOperators.ts
+++ b/packages/grid/x-data-grid/src/colDef/gridNumericOperators.ts
@@ -1,7 +1,8 @@
import { GridFilterInputValue } from '../components/panel/filterPanel/GridFilterInputValue';
import { GridFilterInputMultipleValue } from '../components/panel/filterPanel/GridFilterInputMultipleValue';
import { GridFilterOperator } from '../models/gridFilterOperator';
-import { GridCellParams } from '../models';
+import type { GridApplyQuickFilterV7 } from '../models/colDef/gridColDef';
+import { convertLegacyOperators, tagInternalFilter } from './utils';
const parseNumericValue = (value: unknown) => {
if (value == null) {
@@ -11,151 +12,150 @@ const parseNumericValue = (value: unknown) => {
return Number(value);
};
-export const getGridNumericQuickFilterFn = (value: any) => {
- if (value == null || Number.isNaN(value) || value === '') {
- return null;
- }
+export const getGridNumericQuickFilterFn = tagInternalFilter(
+ (value: any): GridApplyQuickFilterV7 | null => {
+ if (value == null || Number.isNaN(value) || value === '') {
+ return null;
+ }
- return ({ value: columnValue }: GridCellParams): boolean => {
- return parseNumericValue(columnValue) === parseNumericValue(value);
- };
-};
+ return (columnValue): boolean => {
+ return parseNumericValue(columnValue) === parseNumericValue(value);
+ };
+ },
+);
+
+export const getGridNumericOperators = (): GridFilterOperator[] =>
+ convertLegacyOperators([
+ {
+ value: '=',
+ getApplyFilterFnV7: (filterItem) => {
+ if (filterItem.value == null || Number.isNaN(filterItem.value)) {
+ return null;
+ }
-export const getGridNumericOperators = (): GridFilterOperator<
- any,
- number | string | null,
- any
->[] => [
- {
- value: '=',
- getApplyFilterFn: (filterItem) => {
- if (filterItem.value == null || Number.isNaN(filterItem.value)) {
- return null;
- }
-
- return ({ value }): boolean => {
- return parseNumericValue(value) === filterItem.value;
- };
+ return (value): boolean => {
+ return parseNumericValue(value) === filterItem.value;
+ };
+ },
+ InputComponent: GridFilterInputValue,
+ InputComponentProps: { type: 'number' },
},
- InputComponent: GridFilterInputValue,
- InputComponentProps: { type: 'number' },
- },
- {
- value: '!=',
- getApplyFilterFn: (filterItem) => {
- if (filterItem.value == null || Number.isNaN(filterItem.value)) {
- return null;
- }
-
- return ({ value }): boolean => {
- return parseNumericValue(value) !== filterItem.value;
- };
+ {
+ value: '!=',
+ getApplyFilterFnV7: (filterItem) => {
+ if (filterItem.value == null || Number.isNaN(filterItem.value)) {
+ return null;
+ }
+
+ return (value): boolean => {
+ return parseNumericValue(value) !== filterItem.value;
+ };
+ },
+ InputComponent: GridFilterInputValue,
+ InputComponentProps: { type: 'number' },
},
- InputComponent: GridFilterInputValue,
- InputComponentProps: { type: 'number' },
- },
- {
- value: '>',
- getApplyFilterFn: (filterItem) => {
- if (filterItem.value == null || Number.isNaN(filterItem.value)) {
- return null;
- }
-
- return ({ value }): boolean => {
- if (value == null) {
- return false;
+ {
+ value: '>',
+ getApplyFilterFnV7: (filterItem) => {
+ if (filterItem.value == null || Number.isNaN(filterItem.value)) {
+ return null;
}
- return parseNumericValue(value)! > filterItem.value;
- };
+ return (value): boolean => {
+ if (value == null) {
+ return false;
+ }
+
+ return parseNumericValue(value)! > filterItem.value;
+ };
+ },
+ InputComponent: GridFilterInputValue,
+ InputComponentProps: { type: 'number' },
},
- InputComponent: GridFilterInputValue,
- InputComponentProps: { type: 'number' },
- },
- {
- value: '>=',
- getApplyFilterFn: (filterItem) => {
- if (filterItem.value == null || Number.isNaN(filterItem.value)) {
- return null;
- }
-
- return ({ value }): boolean => {
- if (value == null) {
- return false;
+ {
+ value: '>=',
+ getApplyFilterFnV7: (filterItem) => {
+ if (filterItem.value == null || Number.isNaN(filterItem.value)) {
+ return null;
}
- return parseNumericValue(value)! >= filterItem.value;
- };
+ return (value): boolean => {
+ if (value == null) {
+ return false;
+ }
+
+ return parseNumericValue(value)! >= filterItem.value;
+ };
+ },
+ InputComponent: GridFilterInputValue,
+ InputComponentProps: { type: 'number' },
},
- InputComponent: GridFilterInputValue,
- InputComponentProps: { type: 'number' },
- },
- {
- value: '<',
- getApplyFilterFn: (filterItem) => {
- if (filterItem.value == null || Number.isNaN(filterItem.value)) {
- return null;
- }
-
- return ({ value }): boolean => {
- if (value == null) {
- return false;
+ {
+ value: '<',
+ getApplyFilterFnV7: (filterItem) => {
+ if (filterItem.value == null || Number.isNaN(filterItem.value)) {
+ return null;
}
- return parseNumericValue(value)! < filterItem.value;
- };
+ return (value): boolean => {
+ if (value == null) {
+ return false;
+ }
+
+ return parseNumericValue(value)! < filterItem.value;
+ };
+ },
+ InputComponent: GridFilterInputValue,
+ InputComponentProps: { type: 'number' },
},
- InputComponent: GridFilterInputValue,
- InputComponentProps: { type: 'number' },
- },
- {
- value: '<=',
- getApplyFilterFn: (filterItem) => {
- if (filterItem.value == null || Number.isNaN(filterItem.value)) {
- return null;
- }
-
- return ({ value }): boolean => {
- if (value == null) {
- return false;
+ {
+ value: '<=',
+ getApplyFilterFnV7: (filterItem) => {
+ if (filterItem.value == null || Number.isNaN(filterItem.value)) {
+ return null;
}
- return parseNumericValue(value)! <= filterItem.value;
- };
+ return (value): boolean => {
+ if (value == null) {
+ return false;
+ }
+
+ return parseNumericValue(value)! <= filterItem.value;
+ };
+ },
+ InputComponent: GridFilterInputValue,
+ InputComponentProps: { type: 'number' },
},
- InputComponent: GridFilterInputValue,
- InputComponentProps: { type: 'number' },
- },
- {
- value: 'isEmpty',
- getApplyFilterFn: () => {
- return ({ value }): boolean => {
- return value == null;
- };
+ {
+ value: 'isEmpty',
+ getApplyFilterFnV7: () => {
+ return (value): boolean => {
+ return value == null;
+ };
+ },
+ requiresFilterValue: false,
},
- requiresFilterValue: false,
- },
- {
- value: 'isNotEmpty',
- getApplyFilterFn: () => {
- return ({ value }): boolean => {
- return value != null;
- };
+ {
+ value: 'isNotEmpty',
+ getApplyFilterFnV7: () => {
+ return (value): boolean => {
+ return value != null;
+ };
+ },
+ requiresFilterValue: false,
},
- requiresFilterValue: false,
- },
- {
- value: 'isAnyOf',
- getApplyFilterFn: (filterItem) => {
- if (!Array.isArray(filterItem.value) || filterItem.value.length === 0) {
- return null;
- }
-
- return ({ value }): boolean => {
- return value != null && filterItem.value.includes(Number(value));
- };
+ {
+ value: 'isAnyOf',
+ getApplyFilterFnV7: (filterItem) => {
+ if (!Array.isArray(filterItem.value) || filterItem.value.length === 0) {
+ return null;
+ }
+
+ return (value): boolean => {
+ return value != null && filterItem.value.includes(Number(value));
+ };
+ },
+ InputComponent: GridFilterInputMultipleValue,
+ InputComponentProps: { type: 'number' },
},
- InputComponent: GridFilterInputMultipleValue,
- InputComponentProps: { type: 'number' },
- },
-];
+ ]);
diff --git a/packages/grid/x-data-grid/src/colDef/gridSingleSelectOperators.ts b/packages/grid/x-data-grid/src/colDef/gridSingleSelectOperators.ts
index 48b6cda0a371..59dcd552b43f 100644
--- a/packages/grid/x-data-grid/src/colDef/gridSingleSelectOperators.ts
+++ b/packages/grid/x-data-grid/src/colDef/gridSingleSelectOperators.ts
@@ -2,6 +2,7 @@ import { GridFilterInputSingleSelect } from '../components/panel/filterPanel/Gri
import { GridFilterOperator } from '../models/gridFilterOperator';
import { GridFilterInputMultipleSingleSelect } from '../components/panel/filterPanel/GridFilterInputMultipleSingleSelect';
import { isObject } from '../utils/utils';
+import { convertLegacyOperators } from './utils';
const parseObjectValue = (value: unknown) => {
if (value == null || !isObject<{ value: unknown }>(value)) {
@@ -10,36 +11,37 @@ const parseObjectValue = (value: unknown) => {
return value.value;
};
-export const getGridSingleSelectOperators = (): GridFilterOperator[] => [
- {
- value: 'is',
- getApplyFilterFn: (filterItem) => {
- if (filterItem.value == null || filterItem.value === '') {
- return null;
- }
- return ({ value }): boolean => parseObjectValue(value) === parseObjectValue(filterItem.value);
+export const getGridSingleSelectOperators = (): GridFilterOperator[] =>
+ convertLegacyOperators([
+ {
+ value: 'is',
+ getApplyFilterFnV7: (filterItem) => {
+ if (filterItem.value == null || filterItem.value === '') {
+ return null;
+ }
+ return (value): boolean => parseObjectValue(value) === parseObjectValue(filterItem.value);
+ },
+ InputComponent: GridFilterInputSingleSelect,
},
- InputComponent: GridFilterInputSingleSelect,
- },
- {
- value: 'not',
- getApplyFilterFn: (filterItem) => {
- if (filterItem.value == null || filterItem.value === '') {
- return null;
- }
- return ({ value }): boolean => parseObjectValue(value) !== parseObjectValue(filterItem.value);
+ {
+ value: 'not',
+ getApplyFilterFnV7: (filterItem) => {
+ if (filterItem.value == null || filterItem.value === '') {
+ return null;
+ }
+ return (value): boolean => parseObjectValue(value) !== parseObjectValue(filterItem.value);
+ },
+ InputComponent: GridFilterInputSingleSelect,
},
- InputComponent: GridFilterInputSingleSelect,
- },
- {
- value: 'isAnyOf',
- getApplyFilterFn: (filterItem) => {
- if (!Array.isArray(filterItem.value) || filterItem.value.length === 0) {
- return null;
- }
- const filterItemValues = filterItem.value.map(parseObjectValue);
- return ({ value }): boolean => filterItemValues.includes(parseObjectValue(value));
+ {
+ value: 'isAnyOf',
+ getApplyFilterFnV7: (filterItem) => {
+ if (!Array.isArray(filterItem.value) || filterItem.value.length === 0) {
+ return null;
+ }
+ const filterItemValues = filterItem.value.map(parseObjectValue);
+ return (value): boolean => filterItemValues.includes(parseObjectValue(value));
+ },
+ InputComponent: GridFilterInputMultipleSingleSelect,
},
- InputComponent: GridFilterInputMultipleSingleSelect,
- },
-];
+ ]);
diff --git a/packages/grid/x-data-grid/src/colDef/gridStringColDef.ts b/packages/grid/x-data-grid/src/colDef/gridStringColDef.ts
index e9f764da9544..5c1987c056c1 100644
--- a/packages/grid/x-data-grid/src/colDef/gridStringColDef.ts
+++ b/packages/grid/x-data-grid/src/colDef/gridStringColDef.ts
@@ -2,6 +2,7 @@ import { renderEditInputCell } from '../components/cell/GridEditInputCell';
import { gridStringOrNumberComparator } from '../hooks/features/sorting/gridSortingUtils';
import { GridColTypeDef } from '../models/colDef/gridColDef';
import { getGridStringOperators, getGridStringQuickFilterFn } from './gridStringOperators';
+import { convertQuickFilterV7ToLegacy } from './utils';
/**
* TODO: Move pro and premium properties outside of this Community file
@@ -24,5 +25,6 @@ export const GRID_STRING_COL_DEF: GridColTypeDef = {
align: 'left',
filterOperators: getGridStringOperators(),
renderEditCell: renderEditInputCell,
- getApplyQuickFilterFn: getGridStringQuickFilterFn,
+ getApplyQuickFilterFn: convertQuickFilterV7ToLegacy(getGridStringQuickFilterFn),
+ getApplyQuickFilterFnV7: getGridStringQuickFilterFn,
};
diff --git a/packages/grid/x-data-grid/src/colDef/gridStringOperators.ts b/packages/grid/x-data-grid/src/colDef/gridStringOperators.ts
index 20ba2beed424..9a00deb28c33 100644
--- a/packages/grid/x-data-grid/src/colDef/gridStringOperators.ts
+++ b/packages/grid/x-data-grid/src/colDef/gridStringOperators.ts
@@ -1,119 +1,124 @@
import { GridFilterInputValue } from '../components/panel/filterPanel/GridFilterInputValue';
import { escapeRegExp } from '../utils/utils';
+import type { GridApplyQuickFilterV7 } from '../models/colDef/gridColDef';
import { GridFilterItem } from '../models/gridFilterItem';
import { GridFilterOperator } from '../models/gridFilterOperator';
import { GridFilterInputMultipleValue } from '../components/panel/filterPanel/GridFilterInputMultipleValue';
-import { GridCellParams } from '../models';
+import { convertLegacyOperators, tagInternalFilter } from './utils';
-export const getGridStringQuickFilterFn = (value: any) => {
- if (!value) {
- return null;
- }
- const filterRegex = new RegExp(escapeRegExp(value), 'i');
- return ({ formattedValue: columnValue }: GridCellParams): boolean => {
- return columnValue != null ? filterRegex.test(columnValue.toString()) : false;
- };
-};
+export const getGridStringQuickFilterFn = tagInternalFilter(
+ (value: any): GridApplyQuickFilterV7 | null => {
+ if (!value) {
+ return null;
+ }
+ const filterRegex = new RegExp(escapeRegExp(value), 'i');
+ return (_, row, column, apiRef): boolean => {
+ const columnValue = apiRef.current.getRowFormattedValue(row, column);
+ return columnValue != null ? filterRegex.test(columnValue.toString()) : false;
+ };
+ },
+);
export const getGridStringOperators = (
disableTrim: boolean = false,
-): GridFilterOperator[] => [
- {
- value: 'contains',
- getApplyFilterFn: (filterItem: GridFilterItem) => {
- if (!filterItem.value) {
- return null;
- }
- const filterItemValue = disableTrim ? filterItem.value : filterItem.value.trim();
+): GridFilterOperator[] =>
+ convertLegacyOperators([
+ {
+ value: 'contains',
+ getApplyFilterFnV7: (filterItem: GridFilterItem) => {
+ if (!filterItem.value) {
+ return null;
+ }
+ const filterItemValue = disableTrim ? filterItem.value : filterItem.value.trim();
- const filterRegex = new RegExp(escapeRegExp(filterItemValue), 'i');
- return ({ value }): boolean => {
- return value != null ? filterRegex.test(value.toString()) : false;
- };
+ const filterRegex = new RegExp(escapeRegExp(filterItemValue), 'i');
+ return (value): boolean => {
+ return value != null ? filterRegex.test(String(value)) : false;
+ };
+ },
+ InputComponent: GridFilterInputValue,
},
- InputComponent: GridFilterInputValue,
- },
- {
- value: 'equals',
- getApplyFilterFn: (filterItem: GridFilterItem) => {
- if (!filterItem.value) {
- return null;
- }
- const filterItemValue = disableTrim ? filterItem.value : filterItem.value.trim();
+ {
+ value: 'equals',
+ getApplyFilterFnV7: (filterItem: GridFilterItem) => {
+ if (!filterItem.value) {
+ return null;
+ }
+ const filterItemValue = disableTrim ? filterItem.value : filterItem.value.trim();
- const collator = new Intl.Collator(undefined, { sensitivity: 'base', usage: 'search' });
- return ({ value }): boolean => {
- return value != null ? collator.compare(filterItemValue, value.toString()) === 0 : false;
- };
+ const collator = new Intl.Collator(undefined, { sensitivity: 'base', usage: 'search' });
+ return (value): boolean => {
+ return value != null ? collator.compare(filterItemValue, value.toString()) === 0 : false;
+ };
+ },
+ InputComponent: GridFilterInputValue,
},
- InputComponent: GridFilterInputValue,
- },
- {
- value: 'startsWith',
- getApplyFilterFn: (filterItem: GridFilterItem) => {
- if (!filterItem.value) {
- return null;
- }
- const filterItemValue = disableTrim ? filterItem.value : filterItem.value.trim();
+ {
+ value: 'startsWith',
+ getApplyFilterFnV7: (filterItem: GridFilterItem) => {
+ if (!filterItem.value) {
+ return null;
+ }
+ const filterItemValue = disableTrim ? filterItem.value : filterItem.value.trim();
- const filterRegex = new RegExp(`^${escapeRegExp(filterItemValue)}.*$`, 'i');
- return ({ value }): boolean => {
- return value != null ? filterRegex.test(value.toString()) : false;
- };
+ const filterRegex = new RegExp(`^${escapeRegExp(filterItemValue)}.*$`, 'i');
+ return (value): boolean => {
+ return value != null ? filterRegex.test(value.toString()) : false;
+ };
+ },
+ InputComponent: GridFilterInputValue,
},
- InputComponent: GridFilterInputValue,
- },
- {
- value: 'endsWith',
- getApplyFilterFn: (filterItem: GridFilterItem) => {
- if (!filterItem.value) {
- return null;
- }
- const filterItemValue = disableTrim ? filterItem.value : filterItem.value.trim();
+ {
+ value: 'endsWith',
+ getApplyFilterFnV7: (filterItem: GridFilterItem) => {
+ if (!filterItem.value) {
+ return null;
+ }
+ const filterItemValue = disableTrim ? filterItem.value : filterItem.value.trim();
- const filterRegex = new RegExp(`.*${escapeRegExp(filterItemValue)}$`, 'i');
- return ({ value }): boolean => {
- return value != null ? filterRegex.test(value.toString()) : false;
- };
+ const filterRegex = new RegExp(`.*${escapeRegExp(filterItemValue)}$`, 'i');
+ return (value): boolean => {
+ return value != null ? filterRegex.test(value.toString()) : false;
+ };
+ },
+ InputComponent: GridFilterInputValue,
},
- InputComponent: GridFilterInputValue,
- },
- {
- value: 'isEmpty',
- getApplyFilterFn: () => {
- return ({ value }): boolean => {
- return value === '' || value == null;
- };
+ {
+ value: 'isEmpty',
+ getApplyFilterFnV7: () => {
+ return (value): boolean => {
+ return value === '' || value == null;
+ };
+ },
+ requiresFilterValue: false,
},
- requiresFilterValue: false,
- },
- {
- value: 'isNotEmpty',
- getApplyFilterFn: () => {
- return ({ value }): boolean => {
- return value !== '' && value != null;
- };
+ {
+ value: 'isNotEmpty',
+ getApplyFilterFnV7: () => {
+ return (value): boolean => {
+ return value !== '' && value != null;
+ };
+ },
+ requiresFilterValue: false,
},
- requiresFilterValue: false,
- },
- {
- value: 'isAnyOf',
- getApplyFilterFn: (filterItem: GridFilterItem) => {
- if (!Array.isArray(filterItem.value) || filterItem.value.length === 0) {
- return null;
- }
- const filterItemValue = disableTrim
- ? filterItem.value
- : filterItem.value.map((val) => val.trim());
- const collator = new Intl.Collator(undefined, { sensitivity: 'base', usage: 'search' });
+ {
+ value: 'isAnyOf',
+ getApplyFilterFnV7: (filterItem: GridFilterItem) => {
+ if (!Array.isArray(filterItem.value) || filterItem.value.length === 0) {
+ return null;
+ }
+ const filterItemValue = disableTrim
+ ? filterItem.value
+ : filterItem.value.map((val) => val.trim());
+ const collator = new Intl.Collator(undefined, { sensitivity: 'base', usage: 'search' });
- return ({ value }): boolean =>
- value != null
- ? filterItemValue.some((filterValue: GridFilterItem['value']) => {
- return collator.compare(filterValue, value.toString() || '') === 0;
- })
- : false;
+ return (value): boolean =>
+ value != null
+ ? filterItemValue.some((filterValue: GridFilterItem['value']) => {
+ return collator.compare(filterValue, value.toString() || '') === 0;
+ })
+ : false;
+ },
+ InputComponent: GridFilterInputMultipleValue,
},
- InputComponent: GridFilterInputMultipleValue,
- },
-];
+ ]);
diff --git a/packages/grid/x-data-grid/src/colDef/utils.ts b/packages/grid/x-data-grid/src/colDef/utils.ts
new file mode 100644
index 000000000000..cecbf7d46c32
--- /dev/null
+++ b/packages/grid/x-data-grid/src/colDef/utils.ts
@@ -0,0 +1,64 @@
+import * as React from 'react';
+import { GridApiCommunity } from '../models/api/gridApiCommunity';
+import { GetApplyFilterFnV7, GetApplyFilterFnLegacy, GridFilterOperator } from '../models';
+import { GetApplyQuickFilterFnV7, GetApplyQuickFilterFnLegacy } from '../models/colDef/gridColDef';
+
+/**
+ * A global API ref, for v7-to-legacy converter
+ */
+export const GLOBAL_API_REF = {
+ current: null as null | React.MutableRefObject,
+};
+
+/**
+ * A tagger to determine if the filter is internal or custom user-supplied.
+ * To be a valid internal filter, the V7 function *must* be defined/redefined at
+ * the same time as the legacy one.
+ * https://github.com/mui/mui-x/pull/9254#discussion_r1231095551
+ */
+export function tagInternalFilter(fn: T): T {
+ (fn as any).isInternal = true;
+ return fn;
+}
+
+export function isInternalFilter(fn: Function | undefined): boolean {
+ return fn !== undefined && (fn as any).isInternal === true;
+}
+
+export function convertFilterV7ToLegacy(fn: GetApplyFilterFnV7): GetApplyFilterFnLegacy {
+ return tagInternalFilter((filterItem, column) => {
+ const filterFn = fn(filterItem, column);
+ if (!filterFn) {
+ return filterFn;
+ }
+ return (cellParams): boolean => {
+ return filterFn(cellParams.value, cellParams.row, column, GLOBAL_API_REF.current!);
+ };
+ });
+}
+
+export function convertLegacyOperators(
+ ops: Omit[],
+): GridFilterOperator[] {
+ return ops.map((op) => {
+ return {
+ ...op,
+ getApplyFilterFn: convertFilterV7ToLegacy(op.getApplyFilterFnV7!),
+ getApplyFilterFnV7: tagInternalFilter(op.getApplyFilterFnV7!),
+ };
+ });
+}
+
+export function convertQuickFilterV7ToLegacy(
+ fn: GetApplyQuickFilterFnV7,
+): GetApplyQuickFilterFnLegacy {
+ return tagInternalFilter((filterItem, column, apiRef) => {
+ const filterFn = fn(filterItem, column, apiRef);
+ if (!filterFn) {
+ return filterFn;
+ }
+ return (cellParams): boolean => {
+ return filterFn(cellParams.value, cellParams.row, column, apiRef);
+ };
+ });
+}
diff --git a/packages/grid/x-data-grid/src/components/cell/GridCell.tsx b/packages/grid/x-data-grid/src/components/cell/GridCell.tsx
index 45669757a255..b465efbfaf72 100644
--- a/packages/grid/x-data-grid/src/components/cell/GridCell.tsx
+++ b/packages/grid/x-data-grid/src/components/cell/GridCell.tsx
@@ -247,6 +247,7 @@ const GridCell = React.forwardRef((props, ref) =>
const {
align,
children: childrenProp,
+ editCellState,
colIndex,
column,
cellMode,
diff --git a/packages/grid/x-data-grid/src/hooks/features/editing/useGridRowEditing.ts b/packages/grid/x-data-grid/src/hooks/features/editing/useGridRowEditing.ts
index a4db9e81a578..dfc6f29644ce 100644
--- a/packages/grid/x-data-grid/src/hooks/features/editing/useGridRowEditing.ts
+++ b/packages/grid/x-data-grid/src/hooks/features/editing/useGridRowEditing.ts
@@ -28,7 +28,10 @@ import { useGridApiMethod } from '../../utils/useGridApiMethod';
import { gridEditRowsStateSelector } from './gridEditingSelectors';
import { GridRowId } from '../../../models/gridRows';
import { isPrintableKey } from '../../../utils/keyboardUtils';
-import { gridColumnFieldsSelector } from '../columns/gridColumnsSelector';
+import {
+ gridColumnFieldsSelector,
+ gridVisibleColumnFieldsSelector,
+} from '../columns/gridColumnsSelector';
import { GridCellParams } from '../../../models/params/gridCellParams';
import { buildWarning } from '../../../utils/warning';
import { gridRowsDataRowIdToIdLookupSelector } from '../rows/gridRowsSelector';
@@ -189,14 +192,13 @@ export const useGridRowEditing = (
} else if (event.key === 'Enter') {
reason = GridRowEditStopReasons.enterKeyDown;
} else if (event.key === 'Tab') {
- const columnFields = gridColumnFieldsSelector(apiRef).filter((field) => {
+ const columnFields = gridVisibleColumnFieldsSelector(apiRef).filter((field) => {
const column = apiRef.current.getColumn(field);
if (column.type === GRID_ACTIONS_COLUMN_TYPE) {
return true;
}
return apiRef.current.isCellEditable(apiRef.current.getCellParams(params.id, field));
});
-
if (event.shiftKey) {
if (params.field === columnFields[0]) {
// Exit if user pressed Shift+Tab on the first field
diff --git a/packages/grid/x-data-grid/src/hooks/features/filter/gridFilterState.ts b/packages/grid/x-data-grid/src/hooks/features/filter/gridFilterState.ts
index 015d8d8d26e5..96926508a768 100644
--- a/packages/grid/x-data-grid/src/hooks/features/filter/gridFilterState.ts
+++ b/packages/grid/x-data-grid/src/hooks/features/filter/gridFilterState.ts
@@ -1,6 +1,6 @@
import { GridFilterItem, GridLogicOperator } from '../../../models/gridFilterItem';
import { GridFilterModel } from '../../../models/gridFilterModel';
-import { GridRowId } from '../../../models/gridRows';
+import { GridRowId, GridValidRowModel } from '../../../models/gridRows';
export type GridFilterItemResult = { [key: Required['id']]: boolean };
export type GridQuickFilterValueResult = { [key: string]: boolean };
@@ -35,17 +35,20 @@ export interface GridFilterInitialState {
filterModel?: GridFilterModel;
}
+export interface GridAggregatedFilterItemApplierResult {
+ passingFilterItems: null | GridFilterItemResult;
+ passingQuickFilterValues: null | GridQuickFilterValueResult;
+}
+
/**
* @param {GridRowId} rowId The id of the row we want to filter.
* @param {(filterItem: GridFilterItem) => boolean} shouldApplyItem An optional callback to allow the filtering engine to only apply some items.
*/
export type GridAggregatedFilterItemApplier = (
- rowId: GridRowId,
- shouldApplyItem?: (field: string) => boolean,
-) => {
- passingFilterItems: null | GridFilterItemResult;
- passingQuickFilterValues: null | GridQuickFilterValueResult;
-};
+ row: GridValidRowModel,
+ shouldApplyItem: ((field: string) => boolean) | undefined,
+ result: GridAggregatedFilterItemApplierResult,
+) => void;
export interface GridFilteringMethodParams {
isRowMatchingFilters: GridAggregatedFilterItemApplier | null;
diff --git a/packages/grid/x-data-grid/src/hooks/features/filter/gridFilterUtils.ts b/packages/grid/x-data-grid/src/hooks/features/filter/gridFilterUtils.ts
index 95bdbe3b6e75..2c636e0a06c1 100644
--- a/packages/grid/x-data-grid/src/hooks/features/filter/gridFilterUtils.ts
+++ b/packages/grid/x-data-grid/src/hooks/features/filter/gridFilterUtils.ts
@@ -1,13 +1,17 @@
import * as React from 'react';
import {
GridCellParams,
+ GridColDef,
GridFilterItem,
GridFilterModel,
GridLogicOperator,
GridRowId,
+ GridRowIdGetter,
+ GridValidRowModel,
} from '../../../models';
import { GridApiCommunity } from '../../../models/api/gridApiCommunity';
import { GridStateCommunity } from '../../../models/gridStateCommunity';
+import { GLOBAL_API_REF, isInternalFilter } from '../../../colDef/utils';
import {
getDefaultGridFilterModel,
GridAggregatedFilterItemApplier,
@@ -17,13 +21,20 @@ import {
import { buildWarning } from '../../../utils/warning';
import { gridColumnFieldsSelector, gridColumnLookupSelector } from '../columns';
-type GridFilterItemApplier = {
- fn: (rowId: GridRowId) => boolean;
- item: GridFilterItem;
-};
+type GridFilterItemApplier =
+ | {
+ v7: false;
+ fn: (rowId: GridRowId) => boolean;
+ item: GridFilterItem;
+ }
+ | {
+ v7: true;
+ fn: (row: GridValidRowModel) => boolean;
+ item: GridFilterItem;
+ };
type GridFilterItemApplierNotAggregated = (
- rowId: GridRowId,
+ row: GridValidRowModel,
shouldApplyItem?: (field: string) => boolean,
) => GridFilterItemResult;
@@ -165,27 +176,51 @@ const getFilterCallbackFromItem = (
);
}
- const applyFilterOnRow = filterOperator.getApplyFilterFn(newFilterItem, column)!;
+ const hasUserFunctionLegacy = !isInternalFilter(filterOperator.getApplyFilterFn);
+ const hasUserFunctionV7 = !isInternalFilter(filterOperator.getApplyFilterFnV7);
+
+ if (filterOperator.getApplyFilterFnV7 && !(hasUserFunctionLegacy && !hasUserFunctionV7)) {
+ const applyFilterOnRow = filterOperator.getApplyFilterFnV7(newFilterItem, column)!;
+ if (typeof applyFilterOnRow !== 'function') {
+ return null;
+ }
+ return {
+ v7: true,
+ item: newFilterItem,
+ fn: (row: GridValidRowModel) => {
+ const value = apiRef.current.getRowValue(row, column);
+ return applyFilterOnRow(value, row, column, apiRef);
+ },
+ };
+ }
+
+ const applyFilterOnRow = filterOperator.getApplyFilterFn!(newFilterItem, column)!;
if (typeof applyFilterOnRow !== 'function') {
return null;
}
- const fn = (rowId: GridRowId) => {
- const cellParams = apiRef.current.getCellParams(rowId, newFilterItem.field!);
-
- return applyFilterOnRow(cellParams);
+ return {
+ v7: false,
+ item: newFilterItem,
+ fn: (rowId: GridRowId) => {
+ const params = apiRef.current.getCellParams(rowId, newFilterItem.field!);
+ GLOBAL_API_REF.current = apiRef;
+ const result = applyFilterOnRow(params);
+ GLOBAL_API_REF.current = null;
+ return result;
+ },
};
-
- return { fn, item: newFilterItem };
};
/**
* Generates a method to easily check if a row is matching the current filter model.
+ * @param {GridRowIdGetter | undefined} getRowId The getter for row's id.
* @param {GridFilterModel} filterModel The model with which we want to filter the rows.
* @param {React.MutableRefObject} apiRef The API of the grid.
* @returns {GridAggregatedFilterItemApplier | null} A method that checks if a row is matching the current filter model. If `null`, we consider that all the rows are matching the filters.
*/
export const buildAggregatedFilterItemsApplier = (
+ getRowId: GridRowIdGetter | undefined,
filterModel: GridFilterModel,
apiRef: React.MutableRefObject,
): GridFilterItemApplierNotAggregated | null => {
@@ -199,16 +234,17 @@ export const buildAggregatedFilterItemsApplier = (
return null;
}
- return (rowId, shouldApplyFilter) => {
+ return (row, shouldApplyFilter) => {
const resultPerItemId: GridFilterItemResult = {};
- const filteredAppliers = shouldApplyFilter
- ? appliers.filter((applier) => shouldApplyFilter(applier.item.field))
- : appliers;
-
- filteredAppliers.forEach((applier) => {
- resultPerItemId[applier.item.id!] = applier.fn(rowId);
- });
+ for (let i = 0; i < appliers.length; i += 1) {
+ const applier = appliers[i];
+ if (!shouldApplyFilter || shouldApplyFilter(applier.item.field)) {
+ resultPerItemId[applier.item.id!] = applier.v7
+ ? applier.fn(row)
+ : applier.fn(getRowId ? getRowId(row) : row.id);
+ }
+ }
return resultPerItemId;
};
@@ -216,83 +252,121 @@ export const buildAggregatedFilterItemsApplier = (
/**
* Generates a method to easily check if a row is matching the current quick filter.
- * @param {any[]} values The model with which we want to filter the rows.
+ * @param {GridRowIdGetter | undefined} getRowId The getter for row's id.
+ * @param {any[]} filterModel The model with which we want to filter the rows.
* @param {React.MutableRefObject} apiRef The API of the grid.
* @returns {GridAggregatedFilterItemApplier | null} A method that checks if a row is matching the current filter model. If `null`, we consider that all the rows are matching the filters.
*/
export const buildAggregatedQuickFilterApplier = (
+ getRowId: GridRowIdGetter | undefined,
filterModel: GridFilterModel,
apiRef: React.MutableRefObject,
): GridFilterItemApplierNotAggregated | null => {
- const { quickFilterValues = [] } = filterModel;
+ const quickFilterValues = filterModel.quickFilterValues?.filter(Boolean) ?? [];
if (quickFilterValues.length === 0) {
return null;
}
- const columnsFields = gridColumnFieldsSelector(apiRef);
+ const columnFields = gridColumnFieldsSelector(apiRef);
- const appliersPerField: {
- [field: string]: (null | ((params: GridCellParams) => boolean))[];
- } = {};
- columnsFields.forEach((field) => {
+ const appliersPerField = [] as {
+ column: GridColDef;
+ appliers: {
+ v7: boolean;
+ fn: null | ((...args: any[]) => boolean);
+ }[];
+ }[];
+
+ columnFields.forEach((field) => {
const column = apiRef.current.getColumn(field);
const getApplyQuickFilterFn = column?.getApplyQuickFilterFn;
- if (!getApplyQuickFilterFn) {
- return;
+ const getApplyQuickFilterFnV7 = column?.getApplyQuickFilterFnV7;
+
+ const hasUserFunctionLegacy = !isInternalFilter(getApplyQuickFilterFn);
+ const hasUserFunctionV7 = !isInternalFilter(getApplyQuickFilterFnV7);
+
+ if (getApplyQuickFilterFnV7 && !(hasUserFunctionLegacy && !hasUserFunctionV7)) {
+ appliersPerField.push({
+ column,
+ appliers: quickFilterValues.map((value) => ({
+ v7: true,
+ fn: getApplyQuickFilterFnV7(value, column, apiRef),
+ })),
+ });
+ } else if (getApplyQuickFilterFn) {
+ appliersPerField.push({
+ column,
+ appliers: quickFilterValues.map((value) => ({
+ v7: false,
+ fn: getApplyQuickFilterFn(value, column, apiRef),
+ })),
+ });
}
- appliersPerField[field] = quickFilterValues.map((value) =>
- getApplyQuickFilterFn(value, column, apiRef),
- );
});
- // If some value does not have an applier we ignore them
- const sanitizedQuickFilterValues = quickFilterValues.filter((value, index) =>
- Object.keys(appliersPerField).some((field) => appliersPerField[field][index] != null),
- );
+ return function isRowMatchingQuickFilter(row, shouldApplyFilter) {
+ const result = {} as GridQuickFilterValueResult;
+ const usedCellParams = {} as { [field: string]: GridCellParams };
- if (sanitizedQuickFilterValues.length === 0) {
- return null;
- }
+ /* eslint-disable no-restricted-syntax, no-labels, no-continue */
+ outer: for (let v = 0; v < quickFilterValues.length; v += 1) {
+ const filterValue = quickFilterValues[v];
- return (rowId, shouldApplyFilter) => {
- const usedCellParams: { [field: string]: GridCellParams } = {};
- const fieldsToFilter: string[] = [];
+ for (let i = 0; i < appliersPerField.length; i += 1) {
+ const { column, appliers } = appliersPerField[i];
+ const { field } = column;
- Object.keys(appliersPerField).forEach((field) => {
- if (!shouldApplyFilter || shouldApplyFilter(field)) {
- usedCellParams[field] = apiRef.current.getCellParams(rowId, field);
- fieldsToFilter.push(field);
- }
- });
+ if (shouldApplyFilter && !shouldApplyFilter(field)) {
+ continue;
+ }
- const quickFilterValueResult: GridQuickFilterValueResult = {};
- sanitizedQuickFilterValues.forEach((value, index) => {
- const isPassing = fieldsToFilter.some((field) => {
- if (appliersPerField[field][index] == null) {
- return false;
+ const applier = appliers[v];
+ const value = apiRef.current.getRowValue(row, column);
+
+ if (applier.fn === null) {
+ continue;
}
- return appliersPerField[field][index]?.(usedCellParams[field]);
- });
- quickFilterValueResult[value] = isPassing;
- });
- return quickFilterValueResult;
+ if (applier.v7) {
+ const isMatching = applier.fn(value, row, column, apiRef);
+ if (isMatching) {
+ result[filterValue] = true;
+ continue outer;
+ }
+ } else {
+ const cellParams =
+ usedCellParams[field] ??
+ apiRef.current.getCellParams(getRowId ? getRowId(row) : row.id, field);
+ usedCellParams[field] = cellParams;
+
+ const isMatching = applier.fn(cellParams);
+ if (isMatching) {
+ result[filterValue] = true;
+ continue outer;
+ }
+ }
+ }
+
+ result[filterValue] = false;
+ }
+ /* eslint-enable no-restricted-syntax, no-labels, no-continue */
+
+ return result;
};
};
export const buildAggregatedFilterApplier = (
+ getRowId: GridRowIdGetter | undefined,
filterModel: GridFilterModel,
apiRef: React.MutableRefObject,
): GridAggregatedFilterItemApplier => {
- const isRowMatchingFilterItems = buildAggregatedFilterItemsApplier(filterModel, apiRef);
- const isRowMatchingQuickFilter = buildAggregatedQuickFilterApplier(filterModel, apiRef);
-
- return (rowId, shouldApplyFilter) => ({
- passingFilterItems:
- isRowMatchingFilterItems && isRowMatchingFilterItems(rowId, shouldApplyFilter),
- passingQuickFilterValues:
- isRowMatchingQuickFilter && isRowMatchingQuickFilter(rowId, shouldApplyFilter),
- });
+ const isRowMatchingFilterItems = buildAggregatedFilterItemsApplier(getRowId, filterModel, apiRef);
+ const isRowMatchingQuickFilter = buildAggregatedQuickFilterApplier(getRowId, filterModel, apiRef);
+
+ return function isRowMatchingFilters(row, shouldApplyFilter, result) {
+ result.passingFilterItems = isRowMatchingFilterItems?.(row, shouldApplyFilter) ?? null;
+ result.passingQuickFilterValues = isRowMatchingQuickFilter?.(row, shouldApplyFilter) ?? null;
+ };
};
const isNotNull = (result: null | T): result is T => result != null;
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 0dcf9af886a8..5b0d144656ef 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
@@ -5,7 +5,7 @@ import { DataGridProcessedProps } from '../../../models/props/DataGridProps';
import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity';
import { GridFilterApi } from '../../../models/api/gridFilterApi';
import { GridFilterItem } from '../../../models/gridFilterItem';
-import { GridGroupNode, GridRowId } from '../../../models/gridRows';
+import { GridRowId } from '../../../models/gridRows';
import { GridStateCommunity } from '../../../models/gridStateCommunity';
import { useGridApiEventHandler } from '../../utils/useGridApiEventHandler';
import { useGridApiMethod } from '../../utils/useGridApiMethod';
@@ -15,7 +15,7 @@ import { GridPreferencePanelsValue } from '../preferencesPanel/gridPreferencePan
import { getDefaultGridFilterModel } from './gridFilterState';
import { gridFilterModelSelector } from './gridFilterSelector';
import { useFirstRender } from '../../utils/useFirstRender';
-import { GRID_ROOT_GROUP_ID, gridRowTreeSelector } from '../rows';
+import { gridRowsLookupSelector } from '../rows';
import { GridPipeProcessor, useGridRegisterPipeProcessor } from '../../core/pipeProcessing';
import {
GRID_DEFAULT_STRATEGY,
@@ -72,8 +72,10 @@ export const useGridFilter = (
apiRef: React.MutableRefObject,
props: Pick<
DataGridProcessedProps,
+ | 'rows'
| 'initialState'
| 'filterModel'
+ | 'getRowId'
| 'onFilterModelChange'
| 'filterMode'
| 'disableMultipleColumnsFiltering'
@@ -96,7 +98,9 @@ export const useGridFilter = (
apiRef.current.setState((state) => {
const filterModel = gridFilterModelSelector(state, apiRef.current.instanceId);
const isRowMatchingFilters =
- props.filterMode === 'client' ? buildAggregatedFilterApplier(filterModel, apiRef) : null;
+ props.filterMode === 'client'
+ ? buildAggregatedFilterApplier(props.getRowId, filterModel, apiRef)
+ : null;
const filteringResult = apiRef.current.applyStrategyProcessor('filtering', {
isRowMatchingFilters,
@@ -119,7 +123,7 @@ export const useGridFilter = (
};
});
apiRef.current.publishEvent('filteredRowsSet');
- }, [props.filterMode, apiRef]);
+ }, [apiRef, props.filterMode, props.getRowId]);
const addColumnMenuItem = React.useCallback>(
(columnMenuItems, colDef) => {
@@ -384,44 +388,56 @@ export const useGridFilter = (
[props.slots.filterPanel, props.slotProps?.filterPanel],
);
+ const dataRowIdToIdLookup = apiRef.current.state.rows.dataRowIdToModelLookup;
+ const rows = React.useMemo(() => Object.values(dataRowIdToIdLookup), [dataRowIdToIdLookup]);
+
const flatFilteringMethod = React.useCallback>(
(params) => {
- if (props.filterMode === 'client' && params.isRowMatchingFilters) {
- const tree = gridRowTreeSelector(apiRef);
- const rowIds = (tree[GRID_ROOT_GROUP_ID] as GridGroupNode).children;
- const filteredRowsLookup: Record = {};
- const filterCache = {};
-
- for (let i = 0; i < rowIds.length; i += 1) {
- const rowId = rowIds[i];
- let isRowPassing;
- if (typeof rowId === 'string' && rowId.startsWith('auto-generated-group-footer')) {
- isRowPassing = true;
- } else {
- const { passingFilterItems, passingQuickFilterValues } =
- params.isRowMatchingFilters(rowId);
- isRowPassing = passFilterLogic(
- [passingFilterItems],
- [passingQuickFilterValues],
- params.filterModel,
- apiRef,
- filterCache,
- );
- }
- filteredRowsLookup[rowId] = isRowPassing;
- }
+ if (props.filterMode !== 'client' || !params.isRowMatchingFilters) {
return {
- filteredRowsLookup,
+ filteredRowsLookup: {},
filteredDescendantCountLookup: {},
};
}
+ const dataRowIdToModelLookup = gridRowsLookupSelector(apiRef);
+ const filteredRowsLookup: Record = {};
+ const { isRowMatchingFilters } = params;
+ const filterCache = {};
+
+ const result = {
+ passingFilterItems: null,
+ passingQuickFilterValues: null,
+ };
+
+ for (let i = 0; i < rows.length; i += 1) {
+ const row = rows[i];
+
+ isRowMatchingFilters(row, undefined, result);
+
+ const isRowPassing = passFilterLogic(
+ [result.passingFilterItems],
+ [result.passingQuickFilterValues],
+ params.filterModel,
+ apiRef,
+ filterCache,
+ );
+
+ filteredRowsLookup[row.id] = isRowPassing;
+ }
+
+ const footerId = 'auto-generated-group-footer-root';
+ const footer = dataRowIdToModelLookup[footerId];
+ if (footer) {
+ filteredRowsLookup[footerId] = true;
+ }
+
return {
- filteredRowsLookup: {},
+ filteredRowsLookup,
filteredDescendantCountLookup: {},
};
},
- [apiRef, props.filterMode],
+ [apiRef, props.filterMode, rows],
);
useGridRegisterPipeProcessor(apiRef, 'columnMenu', addColumnMenuItem);
diff --git a/packages/grid/x-data-grid/src/hooks/features/pagination/gridPaginationSelector.ts b/packages/grid/x-data-grid/src/hooks/features/pagination/gridPaginationSelector.ts
index c2fc28bd14f2..5bd931769e0e 100644
--- a/packages/grid/x-data-grid/src/hooks/features/pagination/gridPaginationSelector.ts
+++ b/packages/grid/x-data-grid/src/hooks/features/pagination/gridPaginationSelector.ts
@@ -103,14 +103,18 @@ export const gridPaginationRowRangeSelector = createSelectorMemoized(
topLevelRowAdded <= topLevelRowsInCurrentPageCount
) {
const row = visibleSortedRowEntries[lastRowIndex];
- const depth = rowTree[row.id].depth;
+ const depth = rowTree[row.id]?.depth;
- if (topLevelRowAdded < topLevelRowsInCurrentPageCount || depth > 0) {
+ if (depth === undefined) {
lastRowIndex += 1;
- }
-
- if (depth === 0) {
- topLevelRowAdded += 1;
+ } else {
+ if (topLevelRowAdded < topLevelRowsInCurrentPageCount || depth > 0) {
+ lastRowIndex += 1;
+ }
+
+ if (depth === 0) {
+ topLevelRowAdded += 1;
+ }
}
}
diff --git a/packages/grid/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts b/packages/grid/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts
index 198ddbe62396..e7b9e6d967c4 100644
--- a/packages/grid/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts
+++ b/packages/grid/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts
@@ -28,6 +28,7 @@ import { gridPinnedRowsSelector } from './gridRowsSelector';
import { gridDensityFactorSelector } from '../density/densitySelector';
export const GRID_ROOT_GROUP_ID: GridRowId = `auto-generated-group-node-root`;
+export const GRID_ID_AUTOGENERATED = Symbol('mui-autogenerated-id');
export const buildRootGroup = (): GridGroupNode => ({
type: 'group',
diff --git a/packages/grid/x-data-grid/src/hooks/features/rows/useGridParamsApi.ts b/packages/grid/x-data-grid/src/hooks/features/rows/useGridParamsApi.ts
index a7b0df731337..72ec995c11f2 100644
--- a/packages/grid/x-data-grid/src/hooks/features/rows/useGridParamsApi.ts
+++ b/packages/grid/x-data-grid/src/hooks/features/rows/useGridParamsApi.ts
@@ -4,11 +4,13 @@ import { GridParamsApi } from '../../../models/api/gridParamsApi';
import { GridRowId, GridTreeNodeWithRender } from '../../../models/gridRows';
import { GridCellParams, GridValueGetterParams } from '../../../models/params/gridCellParams';
import { GridRowParams } from '../../../models/params/gridRowParams';
+import { DataGridProcessedProps } from '../../../models/props/DataGridProps';
import {
getGridCellElement,
getGridColumnHeaderElement,
getGridRowElement,
} from '../../../utils/domUtils';
+import { GRID_ID_AUTOGENERATED } from './gridRowsUtils';
import { useGridApiMethod } from '../../utils/useGridApiMethod';
import { gridFocusCellSelector, gridTabIndexCellSelector } from '../focus/gridFocusStateSelector';
@@ -22,7 +24,12 @@ export class MissingRowIdError extends Error {}
* TODO: Impossible priority - useGridEditing also needs to be after useGridParamsApi
* TODO: Impossible priority - useGridFocus also needs to be after useGridParamsApi
*/
-export function useGridParamsApi(apiRef: React.MutableRefObject) {
+export function useGridParamsApi(
+ apiRef: React.MutableRefObject,
+ props: Pick,
+) {
+ const { getRowId } = props;
+
const getColumnHeaderParams = React.useCallback(
(field) => ({
field,
@@ -140,6 +147,41 @@ export function useGridParamsApi(apiRef: React.MutableRefObject(
+ (row, colDef) => {
+ const id = (getRowId ? getRowId(row) : row.id) ?? row[GRID_ID_AUTOGENERATED];
+ const field = colDef.field;
+
+ if (!colDef || !colDef.valueGetter) {
+ return row[field];
+ }
+
+ return colDef.valueGetter(getBaseCellParams(id, field));
+ },
+ [getBaseCellParams, getRowId],
+ );
+
+ const getRowFormattedValue = React.useCallback(
+ (row, colDef) => {
+ const value = getRowValue(row, colDef);
+
+ if (!colDef || !colDef.valueFormatter) {
+ return value;
+ }
+
+ const id = (getRowId ? getRowId(row) : row.id) ?? row[GRID_ID_AUTOGENERATED];
+ const field = colDef.field;
+
+ return colDef.valueFormatter({
+ id,
+ field,
+ value,
+ api: apiRef.current,
+ });
+ },
+ [apiRef, getRowId, getRowValue],
+ );
+
const getColumnHeaderElement = React.useCallback(
(field) => {
if (!apiRef.current.rootElementRef!.current) {
@@ -173,6 +215,8 @@ export function useGridParamsApi(apiRef: React.MutableRefObject {
const rootStyle = React.useMemo(() => {
const style = {} as React.CSSProperties;
+
if (!needsHorizontalScrollbar) {
style.overflowX = 'hidden';
}
+
if (rootProps.autoHeight) {
style.overflowY = 'hidden';
}
+
return style;
}, [needsHorizontalScrollbar, rootProps.autoHeight]);
diff --git a/packages/grid/x-data-grid/src/internals/index.ts b/packages/grid/x-data-grid/src/internals/index.ts
index f32a2e42a80f..e8b3a08de287 100644
--- a/packages/grid/x-data-grid/src/internals/index.ts
+++ b/packages/grid/x-data-grid/src/internals/index.ts
@@ -54,7 +54,10 @@ export { useGridPrintExport } from '../hooks/features/export/useGridPrintExport'
export { useGridFilter, filterStateInitializer } from '../hooks/features/filter/useGridFilter';
export { passFilterLogic } from '../hooks/features/filter/gridFilterUtils';
export { isSingleSelectColDef } from '../components/panel/filterPanel/filterPanelUtils';
-export type { GridAggregatedFilterItemApplier } from '../hooks/features/filter/gridFilterState';
+export type {
+ GridAggregatedFilterItemApplier,
+ GridAggregatedFilterItemApplierResult,
+} from '../hooks/features/filter/gridFilterState';
export { useGridFocus, focusStateInitializer } from '../hooks/features/focus/useGridFocus';
export { useGridKeyboardNavigation } from '../hooks/features/keyboardNavigation/useGridKeyboardNavigation';
export {
@@ -141,4 +144,5 @@ export type { GridApiCaches } from '../models/gridApiCaches';
export { serializeCellValue } from '../hooks/features/export/serializers/csvSerializer';
+export * from '../colDef/utils';
export * from './utils';
diff --git a/packages/grid/x-data-grid/src/joy/joySlots.tsx b/packages/grid/x-data-grid/src/joy/joySlots.tsx
index 3b673e065064..c7532196a420 100644
--- a/packages/grid/x-data-grid/src/joy/joySlots.tsx
+++ b/packages/grid/x-data-grid/src/joy/joySlots.tsx
@@ -12,6 +12,8 @@ import JoySelect, { SelectProps as JoySelectProps } from '@mui/joy/Select';
import JoyOption, { OptionProps as JoyOptionProps } from '@mui/joy/Option';
import JoyBox from '@mui/joy/Box';
import JoyTypography from '@mui/joy/Typography';
+import JoyCircularProgress from '@mui/joy/CircularProgress';
+import JoyTooltip from '@mui/joy/Tooltip';
import { unstable_useForkRef as useForkRef } from '@mui/utils';
import joyIconSlots, { GridKeyboardArrowRight, GridKeyboardArrowLeft } from './icons';
import type { UncapitalizeObjectKeys } from '../internals/utils';
@@ -19,6 +21,7 @@ import type { GridSlotsComponent, GridSlotsComponentsProps } from '../models';
import { useGridApiContext } from '../hooks/utils/useGridApiContext';
import { useGridRootProps } from '../hooks/utils/useGridRootProps';
import { gridFilteredTopLevelRowCountSelector, gridPaginationModelSelector } from '../hooks';
+import { GridOverlay } from '../components/containers/GridOverlay';
function convertColor<
T extends
@@ -405,6 +408,17 @@ const Pagination = React.forwardRef<
);
});
+const LoadingOverlay = React.forwardRef<
+ HTMLDivElement,
+ NonNullable
+>((props, ref) => {
+ return (
+
+
+
+ );
+});
+
const joySlots: UncapitalizeObjectKeys> = {
...joyIconSlots,
baseCheckbox: Checkbox,
@@ -416,9 +430,9 @@ const joySlots: UncapitalizeObjectKeys> = {
baseSelectOption: Option,
baseInputLabel: InputLabel,
baseFormControl: JoyFormControl,
- // BaseTooltip: MUITooltip,
- // BasePopper: MUIPopper,
+ baseTooltip: JoyTooltip,
pagination: Pagination,
+ loadingOverlay: LoadingOverlay,
};
export default joySlots;
diff --git a/packages/grid/x-data-grid/src/locales/huHU.ts b/packages/grid/x-data-grid/src/locales/huHU.ts
index 4cf56d92e0e8..4368a4d429cb 100644
--- a/packages/grid/x-data-grid/src/locales/huHU.ts
+++ b/packages/grid/x-data-grid/src/locales/huHU.ts
@@ -70,33 +70,33 @@ const huHUGrid: Partial = {
filterOperatorIsEmpty: 'รผres',
filterOperatorIsNotEmpty: 'nem รผres',
filterOperatorIsAnyOf: 'a kรถvetkezลk egyike:',
- // 'filterOperator=': '=',
- // 'filterOperator!=': '!=',
- // 'filterOperator>': '>',
- // 'filterOperator>=': '>=',
- // 'filterOperator<': '<',
- // 'filterOperator<=': '<=',
+ 'filterOperator=': '=',
+ 'filterOperator!=': '!=',
+ 'filterOperator>': '>',
+ 'filterOperator>=': '>=',
+ 'filterOperator<': '<',
+ 'filterOperator<=': '<=',
// Header filter operators text
- // headerFilterOperatorContains: 'Contains',
- // headerFilterOperatorEquals: 'Equals',
- // headerFilterOperatorStartsWith: 'Starts with',
- // headerFilterOperatorEndsWith: 'Ends with',
+ headerFilterOperatorContains: 'Tartalmazza:',
+ headerFilterOperatorEquals: 'Egyenlล ezzel:',
+ headerFilterOperatorStartsWith: 'Ezzel kezdลdik:',
+ headerFilterOperatorEndsWith: 'Ezzel vรฉgzลdik:',
// headerFilterOperatorIs: 'Is',
// headerFilterOperatorNot: 'Is not',
- // headerFilterOperatorAfter: 'Is after',
- // headerFilterOperatorOnOrAfter: 'Is on or after',
- // headerFilterOperatorBefore: 'Is before',
- // headerFilterOperatorOnOrBefore: 'Is on or before',
- // headerFilterOperatorIsEmpty: 'Is empty',
- // headerFilterOperatorIsNotEmpty: 'Is not empty',
- // headerFilterOperatorIsAnyOf: 'Is any of',
- // 'headerFilterOperator=': 'Equals',
- // 'headerFilterOperator!=': 'Not equals',
- // 'headerFilterOperator>': 'Greater than',
- // 'headerFilterOperator>=': 'Greater than or equal to',
- // 'headerFilterOperator<': 'Less than',
- // 'headerFilterOperator<=': 'Less than or equal to',
+ headerFilterOperatorAfter: 'Ezutรกni:',
+ headerFilterOperatorOnOrAfter: 'Ekkozori vagy ezutรกni:',
+ headerFilterOperatorBefore: 'Ezelลtti:',
+ headerFilterOperatorOnOrBefore: 'Ekkori vagy ezelลtti:',
+ headerFilterOperatorIsEmpty: 'รres',
+ headerFilterOperatorIsNotEmpty: 'Nem รผres',
+ headerFilterOperatorIsAnyOf: 'A kรถvetkezลk egyike:',
+ 'headerFilterOperator=': 'Egyenlล',
+ 'headerFilterOperator!=': 'Nem egyenlล',
+ 'headerFilterOperator>': 'Nagyobb mint',
+ 'headerFilterOperator>=': 'Nagyobb vagy egyenlล',
+ 'headerFilterOperator<': 'Kissebb mint',
+ 'headerFilterOperator<=': 'Kissebb vagy enygenlล',
// Filter values text
filterValueAny: 'bรกrmilyen',
diff --git a/packages/grid/x-data-grid/src/locales/ptBR.ts b/packages/grid/x-data-grid/src/locales/ptBR.ts
index b08de7a06055..504aaa348cac 100644
--- a/packages/grid/x-data-grid/src/locales/ptBR.ts
+++ b/packages/grid/x-data-grid/src/locales/ptBR.ts
@@ -79,12 +79,12 @@ const ptBRGrid: Partial = {
// 'filterOperator<=': '<=',
// Header filter operators text
- // headerFilterOperatorContains: 'Contains',
- // headerFilterOperatorEquals: 'Equals',
- // headerFilterOperatorStartsWith: 'Starts with',
- // headerFilterOperatorEndsWith: 'Ends with',
- // headerFilterOperatorIs: 'Is',
- // headerFilterOperatorNot: 'Is not',
+ headerFilterOperatorContains: 'Contรฉm',
+ headerFilterOperatorEquals: 'Igual',
+ headerFilterOperatorStartsWith: 'Comeรงa com',
+ headerFilterOperatorEndsWith: 'Termina com',
+ headerFilterOperatorIs: 'ร',
+ headerFilterOperatorNot: 'Nรฃo รฉ',
// headerFilterOperatorAfter: 'Is after',
// headerFilterOperatorOnOrAfter: 'Is on or after',
// headerFilterOperatorBefore: 'Is before',
@@ -92,12 +92,12 @@ const ptBRGrid: Partial = {
// headerFilterOperatorIsEmpty: 'Is empty',
// headerFilterOperatorIsNotEmpty: 'Is not empty',
// headerFilterOperatorIsAnyOf: 'Is any of',
- // 'headerFilterOperator=': 'Equals',
- // 'headerFilterOperator!=': 'Not equals',
- // 'headerFilterOperator>': 'Greater than',
- // 'headerFilterOperator>=': 'Greater than or equal to',
- // 'headerFilterOperator<': 'Less than',
- // 'headerFilterOperator<=': 'Less than or equal to',
+ 'headerFilterOperator=': 'Igual',
+ 'headerFilterOperator!=': 'Nรฃo igual',
+ 'headerFilterOperator>': 'Maior que',
+ 'headerFilterOperator>=': 'Maior que ou igual a',
+ 'headerFilterOperator<': 'Menor que',
+ 'headerFilterOperator<=': 'Menor que ou igual a',
// Filter values text
filterValueAny: 'qualquer',
diff --git a/packages/grid/x-data-grid/src/locales/roRO.ts b/packages/grid/x-data-grid/src/locales/roRO.ts
index e9dc4a136346..4a7421fdd047 100644
--- a/packages/grid/x-data-grid/src/locales/roRO.ts
+++ b/packages/grid/x-data-grid/src/locales/roRO.ts
@@ -47,7 +47,7 @@ const roROGrid: Partial = {
// Filter panel text
filterPanelAddFilter: 'Adฤugare filtru',
- // filterPanelRemoveAll: 'Remove all',
+ filterPanelRemoveAll: 'ศterge tot',
filterPanelDeleteIconLabel: 'ศtergere',
filterPanelLogicOperator: 'Operatori logici',
filterPanelOperator: 'Operatori',
@@ -71,33 +71,33 @@ const roROGrid: Partial = {
filterOperatorIsEmpty: 'este gol',
filterOperatorIsNotEmpty: 'nu este gol',
filterOperatorIsAnyOf: 'este una din valori',
- // 'filterOperator=': '=',
- // 'filterOperator!=': '!=',
- // 'filterOperator>': '>',
- // 'filterOperator>=': '>=',
- // 'filterOperator<': '<',
- // 'filterOperator<=': '<=',
+ 'filterOperator=': '=',
+ 'filterOperator!=': '!=',
+ 'filterOperator>': '>',
+ 'filterOperator>=': '>=',
+ 'filterOperator<': '<',
+ 'filterOperator<=': '<=',
// Header filter operators text
- // headerFilterOperatorContains: 'Contains',
- // headerFilterOperatorEquals: 'Equals',
- // headerFilterOperatorStartsWith: 'Starts with',
- // headerFilterOperatorEndsWith: 'Ends with',
- // headerFilterOperatorIs: 'Is',
- // headerFilterOperatorNot: 'Is not',
- // headerFilterOperatorAfter: 'Is after',
- // headerFilterOperatorOnOrAfter: 'Is on or after',
- // headerFilterOperatorBefore: 'Is before',
- // headerFilterOperatorOnOrBefore: 'Is on or before',
- // headerFilterOperatorIsEmpty: 'Is empty',
- // headerFilterOperatorIsNotEmpty: 'Is not empty',
- // headerFilterOperatorIsAnyOf: 'Is any of',
- // 'headerFilterOperator=': 'Equals',
- // 'headerFilterOperator!=': 'Not equals',
- // 'headerFilterOperator>': 'Greater than',
- // 'headerFilterOperator>=': 'Greater than or equal to',
- // 'headerFilterOperator<': 'Less than',
- // 'headerFilterOperator<=': 'Less than or equal to',
+ headerFilterOperatorContains: 'Conศine',
+ headerFilterOperatorEquals: 'Egal cu',
+ headerFilterOperatorStartsWith: 'รncepe cu',
+ headerFilterOperatorEndsWith: 'Se terminฤ cu',
+ headerFilterOperatorIs: 'Este',
+ headerFilterOperatorNot: 'Nu este',
+ headerFilterOperatorAfter: 'Este dupฤ',
+ headerFilterOperatorOnOrAfter: 'Este la sau โdupฤโ',
+ headerFilterOperatorBefore: 'Este รฎnainte de',
+ headerFilterOperatorOnOrBefore: 'este la sau รฎnainte de',
+ headerFilterOperatorIsEmpty: 'Este gol',
+ headerFilterOperatorIsNotEmpty: 'Nu este gol',
+ headerFilterOperatorIsAnyOf: 'Este una din valori',
+ 'headerFilterOperator=': 'Egal cu',
+ 'headerFilterOperator!=': 'Nu este egal cu',
+ 'headerFilterOperator>': 'Mai mare decรขt',
+ 'headerFilterOperator>=': 'Mai mare sau egal cu',
+ 'headerFilterOperator<': 'Mai mic decรขt',
+ 'headerFilterOperator<=': 'Mai mic sau egal cu',
// Filter values text
filterValueAny: 'Aleatoriu',
@@ -107,7 +107,7 @@ const roROGrid: Partial = {
// Column menu text
columnMenuLabel: 'Meniu',
columnMenuShowColumns: 'Afiศeazฤ toate coloanele',
- // columnMenuManageColumns: 'Manage columns',
+ columnMenuManageColumns: 'Gestioneazฤ coloane',
columnMenuFilter: 'Filtru',
columnMenuHideColumn: 'Ascunde',
columnMenuUnsort: 'Dezactivare sortare',
@@ -171,12 +171,12 @@ const roROGrid: Partial = {
rowReorderingHeaderName: 'Reordonare rรขnduri',
// Aggregation
- // aggregationMenuItemHeader: 'Aggregation',
- // aggregationFunctionLabelSum: 'sum',
- // aggregationFunctionLabelAvg: 'avg',
- // aggregationFunctionLabelMin: 'min',
- // aggregationFunctionLabelMax: 'max',
- // aggregationFunctionLabelSize: 'size',
+ aggregationMenuItemHeader: 'Agregare',
+ aggregationFunctionLabelSum: 'Sumฤ',
+ aggregationFunctionLabelAvg: 'Medie',
+ aggregationFunctionLabelMin: 'Minim',
+ aggregationFunctionLabelMax: 'Maxim',
+ aggregationFunctionLabelSize: 'Numฤrul elementelor',
};
export const roRO: Localization = getGridLocalization(roROGrid, roROCore);
diff --git a/packages/grid/x-data-grid/src/models/api/gridParamsApi.ts b/packages/grid/x-data-grid/src/models/api/gridParamsApi.ts
index b04961daccd3..39a220de36e0 100644
--- a/packages/grid/x-data-grid/src/models/api/gridParamsApi.ts
+++ b/packages/grid/x-data-grid/src/models/api/gridParamsApi.ts
@@ -1,4 +1,5 @@
-import { GridValidRowModel, GridRowId, GridTreeNode } from '../gridRows';
+import { GridColDef } from '../colDef';
+import { GridValidRowModel, GridRowId, GridTreeNode, GridRowModel } from '../gridRows';
import { GridCellParams } from '../params/gridCellParams';
import { GridColumnHeaderParams } from '../params/gridColumnHeaderParams';
import { GridRowParams } from '../params/gridRowParams';
@@ -12,6 +13,26 @@ export interface GridParamsApi {
* @returns {v} The cell value.
*/
getCellValue: (id: GridRowId, field: string) => V;
+ /**
+ * Gets the cell value.
+ * Use it instead of `getCellValue` for better performance if you have `row` and `colDef`.
+ * @template V
+ * @param {GridRowModel} row The row model.
+ * @param {GridColDef} colDef The column definition.
+ * @returns {v} The cell value.
+ * @ignore - do not document
+ */
+ getRowValue: (row: GridRowModel, colDef: GridColDef) => V;
+ /**
+ * Gets the cell formatted value
+ * Use it instead of `getCellParams` for better performance if you only need the formatted value.
+ * @template V
+ * @param {GridRowModel} row The row model.
+ * @param {GridColDef} colDef The column definition.
+ * @returns {v} The cell value.
+ * @ignore - do not document
+ */
+ getRowFormattedValue: (row: GridRowModel, colDef: GridColDef) => V;
/**
* Gets the underlying DOM element for a cell at the given `id` and `field`.
* @param {GridRowId} id The id of the row.
diff --git a/packages/grid/x-data-grid/src/models/colDef/gridColDef.ts b/packages/grid/x-data-grid/src/models/colDef/gridColDef.ts
index 449d459f1bdb..5ee29e34fce4 100644
--- a/packages/grid/x-data-grid/src/models/colDef/gridColDef.ts
+++ b/packages/grid/x-data-grid/src/models/colDef/gridColDef.ts
@@ -32,6 +32,29 @@ export type ValueOptions = string | number | { value: any; label: string } | Rec
*/
export type GridKeyValue = string | number | boolean;
+export type GridApplyQuickFilterV7 = (
+ value: V,
+ row: R,
+ column: GridColDef,
+ apiRef: React.MutableRefObject,
+) => boolean;
+
+export type GetApplyQuickFilterFnLegacy<
+ R extends GridValidRowModel = GridValidRowModel,
+ V = any,
+ F = V,
+> = (
+ value: any,
+ colDef: GridStateColDef,
+ apiRef: React.MutableRefObject,
+) => null | ((params: GridCellParams) => boolean);
+
+export type GetApplyQuickFilterFnV7 = (
+ value: any,
+ colDef: GridStateColDef,
+ apiRef: React.MutableRefObject,
+) => null | GridApplyQuickFilterV7;
+
/**
* Column Definition base interface.
*/
@@ -217,11 +240,16 @@ export interface GridBaseColDef} apiRef Deprecated: The API of the grid.
* @returns {null | ((params: GridCellParams) => boolean)} The function to call to check if a row pass this filter value or not.
*/
- getApplyQuickFilterFn?: (
- value: any,
- colDef: GridStateColDef,
- apiRef: React.MutableRefObject,
- ) => null | ((params: GridCellParams) => boolean);
+ getApplyQuickFilterFn?: GetApplyQuickFilterFnLegacy;
+ /**
+ * The callback that generates a filtering function for a given quick filter value.
+ * This function can return `null` to skip filtering for this value and column.
+ * @param {any} value The value with which we want to filter the column.
+ * @param {GridStateColDef} colDef The column from which we want to filter the rows.
+ * @param {React.MutableRefObject} apiRef Deprecated: The API of the grid.
+ * @returns {null | GridApplyQuickFilterV7} The function to call to check if a row pass this filter value or not.
+ */
+ getApplyQuickFilterFnV7?: GetApplyQuickFilterFnV7;
/**
* If `true`, this column cannot be reordered.
* @default false
diff --git a/packages/grid/x-data-grid/src/models/gridFilterOperator.ts b/packages/grid/x-data-grid/src/models/gridFilterOperator.ts
index 31f0b0fb1e2d..d1714c8120aa 100644
--- a/packages/grid/x-data-grid/src/models/gridFilterOperator.ts
+++ b/packages/grid/x-data-grid/src/models/gridFilterOperator.ts
@@ -3,6 +3,28 @@ import { GridFilterItem } from './gridFilterItem';
import { GridCellParams } from './params/gridCellParams';
import type { GridColDef } from './colDef/gridColDef';
import type { GridValidRowModel } from './gridRows';
+import type { GridApiCommunity } from './api/gridApiCommunity';
+
+type ApplyFilterFnLegacy = (
+ params: GridCellParams,
+) => boolean;
+
+type ApplyFilterFnV7 = (
+ value: V,
+ row: R,
+ column: GridColDef,
+ apiRef: React.MutableRefObject,
+) => boolean;
+
+export type GetApplyFilterFnV7 = (
+ filterItem: GridFilterItem,
+ column: GridColDef,
+) => null | ApplyFilterFnV7;
+
+export type GetApplyFilterFnLegacy = (
+ filterItem: GridFilterItem,
+ column: GridColDef,
+) => null | ApplyFilterFnLegacy;
/**
* Filter operator definition interface.
@@ -28,12 +50,18 @@ export interface GridFilterOperator boolean)} The function to call to check if a row pass this filter item or not.
+ * @returns {null | ApplyFilterFnLegacy} The function to call to check if a row pass this filter item or not.
+ */
+ getApplyFilterFn: GetApplyFilterFnLegacy;
+ /**
+ * The callback that generates a filtering function for a given filter item and column.
+ * This function can return `null` to skip filtering for this item and column.
+ * This function uses the more performant V7 API.
+ * @param {GridFilterItem} filterItem The filter item with which we want to filter the column.
+ * @param {GridColDef} column The column from which we want to filter the rows.
+ * @returns {null | ApplyFilterFnV7} The function to call to check if a row pass this filter item or not.
*/
- getApplyFilterFn: (
- filterItem: GridFilterItem,
- column: GridColDef,
- ) => null | ((params: GridCellParams) => boolean);
+ getApplyFilterFnV7?: GetApplyFilterFnV7;
/**
* The input component to render in the filter panel for this filter operator.
*/
diff --git a/packages/grid/x-data-grid/src/models/gridRows.ts b/packages/grid/x-data-grid/src/models/gridRows.ts
index b97ee2905550..1519fd1bddba 100644
--- a/packages/grid/x-data-grid/src/models/gridRows.ts
+++ b/packages/grid/x-data-grid/src/models/gridRows.ts
@@ -1,6 +1,6 @@
import type { GridKeyValue } from './colDef/gridColDef';
-export type GridValidRowModel = { [key: string]: any };
+export type GridValidRowModel = { [key: string | symbol]: any };
export type GridRowsProp = Readonly<
GridRowModel[]
diff --git a/packages/grid/x-data-grid/src/tests/filterPanel.DataGrid.test.tsx b/packages/grid/x-data-grid/src/tests/filterPanel.DataGrid.test.tsx
index 371123288d5a..44f9e654c0a5 100644
--- a/packages/grid/x-data-grid/src/tests/filterPanel.DataGrid.test.tsx
+++ b/packages/grid/x-data-grid/src/tests/filterPanel.DataGrid.test.tsx
@@ -4,6 +4,7 @@ import { spy } from 'sinon';
import {
DataGrid,
DataGridProps,
+ GridCellParams,
GridFilterInputValue,
GridFilterInputValueProps,
GridPreferencePanelsValue,
@@ -102,7 +103,8 @@ describe(' - Filter panel', () => {
sensitivity: 'base',
usage: 'search',
});
- return ({ value }): boolean => {
+ return (params: GridCellParams): boolean => {
+ const value = params.value!;
return collator.compare(filterItem.value, (value && value.toString()) || '') === 0;
};
},
diff --git a/packages/grid/x-data-grid/src/tests/filtering.DataGrid.test.tsx b/packages/grid/x-data-grid/src/tests/filtering.DataGrid.test.tsx
index 74c38b517c6c..177593c31a14 100644
--- a/packages/grid/x-data-grid/src/tests/filtering.DataGrid.test.tsx
+++ b/packages/grid/x-data-grid/src/tests/filtering.DataGrid.test.tsx
@@ -9,6 +9,9 @@ import {
GridFilterItem,
GridPreferencePanelsValue,
GridToolbar,
+ GridFilterOperator,
+ GRID_STRING_COL_DEF,
+ getGridStringOperators,
} from '@mui/x-data-grid';
import { getColumnValues } from 'test/utils/helperFn';
import { spy } from 'sinon';
@@ -1219,6 +1222,171 @@ describe(' - Filter', () => {
});
});
+ describe('v7 filter compatibility', () => {
+ const getRows = (operator: GridFilterOperator) => {
+ const { unmount } = render(
+ ,
+ );
+
+ const values = getColumnValues(0);
+ unmount();
+ return values;
+ };
+
+ it('works with internal filters', () => {
+ const operator: GridFilterOperator = {
+ value: 'equals',
+ getApplyFilterFn: getGridStringOperators().find((o) => o.value === 'equals')!
+ .getApplyFilterFn,
+ getApplyFilterFnV7: getGridStringOperators().find((o) => o.value === 'equals')!
+ .getApplyFilterFnV7,
+ };
+
+ expect(getRows(operator)).to.deep.equal(['UK']);
+ });
+
+ it('works with custom getApplyFilterFn', () => {
+ const operator: GridFilterOperator = {
+ value: 'equals',
+ getApplyFilterFn: () => {
+ return (params): boolean => {
+ return params.value === 'Canada';
+ };
+ },
+ getApplyFilterFnV7: getGridStringOperators().find((o) => o.value === 'equals')!
+ .getApplyFilterFnV7,
+ };
+
+ expect(getRows(operator)).to.deep.equal(['Canada']);
+ });
+
+ it('works with custom getApplyFilterFn and getApplyFilterFnV7', () => {
+ const operator: GridFilterOperator = {
+ value: 'equals',
+ getApplyFilterFn: () => {
+ return (params): boolean => {
+ return params.value === 'Canada';
+ };
+ },
+ getApplyFilterFnV7: () => {
+ return (value): boolean => {
+ return value === 'Spain';
+ };
+ },
+ };
+
+ expect(getRows(operator)).to.deep.equal(['Spain']);
+ });
+
+ it('works with custom getApplyFilterFnV7', () => {
+ const operator: GridFilterOperator = {
+ value: 'equals',
+ getApplyFilterFn: getGridStringOperators().find((o) => o.value === 'equals')!
+ .getApplyFilterFn,
+ getApplyFilterFnV7: () => {
+ return (value): boolean => {
+ return value === 'Spain';
+ };
+ },
+ };
+
+ expect(getRows(operator)).to.deep.equal(['Spain']);
+ });
+ });
+
+ describe('v7 quick filter compatibility', () => {
+ const getRows = (colDef: Partial) => {
+ const { unmount } = render(
+ ,
+ );
+
+ const values = getColumnValues(0);
+ unmount();
+ return values;
+ };
+
+ it('works with internal filters', () => {
+ const colDef: Partial = {
+ getApplyQuickFilterFn: GRID_STRING_COL_DEF.getApplyQuickFilterFn,
+ getApplyQuickFilterFnV7: GRID_STRING_COL_DEF.getApplyQuickFilterFnV7,
+ };
+ expect(getRows(colDef)).to.deep.equal(['UK']);
+ });
+
+ it('works with custom getApplyFilterFn', () => {
+ const colDef: Partial = {
+ getApplyQuickFilterFn: () => {
+ return (params) => {
+ return params.value === 'Canada';
+ };
+ },
+ getApplyQuickFilterFnV7: GRID_STRING_COL_DEF.getApplyQuickFilterFnV7,
+ };
+ expect(getRows(colDef)).to.deep.equal(['Canada']);
+ });
+
+ it('works with custom getApplyFilterFn and getApplyFilterFnV7', () => {
+ const colDef: Partial = {
+ getApplyQuickFilterFn: () => {
+ return (params) => {
+ return params.value === 'Canada';
+ };
+ },
+ getApplyQuickFilterFnV7: () => {
+ return (value) => {
+ return value === 'Spain';
+ };
+ },
+ };
+ expect(getRows(colDef)).to.deep.equal(['Spain']);
+ });
+
+ it('works with custom getApplyFilterFnV7', () => {
+ const colDef: Partial = {
+ getApplyQuickFilterFn: GRID_STRING_COL_DEF.getApplyQuickFilterFn,
+ getApplyQuickFilterFnV7: () => {
+ return (value) => {
+ return value === 'Spain';
+ };
+ },
+ };
+ expect(getRows(colDef)).to.deep.equal(['Spain']);
+ });
+ });
+
it('should translate operators dynamically in toolbar without crashing ', () => {
expect(() => {
return (
diff --git a/packages/x-charts/README.md b/packages/x-charts/README.md
index 6e58b83d847d..2a024445328b 100644
--- a/packages/x-charts/README.md
+++ b/packages/x-charts/README.md
@@ -1,5 +1,33 @@
# @mui/x-charts
-Package under development.
+This package is the community edition of the charts components.
+It's part of MUI X, an open-core extension of MUI, with advanced components.
-The alpha phase will start in the coming months, stay tuned!
+## Installation
+
+Install the package in your project directory with:
+
+```sh
+npm install @mui/x-charts
+```
+
+or
+
+```sh
+yarn add @mui/x-charts
+```
+
+This component has the following peer dependencies that you will need to install as well.
+
+```json
+"peerDependencies": {
+ "@mui/material": "^5.4.1",
+ "@mui/system": "^5.4.1",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+},
+```
+
+## Documentation
+
+[The documentation](https://mui.com/x/react-charts/)
diff --git a/packages/x-charts/package.json b/packages/x-charts/package.json
index baf5c724422a..a1f2bd2de639 100644
--- a/packages/x-charts/package.json
+++ b/packages/x-charts/package.json
@@ -5,11 +5,10 @@
"author": "MUI Team",
"main": "./src/index.js",
"license": "MIT",
- "private": true,
"bugs": {
"url": "https://github.com/mui/mui-x/issues"
},
- "homepage": "https://mui.com/x/react-charts/getting-started/",
+ "homepage": "https://mui.com/x/react-charts/",
"sideEffects": false,
"publishConfig": {
"access": "public"
@@ -40,12 +39,10 @@
},
"dependencies": {
"@babel/runtime": "^7.22.5",
- "@juggle/resize-observer": "^3.4.0",
"@types/d3-color": "^3.1.0",
"@types/d3-scale": "^4.0.3",
"@types/d3-shape": "^3.1.1",
"clsx": "^1.2.1",
- "d3-array": "^3.2.4",
"d3-color": "^3.1.0",
"d3-scale": "^4.0.2",
"d3-shape": "^3.2.0",
diff --git a/packages/x-charts/src/ChartsTooltip/ChartsTooltipTable.tsx b/packages/x-charts/src/ChartsTooltip/ChartsTooltipTable.tsx
index 00d71b554c86..d65245fc417c 100644
--- a/packages/x-charts/src/ChartsTooltip/ChartsTooltipTable.tsx
+++ b/packages/x-charts/src/ChartsTooltip/ChartsTooltipTable.tsx
@@ -22,10 +22,10 @@ export const ChartsTooltipRow = styled('tr', {
name: 'MuiChartsTooltip',
slot: 'Row',
})(({ theme }) => ({
- '&:first-child td': {
+ 'tr:first-of-type& td': {
paddingTop: theme.spacing(1),
},
- '&:last-child td': {
+ 'tr:last-of-type& td': {
paddingBottom: theme.spacing(1),
},
}));
@@ -37,12 +37,6 @@ export const ChartsTooltipCell = styled('td', {
verticalAlign: 'middle',
color: theme.palette.text.secondary,
- '&:first-child': {
- paddingLeft: theme.spacing(2),
- },
- '&:last-child': {
- paddingRight: theme.spacing(2),
- },
[`&.${tooltipClasses.labelCell}`]: {
paddingLeft: theme.spacing(1),
},
@@ -50,6 +44,13 @@ export const ChartsTooltipCell = styled('td', {
paddingLeft: theme.spacing(4),
color: theme.palette.text.primary,
},
+
+ 'td:first-of-type&': {
+ paddingLeft: theme.spacing(2),
+ },
+ 'td:last-of-type&': {
+ paddingRight: theme.spacing(2),
+ },
}));
export const ChartsTooltipMark = styled(Box, {
diff --git a/packages/x-charts/src/ResponsiveChartContainer/index.tsx b/packages/x-charts/src/ResponsiveChartContainer/index.tsx
index 9a32f6c76589..32f1d1505182 100644
--- a/packages/x-charts/src/ResponsiveChartContainer/index.tsx
+++ b/packages/x-charts/src/ResponsiveChartContainer/index.tsx
@@ -1,5 +1,7 @@
import * as React from 'react';
-import { ResizeObserver } from '@juggle/resize-observer';
+import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
+import ownerWindow from '@mui/utils/ownerWindow';
+import { styled } from '@mui/material/styles';
import { ChartContainer, ChartContainerProps } from '../ChartContainer';
import { MakeOptional } from '../models/helpers';
@@ -7,47 +9,113 @@ const useChartDimensions = (
inWidth?: number,
inHeight?: number,
): [React.RefObject, number, number] => {
- const ref = React.useRef(null);
+ const rootRef = React.useRef(null);
+ const displayError = React.useRef(false);
const [width, setWidth] = React.useState(0);
const [height, setHeight] = React.useState(0);
+ // Adaptation of the `computeSizeAndPublishResizeEvent` from the grid.
+ const computeSize = React.useCallback(() => {
+ const mainEl = rootRef?.current;
+
+ if (!mainEl) {
+ return;
+ }
+
+ const win = ownerWindow(mainEl);
+ const computedStyle = win.getComputedStyle(mainEl);
+
+ const newHeight = parseFloat(computedStyle.height) || 0;
+ const newWidth = parseFloat(computedStyle.width) || 0;
+
+ setWidth(newWidth);
+ setHeight(newHeight);
+ }, []);
+
React.useEffect(() => {
- const element = ref.current;
- if (element === null || (inHeight !== undefined && inWidth !== undefined)) {
+ // Ensure the error detection occurs after the first rendering.
+ displayError.current = true;
+ }, []);
+
+ useEnhancedEffect(() => {
+ if (inWidth !== undefined && inHeight !== undefined) {
return () => {};
}
+ computeSize();
- const resizeObserver = new ResizeObserver((entries) => {
- if (Array.isArray(entries) && entries.length) {
- const entry = entries[0];
- if (inWidth === undefined) {
- setWidth(entry.contentRect.width);
- }
- if (inHeight === undefined) {
- setHeight(entry.contentRect.height);
- }
- }
+ const elementToObserve = rootRef.current;
+ if (typeof ResizeObserver === 'undefined') {
+ return () => {};
+ }
+
+ let animationFrame: number;
+ const observer = new ResizeObserver(() => {
+ // See https://github.com/mui/mui-x/issues/8733
+ animationFrame = window.requestAnimationFrame(() => {
+ computeSize();
+ });
});
- resizeObserver.observe(element);
- return () => resizeObserver.disconnect();
- }, [height, inHeight, inWidth, width]);
+ if (elementToObserve) {
+ observer.observe(elementToObserve);
+ }
+
+ return () => {
+ if (animationFrame) {
+ window.cancelAnimationFrame(animationFrame);
+ }
+
+ if (elementToObserve) {
+ observer.unobserve(elementToObserve);
+ }
+ };
+ }, [computeSize, inHeight, inWidth]);
- return [ref, inWidth ?? width, inHeight ?? height];
+ if (process.env.NODE_ENV !== 'production') {
+ if (displayError.current && inWidth === undefined && width === 0) {
+ console.error(
+ `MUI: Charts does not have \`width\` prop, and its container has no \`width\` defined.`,
+ );
+ displayError.current = false;
+ }
+ if (displayError.current && inHeight === undefined && height === 0) {
+ console.error(
+ `MUI: Charts does not have \`height\` prop, and its container has no \`height\` defined.`,
+ );
+ displayError.current = false;
+ }
+ }
+
+ return [rootRef, inWidth ?? width, inHeight ?? height];
};
export type ResponsiveChartContainerProps = MakeOptional;
+const ResizableContainer = styled('div', {
+ name: 'MuiResponsiveChart',
+ slot: 'Container',
+})<{ ownerState: Pick }>(({ ownerState }) => ({
+ width: ownerState.width ?? '100%',
+ height: ownerState.height ?? '100%',
+ display: 'flex',
+ position: 'relative',
+ flexGrow: 1,
+ flexDirection: 'column',
+ alignItems: 'center',
+ justifyContent: 'center',
+ overflow: 'hidden',
+}));
+
export function ResponsiveChartContainer(props: ResponsiveChartContainerProps) {
const [containerRef, width, height] = useChartDimensions(props.width, props.height);
return (
-