diff --git a/.github/workflows/cherry-pick-next-to-master.yml b/.github/workflows/cherry-pick-master-to-v7.yml
similarity index 88%
rename from .github/workflows/cherry-pick-next-to-master.yml
rename to .github/workflows/cherry-pick-master-to-v7.yml
index 614c58330d3a..6f980ac23c16 100644
--- a/.github/workflows/cherry-pick-next-to-master.yml
+++ b/.github/workflows/cherry-pick-master-to-v7.yml
@@ -1,17 +1,17 @@
-name: Cherry pick next to master
+name: Cherry pick master to v7
on:
pull_request_target:
branches:
- - next
+ - master
types: ['closed']
permissions: {}
jobs:
- cherry_pick_to_master:
+ cherry_pick_to_v7:
runs-on: ubuntu-latest
- name: Cherry pick into master
+ name: Cherry pick into v7
permissions:
pull-requests: write
contents: write
@@ -26,7 +26,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: carloscastrojumo/github-cherry-pick-action@503773289f4a459069c832dc628826685b75b4b3 # v1.0.10
with:
- branch: master
+ branch: v7.x
body: 'Cherry-pick of #{old_pull_request_id}'
cherry-pick-branch: ${{ format('cherry-pick-{0}', github.event.number) }}
title: '{old_title} (@${{ github.event.pull_request.user.login }})'
diff --git a/.github/workflows/cherry-pick-master-to-v6.yml b/.github/workflows/cherry-pick-v7-to-v6.yml
similarity index 91%
rename from .github/workflows/cherry-pick-master-to-v6.yml
rename to .github/workflows/cherry-pick-v7-to-v6.yml
index 1b594e5b8200..f7e48ffe9fbe 100644
--- a/.github/workflows/cherry-pick-master-to-v6.yml
+++ b/.github/workflows/cherry-pick-v7-to-v6.yml
@@ -1,17 +1,17 @@
-name: Cherry pick master to v6
+name: Cherry pick v7 to v6
on:
pull_request_target:
branches:
- - master
+ - v7.x
types: ['closed']
permissions: {}
jobs:
- cherry_pick_to_v6:
+ cherry_pick_v7_to_v6:
runs-on: ubuntu-latest
- name: Cherry pick into v6
+ name: Cherry pick v7 into v6
permissions:
pull-requests: write
contents: write
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cad4db17e886..2dac6eb4e0c4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,95 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+## 7.21.0
+
+_Oct 17, 2024_
+
+We'd like to offer a big thanks to the 13 contributors who made this release possible. Here are some highlights ✨:
+
+- 💫 Added [`dataset` prop support for the Scatter Chart component](https://mui.com/x/react-charts/scatter/#using-a-dataset)
+- 🐞 Bugfixes
+- 📚 Documentation improvements
+
+Special thanks go out to the community contributors who have helped make this release possible:
+@k-rajat19, @kalyan90, @rotembarsela, @wangkailang.
+Following are all team members who have contributed to this release:
+@arthurbalduini, @cherniavskii, @flaviendelangle, @JCQuintas, @LukasTy, @MBilalShafi, @arminmeh, @romgrk, @KenanYusuf, @oliviertassinari, @samuelsycamore.
+
+
+
+### Data Grid
+
+#### `@mui/x-data-grid@7.21.0`
+
+- [DataGrid] Fix `onRowSelectionModelChange` firing unnecessarily on initial render (#14909) @MBilalShafi
+- [DataGrid] Fix `onRowSelectionModelChange` not being called after row is removed (#14972) @arminmeh
+- [DataGrid] Fix pagination scrollbar issue on small zoom (#14911) @cherniavskii
+- [DataGrid] Fix scroll jumping (#14929) @romgrk
+- [DataGrid] Fix excessive white space at the end of the Data Grid (#14864) @kalyan90
+
+#### `@mui/x-data-grid-pro@7.21.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
+
+Same changes as in `@mui/x-data-grid@7.21.0`, plus:
+
+- [DataGridPro] Fix indeterminate checkbox state for server-side data (#14956) @MBilalShafi
+- [DataGridPro] Fix scrolling performance when `rowHeight={undefined}` (#14983) @cherniavskii
+- [DataGridPro] List view (#14393) @KenanYusuf @cherniavskii
+
+#### `@mui/x-data-grid-premium@7.21.0` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
+
+Same changes as in `@mui/x-data-grid-pro@7.21.0`.
+
+### Date and Time Pickers
+
+#### `@mui/x-date-pickers@7.21.0`
+
+- [pickers] Cleanup `PageUp` and `PageDown` event handlers on time components (#14928) @arthurbalduini
+- [pickers] Create the new picker's `ownerState` object (#14889) @flaviendelangle
+- [pickers] Fix `PickerValidDate` usage in the Date Range Picker Toolbar (#14925) @flaviendelangle
+
+#### `@mui/x-date-pickers-pro@7.21.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
+
+Same changes as in `@mui/x-date-pickers@7.21.0`.
+
+### Charts
+
+#### `@mui/x-charts@7.21.0`
+
+- [charts] Allow `dataset` to be used with the Scatter Chart (#14915) @JCQuintas
+- [charts] Ensure `reduce motion` preference disables animation on page load (#14417) @JCQuintas
+
+#### `@mui/x-charts-pro@7.0.0-beta.5` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
+
+Same changes as in `@mui/x-charts@7.21.0`.
+
+### Tree View
+
+#### `@mui/x-tree-view@7.21.0`
+
+- [TreeView] Fix `alpha()` usage with CSS variables (#14969) @wangkailang
+- [TreeView] Fix usage of the `aria-selected` attribute (#14991) @flaviendelangle
+- [TreeView] Fix hydration error (#15002) @flaviendelangle
+
+### `@mui/x-codemod@7.21.0`
+
+- [codemod] Add a new utility to rename imports (#14919) @flaviendelangle
+
+### Docs
+
+- [docs] Add recipe showing how to toggle detail panels on row click (#14666) @k-rajat19
+- [docs] Fix broken link to the validation section in the Data grid component (#14973) @arminmeh
+- [docs] Update v5 migration codesandbox @oliviertassinari
+- [docs] Enforce component style rules for the Tree View (#14963) @samuelsycamore
+
+### Core
+
+- [core] Fix shortcut with localization keyboard (#14220) @rotembarsela
+- [core] Fix docs deploy command (#14920) @arminmeh
+- [code-infra] Prepare some tests to work in `vitest/playwright` (#14926) @JCQuintas
+- [test] Fix `AdapterDayjs` coverage calculation (#14957) @LukasTy
+- [test] Fix split infinitive API convention use @oliviertassinari
+
## 7.20.0
_Oct 11, 2024_
@@ -79,7 +168,7 @@ Same changes as in `@mui/x-charts@7.20.0`.
- [docs] Add custom columns panel demo (#14825) @cherniavskii
- [docs] Capitalize all instances of "Data Grid" (#14884) @samuelsycamore
- [docs] Divide charts `tooltip` and `highlighting` pages (#14824) @JCQuintas
-- [docs] Document the `TreeItem2` component and the `useTreeItem2` hook (#14551) @noraleonte
+- [docs] Document the `` component and the `useTreeItem2` hook (#14551) @noraleonte
- [docs] Fix column pinning for "Disable detail panel content scroll" section (#14854 and #14885) @kalyan90
- [docs] Fix detail panel demo not working well with pinned columns (#14883) @cherniavskii
- [docs] New recipe of a read-only field (#14606) @flaviendelangle
@@ -200,7 +289,7 @@ Same changes as in `@mui/x-charts@7.19.0`.
- [code-infra] Remove custom playwright installation steps (#14728) @Janpot
- [code-infra] Replace or remove all instances of `e` identifier (#14724) @samuelsycamore
- [infra] Adds community contribution section to the changelog script (#14799) @michelengelen
-- [infra] Fix line break in Stack Overflow message @oliviertassinari
+- [infra] Fix line break in Stack Overflow message @oliviertassinari
- [test] Fix `Escape` event firing event (#14797) @oliviertassinari
## 7.18.0
@@ -292,7 +381,7 @@ Same changes as in `@mui/x-charts@7.18.0`.
- [core] Fix 301 link to Next.js and git diff @oliviertassinari
- [core] Fix failing CI on `master` (#14644) @cherniavskii
- [core] Fix `package.json` repository rule @oliviertassinari
-- [core] MUI X repository moved to a new location @oliviertassinari
+- [core] MUI X repository moved to a new location @oliviertassinari
- [docs-infra] Strengthen CSP (#14581) @oliviertassinari
- [license] Finish renaming of LicensingModel (#14615) @oliviertassinari
@@ -316,7 +405,7 @@ We'd like to offer a big thanks to the 12 contributors who made this release pos
- [DataGrid] Add "does not equal" and "does not contain" filter operators (#14489) @KenanYusuf
- [DataGrid] Add demo to the "Custom columns" page that does not use generator (#13695) @arminmeh
-- [DataGrid] Fix Voice Over reading the column name twice (#14482) @arminmeh
+- [DataGrid] Fix VoiceOver reading the column name twice (#14482) @arminmeh
- [DataGrid] Fix bug in CRUD example (#14513) @michelengelen
- [DataGrid] Fix failing jsdom tests caused by `:has()` selectors (#14559) @KenanYusuf
- [DataGrid] Refactor string operator filter functions (#14564) @KenanYusuf
@@ -367,7 +456,7 @@ Same changes as in `@mui/x-charts@7.17.0`.
### Docs
-- [docs] Add missing callout on "Imperative API" tree view sections (#14503) @flaviendelangle
+- [docs] Add missing callout on "Imperative API" Tree View sections (#14503) @flaviendelangle
- [docs] Fix broken redirection to MUI X v5 @oliviertassinari
- [docs] Fix multiple `console.error` messages on `charts` docs (#14554) @JCQuintas
- [docs] Fixed typo in Row Grouping recipes (#14549) @Miodini
@@ -708,7 +797,7 @@ Same changes as in `@mui/x-charts@7.13.0`.
- [core] Fix ESLint issue (#14207) @LukasTy
- [core] Fix Netlify build cache issue (#14182) @cherniavskii
- [code-infra] Refactor Netlify `cache-docs` plugin setup (#14105) @LukasTy
-- [internals] Move utils needed for tree view virtualization to shared package (#14202) @flaviendelangle
+- [internals] Move utils needed for Tree View virtualization to shared package (#14202) @flaviendelangle
## 7.12.1
@@ -799,7 +888,7 @@ This expansion of the Pro plan comes with some adjustments to our pricing strate
We'd like to offer a big thanks to the 12 contributors who made this release possible. Here are some highlights ✨:
-- 🎁 Introduce [item reordering using drag and drop](https://mui.com/x/react-tree-view/rich-tree-view/ordering/) on the `RichTreeViewPro` component
+- 🎁 Introduce [item reordering using drag and drop](https://mui.com/x/react-tree-view/rich-tree-view/ordering/) on the `` component
@@ -1136,7 +1225,7 @@ _Jul 5, 2024_
We'd like to offer a big thanks to the 7 contributors who made this release possible. Here are some highlights ✨:
- 🔄 Add loading overlay variants, including a skeleton loader option to the Data Grid component. See [Loading overlay docs](https://mui.com/x/react-data-grid/overlays/#loading-overlay) for more details.
-- 🌳 Add `selectItem` and `getItemDOMElement` methods to the TreeView component public API
+- 🌳 Add `selectItem()` and `getItemDOMElement()` methods to the TreeView component public API
- ⛏️ Make the `usePickersTranslations` hook public in the pickers component
- 🐞 Bugfixes
@@ -1181,7 +1270,7 @@ Same changes as in `@mui/x-date-pickers@7.9.0`.
#### `@mui/x-tree-view@7.9.0`
-- [TreeView] Add `selectItem` and `getItemDOMElement` methods to the public API (#13485) @flaviendelangle
+- [TreeView] Add `selectItem()` and `getItemDOMElement()` methods to the public API (#13485) @flaviendelangle
### Docs
@@ -1292,7 +1381,7 @@ Same changes as in `@mui/x-date-pickers@7.8.0`.
- [core] Add eslint rule to restrict import from `../internals` root (#13633) @JCQuintas
- [docs-infra] Sync `\_app` folder with monorepo (#13582) @Janpot
-- [license] Allow usage of charts and tree view pro package for old premium licenses (#13619) @flaviendelangle
+- [license] Allow usage of Charts and Tree View Pro package for old premium licenses (#13619) @flaviendelangle
## 7.7.1
@@ -1360,7 +1449,7 @@ Same changes as in `@mui/x-date-pickers@7.7.1`, plus:
- [TreeView] Improve typing to support optional dependencies in plugins and in the item (#13523) @flaviendelangle
- [TreeView] Move `useTreeViewId` to the core plugins (#13566) @flaviendelangle
- [TreeView] Remove unused state from `useTreeViewId` (#13579) @flaviendelangle
-- [TreeView] Support `itemId` with escaping characters when using `SimpleTreeView` (#13487) @oukunan
+- [TreeView] Support `itemId` with escaping characters when using Simple Tree View (#13487) @oukunan
### Docs
@@ -1440,7 +1529,7 @@ Same changes as in `@mui/x-date-pickers@7.7.0`.
- [TreeView] Improve TypeScript for plugins (#13380) @flaviendelangle
- [TreeView] Improve the typing of the cancelable events (#13152) @flaviendelangle
- [TreeView] Prepare support for PigmentCSS (#13412) @flaviendelangle
-- [TreeView] Refactor the tree view internals to prepare for headless API (#13311) @flaviendelangle
+- [TreeView] Refactor the Tree View internals to prepare for headless API (#13311) @flaviendelangle
### Docs
@@ -1455,7 +1544,7 @@ Same changes as in `@mui/x-date-pickers@7.7.0`.
- [core] Add `eslint-plugin-react-compiler` experimental version and rules (#13415) @JCQuintas
- [core] Minor setup cleanup (#13467) @LukasTy
- [infra] Adjust CI setup (#13448) @LukasTy
-- [test] Add tests for the custom slots of `TreeItem2` (#13314) @flaviendelangle
+- [test] Add tests for the custom slots of `` (#13314) @flaviendelangle
## 7.6.2
@@ -1640,7 +1729,7 @@ _May 23, 2024_
We'd like to offer a big thanks to the 6 contributors who made this release possible. Here are some highlights ✨:
-- 🧰 Improve tree view testing
+- 🧰 Improve Tree View testing
- 📊 Add `label` to be displayed in BarChart
### Data Grid
@@ -1816,7 +1905,7 @@ Same changes as in `@mui/x-date-pickers@7.4.0`.
#### `@mui/x-tree-view@7.4.0`
-- [TreeView] Fix props propagation and theme entry in `TreeItem2` (#12889) @flaviendelangle
+- [TreeView] Fix props propagation and theme entry in `` (#12889) @flaviendelangle
### Docs
@@ -2126,7 +2215,7 @@ Same changes as in `@mui/x-date-pickers@7.2.0`, plus:
### Docs
- [docs] Add `AxisFormatter` documentation for customizing tick/tooltip value formatting (#12700) @JCQuintas
-- [docs] Add file explorer example to rich tree view customization docs (#12707) @noraleonte
+- [docs] Add file explorer example to rich Tree View customization docs (#12707) @noraleonte
- [docs] Do not use import of depth 3 in the doc (#12716) @flaviendelangle
- [docs] Explain how to clip plots with composition (#12679) @alexfauquette
- [docs] Fix typo in Data Grid v7 migration page (#12720) @bfaulk96
@@ -2202,7 +2291,7 @@ Same changes as in `@mui/x-date-pickers@7.1.1`, plus:
#### `@mui/x-tree-view@7.1.1`
- [TreeView] Add JSDoc to all `publicAPI` methods (#12649) @flaviendelangle
-- [TreeView] Create `RichTreeViewPro` component (not released yet) (#12610) @flaviendelangle
+- [TreeView] Create `` component (not released yet) (#12610) @flaviendelangle
- [TreeView] Create Pro package (not released yet) (#12240) @flaviendelangle
- [TreeView] Fix typo in errors (#12623) @alissa-tung
- [TreeView] New API method: `setItemExpansion` (#12595) @flaviendelangle
@@ -2222,13 +2311,13 @@ Same changes as in `@mui/x-date-pickers@7.1.1`, plus:
- [docs] Move Data Grid interfaces to standard API page layout (#12016) @alexfauquette
- [docs] Remove ` around @default values (#12158) @alexfauquette
- [docs] Remove `day` from the default `dayOfWeekFormatter` function params (#12644) @LukasTy
-- [docs] Use `TreeItem2` for icon expansion example on `RichTreeView` (#12563) @flaviendelangle
+- [docs] Use `` for icon expansion example on `` (#12563) @flaviendelangle
### Core
- [core] Add cherry-pick `master` to `v6` action (#12648) @LukasTy
- [core] Fix typo in `@mui/x-tree-view-pro/themeAugmentation` (#12674) @flaviendelangle
-- [core] Introduce `describeTreeView` to run test on `SimpleTreeView` and `RichTreeView`, using `TreeItem` and `TreeItem2` + migrate expansion tests (#12428) @flaviendelangle
+- [core] Introduce `describeTreeView` to run test on `` and ``, using `` and `` + migrate expansion tests (#12428) @flaviendelangle
- [core] Limit `test-types` CI step allowed memory (#12651) @LukasTy
- [core] Remove explicit `express` package (#12602) @LukasTy
- [core] Update to new embedded translations in the docs package (#12232) @Janpot
@@ -2293,7 +2382,7 @@ Same changes as in `@mui/x-date-pickers@7.1.0`, plus:
#### `@mui/x-tree-view@7.1.0`
-- [TreeView] Do not use outdated version of the state to compute new label first char in `RichTreeView` (#12512) @flaviendelangle
+- [TreeView] Do not use outdated version of the state to compute new label first char in Rich Tree View (#12512) @flaviendelangle
### Docs
@@ -2420,7 +2509,7 @@ Same changes as in `@mui/x-date-pickers@7.0.0`, plus:
#### Breaking changes
-- The required `nodeId` prop used by the `TreeItem` has been renamed to `itemId` for consistency:
+- The required `nodeId` prop used by `` has been renamed to `itemId` for consistency:
```diff
@@ -2573,7 +2662,7 @@ The `onNodeFocus` callback has been renamed to `onItemFocus` for consistency:
#### `@mui/x-tree-view@7.0.0-beta.7`
- [TreeView] Clean the usage of the term "item" and "node" in API introduced during v7 (#12368) @noraleonte
-- [TreeView] Introduce a new `TreeItem2` component and a new `useTreeItem2` hook (#11721) @flaviendelangle
+- [TreeView] Introduce a new `` component and a new `useTreeItem2` hook (#11721) @flaviendelangle
- [TreeView] Rename `onNodeFocus` to `onItemFocus` (#12419) @noraleonte
### Docs
@@ -2631,9 +2720,9 @@ Same changes as in `@mui/x-data-grid-pro@7.0.0-beta.6`.
#### Breaking changes
-- The component used to animate the item children is now defined as a slot on the `TreeItem` component.
+- The component used to animate the item children is now defined as a slot on the `` component.
- If you were passing a `TransitionComponent` or `TransitionProps` to your `TreeItem` component,
+ If you were passing a `TransitionComponent` or `TransitionProps` to your `` component,
you need to use the new `groupTransition` slot on this component:
```diff
@@ -2649,7 +2738,7 @@ Same changes as in `@mui/x-data-grid-pro@7.0.0-beta.6`.
```
-- The `group` class of the `TreeItem` component has been renamed to `groupTransition` to match with its new slot name.
+- The `group` class of the `` component has been renamed to `groupTransition` to match with its new slot name.
```diff
const StyledTreeItem = styled(TreeItem)({
@@ -2663,14 +2752,14 @@ Same changes as in `@mui/x-data-grid-pro@7.0.0-beta.6`.
#### `@mui/x-tree-view@7.0.0-beta.6`
- [TreeView] Fix invalid nodes state when updating `props.items` (#12359) @flaviendelangle
-- [TreeView] In the `RichTreeView`, do not use the item id as the HTML id attribute (#12319) @flaviendelangle
+- [TreeView] In the Rich Tree View, do not use the item id as the HTML id attribute (#12319) @flaviendelangle
- [TreeView] New instance and publicAPI method: `getItem` (#12251) @flaviendelangle
- [TreeView] Replace `TransitionComponent` and `TransitionProps` with a `groupTransition` slot (#12336) @flaviendelangle
### Docs
- [docs] Add a note about `z-index` usage in SVG (#12337) @alexfauquette
-- [docs] `RichTreeView` customization docs (#12231) @noraleonte
+- [docs] Rich Tree View customization docs (#12231) @noraleonte
### Core
@@ -2813,7 +2902,8 @@ Same changes as in `@mui/x-data-grid-pro@7.0.0-beta.4`.
```
- The headless field hooks (e.g.: `useDateField`) now returns a new prop called `enableAccessibleFieldDOMStructure`.
- This property is utilized to determine whether the anticipated UI is constructed using an accessible DOM structure. Learn more about this new [accessible DOM structure](/x/react-date-pickers/fields/#accessible-dom-structure).
+ This property is utilized to determine whether the anticipated UI is constructed using an accessible DOM structure.
+ Learn more about this new accessible DOM structure in the [v8 migration guide](https://next.mui.com/x/migration/migration-pickers-v7/#new-dom-structure-for-the-field).
When building a custom UI, you are most-likely only supporting one DOM structure, so you can remove `enableAccessibleFieldDOMStructure` before it is passed to the DOM:
@@ -3323,7 +3413,7 @@ Same changes as in `@mui/x-date-pickers@7.0.0-beta.0`, plus:
### Docs
-- [docs] Add `contextValue` to the headless tree view doc (#11705) @flaviendelangle
+- [docs] Add `contextValue` to the headless Tree View doc (#11705) @flaviendelangle
- [docs] Add section for the `disableSelection` prop (#11821) @flaviendelangle
- [docs] Fix brand name non-breaking space (#11758) @oliviertassinari
- [docs] Fix typo in Data Grid components page (#11775) @flaviendelangle
@@ -3346,7 +3436,7 @@ We'd like to offer a big thanks to the 11 contributors who made this release pos
- 🎁 The Data Grid headers have been refactored to bring immense improvements to scrolling, state management, and overall performance of the grid.
- ⚙️ The Data Grid disabled column-specific features like filtering, sorting, grouping, etc. could now be accessed programmatically. See the related [docs](https://next.mui.com/x/react-data-grid/api-object/#access-the-disabled-column-features) section.
-- 🚀 Uplift the `SimpleTreeView` customization examples (#11424) @noraleonte
+- 🚀 Uplift the Simple Tree View customization examples (#11424) @noraleonte
- 🌍 Add Croatian (hr-HR), Portuguese (pt-PT), and Chinese (Hong Kong) (zh-HK) locales (#11668) on the Data Grid @BCaspari
- 🐞 Bugfixes
- 💔 Bump `@mui/material` peer dependency for all packages (#11692) @LukasTy
@@ -3557,7 +3647,7 @@ Same changes as in `@mui/x-date-pickers@7.0.0-alpha.9`.
```
- The `useTreeItem` hook has been renamed `useTreeItemState`.
- This will help create a new headless version of the `TreeItem` component based on a future `useTreeItem` hook.
+ This will help create a new headless version of the Tree Item component based on a future `useTreeItem` hook.
```diff
-import { TreeItem, useTreeItem } from '@mui/x-tree-view/TreeItem';
@@ -3657,13 +3747,13 @@ Same changes as in `@mui/x-date-pickers@7.0.0-alpha.9`.
- [docs] Cleanup and fix Pickers Playground styling (#11700) @LukasTy
- [docs] First draft of the Tree View custom plugin doc (#11564) @flaviendelangle
- [docs] Fix Pickers migration syntax and diffs (#11695) @LukasTy
-- [docs] Fix generated tree view API docs (#11737) @LukasTy
+- [docs] Fix generated Tree View API docs (#11737) @LukasTy
- [docs] Generate docs for Tree View slots (#11730) @flaviendelangle
- [docs] Improve codemod for v7 (#11650) @oliviertassinari
- [docs] Improve Data Grid `pageSizeOptions` prop documentation (#11682) @oliviertassinari
- [docs] Parse markdown on API docs demo titles (#11728) @LukasTy
- [docs] Remove the description from the `className` prop (#11693) @oliviertassinari
-- [docs] Uplift `SimpleTreeView` customization examples (#11424) @noraleonte
+- [docs] Uplift Simple Tree View customization examples (#11424) @noraleonte
- [docs] Uplift the Date Pickers playground (#11555) @danilo-leal
### Core
@@ -3740,8 +3830,8 @@ Same changes as in `@mui/x-date-pickers@7.0.0-alpha.8`.
### Tree View / `@mui/x-tree-view@7.0.0-alpha.8`
-- [tree view] Cleanup `onKeyDown` handler (#11481) @flaviendelangle
-- [tree view] Define the parameters used by each plugin to avoid listing them in each component (#11473) @flaviendelangle
+- [TreeView] Cleanup `onKeyDown` handler (#11481) @flaviendelangle
+- [TreeView] Define the parameters used by each plugin to avoid listing them in each component (#11473) @flaviendelangle
### Docs
@@ -3768,7 +3858,7 @@ We'd like to offer a big thanks to the 7 contributors who made this release poss
- 🎁 New component to create a Tree View from a structured data source:
- You can now directly pass your data to the `RichTreeView` component instead of manually converting it into JSX `TreeItem` components:
+ You can now directly pass your data to the `` component instead of manually converting it into JSX `` components:
```tsx
const ITEMS = [
@@ -5099,7 +5189,7 @@ Here is an example of the renaming for the `` component.
### Core
-- [core] Adds migration docs for charts, pickers and tree view (#10926) @michelengelen
+- [core] Adds migration docs for Charts, Pickers, and Tree View (#10926) @michelengelen
- [core] Bump monorepo (#10959) @LukasTy
- [core] Changed prettier branch value to next (#10917) @michelengelen
- [core] Fix GitHub title tag consistency @oliviertassinari
diff --git a/changelogOld/CHANGELOG.v6.md b/changelogOld/CHANGELOG.v6.md
index 0401e317fe08..985e7aba0905 100644
--- a/changelogOld/CHANGELOG.v6.md
+++ b/changelogOld/CHANGELOG.v6.md
@@ -1485,7 +1485,7 @@ Same changes as in `@mui/x-date-pickers@6.13.0`, plus:
- [docs] Fix charts demo using too deep import (#10263) @LukasTy
- [docs] Fix `e.g.` typo @oliviertassinari
- [docs] Fix npm package indentation @oliviertassinari
-- [docs] Fix typo in tree view docs @oliviertassinari
+- [docs] Fix typo in Tree View docs @oliviertassinari
- [docs] Improve the week picker example (#8257) @flaviendelangle
- [docs] Include code links in the Data Grid demo (#10219) @cherniavskii
- [docs] Polish page for SEO (#10216) @oliviertassinari
@@ -1546,7 +1546,7 @@ Same changes as in `@mui/x-date-pickers@6.12.1`.
- [docs] Add `DemoContainer` and `DemoItem` JSDoc (#10186) @LukasTy
- [docs] Add link to `custom layout` page (#10184) @LukasTy
-- [docs] Add tree view nav item (#10181) @LukasTy
+- [docs] Add Tree View nav item (#10181) @LukasTy
- [docs] Fix wrong chart tooltip reference (#10169) @oliviertassinari
- [docs] Improve chart SEO (#10170) @oliviertassinari
- [docs] Precise expired license key condition (#10165) @oliviertassinari
@@ -1748,7 +1748,7 @@ _Aug 4, 2023_
We'd like to offer a big thanks to the 12 contributors who made this release possible. Here are some highlights ✨:
-- ⌚️ Move the tree view component from `@mui/lab` package
+- ⌚️ Move the Tree View component from `@mui/lab` package
The `` component has been moved to the MUI X repository.
It is now accessible from its own package: `@mui/x-tree-view`.
@@ -1804,7 +1804,7 @@ Same changes as in `@mui/x-date-pickers@6.11.0`.
### Tree View / `@mui/x-tree-view@6.0.0-alpha.0`
- [TreeView] Add missing exported types (#9862) @flaviendelangle
-- [TreeView] Add tree view to changelog generator script (#9903) @MBilalShafi
+- [TreeView] Add Tree View to changelog generator script (#9903) @MBilalShafi
- [TreeView] Create the package on the X repository (#9798) @flaviendelangle
- [TreeView] Improve props typing (#9855) @flaviendelangle
diff --git a/codecov.yml b/codecov.yml
index 4a05503c5b9e..b4af65812615 100644
--- a/codecov.yml
+++ b/codecov.yml
@@ -10,15 +10,15 @@ coverage:
adapters:
target: 100%
paths:
- - 'packages/x-date-pickers/src/AdapterDateFns/AdapterDateFns.ts'
- - 'packages/x-date-pickers/src/AdapterDateFnsV3/AdapterDateFnsV3.ts'
- - 'packages/x-date-pickers/src/AdapterDateFnsJalali/AdapterDateFnsJalali.ts'
- - 'packages/x-date-pickers/src/AdapterDateFnsJalaliV3/AdapterDateFnsJalaliV3.ts'
- - 'packages/x-date-pickers/src/AdapterDayjs/AdapterDayjs.ts'
- - 'packages/x-date-pickers/src/AdapterLuxon/AdapterLuxon.ts'
- - 'packages/x-date-pickers/src/AdapterMoment/AdapterMoment.ts'
- - 'packages/x-date-pickers/src/AdapterMomentHijri/AdapterMomentHijri.ts'
- - 'packages/x-date-pickers/src/AdapterMomentJalaali/AdapterMomentJalaali.ts'
+ - packages/x-date-pickers/src/AdapterDateFns/AdapterDateFns.ts
+ - packages/x-date-pickers/src/AdapterDateFnsV3/AdapterDateFnsV3.ts
+ - packages/x-date-pickers/src/AdapterDateFnsJalali/AdapterDateFnsJalali.ts
+ - packages/x-date-pickers/src/AdapterDateFnsJalaliV3/AdapterDateFnsJalaliV3.ts
+ - packages/x-date-pickers/src/AdapterDayjs/AdapterDayjs.ts
+ - packages/x-date-pickers/src/AdapterLuxon/AdapterLuxon.ts
+ - packages/x-date-pickers/src/AdapterMoment/AdapterMoment.ts
+ - packages/x-date-pickers/src/AdapterMomentHijri/AdapterMomentHijri.ts
+ - packages/x-date-pickers/src/AdapterMomentJalaali/AdapterMomentJalaali.ts
patch: off
comment: false
diff --git a/docs/.link-check-errors.txt b/docs/.link-check-errors.txt
index 6ecc503cc78a..0438fa82a091 100644
--- a/docs/.link-check-errors.txt
+++ b/docs/.link-check-errors.txt
@@ -1,2 +1,3 @@
Broken links found by `docs:link-check` that exist:
+- https://mui.com/x/react-date-pickers/fields/#accessible-dom-structure
diff --git a/docs/data/charts/areas-demo/areas-demo.md b/docs/data/charts/areas-demo/areas-demo.md
index 92432f02ad72..d784d0996c93 100644
--- a/docs/data/charts/areas-demo/areas-demo.md
+++ b/docs/data/charts/areas-demo/areas-demo.md
@@ -36,7 +36,7 @@ You can pass this gradient definition as a children of the `` and u
To do so you will need to use the [``](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/linearGradient) and [``](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/stop) SVG elements.
The first part is to get the SVG total height.
-Which can be done with the `useDrawingArea` hook.
+Which can be done with the `useDrawingArea()` hook.
It's useful to define the `` as a vector that goes from the top to the bottom of our SVG container.
Then to define where the gradient should switch from one color to another, you can use the `useYScale` hook to get the y coordinate of value 0.
diff --git a/docs/data/charts/axis/axis.md b/docs/data/charts/axis/axis.md
index e415596c2583..e8edd2836409 100644
--- a/docs/data/charts/axis/axis.md
+++ b/docs/data/charts/axis/axis.md
@@ -56,7 +56,7 @@ Which expects an array of value coherent with the `scaleType`:
Some series types also require specific axis attributes:
- line plots require an `xAxis` to have `data` provided
-- bar plots require an `xAxis` with `scaleType='band'` and some `data` provided.
+- bar plots require an `xAxis` with `scaleType="band"` and some `data` provided.
### Axis formatter
diff --git a/docs/data/charts/bars/bars.md b/docs/data/charts/bars/bars.md
index 11c42dd85e93..606f2895de13 100644
--- a/docs/data/charts/bars/bars.md
+++ b/docs/data/charts/bars/bars.md
@@ -100,7 +100,7 @@ Learn more about the `colorMap` properties in the [Styling docs](/x/react-charts
{{"demo": "ColorScale.js"}}
-### Border Radius
+### Border radius
To give your bar chart rounded corners, you can change the value of the `borderRadius` property on the [BarChart](/x/api/charts/bar-chart/#bar-chart-prop-slots).
@@ -117,7 +117,7 @@ Or you can pass `'value'` to display the raw value of the bar.
{{"demo": "BarLabel.js"}}
-### Custom Labels
+### Custom labels
You can display, change, or hide labels based on conditional logic.
To do so, provide a function to the `barLabel`.
@@ -174,7 +174,7 @@ import ChartsOnAxisClickHandler from '@mui/x-charts/ChartsOnAxisClickHandler';
To skip animation at the creation and update of your chart, you can use the `skipAnimation` prop.
When set to `true` it skips animation powered by `@react-spring/web`.
-Charts containers already use the `useReducedMotion` from `@react-spring/web` to skip animation [according to user preferences](https://react-spring.dev/docs/utilities/use-reduced-motion#why-is-it-important).
+Charts containers already use the `useReducedMotion()` from `@react-spring/web` to skip animation [according to user preferences](https://react-spring.dev/docs/utilities/use-reduced-motion#why-is-it-important).
```jsx
// For a single component chart
diff --git a/docs/data/charts/components/components.md b/docs/data/charts/components/components.md
index 5cfff2f9f6d9..be2f67d72870 100644
--- a/docs/data/charts/components/components.md
+++ b/docs/data/charts/components/components.md
@@ -20,7 +20,7 @@ Charts dimensions are defined by a few props:
The term **drawing area** refers to the space available to plot data (scatter points, lines, or pie arcs).
The `margin` is used to leave some space for extra elements, such as the axes, the legend, or the title.
-You can use the `useDrawingArea` hook in the charts subcomponents to get the coordinates of the **drawing area**.
+You can use the `useDrawingArea()` hook in the charts subcomponents to get the coordinates of the **drawing area**.
```jsx
import { useDrawingArea } from '@mui/x-charts';
diff --git a/docs/data/charts/gauge/gauge.md b/docs/data/charts/gauge/gauge.md
index 30c5df560756..465560c8527d 100644
--- a/docs/data/charts/gauge/gauge.md
+++ b/docs/data/charts/gauge/gauge.md
@@ -101,7 +101,7 @@ import {
### Creating your components
-To create your own components, use the `useGaugeState` hook which provides all you need about the gauge configuration:
+To create your own components, use the `useGaugeState()` hook which provides all you need about the gauge configuration:
- information about the value: `value`, `valueMin`, `valueMax`
- information to plot the arc: `startAngle`, `endAngle`, `outerRadius`, `innerRadius`, `cornerRadius`, `cx`, and `cy`
diff --git a/docs/data/charts/getting-started/getting-started.md b/docs/data/charts/getting-started/getting-started.md
index 6c6057abfc00..83dbff7001c7 100644
--- a/docs/data/charts/getting-started/getting-started.md
+++ b/docs/data/charts/getting-started/getting-started.md
@@ -4,20 +4,20 @@ githubLabel: 'component: charts'
packageName: '@mui/x-charts'
---
-# Charts - Getting Started
+# Charts - Getting started
-
Get started with the MUI X Charts components. Install the package, configure your application, and start using the components.
+
Install the MUI X Charts package to start building React data visualization components.
## Installation
-Using your favorite package manager, install `@mui/x-charts-pro` for the commercial version, or `@mui/x-charts` for the free community version.
+Run one of the following commands to install the free Community version or the paid Pro version of the MUI X Charts:
{{"component": "modules/components/ChartsInstallationInstructions.js"}}
-The Charts package has a peer dependency on `@mui/material`.
-If you are not already using it in your project, you can install it with:
+The Charts packages have a peer dependency on `@mui/material`.
+If you're not already using it, install it with the following command:
@@ -37,7 +37,7 @@ yarn add @mui/material @emotion/react @emotion/styled
-Please note that [react](https://www.npmjs.com/package/react) and [react-dom](https://www.npmjs.com/package/react-dom) are peer dependencies too:
+[`react`](https://www.npmjs.com/package/react) and [`react-dom`](https://www.npmjs.com/package/react-dom) are also peer dependencies:
```json
"peerDependencies": {
@@ -46,85 +46,66 @@ Please note that [react](https://www.npmjs.com/package/react) and [react-dom](ht
},
```
-### Style engine
-
-Material UI is using [Emotion](https://emotion.sh/docs/introduction) as a styling engine by default. If you want to use [`styled-components`](https://styled-components.com/) instead, run:
-
-
-```bash npm
-npm install @mui/styled-engine-sc styled-components
-```
-
-```bash pnpm
-pnpm add @mui/styled-engine-sc styled-components
-```
-
-```bash yarn
-yarn add @mui/styled-engine-sc styled-components
-```
-
-
-
-Take a look at the [Styled engine guide](/material-ui/integrations/styled-components/) for more information about how to configure `styled-components` as the style engine.
-
### Usage with D3
To help folks using CommonJS, the `@mui/x-charts` package uses a vendored package named `@mui/x-charts-vendor` to access D3 libraries.
+You can import D3 functions from `@mui/x-charts-vendor/d3-color`.
-If you need some D3 functions, you can import them with `@mui/x-charts-vendor/d3-color`.
+## Rendering Charts
-## Displaying charts
+MUI X Charts can be rendered as _self-contained_ or _composable_ components.
+[Self-contained components](#self-contained-charts) are simpler to get started with and are recommended for most common use cases; more complex visualization (such as combining Bar and Line Charts on a single plot) requires [custom composition](#composable-charts).
-A Chart can be rendered in one of two ways: as a single component, or by composing subcomponents.
+### Self-contained Charts
-### Single charts
+Self-contained Chart components are imported and rendered as a single React component (such as `` or ``) which contains all of the necessary subcomponents.
-For common use cases, the single component is the recommended way.
-Those components' names end with "Chart", as opposed to "Plot", and only require the series prop describing the data to render.
+These components require a `series` prop describing the data to render, as well as a numerical value (rendered in pixels) for the `height` prop.
+The `width` prop is optional; if no value is provided, the Charts expand to fill the available space.
{{"demo": "SimpleCharts.js"}}
-### Composed charts
+### Composable Charts
-To combine different Charts, like Lines with Bars, you can use composition with the `ChartContainer` wrapper.
+More complex use cases require composition of the necessary subcomponents inside of a Chart Container wrapper.
+Subcomponents include:
-Inside this wrapper, render either axis components, such as `XAxis` and `YAxis`, or any plot component like `BarPlot`, `LinePlot`, `AreaPlot`, and `ScatterPlot`.
+- Axis components – to define the X and Y axes
+- Plot components – to create Bars, Lines, or any other Chart type
+- Auxillary components - to add Tooltips, Highlights, and more
+- Utilities - such as classes and types
-Visit the [Composition page](/x/react-charts/composition/) for more details.
+See the [Charts composition documentation](/x/react-charts/composition/) for complete details.
-{{"demo": "Combining.js"}}
+The demo below shows how to use composition to create a custom Chart that combines a Bar and a Line Chart on a single plot:
-### Positions
+{{"demo": "Combining.js"}}
-Charts are composed of two main areas.
-The SVG defined by its `width` and `height` delimits the available space.
+## Chart layouts
-Within this SVG, a dedicated "drawing area" (aka "plot area") serves as the canvas for data representation.
-Here, elements like lines, bars, and areas visually depict the information.
-It's controlled by the `margin = {top, bottom, left, right}` object defining the margin between the SVG and the drawing area.
+The layout of a Chart is defined by two main spaces: the plot area, and the outer margins.
-The space left by margins can display axes, titles, a legend, or any other additional information.
+The `width` and `height` props define the dimensions of the SVG which is the root of the chart.
+Within this SVG, the plot area (or drawing area) serves as the canvas for data visualization, where the lines, bars or other visual elements are rendered.
+The size of the plot area is determined by the `margin = {top, bottom, left, right}` object which defines its outer margins inside the SVG.
+The outer margin space is where information like axes, titles, and legends are displayed.
-For more information about the position configuration, visit the [styling page](/x/react-charts/styling/#styling).
+See the [Styling documentation](/x/react-charts/styling/#placement) for complete details.
## Axis management
-MUI X Charts have a flexible approach to axis management, supporting multiple-axis charts with any combination of scales and ranges.
-
-Visit the [Axis page](/x/react-charts/axis/) for more details.
-
-## Styling
+MUI X Charts take a flexible approach to axis management, with support for multiple axes and any combination of scales and ranges.
-MUI X Charts follows the Material UI styling and features all of the customization tools you'd find there, making tweaking charts as straightforward as designing buttons.
-
-Visit the [Styling page](/x/react-charts/styling/) for more details.
+See the [Axis documentation](/x/react-charts/axis/) for complete details.
## TypeScript
-In order to benefit from the [CSS overrides](/material-ui/customization/theme-components/#theme-style-overrides) and [default prop customization](/material-ui/customization/theme-components/#theme-default-props) with the theme, TypeScript users need to import the following types.
-Internally, it uses module augmentation to extend the default theme structure.
+To benefit from [CSS overrides](/material-ui/customization/theme-components/#theme-style-overrides) and [default prop customization](/material-ui/customization/theme-components/#theme-default-props) with the theme, TypeScript users must import the following types.
+These types use module augmentation to extend the default theme structure.
```tsx
+// only one import is necessary,
+// from the version you're currently using.
import type {} from '@mui/x-charts/themeAugmentation';
import type {} from '@mui/x-charts-pro/themeAugmentation';
@@ -140,8 +121,3 @@ const theme = createTheme({
},
});
```
-
-:::info
-You don't have to import the theme augmentation from both `@mui/x-charts` and `@mui/x-charts-pro` when using `@mui/x-charts-pro`.
-Importing it from `@mui/x-charts-pro` is enough.
-:::
diff --git a/docs/data/charts/lines/lines.md b/docs/data/charts/lines/lines.md
index be651d4dd57a..de9a55dfb928 100644
--- a/docs/data/charts/lines/lines.md
+++ b/docs/data/charts/lines/lines.md
@@ -235,7 +235,7 @@ sx={{
To skip animation at the creation and update of your chart, you can use the `skipAnimation` prop.
When set to `true` it skips animation powered by `@react-spring/web`.
-Charts containers already use the `useReducedMotion` from `@react-spring/web` to skip animation [according to user preferences](https://react-spring.dev/docs/utilities/use-reduced-motion#why-is-it-important).
+Charts containers already use the `useReducedMotion()` from `@react-spring/web` to skip animation [according to user preferences](https://react-spring.dev/docs/utilities/use-reduced-motion#why-is-it-important).
:::warning
If you support interactive ways to add or remove series from your chart, you have to provide the series' id.
diff --git a/docs/data/charts/overview/overview.md b/docs/data/charts/overview/overview.md
index ef86f4a0793f..92f1d289714d 100644
--- a/docs/data/charts/overview/overview.md
+++ b/docs/data/charts/overview/overview.md
@@ -7,34 +7,33 @@ packageName: '@mui/x-charts'
# MUI X Charts
-
A fast and extendable library of react chart components for data visualization.
+
A collection of React chart components for data visualization.
{{"component": "@mui/docs/ComponentLinkHeader", "design": false}}
## Overview
-The `@mui/x-charts` is an MIT library for rendering charts relying on [D3.js](https://d3js.org/) for data manipulation and SVG for rendering.
-And, like other MUI X components, charts are production-ready components that integrate smoothly into your app.
+MUI X Charts is a library of production-ready components for rendering charts with React.
+It uses [D3.js](https://d3js.org/) for data manipulation and SVGs for rendering.
-With a high level of customization, MUI X Charts provides three levels of customization layers: **single components** with great defaults, extensive **configuration props**, and **subcomponents** for flexible composition.
-Additionally, you can also use all the [MUI System](https://mui.com/system/getting-started/) tools, such as the theme override or the `sx` prop.
+The components provide a high level of customization, with beautiful defaults as well as extensive configuration props and flexible composition options.
+They also have access to all [MUI System](https://mui.com/system/getting-started/) tools such as theme overrides and the `sx` prop.
{{"demo": "ChartsOverviewDemo.js", "defaultCodeOpen": true}}
-## Using the documentation
+## All MUI X Charts
-The MUI X Charts documentation has a slightly different structure than other MUI X components.
-Instead of having a long page for each, the pages are divided in two:
+{{"component": "modules/components/ChartComponentsGrid.js"}}
-1. General description of the built-in features the component provides.
-2. A set of examples demonstrating the component with customizations.
+## Using this documentation
-## All MUI X Charts components
+Each Chart type has two accompanying documents:
-{{"component": "modules/components/ChartComponentsGrid.js"}}
+1. **Overview** – a general description of built-in features
+2. **Demo** – a collection of custom examples
## Supported features
-The features that are shared across multiple Charts components, such as axes and legends, are also documented on separate pages.
+Features shared across Chart components such as axes and legends are described in standalone documents:
{{"component": "modules/components/ChartFeaturesGrid.js"}}
diff --git a/docs/data/charts/pie/pie.md b/docs/data/charts/pie/pie.md
index 047a4cc576e2..eda5601ffc78 100644
--- a/docs/data/charts/pie/pie.md
+++ b/docs/data/charts/pie/pie.md
@@ -110,7 +110,7 @@ const onItemClick = (
To skip animation at the creation and update of your chart you can use the `skipAnimation` prop.
When set to `true` it skips animation powered by `@react-spring/web`.
-Charts containers already use the `useReducedMotion` from `@react-spring/web` to skip animation [according to user preferences](https://react-spring.dev/docs/utilities/use-reduced-motion#why-is-it-important).
+Charts containers already use the `useReducedMotion()` from `@react-spring/web` to skip animation [according to user preferences](https://react-spring.dev/docs/utilities/use-reduced-motion#why-is-it-important).
```jsx
// For a single component chart
diff --git a/docs/data/charts/tooltip/CustomAxisTooltip.js b/docs/data/charts/tooltip/CustomAxisTooltip.js
index bb893b9e83b1..c8b63c7f6cec 100644
--- a/docs/data/charts/tooltip/CustomAxisTooltip.js
+++ b/docs/data/charts/tooltip/CustomAxisTooltip.js
@@ -3,22 +3,80 @@ import NoSsr from '@mui/material/NoSsr';
import Popper from '@mui/material/Popper';
import Paper from '@mui/material/Paper';
import Typography from '@mui/material/Typography';
-import { useAxisTooltip, useMouseTracker } from '@mui/x-charts/ChartsTooltip';
+import { useAxisTooltip } from '@mui/x-charts/ChartsTooltip';
+import { useSvgRef } from '@mui/x-charts/hooks';
import { generateVirtualElement } from './generateVirtualElement';
+function usePointer() {
+ const svgRef = useSvgRef();
+ const popperRef = React.useRef(null);
+ const virtualElement = React.useRef(generateVirtualElement({ x: 0, y: 0 }));
+
+ // Use a ref to avoid rerendering on every mousemove event.
+ const [pointer, setPointer] = React.useState({
+ isActive: false,
+ isMousePointer: false,
+ pointerHeight: 0,
+ });
+
+ React.useEffect(() => {
+ const element = svgRef.current;
+ if (element === null) {
+ return () => {};
+ }
+
+ const handleOut = (event) => {
+ if (event.pointerType !== 'mouse') {
+ setPointer((prev) => ({
+ ...prev,
+ isActive: false,
+ }));
+ }
+ };
+
+ const handleEnter = (event) => {
+ setPointer({
+ isActive: true,
+ isMousePointer: event.pointerType === 'mouse',
+ pointerHeight: event.height,
+ });
+ };
+
+ const handleMove = (event) => {
+ virtualElement.current = generateVirtualElement({
+ x: event.clientX,
+ y: event.clientY,
+ });
+ popperRef.current?.update();
+ };
+
+ element.addEventListener('pointerenter', handleEnter);
+ element.addEventListener('pointerup', handleOut);
+ element.addEventListener('pointermove', handleMove);
+
+ return () => {
+ element.removeEventListener('pointerenter', handleEnter);
+ element.removeEventListener('pointerup', handleOut);
+ element.removeEventListener('pointermove', handleMove);
+ };
+ }, [svgRef]);
+
+ return { ...pointer, popperRef, anchorEl: virtualElement.current };
+}
+
export function CustomAxisTooltip() {
const tooltipData = useAxisTooltip();
- const mousePosition = useMouseTracker(); // Track the mouse position on chart.
+ const { isActive, isMousePointer, pointerHeight, popperRef, anchorEl } =
+ usePointer();
- if (!tooltipData || !mousePosition) {
+ if (!tooltipData || !isActive) {
// No data to display
return null;
}
// The pointer type can be used to have different behavior based on pointer type.
- const isMousePointer = mousePosition?.pointerType === 'mouse';
// Adapt the tooltip offset to the size of the pointer.
- const yOffset = isMousePointer ? 0 : 40 - mousePosition.height;
+ const yOffset = isMousePointer ? 0 : 40 - pointerHeight;
return (
@@ -29,7 +87,8 @@ export function CustomAxisTooltip() {
}}
open
placement={isMousePointer ? 'top-end' : 'top'}
- anchorEl={generateVirtualElement(mousePosition)}
+ anchorEl={anchorEl}
+ popperRef={popperRef}
modifiers={[
{
name: 'offset',
@@ -81,7 +140,7 @@ export function CustomAxisTooltip() {
{tooltipData.seriesItems.map((seriesItem) => (
-
+
{
+ const svgRef = useSvgRef();
+ const popperRef: PopperProps['popperRef'] = React.useRef(null);
+ const virtualElement = React.useRef(generateVirtualElement({ x: 0, y: 0 }));
+
+ // Use a ref to avoid rerendering on every mousemove event.
+ const [pointer, setPointer] = React.useState({
+ isActive: false,
+ isMousePointer: false,
+ pointerHeight: 0,
+ });
+
+ React.useEffect(() => {
+ const element = svgRef.current;
+ if (element === null) {
+ return () => {};
+ }
+
+ const handleOut = (event: PointerEvent) => {
+ if (event.pointerType !== 'mouse') {
+ setPointer((prev) => ({
+ ...prev,
+ isActive: false,
+ }));
+ }
+ };
+
+ const handleEnter = (event: PointerEvent) => {
+ setPointer({
+ isActive: true,
+ isMousePointer: event.pointerType === 'mouse',
+ pointerHeight: event.height,
+ });
+ };
+
+ const handleMove = (event: PointerEvent) => {
+ virtualElement.current = generateVirtualElement({
+ x: event.clientX,
+ y: event.clientY,
+ });
+ popperRef.current?.update();
+ };
+
+ element.addEventListener('pointerenter', handleEnter);
+ element.addEventListener('pointerup', handleOut);
+ element.addEventListener('pointermove', handleMove);
+
+ return () => {
+ element.removeEventListener('pointerenter', handleEnter);
+ element.removeEventListener('pointerup', handleOut);
+ element.removeEventListener('pointermove', handleMove);
+ };
+ }, [svgRef]);
+
+ return { ...pointer, popperRef, anchorEl: virtualElement.current };
+}
+
export function CustomAxisTooltip() {
const tooltipData = useAxisTooltip();
- const mousePosition = useMouseTracker(); // Track the mouse position on chart.
+ const { isActive, isMousePointer, pointerHeight, popperRef, anchorEl } =
+ usePointer();
- if (!tooltipData || !mousePosition) {
+ if (!tooltipData || !isActive) {
// No data to display
return null;
}
// The pointer type can be used to have different behavior based on pointer type.
- const isMousePointer = mousePosition?.pointerType === 'mouse';
// Adapt the tooltip offset to the size of the pointer.
- const yOffset = isMousePointer ? 0 : 40 - mousePosition.height;
+ const yOffset = isMousePointer ? 0 : 40 - pointerHeight;
return (
@@ -29,7 +93,8 @@ export function CustomAxisTooltip() {
}}
open
placement={isMousePointer ? 'top-end' : 'top'}
- anchorEl={generateVirtualElement(mousePosition)}
+ anchorEl={anchorEl}
+ popperRef={popperRef}
modifiers={[
{
name: 'offset',
@@ -81,7 +146,7 @@ export function CustomAxisTooltip() {
{tooltipData.seriesItems.map((seriesItem) => (
-
+
{
+ const element = svgRef.current;
+ if (element === null) {
+ return () => {};
+ }
+
+ const handleOut = (event) => {
+ if (event.pointerType !== 'mouse') {
+ setPointer((prev) => ({
+ ...prev,
+ isActive: false,
+ }));
+ }
+ };
+
+ const handleEnter = (event) => {
+ setPointer({
+ isActive: true,
+ isMousePointer: event.pointerType === 'mouse',
+ pointerHeight: event.height,
+ });
+ };
+
+ const handleMove = (event) => {
+ virtualElement.current = generateVirtualElement({
+ x: event.clientX,
+ y: event.clientY,
+ });
+ popperRef.current?.update();
+ };
+
+ element.addEventListener('pointerenter', handleEnter);
+ element.addEventListener('pointerup', handleOut);
+ element.addEventListener('pointermove', handleMove);
+
+ return () => {
+ element.removeEventListener('pointerenter', handleEnter);
+ element.removeEventListener('pointerup', handleOut);
+ element.removeEventListener('pointermove', handleMove);
+ };
+ }, [svgRef]);
+
+ return { ...pointer, popperRef, anchorEl: virtualElement.current };
+}
+
export function CustomItemTooltip() {
const tooltipData = useItemTooltip();
- const mousePosition = useMouseTracker(); // Track the mouse position on chart.
+ const { isActive, isMousePointer, pointerHeight, popperRef, anchorEl } =
+ usePointer();
- if (!tooltipData || !mousePosition) {
+ if (!tooltipData || !isActive) {
// No data to display
return null;
}
- // The pointer type can be used to have different behavior based on pointer type.
- const isMousePointer = mousePosition?.pointerType === 'mouse';
// Adapt the tooltip offset to the size of the pointer.
- const yOffset = isMousePointer ? 0 : 40 - mousePosition.height;
+ const yOffset = isMousePointer ? 0 : 40 - pointerHeight;
return (
@@ -30,7 +87,8 @@ export function CustomItemTooltip() {
}}
open
placement={isMousePointer ? 'top-end' : 'top'}
- anchorEl={generateVirtualElement(mousePosition)}
+ anchorEl={anchorEl}
+ popperRef={popperRef}
modifiers={[
{
name: 'offset',
diff --git a/docs/data/charts/tooltip/CustomItemTooltip.tsx b/docs/data/charts/tooltip/CustomItemTooltip.tsx
index fcaf28469db1..926b4fd3179d 100644
--- a/docs/data/charts/tooltip/CustomItemTooltip.tsx
+++ b/docs/data/charts/tooltip/CustomItemTooltip.tsx
@@ -1,25 +1,88 @@
import * as React from 'react';
import NoSsr from '@mui/material/NoSsr';
-import Popper from '@mui/material/Popper';
+import Popper, { PopperProps } from '@mui/material/Popper';
import Paper from '@mui/material/Paper';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
-import { useItemTooltip, useMouseTracker } from '@mui/x-charts/ChartsTooltip';
+import { useItemTooltip } from '@mui/x-charts/ChartsTooltip';
+import { useSvgRef } from '@mui/x-charts/hooks';
import { generateVirtualElement } from './generateVirtualElement';
+type PointerState = {
+ isActive: boolean;
+ isMousePointer: boolean;
+ pointerHeight: number;
+};
+
+function usePointer(): PointerState & Pick {
+ const svgRef = useSvgRef();
+ const popperRef: PopperProps['popperRef'] = React.useRef(null);
+ const virtualElement = React.useRef(generateVirtualElement({ x: 0, y: 0 }));
+
+ // Use a ref to avoid rerendering on every mousemove event.
+ const [pointer, setPointer] = React.useState({
+ isActive: false,
+ isMousePointer: false,
+ pointerHeight: 0,
+ });
+
+ React.useEffect(() => {
+ const element = svgRef.current;
+ if (element === null) {
+ return () => {};
+ }
+
+ const handleOut = (event: PointerEvent) => {
+ if (event.pointerType !== 'mouse') {
+ setPointer((prev) => ({
+ ...prev,
+ isActive: false,
+ }));
+ }
+ };
+
+ const handleEnter = (event: PointerEvent) => {
+ setPointer({
+ isActive: true,
+ isMousePointer: event.pointerType === 'mouse',
+ pointerHeight: event.height,
+ });
+ };
+
+ const handleMove = (event: PointerEvent) => {
+ virtualElement.current = generateVirtualElement({
+ x: event.clientX,
+ y: event.clientY,
+ });
+ popperRef.current?.update();
+ };
+
+ element.addEventListener('pointerenter', handleEnter);
+ element.addEventListener('pointerup', handleOut);
+ element.addEventListener('pointermove', handleMove);
+
+ return () => {
+ element.removeEventListener('pointerenter', handleEnter);
+ element.removeEventListener('pointerup', handleOut);
+ element.removeEventListener('pointermove', handleMove);
+ };
+ }, [svgRef]);
+
+ return { ...pointer, popperRef, anchorEl: virtualElement.current };
+}
+
export function CustomItemTooltip() {
const tooltipData = useItemTooltip();
- const mousePosition = useMouseTracker(); // Track the mouse position on chart.
+ const { isActive, isMousePointer, pointerHeight, popperRef, anchorEl } =
+ usePointer();
- if (!tooltipData || !mousePosition) {
+ if (!tooltipData || !isActive) {
// No data to display
return null;
}
- // The pointer type can be used to have different behavior based on pointer type.
- const isMousePointer = mousePosition?.pointerType === 'mouse';
// Adapt the tooltip offset to the size of the pointer.
- const yOffset = isMousePointer ? 0 : 40 - mousePosition.height;
+ const yOffset = isMousePointer ? 0 : 40 - pointerHeight;
return (
@@ -30,7 +93,8 @@ export function CustomItemTooltip() {
}}
open
placement={isMousePointer ? 'top-end' : 'top'}
- anchorEl={generateVirtualElement(mousePosition)}
+ anchorEl={anchorEl}
+ popperRef={popperRef}
modifiers={[
{
name: 'offset',
diff --git a/docs/data/charts/tooltip/ItemTooltip.js b/docs/data/charts/tooltip/ItemTooltip.js
index 68fbab1d77ae..cb2a90370e5e 100644
--- a/docs/data/charts/tooltip/ItemTooltip.js
+++ b/docs/data/charts/tooltip/ItemTooltip.js
@@ -1,23 +1,80 @@
import * as React from 'react';
import NoSsr from '@mui/material/NoSsr';
import Popper from '@mui/material/Popper';
-import { useItemTooltip, useMouseTracker } from '@mui/x-charts/ChartsTooltip';
+import { useItemTooltip } from '@mui/x-charts/ChartsTooltip';
+import { useSvgRef } from '@mui/x-charts/hooks';
import { CustomItemTooltipContent } from './CustomItemTooltipContent';
import { generateVirtualElement } from './generateVirtualElement';
+function usePointer() {
+ const svgRef = useSvgRef();
+ const popperRef = React.useRef(null);
+ const virtualElement = React.useRef(generateVirtualElement({ x: 0, y: 0 }));
+
+ // Use a ref to avoid rerendering on every mousemove event.
+ const [pointer, setPointer] = React.useState({
+ isActive: false,
+ isMousePointer: false,
+ pointerHeight: 0,
+ });
+
+ React.useEffect(() => {
+ const element = svgRef.current;
+ if (element === null) {
+ return () => {};
+ }
+
+ const handleOut = (event) => {
+ if (event.pointerType !== 'mouse') {
+ setPointer((prev) => ({
+ ...prev,
+ isActive: false,
+ }));
+ }
+ };
+
+ const handleEnter = (event) => {
+ setPointer({
+ isActive: true,
+ isMousePointer: event.pointerType === 'mouse',
+ pointerHeight: event.height,
+ });
+ };
+
+ const handleMove = (event) => {
+ virtualElement.current = generateVirtualElement({
+ x: event.clientX,
+ y: event.clientY,
+ });
+ popperRef.current?.update();
+ };
+
+ element.addEventListener('pointerenter', handleEnter);
+ element.addEventListener('pointerup', handleOut);
+ element.addEventListener('pointermove', handleMove);
+
+ return () => {
+ element.removeEventListener('pointerenter', handleEnter);
+ element.removeEventListener('pointerup', handleOut);
+ element.removeEventListener('pointermove', handleMove);
+ };
+ }, [svgRef]);
+
+ return { ...pointer, popperRef, anchorEl: virtualElement.current };
+}
+
export function ItemTooltip() {
const tooltipData = useItemTooltip();
- const mousePosition = useMouseTracker(); // Track the mouse position on chart.
+ const { isActive, isMousePointer, pointerHeight, popperRef, anchorEl } =
+ usePointer();
- if (!tooltipData || !mousePosition) {
+ if (!tooltipData || !isActive) {
// No data to display
return null;
}
- // The pointer type can be used to have different behavior based on pointer type.
- const isMousePointer = mousePosition?.pointerType === 'mouse';
// Adapt the tooltip offset to the size of the pointer.
- const yOffset = isMousePointer ? 0 : 40 - mousePosition.height;
+ const yOffset = isMousePointer ? 0 : 40 - pointerHeight;
return (
@@ -28,7 +85,8 @@ export function ItemTooltip() {
}}
open
placement={isMousePointer ? 'top-end' : 'top'}
- anchorEl={generateVirtualElement(mousePosition)}
+ anchorEl={anchorEl}
+ popperRef={popperRef}
modifiers={[
{
name: 'offset',
diff --git a/docs/data/charts/tooltip/ItemTooltip.tsx b/docs/data/charts/tooltip/ItemTooltip.tsx
index 68fbab1d77ae..5069ad32df3d 100644
--- a/docs/data/charts/tooltip/ItemTooltip.tsx
+++ b/docs/data/charts/tooltip/ItemTooltip.tsx
@@ -1,23 +1,86 @@
import * as React from 'react';
import NoSsr from '@mui/material/NoSsr';
-import Popper from '@mui/material/Popper';
-import { useItemTooltip, useMouseTracker } from '@mui/x-charts/ChartsTooltip';
+import Popper, { PopperProps } from '@mui/material/Popper';
+import { useItemTooltip } from '@mui/x-charts/ChartsTooltip';
+import { useSvgRef } from '@mui/x-charts/hooks';
import { CustomItemTooltipContent } from './CustomItemTooltipContent';
import { generateVirtualElement } from './generateVirtualElement';
+type PointerState = {
+ isActive: boolean;
+ isMousePointer: boolean;
+ pointerHeight: number;
+};
+
+function usePointer(): PointerState & Pick {
+ const svgRef = useSvgRef();
+ const popperRef: PopperProps['popperRef'] = React.useRef(null);
+ const virtualElement = React.useRef(generateVirtualElement({ x: 0, y: 0 }));
+
+ // Use a ref to avoid rerendering on every mousemove event.
+ const [pointer, setPointer] = React.useState({
+ isActive: false,
+ isMousePointer: false,
+ pointerHeight: 0,
+ });
+
+ React.useEffect(() => {
+ const element = svgRef.current;
+ if (element === null) {
+ return () => {};
+ }
+
+ const handleOut = (event: PointerEvent) => {
+ if (event.pointerType !== 'mouse') {
+ setPointer((prev) => ({
+ ...prev,
+ isActive: false,
+ }));
+ }
+ };
+
+ const handleEnter = (event: PointerEvent) => {
+ setPointer({
+ isActive: true,
+ isMousePointer: event.pointerType === 'mouse',
+ pointerHeight: event.height,
+ });
+ };
+
+ const handleMove = (event: PointerEvent) => {
+ virtualElement.current = generateVirtualElement({
+ x: event.clientX,
+ y: event.clientY,
+ });
+ popperRef.current?.update();
+ };
+
+ element.addEventListener('pointerenter', handleEnter);
+ element.addEventListener('pointerup', handleOut);
+ element.addEventListener('pointermove', handleMove);
+
+ return () => {
+ element.removeEventListener('pointerenter', handleEnter);
+ element.removeEventListener('pointerup', handleOut);
+ element.removeEventListener('pointermove', handleMove);
+ };
+ }, [svgRef]);
+
+ return { ...pointer, popperRef, anchorEl: virtualElement.current };
+}
+
export function ItemTooltip() {
const tooltipData = useItemTooltip();
- const mousePosition = useMouseTracker(); // Track the mouse position on chart.
+ const { isActive, isMousePointer, pointerHeight, popperRef, anchorEl } =
+ usePointer();
- if (!tooltipData || !mousePosition) {
+ if (!tooltipData || !isActive) {
// No data to display
return null;
}
- // The pointer type can be used to have different behavior based on pointer type.
- const isMousePointer = mousePosition?.pointerType === 'mouse';
// Adapt the tooltip offset to the size of the pointer.
- const yOffset = isMousePointer ? 0 : 40 - mousePosition.height;
+ const yOffset = isMousePointer ? 0 : 40 - pointerHeight;
return (
@@ -28,7 +91,8 @@ export function ItemTooltip() {
}}
open
placement={isMousePointer ? 'top-end' : 'top'}
- anchorEl={generateVirtualElement(mousePosition)}
+ anchorEl={anchorEl}
+ popperRef={popperRef}
modifiers={[
{
name: 'offset',
diff --git a/docs/data/charts/tooltip/ItemTooltipFixedY.js b/docs/data/charts/tooltip/ItemTooltipFixedY.js
index 4e19cd1bc9f6..11bfb8fe8668 100644
--- a/docs/data/charts/tooltip/ItemTooltipFixedY.js
+++ b/docs/data/charts/tooltip/ItemTooltipFixedY.js
@@ -1,28 +1,92 @@
import * as React from 'react';
import NoSsr from '@mui/material/NoSsr';
import Popper from '@mui/material/Popper';
-import { useItemTooltip, useMouseTracker } from '@mui/x-charts/ChartsTooltip';
+import { useItemTooltip } from '@mui/x-charts/ChartsTooltip';
import { useDrawingArea, useSvgRef } from '@mui/x-charts/hooks';
import { CustomItemTooltipContent } from './CustomItemTooltipContent';
import { generateVirtualElement } from './generateVirtualElement';
+function usePointer() {
+ const svgRef = useSvgRef();
+
+ // Use a ref to avoid rerendering on every mousemove event.
+ const [pointer, setPointer] = React.useState({
+ isActive: false,
+ isMousePointer: false,
+ pointerHeight: 0,
+ });
+
+ React.useEffect(() => {
+ const element = svgRef.current;
+ if (element === null) {
+ return () => {};
+ }
+
+ const handleOut = (event) => {
+ if (event.pointerType !== 'mouse') {
+ setPointer((prev) => ({
+ ...prev,
+ isActive: false,
+ }));
+ }
+ };
+
+ const handleEnter = (event) => {
+ setPointer({
+ isActive: true,
+ isMousePointer: event.pointerType === 'mouse',
+ pointerHeight: event.height,
+ });
+ };
+
+ element.addEventListener('pointerenter', handleEnter);
+ element.addEventListener('pointerup', handleOut);
+
+ return () => {
+ element.removeEventListener('pointerenter', handleEnter);
+ element.removeEventListener('pointerup', handleOut);
+ };
+ }, [svgRef]);
+
+ return pointer;
+}
+
export function ItemTooltipFixedY() {
const tooltipData = useItemTooltip();
- const mousePosition = useMouseTracker();
+ const { isActive } = usePointer();
+
+ const popperRef = React.useRef(null);
+ const virtualElement = React.useRef(generateVirtualElement({ x: 0, y: 0 }));
const svgRef = useSvgRef(); // Get the ref of the component.
const drawingArea = useDrawingArea(); // Get the dimensions of the chart inside the .
- if (!tooltipData || !mousePosition) {
+ React.useEffect(() => {
+ const element = svgRef.current;
+ if (element === null) {
+ return () => {};
+ }
+
+ const handleMove = (event) => {
+ virtualElement.current = generateVirtualElement({
+ x: event.clientX,
+ // Add the y-coordinate of the to the to margin between the and the drawing area
+ y: svgRef.current.getBoundingClientRect().top + drawingArea.top,
+ });
+ popperRef.current?.update();
+ };
+
+ element.addEventListener('pointermove', handleMove);
+
+ return () => {
+ element.removeEventListener('pointermove', handleMove);
+ };
+ }, [svgRef, drawingArea.top]);
+
+ if (!tooltipData || !isActive) {
// No data to display
return null;
}
- const tooltipPosition = {
- ...mousePosition,
- // Add the y-coordinate of the to the to margin between the and the drawing area
- y: svgRef.current.getBoundingClientRect().top + drawingArea.top,
- };
-
return (
diff --git a/docs/data/charts/tooltip/ItemTooltipFixedY.tsx b/docs/data/charts/tooltip/ItemTooltipFixedY.tsx
index 3059c260afca..b6feefe896f4 100644
--- a/docs/data/charts/tooltip/ItemTooltipFixedY.tsx
+++ b/docs/data/charts/tooltip/ItemTooltipFixedY.tsx
@@ -1,28 +1,98 @@
import * as React from 'react';
import NoSsr from '@mui/material/NoSsr';
-import Popper from '@mui/material/Popper';
-import { useItemTooltip, useMouseTracker } from '@mui/x-charts/ChartsTooltip';
+import Popper, { PopperProps } from '@mui/material/Popper';
+import { useItemTooltip } from '@mui/x-charts/ChartsTooltip';
import { useDrawingArea, useSvgRef } from '@mui/x-charts/hooks';
import { CustomItemTooltipContent } from './CustomItemTooltipContent';
-import { generateVirtualElement, MousePosition } from './generateVirtualElement';
+import { generateVirtualElement } from './generateVirtualElement';
+
+type PointerState = {
+ isActive: boolean;
+ isMousePointer: boolean;
+ pointerHeight: number;
+};
+
+function usePointer(): PointerState {
+ const svgRef = useSvgRef();
+
+ // Use a ref to avoid rerendering on every mousemove event.
+ const [pointer, setPointer] = React.useState({
+ isActive: false,
+ isMousePointer: false,
+ pointerHeight: 0,
+ });
+
+ React.useEffect(() => {
+ const element = svgRef.current;
+ if (element === null) {
+ return () => {};
+ }
+
+ const handleOut = (event: PointerEvent) => {
+ if (event.pointerType !== 'mouse') {
+ setPointer((prev) => ({
+ ...prev,
+ isActive: false,
+ }));
+ }
+ };
+
+ const handleEnter = (event: PointerEvent) => {
+ setPointer({
+ isActive: true,
+ isMousePointer: event.pointerType === 'mouse',
+ pointerHeight: event.height,
+ });
+ };
+
+ element.addEventListener('pointerenter', handleEnter);
+ element.addEventListener('pointerup', handleOut);
+
+ return () => {
+ element.removeEventListener('pointerenter', handleEnter);
+ element.removeEventListener('pointerup', handleOut);
+ };
+ }, [svgRef]);
+
+ return pointer;
+}
export function ItemTooltipFixedY() {
const tooltipData = useItemTooltip();
- const mousePosition = useMouseTracker();
+ const { isActive } = usePointer();
+
+ const popperRef: PopperProps['popperRef'] = React.useRef(null);
+ const virtualElement = React.useRef(generateVirtualElement({ x: 0, y: 0 }));
const svgRef = useSvgRef(); // Get the ref of the component.
const drawingArea = useDrawingArea(); // Get the dimensions of the chart inside the .
- if (!tooltipData || !mousePosition) {
+ React.useEffect(() => {
+ const element = svgRef.current;
+ if (element === null) {
+ return () => {};
+ }
+
+ const handleMove = (event: PointerEvent) => {
+ virtualElement.current = generateVirtualElement({
+ x: event.clientX,
+ // Add the y-coordinate of the to the to margin between the and the drawing area
+ y: svgRef.current.getBoundingClientRect().top + drawingArea.top,
+ });
+ popperRef.current?.update();
+ };
+
+ element.addEventListener('pointermove', handleMove);
+
+ return () => {
+ element.removeEventListener('pointermove', handleMove);
+ };
+ }, [svgRef, drawingArea.top]);
+
+ if (!tooltipData || !isActive) {
// No data to display
return null;
}
- const tooltipPosition: MousePosition = {
- ...mousePosition,
- // Add the y-coordinate of the to the to margin between the and the drawing area
- y: svgRef.current.getBoundingClientRect().top + drawingArea.top,
- };
-
return (
diff --git a/docs/data/charts/tooltip/ItemTooltipTopElement.js b/docs/data/charts/tooltip/ItemTooltipTopElement.js
index 7d86e69b81e4..a3b52483984e 100644
--- a/docs/data/charts/tooltip/ItemTooltipTopElement.js
+++ b/docs/data/charts/tooltip/ItemTooltipTopElement.js
@@ -2,14 +2,59 @@ import * as React from 'react';
import NoSsr from '@mui/material/NoSsr';
import Popper from '@mui/material/Popper';
-import { useItemTooltip, useMouseTracker } from '@mui/x-charts/ChartsTooltip';
+import { useItemTooltip } from '@mui/x-charts/ChartsTooltip';
import { useSvgRef, useXAxis, useXScale, useYScale } from '@mui/x-charts/hooks';
import { CustomItemTooltipContent } from './CustomItemTooltipContent';
import { generateVirtualElement } from './generateVirtualElement';
+function usePointer() {
+ const svgRef = useSvgRef();
+
+ // Use a ref to avoid rerendering on every mousemove event.
+ const [pointer, setPointer] = React.useState({
+ isActive: false,
+ isMousePointer: false,
+ pointerHeight: 0,
+ });
+
+ React.useEffect(() => {
+ const element = svgRef.current;
+ if (element === null) {
+ return () => {};
+ }
+
+ const handleOut = (event) => {
+ if (event.pointerType !== 'mouse') {
+ setPointer((prev) => ({
+ ...prev,
+ isActive: false,
+ }));
+ }
+ };
+
+ const handleEnter = (event) => {
+ setPointer({
+ isActive: true,
+ isMousePointer: event.pointerType === 'mouse',
+ pointerHeight: event.height,
+ });
+ };
+
+ element.addEventListener('pointerenter', handleEnter);
+ element.addEventListener('pointerup', handleOut);
+
+ return () => {
+ element.removeEventListener('pointerenter', handleEnter);
+ element.removeEventListener('pointerup', handleOut);
+ };
+ }, [svgRef]);
+
+ return pointer;
+}
+
export function ItemTooltipTopElement() {
const tooltipData = useItemTooltip();
- const mousePosition = useMouseTracker();
+ const { isActive } = usePointer();
// Get xAxis config to access its data array.
const xAxis = useXAxis();
// Get the scale which map values to SVG coordinates.
@@ -21,7 +66,7 @@ export function ItemTooltipTopElement() {
// Get the ref of the component.
const svgRef = useSvgRef();
- if (!tooltipData || !mousePosition || !xAxis.data) {
+ if (!tooltipData || !isActive || !xAxis.data) {
// No data to display
return null;
}
@@ -41,7 +86,6 @@ export function ItemTooltipTopElement() {
const svgXPosition = xScale(xValue) ?? 0;
const tooltipPosition = {
- ...mousePosition,
// Add half of `yScale.step()` to be in the middle of the band.
x:
svgRef.current.getBoundingClientRect().left + svgXPosition + xScale.step() / 2,
diff --git a/docs/data/charts/tooltip/ItemTooltipTopElement.tsx b/docs/data/charts/tooltip/ItemTooltipTopElement.tsx
index d69ab33e96da..a84a45cdc39b 100644
--- a/docs/data/charts/tooltip/ItemTooltipTopElement.tsx
+++ b/docs/data/charts/tooltip/ItemTooltipTopElement.tsx
@@ -2,14 +2,65 @@ import * as React from 'react';
import { ScaleBand } from '@mui/x-charts-vendor/d3-scale';
import NoSsr from '@mui/material/NoSsr';
import Popper from '@mui/material/Popper';
-import { useItemTooltip, useMouseTracker } from '@mui/x-charts/ChartsTooltip';
+import { useItemTooltip } from '@mui/x-charts/ChartsTooltip';
import { useSvgRef, useXAxis, useXScale, useYScale } from '@mui/x-charts/hooks';
import { CustomItemTooltipContent } from './CustomItemTooltipContent';
-import { generateVirtualElement, MousePosition } from './generateVirtualElement';
+import { generateVirtualElement } from './generateVirtualElement';
+
+type PointerState = {
+ isActive: boolean;
+ isMousePointer: boolean;
+ pointerHeight: number;
+};
+
+function usePointer(): PointerState {
+ const svgRef = useSvgRef();
+
+ // Use a ref to avoid rerendering on every mousemove event.
+ const [pointer, setPointer] = React.useState({
+ isActive: false,
+ isMousePointer: false,
+ pointerHeight: 0,
+ });
+
+ React.useEffect(() => {
+ const element = svgRef.current;
+ if (element === null) {
+ return () => {};
+ }
+
+ const handleOut = (event: PointerEvent) => {
+ if (event.pointerType !== 'mouse') {
+ setPointer((prev) => ({
+ ...prev,
+ isActive: false,
+ }));
+ }
+ };
+
+ const handleEnter = (event: PointerEvent) => {
+ setPointer({
+ isActive: true,
+ isMousePointer: event.pointerType === 'mouse',
+ pointerHeight: event.height,
+ });
+ };
+
+ element.addEventListener('pointerenter', handleEnter);
+ element.addEventListener('pointerup', handleOut);
+
+ return () => {
+ element.removeEventListener('pointerenter', handleEnter);
+ element.removeEventListener('pointerup', handleOut);
+ };
+ }, [svgRef]);
+
+ return pointer;
+}
export function ItemTooltipTopElement() {
const tooltipData = useItemTooltip<'bar'>();
- const mousePosition = useMouseTracker();
+ const { isActive } = usePointer();
// Get xAxis config to access its data array.
const xAxis = useXAxis();
// Get the scale which map values to SVG coordinates.
@@ -21,7 +72,7 @@ export function ItemTooltipTopElement() {
// Get the ref of the component.
const svgRef = useSvgRef();
- if (!tooltipData || !mousePosition || !xAxis.data) {
+ if (!tooltipData || !isActive || !xAxis.data) {
// No data to display
return null;
}
@@ -40,8 +91,7 @@ export function ItemTooltipTopElement() {
const svgYPosition = yScale(tooltipData.value) ?? 0;
const svgXPosition = xScale(xValue) ?? 0;
- const tooltipPosition: MousePosition = {
- ...mousePosition,
+ const tooltipPosition = {
// Add half of `yScale.step()` to be in the middle of the band.
x:
svgRef.current.getBoundingClientRect().left +
diff --git a/docs/data/charts/tooltip/tooltip.md b/docs/data/charts/tooltip/tooltip.md
index 655886065223..f53171fca6e5 100644
--- a/docs/data/charts/tooltip/tooltip.md
+++ b/docs/data/charts/tooltip/tooltip.md
@@ -15,8 +15,8 @@ If you are using composition, you can add the `` component and
The tooltip can be triggered by two kinds of events:
-- `'item'`—when the user's mouse hovers over an item on the chart, the tooltip will display data about this specific item.
-- `'axis'`—the user's mouse position is associated with a value of the x-axis. The tooltip will display data about all series at this specific x value.
+- `'item'`—when the user's mouse hovers over an item on the chart, the tooltip displays data about this specific item.
+- `'axis'`—the user's mouse position is associated with a value of the x-axis. The tooltip displays data about all series at this specific x value.
- `'none'`—disable the tooltip.
{{"demo": "Interaction.js"}}
@@ -79,7 +79,7 @@ See [Label—Conditional formatting](/x/react-charts/label/#conditional-formatti
### Hiding values
You can hide the axis value with `hideTooltip` in the `xAxis` props.
-It will remove the header showing the x-axis value from the tooltip.
+It removes the header showing the x-axis value from the tooltip.
```jsx
({
- color: ownerState.open ? 'secondary' : 'primary',
+ color: ownerState.isPickerOpen ? 'secondary' : 'primary',
}),
}}
/>
diff --git a/docs/data/common-concepts/custom-components/CustomSlotPropsCallback.tsx b/docs/data/common-concepts/custom-components/CustomSlotPropsCallback.tsx
index e1272f2776ba..ea3b72c58ed1 100644
--- a/docs/data/common-concepts/custom-components/CustomSlotPropsCallback.tsx
+++ b/docs/data/common-concepts/custom-components/CustomSlotPropsCallback.tsx
@@ -9,7 +9,7 @@ export default function CustomSlotPropsCallback() {
({
- color: ownerState.open ? 'secondary' : 'primary',
+ color: ownerState.isPickerOpen ? 'secondary' : 'primary',
}),
}}
/>
diff --git a/docs/data/common-concepts/custom-components/CustomSlotPropsCallback.tsx.preview b/docs/data/common-concepts/custom-components/CustomSlotPropsCallback.tsx.preview
index 100188718fae..70bc3e35f25e 100644
--- a/docs/data/common-concepts/custom-components/CustomSlotPropsCallback.tsx.preview
+++ b/docs/data/common-concepts/custom-components/CustomSlotPropsCallback.tsx.preview
@@ -1,7 +1,7 @@
({
- color: ownerState.open ? 'secondary' : 'primary',
+ color: ownerState.isPickerOpen ? 'secondary' : 'primary',
}),
}}
/>
\ No newline at end of file
diff --git a/docs/data/common-concepts/custom-components/custom-components.md b/docs/data/common-concepts/custom-components/custom-components.md
index cd89c78cbe62..1875037ac5bf 100644
--- a/docs/data/common-concepts/custom-components/custom-components.md
+++ b/docs/data/common-concepts/custom-components/custom-components.md
@@ -11,7 +11,7 @@ This is the role of all the `baseXXX` component on the Data Grid component (`bas
These slots receive props that should be as generic as possible so that it is easy to interface any other design system.
Other slots allow you to override parts of the MUI X UI components with a custom UI built specifically for this component.
-This is the role of slots like `calendarHeader` on the `DateCalendar` component or `item` on the `RichTreeView` component.
+This is the role of slots like `calendarHeader` on the `DateCalendar` component or `item` on the Rich Tree View component.
These slots receive props specific to this part of the UI and will most likely not be re-use throughout your application.
## Basic usage
diff --git a/docs/data/data-grid/column-definition/AutogeneratedRows.js b/docs/data/data-grid/column-definition/AutogeneratedRows.js
index d5689bc6ecbd..b9059be151f0 100644
--- a/docs/data/data-grid/column-definition/AutogeneratedRows.js
+++ b/docs/data/data-grid/column-definition/AutogeneratedRows.js
@@ -1,6 +1,7 @@
import * as React from 'react';
import {
DataGridPremium,
+ GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD,
isAutogeneratedRow,
useGridApiRef,
useKeepGroupedColumnsHidden,
@@ -8,7 +9,7 @@ import {
import { useMovieData } from '@mui/x-data-grid-generator';
const columns = [
- { field: '__row_group_by_columns_group__', width: 200 },
+ { field: GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, width: 200 },
{ field: 'company', width: 200 },
{
field: 'title',
diff --git a/docs/data/data-grid/column-definition/AutogeneratedRows.tsx b/docs/data/data-grid/column-definition/AutogeneratedRows.tsx
index c58c4bf79e2d..cb127be3cb88 100644
--- a/docs/data/data-grid/column-definition/AutogeneratedRows.tsx
+++ b/docs/data/data-grid/column-definition/AutogeneratedRows.tsx
@@ -1,6 +1,7 @@
import * as React from 'react';
import {
DataGridPremium,
+ GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD,
GridColDef,
isAutogeneratedRow,
useGridApiRef,
@@ -9,7 +10,7 @@ import {
import { useMovieData } from '@mui/x-data-grid-generator';
const columns: GridColDef[] = [
- { field: '__row_group_by_columns_group__', width: 200 },
+ { field: GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, width: 200 },
{ field: 'company', width: 200 },
{
field: 'title',
diff --git a/docs/data/data-grid/column-definition/column-definition.md b/docs/data/data-grid/column-definition/column-definition.md
index 75364b0c7c81..89c245b09175 100644
--- a/docs/data/data-grid/column-definition/column-definition.md
+++ b/docs/data/data-grid/column-definition/column-definition.md
@@ -102,8 +102,8 @@ Read more in the [handling autogenerated rows](/x/react-data-grid/column-definit
:::
:::warning
-[Row grouping](/x/react-data-grid/row-grouping/) uses the [`groupingValueGetter`](/x/react-data-grid/row-grouping/#using-groupingvaluegetter-for-complex-grouping-value) instead of `valueGetter` to get the value for the grouping.
-The value passed to the `groupingValueGetter` is the raw row value (`row[field]`) even if the column definition has a `valueGetter` defined.
+[Row grouping](/x/react-data-grid/row-grouping/) uses the [`groupingValueGetter()`](/x/react-data-grid/row-grouping/#using-groupingvaluegetter-for-complex-grouping-value) instead of `valueGetter` to get the value for the grouping.
+The value passed to the `groupingValueGetter()` is the raw row value (`row[field]`) even if the column definition has a `valueGetter` defined.
:::
### Value formatter
diff --git a/docs/data/data-grid/column-visibility/ColumnSelectorGridCustomizeColumns.js b/docs/data/data-grid/column-visibility/ColumnSelectorGridCustomizeColumns.js
index bfa80b2c2523..96ed3a295aa2 100644
--- a/docs/data/data-grid/column-visibility/ColumnSelectorGridCustomizeColumns.js
+++ b/docs/data/data-grid/column-visibility/ColumnSelectorGridCustomizeColumns.js
@@ -4,10 +4,11 @@ import {
GridToolbar,
useKeepGroupedColumnsHidden,
useGridApiRef,
+ GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD,
} from '@mui/x-data-grid-premium';
import { useDemoData } from '@mui/x-data-grid-generator';
-const hiddenFields = ['id', '__row_group_by_columns_group__', 'status'];
+const hiddenFields = ['id', GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, 'status'];
const getTogglableColumns = (columns) => {
return columns
diff --git a/docs/data/data-grid/column-visibility/ColumnSelectorGridCustomizeColumns.tsx b/docs/data/data-grid/column-visibility/ColumnSelectorGridCustomizeColumns.tsx
index 9c667a5f013e..83eb196585b7 100644
--- a/docs/data/data-grid/column-visibility/ColumnSelectorGridCustomizeColumns.tsx
+++ b/docs/data/data-grid/column-visibility/ColumnSelectorGridCustomizeColumns.tsx
@@ -5,10 +5,11 @@ import {
GridColDef,
useKeepGroupedColumnsHidden,
useGridApiRef,
+ GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD,
} from '@mui/x-data-grid-premium';
import { useDemoData } from '@mui/x-data-grid-generator';
-const hiddenFields = ['id', '__row_group_by_columns_group__', 'status'];
+const hiddenFields = ['id', GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, 'status'];
const getTogglableColumns = (columns: GridColDef[]) => {
return columns
diff --git a/docs/data/data-grid/column-visibility/column-visibility.md b/docs/data/data-grid/column-visibility/column-visibility.md
index 08d912a07057..3b7a149dd701 100644
--- a/docs/data/data-grid/column-visibility/column-visibility.md
+++ b/docs/data/data-grid/column-visibility/column-visibility.md
@@ -86,8 +86,13 @@ In the following demo, the columns panel is disabled, and access to columns `id`
To show or hide specific columns in the column visibility panel, use the `slotProps.columnsManagement.getTogglableColumns` prop. It should return an array of column field names.
```tsx
-// stop `id`, `__row_group_by_columns_group__`, and `status` columns to be togglable
-const hiddenFields = ['id', '__row_group_by_columns_group__', 'status'];
+import {
+ DataGridPremium,
+ GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD,
+} from '@mui/x-data-grid-premium';
+
+// stop `id`, GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, and `status` columns to be togglable
+const hiddenFields = ['id', GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, 'status'];
const getTogglableColumns = (columns: GridColDef[]) => {
return columns
@@ -95,7 +100,7 @@ const getTogglableColumns = (columns: GridColDef[]) => {
.map((column) => column.field);
};
-;
```
-Note that `createTheme` accepts any number of arguments.
+Note that `createTheme()` accepts any number of arguments.
If you are already using the [translations of the core components](/material-ui/guides/localization/#locale-text), you can add `bgBG` as a new argument.
The same import works for Data Grid Pro as it's an extension of Data Grid.
@@ -86,7 +86,7 @@ const theme = createTheme(
;
```
-If you want to pass language translations directly to the Data Grid without using `createTheme` and `ThemeProvider`, you can directly load the language translations from `@mui/x-data-grid/locales`.
+If you want to pass language translations directly to the Data Grid without using `createTheme()` and `ThemeProvider`, you can directly load the language translations from `@mui/x-data-grid/locales`.
```jsx
import { DataGrid } from '@mui/x-data-grid';
diff --git a/docs/data/data-grid/overview/DataGridPremiumDemo.js b/docs/data/data-grid/overview/DataGridPremiumDemo.js
index 98a6959cff62..3e99541b76cb 100644
--- a/docs/data/data-grid/overview/DataGridPremiumDemo.js
+++ b/docs/data/data-grid/overview/DataGridPremiumDemo.js
@@ -2,6 +2,7 @@ import * as React from 'react';
import Box from '@mui/material/Box';
import {
DataGridPremium,
+ GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD,
GridToolbar,
useGridApiRef,
useKeepGroupedColumnsHidden,
@@ -40,7 +41,7 @@ export default function DataGridPremiumDemo() {
model: ['commodity'],
},
sorting: {
- sortModel: [{ field: '__row_group_by_columns_group__', sort: 'asc' }],
+ sortModel: [{ field: GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, sort: 'asc' }],
},
aggregation: {
model: {
diff --git a/docs/data/data-grid/overview/DataGridPremiumDemo.tsx b/docs/data/data-grid/overview/DataGridPremiumDemo.tsx
index 98a6959cff62..3e99541b76cb 100644
--- a/docs/data/data-grid/overview/DataGridPremiumDemo.tsx
+++ b/docs/data/data-grid/overview/DataGridPremiumDemo.tsx
@@ -2,6 +2,7 @@ import * as React from 'react';
import Box from '@mui/material/Box';
import {
DataGridPremium,
+ GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD,
GridToolbar,
useGridApiRef,
useKeepGroupedColumnsHidden,
@@ -40,7 +41,7 @@ export default function DataGridPremiumDemo() {
model: ['commodity'],
},
sorting: {
- sortModel: [{ field: '__row_group_by_columns_group__', sort: 'asc' }],
+ sortModel: [{ field: GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, sort: 'asc' }],
},
aggregation: {
model: {
diff --git a/docs/data/data-grid/pagination/PageSizeCustomOptions.js b/docs/data/data-grid/pagination/PageSizeCustomOptions.js
index 667abfb9a412..2cdb2ddfa58b 100644
--- a/docs/data/data-grid/pagination/PageSizeCustomOptions.js
+++ b/docs/data/data-grid/pagination/PageSizeCustomOptions.js
@@ -17,7 +17,7 @@ export default function PageSizeCustomOptions() {
...data.initialState,
pagination: { paginationModel: { pageSize: 5 } },
}}
- pageSizeOptions={[5, 10, 25]}
+ pageSizeOptions={[5, 10, 25, { value: -1, label: 'All' }]}
/>
);
diff --git a/docs/data/data-grid/pagination/PageSizeCustomOptions.tsx b/docs/data/data-grid/pagination/PageSizeCustomOptions.tsx
index 667abfb9a412..2cdb2ddfa58b 100644
--- a/docs/data/data-grid/pagination/PageSizeCustomOptions.tsx
+++ b/docs/data/data-grid/pagination/PageSizeCustomOptions.tsx
@@ -17,7 +17,7 @@ export default function PageSizeCustomOptions() {
...data.initialState,
pagination: { paginationModel: { pageSize: 5 } },
}}
- pageSizeOptions={[5, 10, 25]}
+ pageSizeOptions={[5, 10, 25, { value: -1, label: 'All' }]}
/>
);
diff --git a/docs/data/data-grid/pagination/PageSizeCustomOptions.tsx.preview b/docs/data/data-grid/pagination/PageSizeCustomOptions.tsx.preview
index 88965a8c26f4..1f4dad3d8994 100644
--- a/docs/data/data-grid/pagination/PageSizeCustomOptions.tsx.preview
+++ b/docs/data/data-grid/pagination/PageSizeCustomOptions.tsx.preview
@@ -4,5 +4,5 @@
...data.initialState,
pagination: { paginationModel: { pageSize: 5 } },
}}
- pageSizeOptions={[5, 10, 25]}
+ pageSizeOptions={[5, 10, 25, { value: -1, label: 'All' }]}
/>
\ 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 90b26b56d8d7..7259d7fca5b0 100644
--- a/docs/data/data-grid/pagination/pagination.md
+++ b/docs/data/data-grid/pagination/pagination.md
@@ -41,10 +41,10 @@ You should provide an array of items, each item should be one of these types:
```
-- **object**, the `value` and `label` keys will be used respectively for the value and label of the option.
+- **object**, the `value` and `label` keys will be used respectively for the value and label of the option. Define `value` as `-1` to display all results.
```jsx
-
+
```
{{"demo": "PageSizeCustomOptions.js", "bg": "inline"}}
diff --git a/docs/data/data-grid/row-grouping/RowGroupingFullExample.js b/docs/data/data-grid/row-grouping/RowGroupingFullExample.js
index d1a08e3ff062..52040b1639af 100644
--- a/docs/data/data-grid/row-grouping/RowGroupingFullExample.js
+++ b/docs/data/data-grid/row-grouping/RowGroupingFullExample.js
@@ -1,6 +1,7 @@
import * as React from 'react';
import {
DataGridPremium,
+ GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD,
useGridApiRef,
useKeepGroupedColumnsHidden,
} from '@mui/x-data-grid-premium';
@@ -23,7 +24,7 @@ export default function RowGroupingFullExample() {
model: ['commodity'],
},
sorting: {
- sortModel: [{ field: '__row_group_by_columns_group__', sort: 'asc' }],
+ sortModel: [{ field: GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, sort: 'asc' }],
},
},
});
diff --git a/docs/data/data-grid/row-grouping/RowGroupingFullExample.tsx b/docs/data/data-grid/row-grouping/RowGroupingFullExample.tsx
index d1a08e3ff062..52040b1639af 100644
--- a/docs/data/data-grid/row-grouping/RowGroupingFullExample.tsx
+++ b/docs/data/data-grid/row-grouping/RowGroupingFullExample.tsx
@@ -1,6 +1,7 @@
import * as React from 'react';
import {
DataGridPremium,
+ GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD,
useGridApiRef,
useKeepGroupedColumnsHidden,
} from '@mui/x-data-grid-premium';
@@ -23,7 +24,7 @@ export default function RowGroupingFullExample() {
model: ['commodity'],
},
sorting: {
- sortModel: [{ field: '__row_group_by_columns_group__', sort: 'asc' }],
+ sortModel: [{ field: GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD, sort: 'asc' }],
},
},
});
diff --git a/docs/data/data-grid/row-grouping/row-grouping.md b/docs/data/data-grid/row-grouping/row-grouping.md
index b70899fb38b4..13f56a2ebac8 100644
--- a/docs/data/data-grid/row-grouping/row-grouping.md
+++ b/docs/data/data-grid/row-grouping/row-grouping.md
@@ -11,6 +11,10 @@ In the following example, movies are grouped based on their production `company`
{{"demo": "RowGroupingBasicExample.js", "bg": "inline", "defaultCodeOpen": false}}
+:::info
+If you are looking for row grouping on the server-side, see [server-side row grouping](/x/react-data-grid/server-side-data/row-grouping/).
+:::
+
## Grouping criteria
### Initialize the row grouping
@@ -252,6 +256,10 @@ Use the `setRowChildrenExpansion` method on `apiRef` to programmatically set the
{{"demo": "RowGroupingSetChildrenExpansion.js", "bg": "inline", "defaultCodeOpen": false}}
+:::warning
+The `apiRef.current.setRowChildrenExpansion` method is not compatible with the [server-side tree data](/x/react-data-grid/server-side-data/tree-data/) and [server-side row grouping](/x/react-data-grid/server-side-data/row-grouping/). Use `apiRef.current.unstable_dataSource.fetchRows` instead.
+:::
+
### Customize grouping cell indent
To change the default cell indent, you can use the `--DataGrid-cellOffsetMultiplier` CSS variable:
@@ -280,10 +288,6 @@ If you are rendering leaves with the `leafField` property of `groupingColDef`, t
You can force the filtering to be applied on another grouping criteria with the `mainGroupingCriteria` property of `groupingColDef`
-:::warning
-This feature is not yet compatible with `sortingMode = "server"` and `filteringMode = "server"`.
-:::
-
{{"demo": "RowGroupingFilteringSingleGroupingColDef.js", "bg": "inline", "defaultCodeOpen": false}}
### Multiple grouping columns
@@ -376,6 +380,10 @@ const rows = apiRef.current.getRowGroupChildren({
{{"demo": "RowGroupingGetRowGroupChildren.js", "bg": "inline", "defaultCodeOpen": false}}
+:::warning
+The `apiRef.current.getRowGroupChildren` method is not compatible with the [server-side row grouping](/x/react-data-grid/server-side-data/row-grouping/) since all the rows might not be available to get at a given instance.
+:::
+
## Row group panel 🚧
:::warning
diff --git a/docs/data/data-grid/server-side-data/ServerSideRowGroupingDataGrid.js b/docs/data/data-grid/server-side-data/ServerSideRowGroupingDataGrid.js
new file mode 100644
index 000000000000..fc75932d136b
--- /dev/null
+++ b/docs/data/data-grid/server-side-data/ServerSideRowGroupingDataGrid.js
@@ -0,0 +1,69 @@
+import * as React from 'react';
+import {
+ DataGridPremium,
+ useGridApiRef,
+ useKeepGroupedColumnsHidden,
+} from '@mui/x-data-grid-premium';
+import { useMockServer } from '@mui/x-data-grid-generator';
+import Button from '@mui/material/Button';
+
+export default function ServerSideRowGroupingDataGrid() {
+ const apiRef = useGridApiRef();
+
+ const { fetchRows, columns } = useMockServer({
+ rowGrouping: true,
+ });
+
+ const dataSource = React.useMemo(() => {
+ return {
+ getRows: async (params) => {
+ const urlParams = new URLSearchParams({
+ paginationModel: JSON.stringify(params.paginationModel),
+ filterModel: JSON.stringify(params.filterModel),
+ sortModel: JSON.stringify(params.sortModel),
+ groupKeys: JSON.stringify(params.groupKeys),
+ groupFields: JSON.stringify(params.groupFields),
+ });
+ const getRowsResponse = await fetchRows(
+ `https://mui.com/x/api/data-grid?${urlParams.toString()}`,
+ );
+ return {
+ rows: getRowsResponse.rows,
+ rowCount: getRowsResponse.rowCount,
+ };
+ },
+ getGroupKey: (row) => row.group,
+ getChildrenCount: (row) => row.descendantCount,
+ };
+ }, [fetchRows]);
+
+ const initialState = useKeepGroupedColumnsHidden({
+ apiRef,
+ initialState: {
+ rowGrouping: {
+ model: ['company', 'director'],
+ },
+ },
+ });
+
+ return (
+
Lazy-loaded row grouping with server-side data source.
-:::warning
-This feature isn't implemented yet. It's coming.
+To dynamically load row grouping data from the server, including lazy-loading of children, create a data source and pass the `unstable_dataSource` prop to the Data Grid, as mentioned in the [overview](/x/react-data-grid/server-side-data/) section.
+
+:::info
+If you are looking for row grouping on the client-side, see [client-side row grouping](/x/react-data-grid/row-grouping/).
+:::
+
+Similar to the [tree data](/x/react-data-grid/server-side-data/tree-data/), you need to pass some additional properties to enable the data source row grouping feature:
+
+- `getGroupKey()`: Returns the group key for the row.
+- `getChildrenCount()`: Returns the number of children for the row. If the children count is not available for some reason, but there are some children, returns `-1`.
+
+```tsx
+const customDataSource: GridDataSource = {
+ getRows: async (params) => {
+ // Fetch the data from the server
+ },
+ getGroupKey: (row) => {
+ // Return the group key for the row, e.g. `name`
+ return row.name;
+ },
+ getChildrenCount: (row) => {
+ // Return the number of children for the row
+ return row.childrenCount;
+ },
+};
+```
-👍 Upvote [issue #10859](https://github.com/mui/mui-x/issues/10859) if you want to see it land faster.
+In addition to `groupKeys`, the `getRows()` callback receives a `groupFields` parameter. This corresponds to the current `rowGroupingModel`. Use `groupFields` on the server to group the data for each `getRows()` call.
-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.
+```tsx
+const getRows: async (params) => {
+ const urlParams = new URLSearchParams({
+ // Example: JSON.stringify(['20th Century Fox', 'James Cameron'])
+ groupKeys: JSON.stringify(params.groupKeys),
+ // Example: JSON.stringify(['company', 'director'])
+ groupFields: JSON.stringify(params.groupFields),
+ });
+ const getRowsResponse = await fetchRows(
+ // Server should group the data based on `groupFields` and
+ // extract the rows for the nested level based on `groupKeys`
+ `https://mui.com/x/api/data-grid?${urlParams.toString()}`,
+ );
+ return {
+ rows: getRowsResponse.rows,
+ rowCount: getRowsResponse.rowCount,
+ };
+}
+```
+
+{{"demo": "ServerSideRowGroupingDataGrid.js", "bg": "inline"}}
+
+:::warning
+For complex data, consider using `colDef.groupingValueGetter` to extract the grouping value. This value is passed in the `groupKeys` parameter when `getRows` is called.
+
+Ensure your backend can interpret the `groupKeys` parameter generated by `colDef.groupingValueGetter` to retrieve grouping values for child rows.
:::
+
+## Error handling
+
+If an error occurs during a `getRows` call, the Data Grid displays an error message in the row group cell. `unstable_onDataSourceError` is also triggered with the error and the fetch params.
+
+This example shows error handling with toast notifications and default error messages in grouping cells. Caching is disabled for simplicity.
+
+{{"demo": "ServerSideRowGroupingErrorHandling.js", "bg": "inline"}}
+
+## Group expansion
+
+The group expansion works similar to the [data source tree data](/x/react-data-grid/server-side-data/tree-data/#group-expansion).
+The following demo uses `defaultGroupingExpansionDepth='-1'` to expand all the groups.
+
+{{"demo": "ServerSideRowGroupingGroupExpansion.js", "bg": "inline"}}
+
+## Demo
+
+In the following demo, use the auto generated data based on the `Commodities` dataset to simulate the server-side row grouping.
+
+{{"demo": "ServerSideRowGroupingFullDataGrid.js", "bg": "inline"}}
+
+## API
+
+- [DataGrid](/x/api/data-grid/data-grid/)
+- [DataGridPro](/x/api/data-grid/data-grid-pro/)
+- [DataGridPremium](/x/api/data-grid/data-grid-premium/)
diff --git a/docs/data/data-grid/server-side-data/tree-data.md b/docs/data/data-grid/server-side-data/tree-data.md
index 8e77fe0542bf..d5c725ac456e 100644
--- a/docs/data/data-grid/server-side-data/tree-data.md
+++ b/docs/data/data-grid/server-side-data/tree-data.md
@@ -8,8 +8,14 @@ title: React Server-side tree data
To dynamically load tree data from the server, including lazy-loading of children, you must create a data source and pass the `unstable_dataSource` prop to the Data Grid, as detailed in the [overview section](/x/react-data-grid/server-side-data/).
-The data source also requires some additional props to handle tree data, namely `getGroupKey` and `getChildrenCount`.
-If the children count is not available for some reason, but there are some children, `getChildrenCount` should return `-1`.
+:::info
+If you are looking for tree data on the client-side, see [client-side tree data](/x/react-data-grid/tree-data/).
+:::
+
+The data source also requires some additional props to handle tree data:
+
+- `getGroupKey()`: Returns the group key for the row.
+- `getChildrenCount()`: Returns the number of children for the row. If the children count is not available for some reason, but there are some children, returns `-1`.
```tsx
const customDataSource: GridDataSource = {
@@ -27,6 +33,26 @@ const customDataSource: GridDataSource = {
};
```
+Like the other parameters such as `filterModel`, `sortModel`, and `paginationModel`, the `getRows()` callback receives a `groupKeys` parameter that corresponds to the keys provided for each nested level in `getGroupKey()`.
+Use `groupKeys` on the server to extract the rows for a given nested level.
+
+```tsx
+const getRows: async (params) => {
+ const urlParams = new URLSearchParams({
+ // Example: JSON.stringify(['Billy Houston', 'Lora Dean'])
+ groupKeys: JSON.stringify(params.groupKeys),
+ });
+ const getRowsResponse = await fetchRows(
+ // Server should extract the rows for the nested level based on `groupKeys`
+ `https://mui.com/x/api/data-grid?${urlParams.toString()}`,
+ );
+ return {
+ rows: getRowsResponse.rows,
+ rowCount: getRowsResponse.rowCount,
+ };
+}
+```
+
The following tree data example supports filtering, sorting, and pagination on the server.
It also caches the data by default.
diff --git a/docs/data/data-grid-component-api-pages.ts b/docs/data/dataGridApiPages.ts
similarity index 89%
rename from docs/data/data-grid-component-api-pages.ts
rename to docs/data/dataGridApiPages.ts
index 5aed416321e1..37479bd4801b 100644
--- a/docs/data/data-grid-component-api-pages.ts
+++ b/docs/data/dataGridApiPages.ts
@@ -1,6 +1,6 @@
import type { MuiPage } from 'docs/src/MuiPage';
-const apiPages: MuiPage[] = [
+const dataGridApiPages: MuiPage[] = [
{
pathname: '/x/api/data-grid/data-grid',
title: 'DataGrid',
@@ -28,4 +28,4 @@ const apiPages: MuiPage[] = [
title: 'GridToolbarQuickFilter',
},
];
-export default apiPages;
+export default dataGridApiPages;
diff --git a/docs/data/date-pickers/custom-field/BrowserV6Field.js b/docs/data/date-pickers/custom-field/BrowserV6Field.js
deleted file mode 100644
index 63be3f56e884..000000000000
--- a/docs/data/date-pickers/custom-field/BrowserV6Field.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import * as React from 'react';
-
-import { unstable_useForkRef as useForkRef } from '@mui/utils';
-import Box from '@mui/material/Box';
-import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
-import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
-import { DatePicker } from '@mui/x-date-pickers/DatePicker';
-import { unstable_useDateField as useDateField } from '@mui/x-date-pickers/DateField';
-import { useClearableField } from '@mui/x-date-pickers/hooks';
-
-const BrowserField = React.forwardRef((props, ref) => {
- const {
- // Should be ignored
- enableAccessibleFieldDOMStructure,
- disabled,
- id,
- label,
- inputRef,
- InputProps: { ref: containerRef, startAdornment, endAdornment } = {},
- // extracting `error`, 'focused', and `ownerState` as `input` does not support those props
- error,
- focused,
- ownerState,
- sx,
- ...other
- } = props;
-
- const handleRef = useForkRef(containerRef, ref);
-
- return (
-
- {startAdornment}
-
- {endAdornment}
-
- );
-});
-
-const BrowserDateField = React.forwardRef((props, ref) => {
- const { slots, slotProps, ...textFieldProps } = props;
-
- const fieldResponse = useDateField({
- ...textFieldProps,
- enableAccessibleFieldDOMStructure: false,
- });
-
- /* If you don't need a clear button, you can skip the use of this hook */
- const processedFieldProps = useClearableField({
- ...fieldResponse,
- slots,
- slotProps,
- });
-
- return ;
-});
-
-const BrowserDatePicker = React.forwardRef((props, ref) => {
- return (
-
- );
-});
-
-export default function BrowserV6Field() {
- return (
-
-
-
- );
-}
diff --git a/docs/data/date-pickers/custom-field/BrowserV6Field.tsx b/docs/data/date-pickers/custom-field/BrowserV6Field.tsx
deleted file mode 100644
index 49138cd42863..000000000000
--- a/docs/data/date-pickers/custom-field/BrowserV6Field.tsx
+++ /dev/null
@@ -1,135 +0,0 @@
-import * as React from 'react';
-import { Dayjs } from 'dayjs';
-import { unstable_useForkRef as useForkRef } from '@mui/utils';
-import Box from '@mui/material/Box';
-import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
-import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
-import { DatePicker, DatePickerProps } from '@mui/x-date-pickers/DatePicker';
-import {
- unstable_useDateField as useDateField,
- UseDateFieldProps,
-} from '@mui/x-date-pickers/DateField';
-import { useClearableField } from '@mui/x-date-pickers/hooks';
-import {
- BaseSingleInputFieldProps,
- DateValidationError,
- FieldSection,
-} from '@mui/x-date-pickers/models';
-
-interface BrowserFieldProps
- extends Omit, 'size'> {
- label?: React.ReactNode;
- inputRef?: React.Ref;
- InputProps?: {
- ref?: React.Ref;
- endAdornment?: React.ReactNode;
- startAdornment?: React.ReactNode;
- };
- error?: boolean;
- focused?: boolean;
- ownerState?: any;
- sx?: any;
- enableAccessibleFieldDOMStructure: boolean;
-}
-
-type BrowserFieldComponent = ((
- props: BrowserFieldProps & React.RefAttributes,
-) => React.JSX.Element) & { propTypes?: any };
-
-const BrowserField = React.forwardRef(
- (props: BrowserFieldProps, ref: React.Ref) => {
- const {
- // Should be ignored
- enableAccessibleFieldDOMStructure,
-
- disabled,
- id,
- label,
- inputRef,
- InputProps: { ref: containerRef, startAdornment, endAdornment } = {},
- // extracting `error`, 'focused', and `ownerState` as `input` does not support those props
- error,
- focused,
- ownerState,
- sx,
- ...other
- } = props;
-
- const handleRef = useForkRef(containerRef, ref);
-
- return (
-
- {startAdornment}
-
- {endAdornment}
-
- );
- },
-) as BrowserFieldComponent;
-
-interface BrowserDateFieldProps
- extends UseDateFieldProps,
- BaseSingleInputFieldProps<
- Dayjs | null,
- Dayjs,
- FieldSection,
- false,
- DateValidationError
- > {}
-
-const BrowserDateField = React.forwardRef(
- (props: BrowserDateFieldProps, ref: React.Ref) => {
- const { slots, slotProps, ...textFieldProps } = props;
-
- const fieldResponse = useDateField({
- ...textFieldProps,
- enableAccessibleFieldDOMStructure: false,
- });
-
- /* If you don't need a clear button, you can skip the use of this hook */
- const processedFieldProps = useClearableField({
- ...fieldResponse,
- slots,
- slotProps,
- });
-
- return ;
- },
-);
-
-const BrowserDatePicker = React.forwardRef(
- (props: DatePickerProps, ref: React.Ref) => {
- return (
-
- ref={ref}
- {...props}
- slots={{ ...props.slots, field: BrowserDateField }}
- />
- );
- },
-);
-
-export default function BrowserV6Field() {
- return (
-
-
-
- );
-}
diff --git a/docs/data/date-pickers/custom-field/BrowserV6Field.tsx.preview b/docs/data/date-pickers/custom-field/BrowserV6Field.tsx.preview
deleted file mode 100644
index 0bb9e399d3cb..000000000000
--- a/docs/data/date-pickers/custom-field/BrowserV6Field.tsx.preview
+++ /dev/null
@@ -1,5 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/data/date-pickers/custom-field/BrowserV6MultiInputRangeField.js b/docs/data/date-pickers/custom-field/BrowserV6MultiInputRangeField.js
deleted file mode 100644
index 5421fd0d4348..000000000000
--- a/docs/data/date-pickers/custom-field/BrowserV6MultiInputRangeField.js
+++ /dev/null
@@ -1,140 +0,0 @@
-import * as React from 'react';
-
-import { unstable_useForkRef as useForkRef } from '@mui/utils';
-import useSlotProps from '@mui/utils/useSlotProps';
-import Box from '@mui/material/Box';
-import Stack from '@mui/material/Stack';
-import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
-import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
-import { DateRangePicker } from '@mui/x-date-pickers-pro/DateRangePicker';
-import { unstable_useMultiInputDateRangeField as useMultiInputDateRangeField } from '@mui/x-date-pickers-pro/MultiInputDateRangeField';
-
-const BrowserField = React.forwardRef((props, ref) => {
- const {
- // Should be ignored
- enableAccessibleFieldDOMStructure,
- disabled,
- id,
- label,
- inputRef,
- InputProps: { ref: containerRef, startAdornment, endAdornment } = {},
- // extracting `error`, 'focused', and `ownerState` as `input` does not support those props
- error,
- focused,
- ownerState,
- sx,
- ...other
- } = props;
-
- const handleRef = useForkRef(containerRef, ref);
-
- return (
-
- {startAdornment}
-
- {endAdornment}
-
- );
-});
-
-const BrowserMultiInputDateRangeField = React.forwardRef((props, ref) => {
- const {
- slotProps,
- value,
- defaultValue,
- format,
- onChange,
- readOnly,
- disabled,
- onError,
- shouldDisableDate,
- minDate,
- maxDate,
- disableFuture,
- disablePast,
- selectedSections,
- onSelectedSectionsChange,
- className,
- unstableStartFieldRef,
- unstableEndFieldRef,
- } = props;
-
- const startTextFieldProps = useSlotProps({
- elementType: 'input',
- externalSlotProps: slotProps?.textField,
- ownerState: { ...props, position: 'start' },
- });
-
- const endTextFieldProps = useSlotProps({
- elementType: 'input',
- externalSlotProps: slotProps?.textField,
- ownerState: { ...props, position: 'end' },
- });
-
- const fieldResponse = useMultiInputDateRangeField({
- sharedProps: {
- value,
- defaultValue,
- format,
- onChange,
- readOnly,
- disabled,
- onError,
- shouldDisableDate,
- minDate,
- maxDate,
- disableFuture,
- disablePast,
- selectedSections,
- onSelectedSectionsChange,
- enableAccessibleFieldDOMStructure: false,
- },
- startTextFieldProps,
- endTextFieldProps,
- unstableStartFieldRef,
- unstableEndFieldRef,
- });
-
- return (
-
-
- —
-
-
- );
-});
-
-const BrowserDateRangePicker = React.forwardRef((props, ref) => {
- return (
-
- );
-});
-
-export default function BrowserV6MultiInputRangeField() {
- return (
-
-
-
- );
-}
diff --git a/docs/data/date-pickers/custom-field/BrowserV6MultiInputRangeField.tsx b/docs/data/date-pickers/custom-field/BrowserV6MultiInputRangeField.tsx
deleted file mode 100644
index b52029d14cde..000000000000
--- a/docs/data/date-pickers/custom-field/BrowserV6MultiInputRangeField.tsx
+++ /dev/null
@@ -1,196 +0,0 @@
-import * as React from 'react';
-import { Dayjs } from 'dayjs';
-import { unstable_useForkRef as useForkRef } from '@mui/utils';
-import useSlotProps from '@mui/utils/useSlotProps';
-import Box from '@mui/material/Box';
-import Stack from '@mui/material/Stack';
-import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
-import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
-import {
- DateRangePicker,
- DateRangePickerProps,
-} from '@mui/x-date-pickers-pro/DateRangePicker';
-import { unstable_useMultiInputDateRangeField as useMultiInputDateRangeField } from '@mui/x-date-pickers-pro/MultiInputDateRangeField';
-import {
- BaseMultiInputFieldProps,
- DateRange,
- DateRangeValidationError,
- MultiInputFieldSlotTextFieldProps,
- RangeFieldSection,
- UseDateRangeFieldProps,
-} from '@mui/x-date-pickers-pro/models';
-
-interface BrowserFieldProps
- extends Omit, 'size'> {
- label?: React.ReactNode;
- inputRef?: React.Ref;
- InputProps?: {
- ref?: React.Ref;
- endAdornment?: React.ReactNode;
- startAdornment?: React.ReactNode;
- };
- error?: boolean;
- focused?: boolean;
- ownerState?: any;
- sx?: any;
- enableAccessibleFieldDOMStructure: boolean;
-}
-
-type BrowserFieldComponent = ((
- props: BrowserFieldProps & React.RefAttributes,
-) => React.JSX.Element) & { propTypes?: any };
-
-const BrowserField = React.forwardRef(
- (props: BrowserFieldProps, ref: React.Ref) => {
- const {
- // Should be ignored
- enableAccessibleFieldDOMStructure,
-
- disabled,
- id,
- label,
- inputRef,
- InputProps: { ref: containerRef, startAdornment, endAdornment } = {},
- // extracting `error`, 'focused', and `ownerState` as `input` does not support those props
- error,
- focused,
- ownerState,
- sx,
- ...other
- } = props;
-
- const handleRef = useForkRef(containerRef, ref);
-
- return (
-
- {startAdornment}
-
- {endAdornment}
-
- );
- },
-) as BrowserFieldComponent;
-
-interface BrowserMultiInputDateRangeFieldProps
- extends UseDateRangeFieldProps,
- BaseMultiInputFieldProps<
- DateRange,
- Dayjs,
- RangeFieldSection,
- false,
- DateRangeValidationError
- > {}
-
-type BrowserMultiInputDateRangeFieldComponent = ((
- props: BrowserMultiInputDateRangeFieldProps & React.RefAttributes,
-) => React.JSX.Element) & { propTypes?: any };
-
-const BrowserMultiInputDateRangeField = React.forwardRef(
- (props: BrowserMultiInputDateRangeFieldProps, ref: React.Ref) => {
- const {
- slotProps,
- value,
- defaultValue,
- format,
- onChange,
- readOnly,
- disabled,
- onError,
- shouldDisableDate,
- minDate,
- maxDate,
- disableFuture,
- disablePast,
- selectedSections,
- onSelectedSectionsChange,
- className,
- unstableStartFieldRef,
- unstableEndFieldRef,
- } = props;
-
- const startTextFieldProps = useSlotProps({
- elementType: 'input',
- externalSlotProps: slotProps?.textField,
- ownerState: { ...props, position: 'start' },
- }) as MultiInputFieldSlotTextFieldProps;
-
- const endTextFieldProps = useSlotProps({
- elementType: 'input',
- externalSlotProps: slotProps?.textField,
- ownerState: { ...props, position: 'end' },
- }) as MultiInputFieldSlotTextFieldProps;
-
- const fieldResponse = useMultiInputDateRangeField<
- Dayjs,
- false,
- MultiInputFieldSlotTextFieldProps
- >({
- sharedProps: {
- value,
- defaultValue,
- format,
- onChange,
- readOnly,
- disabled,
- onError,
- shouldDisableDate,
- minDate,
- maxDate,
- disableFuture,
- disablePast,
- selectedSections,
- onSelectedSectionsChange,
- enableAccessibleFieldDOMStructure: false,
- },
- startTextFieldProps,
- endTextFieldProps,
- unstableStartFieldRef,
- unstableEndFieldRef,
- });
-
- return (
-
-
- —
-
-
- );
- },
-) as BrowserMultiInputDateRangeFieldComponent;
-
-const BrowserDateRangePicker = React.forwardRef(
- (props: DateRangePickerProps, ref: React.Ref) => {
- return (
-
- );
- },
-);
-
-export default function BrowserV6MultiInputRangeField() {
- return (
-
-
-
- );
-}
diff --git a/docs/data/date-pickers/custom-field/BrowserV6MultiInputRangeField.tsx.preview b/docs/data/date-pickers/custom-field/BrowserV6MultiInputRangeField.tsx.preview
deleted file mode 100644
index d797406fa999..000000000000
--- a/docs/data/date-pickers/custom-field/BrowserV6MultiInputRangeField.tsx.preview
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/data/date-pickers/custom-field/BrowserV6SingleInputRangeField.js b/docs/data/date-pickers/custom-field/BrowserV6SingleInputRangeField.js
deleted file mode 100644
index 311029bbc6fa..000000000000
--- a/docs/data/date-pickers/custom-field/BrowserV6SingleInputRangeField.js
+++ /dev/null
@@ -1,137 +0,0 @@
-import * as React from 'react';
-
-import { unstable_useForkRef as useForkRef } from '@mui/utils';
-import useSlotProps from '@mui/utils/useSlotProps';
-import Box from '@mui/material/Box';
-import IconButton from '@mui/material/IconButton';
-import InputAdornment from '@mui/material/InputAdornment';
-import { DateRangeIcon } from '@mui/x-date-pickers/icons';
-import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
-import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
-import { DateRangePicker } from '@mui/x-date-pickers-pro/DateRangePicker';
-import { unstable_useSingleInputDateRangeField as useSingleInputDateRangeField } from '@mui/x-date-pickers-pro/SingleInputDateRangeField';
-import { useClearableField } from '@mui/x-date-pickers/hooks';
-
-const BrowserField = React.forwardRef((props, ref) => {
- const {
- // Should be ignored
- enableAccessibleFieldDOMStructure,
- disabled,
- id,
- label,
- inputRef,
- InputProps: { ref: containerRef, startAdornment, endAdornment } = {},
- // extracting `error`, 'focused', and `ownerState` as `input` does not support those props
- error,
- focused,
- ownerState,
- sx,
- ...other
- } = props;
-
- const handleRef = useForkRef(containerRef, ref);
-
- return (
-
- {startAdornment}
-
- {endAdornment}
-
- );
-});
-
-const BrowserSingleInputDateRangeField = React.forwardRef((props, ref) => {
- const { slots, slotProps, onAdornmentClick, ...other } = props;
-
- const textFieldProps = useSlotProps({
- elementType: 'input',
- externalSlotProps: slotProps?.textField,
- externalForwardedProps: other,
- ownerState: props,
- });
-
- textFieldProps.InputProps = {
- ...textFieldProps.InputProps,
- endAdornment: (
-
-
-
-
-
- ),
- };
-
- const fieldResponse = useSingleInputDateRangeField({
- ...textFieldProps,
- enableAccessibleFieldDOMStructure: false,
- });
-
- /* If you don't need a clear button, you can skip the use of this hook */
- const processedFieldProps = useClearableField({
- ...fieldResponse,
- slots,
- slotProps,
- });
-
- return (
-
- );
-});
-
-BrowserSingleInputDateRangeField.fieldType = 'single-input';
-
-const BrowserSingleInputDateRangePicker = React.forwardRef((props, ref) => {
- const [isOpen, setIsOpen] = React.useState(false);
-
- const toggleOpen = () => setIsOpen((currentOpen) => !currentOpen);
-
- const handleOpen = () => setIsOpen(true);
-
- const handleClose = () => setIsOpen(false);
-
- return (
-
- );
-});
-
-export default function BrowserV6SingleInputRangeField() {
- return (
-
-
-
- );
-}
diff --git a/docs/data/date-pickers/custom-field/BrowserV6SingleInputRangeField.tsx b/docs/data/date-pickers/custom-field/BrowserV6SingleInputRangeField.tsx
deleted file mode 100644
index 6db84b3f6c57..000000000000
--- a/docs/data/date-pickers/custom-field/BrowserV6SingleInputRangeField.tsx
+++ /dev/null
@@ -1,196 +0,0 @@
-import * as React from 'react';
-import { Dayjs } from 'dayjs';
-import { unstable_useForkRef as useForkRef } from '@mui/utils';
-import useSlotProps from '@mui/utils/useSlotProps';
-import Box from '@mui/material/Box';
-import IconButton from '@mui/material/IconButton';
-import InputAdornment from '@mui/material/InputAdornment';
-import { DateRangeIcon } from '@mui/x-date-pickers/icons';
-import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
-import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
-import {
- DateRangePicker,
- DateRangePickerProps,
-} from '@mui/x-date-pickers-pro/DateRangePicker';
-import {
- unstable_useSingleInputDateRangeField as useSingleInputDateRangeField,
- SingleInputDateRangeFieldProps,
- UseSingleInputDateRangeFieldProps,
-} from '@mui/x-date-pickers-pro/SingleInputDateRangeField';
-import { useClearableField } from '@mui/x-date-pickers/hooks';
-import { BaseSingleInputFieldProps } from '@mui/x-date-pickers/models';
-import {
- DateRangeValidationError,
- RangeFieldSection,
- DateRange,
- FieldType,
-} from '@mui/x-date-pickers-pro/models';
-
-interface BrowserFieldProps
- extends Omit, 'size'> {
- label?: React.ReactNode;
- inputRef?: React.Ref;
- InputProps?: {
- ref?: React.Ref;
- endAdornment?: React.ReactNode;
- startAdornment?: React.ReactNode;
- };
- error?: boolean;
- focused?: boolean;
- ownerState?: any;
- sx?: any;
- enableAccessibleFieldDOMStructure: boolean;
-}
-
-type BrowserFieldComponent = ((
- props: BrowserFieldProps & React.RefAttributes,
-) => React.JSX.Element) & { propTypes?: any };
-
-const BrowserField = React.forwardRef(
- (props: BrowserFieldProps, ref: React.Ref) => {
- const {
- // Should be ignored
- enableAccessibleFieldDOMStructure,
-
- disabled,
- id,
- label,
- inputRef,
- InputProps: { ref: containerRef, startAdornment, endAdornment } = {},
- // extracting `error`, 'focused', and `ownerState` as `input` does not support those props
- error,
- focused,
- ownerState,
- sx,
- ...other
- } = props;
-
- const handleRef = useForkRef(containerRef, ref);
-
- return (
-
- {startAdornment}
-
- {endAdornment}
-
- );
- },
-) as BrowserFieldComponent;
-
-interface BrowserSingleInputDateRangeFieldProps
- extends UseSingleInputDateRangeFieldProps,
- BaseSingleInputFieldProps<
- DateRange,
- Dayjs,
- RangeFieldSection,
- false,
- DateRangeValidationError
- > {
- onAdornmentClick?: () => void;
-}
-
-type BrowserSingleInputDateRangeFieldComponent = ((
- props: BrowserSingleInputDateRangeFieldProps & React.RefAttributes,
-) => React.JSX.Element) & { fieldType?: FieldType };
-
-const BrowserSingleInputDateRangeField = React.forwardRef(
- (props: BrowserSingleInputDateRangeFieldProps, ref: React.Ref) => {
- const { slots, slotProps, onAdornmentClick, ...other } = props;
-
- const textFieldProps: SingleInputDateRangeFieldProps =
- useSlotProps({
- elementType: 'input',
- externalSlotProps: slotProps?.textField,
- externalForwardedProps: other,
- ownerState: props as any,
- });
-
- textFieldProps.InputProps = {
- ...textFieldProps.InputProps,
- endAdornment: (
-
-
-
-
-
- ),
- };
-
- const fieldResponse = useSingleInputDateRangeField<
- Dayjs,
- false,
- typeof textFieldProps
- >({ ...textFieldProps, enableAccessibleFieldDOMStructure: false });
-
- /* If you don't need a clear button, you can skip the use of this hook */
- const processedFieldProps = useClearableField({
- ...fieldResponse,
- slots,
- slotProps,
- });
-
- return (
-
- );
- },
-) as BrowserSingleInputDateRangeFieldComponent;
-
-BrowserSingleInputDateRangeField.fieldType = 'single-input';
-
-const BrowserSingleInputDateRangePicker = React.forwardRef(
- (props: DateRangePickerProps, ref: React.Ref) => {
- const [isOpen, setIsOpen] = React.useState(false);
-
- const toggleOpen = () => setIsOpen((currentOpen) => !currentOpen);
-
- const handleOpen = () => setIsOpen(true);
-
- const handleClose = () => setIsOpen(false);
-
- return (
-
- );
- },
-);
-
-export default function BrowserV6SingleInputRangeField() {
- return (
-
-
-
- );
-}
diff --git a/docs/data/date-pickers/custom-field/BrowserV6SingleInputRangeField.tsx.preview b/docs/data/date-pickers/custom-field/BrowserV6SingleInputRangeField.tsx.preview
deleted file mode 100644
index bcaf8043948f..000000000000
--- a/docs/data/date-pickers/custom-field/BrowserV6SingleInputRangeField.tsx.preview
+++ /dev/null
@@ -1,5 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx b/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx
index c4ef19f2f15b..b45092eb35ef 100644
--- a/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx
+++ b/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx
@@ -201,7 +201,7 @@ const BrowserMultiInputDateRangeField = React.forwardRef(
) as BrowserMultiInputDateRangeFieldComponent;
const BrowserDateRangePicker = React.forwardRef(
- (props: DateRangePickerProps, ref: React.Ref) => {
+ (props: DateRangePickerProps, ref: React.Ref) => {
return (
-
-
+
+
);
diff --git a/docs/data/date-pickers/custom-field/MaterialV6Field.tsx b/docs/data/date-pickers/custom-field/MaterialV6Field.tsx
index 35d4e0ca73ea..98a5d2d58c27 100644
--- a/docs/data/date-pickers/custom-field/MaterialV6Field.tsx
+++ b/docs/data/date-pickers/custom-field/MaterialV6Field.tsx
@@ -9,8 +9,8 @@ export default function MaterialV6Field() {
return (
-
-
+
+
);
diff --git a/docs/data/date-pickers/custom-field/MaterialV6Field.tsx.preview b/docs/data/date-pickers/custom-field/MaterialV6Field.tsx.preview
index 027cb7beacfa..9041ed886d8b 100644
--- a/docs/data/date-pickers/custom-field/MaterialV6Field.tsx.preview
+++ b/docs/data/date-pickers/custom-field/MaterialV6Field.tsx.preview
@@ -1,2 +1,2 @@
-
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/docs/data/date-pickers/custom-field/MaterialV6FieldWrapped.js b/docs/data/date-pickers/custom-field/MaterialV6FieldWrapped.js
deleted file mode 100644
index df1b5053a745..000000000000
--- a/docs/data/date-pickers/custom-field/MaterialV6FieldWrapped.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import * as React from 'react';
-import MuiTextField from '@mui/material/TextField';
-import { DemoContainer } from '@mui/x-date-pickers/internals/demo';
-import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
-import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
-import { DateField } from '@mui/x-date-pickers/DateField';
-import { DatePicker } from '@mui/x-date-pickers/DatePicker';
-
-const TextField = React.forwardRef((props, ref) => (
-
-));
-
-export default function MaterialV6FieldWrapped() {
- return (
-
-
-
-
-
-
- );
-}
diff --git a/docs/data/date-pickers/custom-field/MaterialV6FieldWrapped.tsx b/docs/data/date-pickers/custom-field/MaterialV6FieldWrapped.tsx
deleted file mode 100644
index 0c90908a7d4b..000000000000
--- a/docs/data/date-pickers/custom-field/MaterialV6FieldWrapped.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import * as React from 'react';
-import MuiTextField, { TextFieldProps } from '@mui/material/TextField';
-import { DemoContainer } from '@mui/x-date-pickers/internals/demo';
-import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
-import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
-import { DateField } from '@mui/x-date-pickers/DateField';
-import { DatePicker } from '@mui/x-date-pickers/DatePicker';
-
-const TextField = React.forwardRef(
- (props: TextFieldProps, ref: React.Ref) => (
-
- ),
-);
-
-export default function MaterialV6FieldWrapped() {
- return (
-
-
-
-
-
-
- );
-}
diff --git a/docs/data/date-pickers/custom-field/MaterialV6FieldWrapped.tsx.preview b/docs/data/date-pickers/custom-field/MaterialV6FieldWrapped.tsx.preview
deleted file mode 100644
index cd5ff731abbc..000000000000
--- a/docs/data/date-pickers/custom-field/MaterialV6FieldWrapped.tsx.preview
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/docs/data/date-pickers/custom-field/MaterialV7Field.js b/docs/data/date-pickers/custom-field/MaterialV7Field.js
deleted file mode 100644
index 07ba449750d6..000000000000
--- a/docs/data/date-pickers/custom-field/MaterialV7Field.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import * as React from 'react';
-import { DemoContainer } from '@mui/x-date-pickers/internals/demo';
-import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
-import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
-import { DatePicker } from '@mui/x-date-pickers/DatePicker';
-import { DateField } from '@mui/x-date-pickers/DateField';
-
-export default function MaterialV7Field() {
- return (
-
-
-
-
-
-
- );
-}
diff --git a/docs/data/date-pickers/custom-field/MaterialV7Field.tsx b/docs/data/date-pickers/custom-field/MaterialV7Field.tsx
deleted file mode 100644
index 07ba449750d6..000000000000
--- a/docs/data/date-pickers/custom-field/MaterialV7Field.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import * as React from 'react';
-import { DemoContainer } from '@mui/x-date-pickers/internals/demo';
-import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
-import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
-import { DatePicker } from '@mui/x-date-pickers/DatePicker';
-import { DateField } from '@mui/x-date-pickers/DateField';
-
-export default function MaterialV7Field() {
- return (
-
-
-
-
-
-
- );
-}
diff --git a/docs/data/date-pickers/custom-field/MaterialV7Field.tsx.preview b/docs/data/date-pickers/custom-field/MaterialV7Field.tsx.preview
deleted file mode 100644
index 9708ed359729..000000000000
--- a/docs/data/date-pickers/custom-field/MaterialV7Field.tsx.preview
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.js b/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.js
index d125a8479b5c..22560a3bcc80 100644
--- a/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.js
+++ b/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.js
@@ -14,14 +14,8 @@ export default function MaterialV7FieldWrapped() {
return (
-
-
+
+
);
diff --git a/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.tsx b/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.tsx
index 82e06da7316b..d054e12c04de 100644
--- a/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.tsx
+++ b/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.tsx
@@ -19,14 +19,8 @@ export default function MaterialV7FieldWrapped() {
return (
-
-
+
+
);
diff --git a/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.tsx.preview b/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.tsx.preview
index 17535291f5f3..a31c9c5bc351 100644
--- a/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.tsx.preview
+++ b/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.tsx.preview
@@ -1,8 +1,2 @@
-
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/docs/data/date-pickers/custom-field/PickerWithAutocompleteField.tsx b/docs/data/date-pickers/custom-field/PickerWithAutocompleteField.tsx
index 1aac33d076c0..92e99e278e87 100644
--- a/docs/data/date-pickers/custom-field/PickerWithAutocompleteField.tsx
+++ b/docs/data/date-pickers/custom-field/PickerWithAutocompleteField.tsx
@@ -14,12 +14,12 @@ import {
} from '@mui/x-date-pickers/models';
interface AutoCompleteFieldProps
- extends UseDateFieldProps,
+ extends UseDateFieldProps,
BaseSingleInputFieldProps<
Dayjs | null,
Dayjs,
FieldSection,
- false,
+ true,
DateValidationError
> {
/**
diff --git a/docs/data/date-pickers/custom-field/PickerWithButtonField.tsx b/docs/data/date-pickers/custom-field/PickerWithButtonField.tsx
index aa09717fb29c..8acbab77d7c4 100644
--- a/docs/data/date-pickers/custom-field/PickerWithButtonField.tsx
+++ b/docs/data/date-pickers/custom-field/PickerWithButtonField.tsx
@@ -12,12 +12,12 @@ import {
} from '@mui/x-date-pickers/models';
interface ButtonFieldProps
- extends UseDateFieldProps,
+ extends UseDateFieldProps,
BaseSingleInputFieldProps<
Dayjs | null,
Dayjs,
FieldSection,
- false,
+ true,
DateValidationError
> {
setOpen?: React.Dispatch>;
diff --git a/docs/data/date-pickers/custom-field/custom-behavior/MaskedMaterialTextField.js b/docs/data/date-pickers/custom-field/custom-behavior/MaskedMaterialTextField.js
new file mode 100644
index 000000000000..0723d4565c51
--- /dev/null
+++ b/docs/data/date-pickers/custom-field/custom-behavior/MaskedMaterialTextField.js
@@ -0,0 +1,164 @@
+import * as React from 'react';
+import dayjs from 'dayjs';
+import { useRifm } from 'rifm';
+import TextField from '@mui/material/TextField';
+import useControlled from '@mui/utils/useControlled';
+import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
+import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
+import { DatePicker } from '@mui/x-date-pickers/DatePicker';
+import { useSplitFieldProps, useParsedFormat } from '@mui/x-date-pickers/hooks';
+import { useValidation, validateDate } from '@mui/x-date-pickers/validation';
+
+const MASK_USER_INPUT_SYMBOL = '_';
+const ACCEPT_REGEX = /[\d]/gi;
+
+const staticDateWith2DigitTokens = dayjs('2019-11-21T11:30:00.000');
+const staticDateWith1DigitTokens = dayjs('2019-01-01T09:00:00.000');
+
+function getValueStrFromValue(value, format) {
+ if (value == null) {
+ return '';
+ }
+
+ return value.isValid() ? value.format(format) : '';
+}
+
+function MaskedField(props) {
+ const { slots, slotProps, ...other } = props;
+
+ const { forwardedProps, internalProps } = useSplitFieldProps(other, 'date');
+
+ const {
+ format,
+ value: valueProp,
+ defaultValue,
+ onChange,
+ timezone,
+ onError,
+ } = internalProps;
+
+ const [value, setValue] = useControlled({
+ controlled: valueProp,
+ default: defaultValue ?? null,
+ name: 'MaskedField',
+ state: 'value',
+ });
+
+ // Control the input text
+ const [inputValue, setInputValue] = React.useState(() =>
+ getValueStrFromValue(value, format),
+ );
+
+ React.useEffect(() => {
+ if (value && value.isValid()) {
+ const newDisplayDate = getValueStrFromValue(value, format);
+ setInputValue(newDisplayDate);
+ }
+ }, [format, value]);
+
+ const parsedFormat = useParsedFormat(internalProps);
+
+ const { hasValidationError, getValidationErrorForNewValue } = useValidation({
+ value,
+ timezone,
+ onError,
+ props: internalProps,
+ validator: validateDate,
+ });
+
+ const handleValueStrChange = (newValueStr) => {
+ setInputValue(newValueStr);
+
+ const newValue = dayjs(newValueStr, format);
+ setValue(newValue);
+
+ if (onChange) {
+ onChange(newValue, {
+ validationError: getValidationErrorForNewValue(newValue),
+ });
+ }
+ };
+
+ const rifmFormat = React.useMemo(() => {
+ const formattedDateWith1Digit = staticDateWith1DigitTokens.format(format);
+ const inferredFormatPatternWith1Digits = formattedDateWith1Digit.replace(
+ ACCEPT_REGEX,
+ MASK_USER_INPUT_SYMBOL,
+ );
+ const inferredFormatPatternWith2Digits = staticDateWith2DigitTokens
+ .format(format)
+ .replace(ACCEPT_REGEX, '_');
+
+ if (inferredFormatPatternWith1Digits !== inferredFormatPatternWith2Digits) {
+ throw new Error(
+ `Mask does not support numbers with variable length such as 'M'.`,
+ );
+ }
+
+ const maskToUse = inferredFormatPatternWith1Digits;
+
+ return function formatMaskedDate(valueToFormat) {
+ let outputCharIndex = 0;
+ return valueToFormat
+ .split('')
+ .map((character, characterIndex) => {
+ ACCEPT_REGEX.lastIndex = 0;
+
+ if (outputCharIndex > maskToUse.length - 1) {
+ return '';
+ }
+
+ const maskChar = maskToUse[outputCharIndex];
+ const nextMaskChar = maskToUse[outputCharIndex + 1];
+
+ const acceptedChar = ACCEPT_REGEX.test(character) ? character : '';
+ const formattedChar =
+ maskChar === MASK_USER_INPUT_SYMBOL
+ ? acceptedChar
+ : maskChar + acceptedChar;
+
+ outputCharIndex += formattedChar.length;
+
+ const isLastCharacter = characterIndex === valueToFormat.length - 1;
+ if (
+ isLastCharacter &&
+ nextMaskChar &&
+ nextMaskChar !== MASK_USER_INPUT_SYMBOL
+ ) {
+ // when cursor at the end of mask part (e.g. month) prerender next symbol "21" -> "21/"
+ return formattedChar ? formattedChar + nextMaskChar : '';
+ }
+
+ return formattedChar;
+ })
+ .join('');
+ };
+ }, [format]);
+
+ const rifmProps = useRifm({
+ value: inputValue,
+ onChange: handleValueStrChange,
+ format: rifmFormat,
+ });
+
+ return (
+
+ );
+}
+
+function MaskedFieldDatePicker(props) {
+ return ;
+}
+
+export default function MaskedMaterialTextField() {
+ return (
+
+
+
+ );
+}
diff --git a/docs/data/date-pickers/custom-field/custom-behavior/MaskedMaterialTextField.tsx b/docs/data/date-pickers/custom-field/custom-behavior/MaskedMaterialTextField.tsx
new file mode 100644
index 000000000000..a589022eada6
--- /dev/null
+++ b/docs/data/date-pickers/custom-field/custom-behavior/MaskedMaterialTextField.tsx
@@ -0,0 +1,168 @@
+import * as React from 'react';
+import dayjs, { Dayjs } from 'dayjs';
+import { useRifm } from 'rifm';
+import TextField from '@mui/material/TextField';
+import useControlled from '@mui/utils/useControlled';
+import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
+import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
+import {
+ DatePicker,
+ DatePickerProps,
+ DatePickerFieldProps,
+} from '@mui/x-date-pickers/DatePicker';
+import { useSplitFieldProps, useParsedFormat } from '@mui/x-date-pickers/hooks';
+import { useValidation, validateDate } from '@mui/x-date-pickers/validation';
+
+const MASK_USER_INPUT_SYMBOL = '_';
+const ACCEPT_REGEX = /[\d]/gi;
+
+const staticDateWith2DigitTokens = dayjs('2019-11-21T11:30:00.000');
+const staticDateWith1DigitTokens = dayjs('2019-01-01T09:00:00.000');
+
+function getValueStrFromValue(value: Dayjs | null, format: string) {
+ if (value == null) {
+ return '';
+ }
+
+ return value.isValid() ? value.format(format) : '';
+}
+
+function MaskedField(props: DatePickerFieldProps) {
+ const { slots, slotProps, ...other } = props;
+
+ const { forwardedProps, internalProps } = useSplitFieldProps(other, 'date');
+
+ const {
+ format,
+ value: valueProp,
+ defaultValue,
+ onChange,
+ timezone,
+ onError,
+ } = internalProps;
+
+ const [value, setValue] = useControlled({
+ controlled: valueProp,
+ default: defaultValue ?? null,
+ name: 'MaskedField',
+ state: 'value',
+ });
+
+ // Control the input text
+ const [inputValue, setInputValue] = React.useState(() =>
+ getValueStrFromValue(value, format),
+ );
+
+ React.useEffect(() => {
+ if (value && value.isValid()) {
+ const newDisplayDate = getValueStrFromValue(value, format);
+ setInputValue(newDisplayDate);
+ }
+ }, [format, value]);
+
+ const parsedFormat = useParsedFormat(internalProps);
+
+ const { hasValidationError, getValidationErrorForNewValue } = useValidation({
+ value,
+ timezone,
+ onError,
+ props: internalProps,
+ validator: validateDate,
+ });
+
+ const handleValueStrChange = (newValueStr: string) => {
+ setInputValue(newValueStr);
+
+ const newValue = dayjs(newValueStr, format);
+ setValue(newValue);
+
+ if (onChange) {
+ onChange(newValue, {
+ validationError: getValidationErrorForNewValue(newValue),
+ });
+ }
+ };
+
+ const rifmFormat = React.useMemo(() => {
+ const formattedDateWith1Digit = staticDateWith1DigitTokens.format(format);
+ const inferredFormatPatternWith1Digits = formattedDateWith1Digit.replace(
+ ACCEPT_REGEX,
+ MASK_USER_INPUT_SYMBOL,
+ );
+ const inferredFormatPatternWith2Digits = staticDateWith2DigitTokens
+ .format(format)
+ .replace(ACCEPT_REGEX, '_');
+
+ if (inferredFormatPatternWith1Digits !== inferredFormatPatternWith2Digits) {
+ throw new Error(
+ `Mask does not support numbers with variable length such as 'M'.`,
+ );
+ }
+
+ const maskToUse = inferredFormatPatternWith1Digits;
+
+ return function formatMaskedDate(valueToFormat: string) {
+ let outputCharIndex = 0;
+ return valueToFormat
+ .split('')
+ .map((character, characterIndex) => {
+ ACCEPT_REGEX.lastIndex = 0;
+
+ if (outputCharIndex > maskToUse.length - 1) {
+ return '';
+ }
+
+ const maskChar = maskToUse[outputCharIndex];
+ const nextMaskChar = maskToUse[outputCharIndex + 1];
+
+ const acceptedChar = ACCEPT_REGEX.test(character) ? character : '';
+ const formattedChar =
+ maskChar === MASK_USER_INPUT_SYMBOL
+ ? acceptedChar
+ : maskChar + acceptedChar;
+
+ outputCharIndex += formattedChar.length;
+
+ const isLastCharacter = characterIndex === valueToFormat.length - 1;
+ if (
+ isLastCharacter &&
+ nextMaskChar &&
+ nextMaskChar !== MASK_USER_INPUT_SYMBOL
+ ) {
+ // when cursor at the end of mask part (e.g. month) prerender next symbol "21" -> "21/"
+ return formattedChar ? formattedChar + nextMaskChar : '';
+ }
+
+ return formattedChar;
+ })
+ .join('');
+ };
+ }, [format]);
+
+ const rifmProps = useRifm({
+ value: inputValue,
+ onChange: handleValueStrChange,
+ format: rifmFormat,
+ });
+
+ return (
+
+ );
+}
+
+function MaskedFieldDatePicker(props: DatePickerProps) {
+ return ;
+}
+
+export default function MaskedMaterialTextField() {
+ return (
+
+
+
+ );
+}
diff --git a/docs/data/date-pickers/custom-field/custom-behavior/MaskedMaterialTextField.tsx.preview b/docs/data/date-pickers/custom-field/custom-behavior/MaskedMaterialTextField.tsx.preview
new file mode 100644
index 000000000000..1340a82dd55d
--- /dev/null
+++ b/docs/data/date-pickers/custom-field/custom-behavior/MaskedMaterialTextField.tsx.preview
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/data/date-pickers/custom-field/custom-behavior/ReadOnlyMaterialTextField.tsx b/docs/data/date-pickers/custom-field/custom-behavior/ReadOnlyMaterialTextField.tsx
index c9cdc16eae4e..04223bd73a6e 100644
--- a/docs/data/date-pickers/custom-field/custom-behavior/ReadOnlyMaterialTextField.tsx
+++ b/docs/data/date-pickers/custom-field/custom-behavior/ReadOnlyMaterialTextField.tsx
@@ -16,7 +16,7 @@ import {
} from '@mui/x-date-pickers/hooks';
import { CalendarIcon } from '@mui/x-date-pickers/icons';
-function ReadOnlyDateField(props: DatePickerFieldProps) {
+function ReadOnlyDateField(props: DatePickerFieldProps) {
const { internalProps, forwardedProps } = useSplitFieldProps(props, 'date');
const { value, timezone, format } = internalProps;
const { InputProps, slotProps, slots, ...other } = forwardedProps;
diff --git a/docs/data/date-pickers/custom-field/custom-field.md b/docs/data/date-pickers/custom-field/custom-field.md
index 4f5b5f782fb3..9c4cc5216bb3 100644
--- a/docs/data/date-pickers/custom-field/custom-field.md
+++ b/docs/data/date-pickers/custom-field/custom-field.md
@@ -66,30 +66,9 @@ Setting `formatDensity` to `"spacious"` will add a space before and after each `
{{"demo": "FieldFormatDensity.js"}}
-## Usage with Material UI
+## With Material UI
-### Using Material `TextField`
-
-You can import the `TextField` component to create custom wrappers:
-
-{{"demo": "MaterialV6FieldWrapped.js"}}
-
-:::success
-This approach is only recommended if you need complex customizations on your `TextField`,
-or if you already have a wrapper also used outside the Date and Time Pickers.
-
-If you just need to set some default props, you can use [the `slotProps` prop](/x/react-date-pickers/custom-field/#customize-the-textfield).
-:::
-
-### Using Material `PickersTextField`
-
-Pass the `enableAccessibleFieldDOMStructure` to any Field or Picker component to enable the accessible DOM structure:
-
-{{"demo": "MaterialV7Field.js"}}
-
-:::success
-Learn more about the [accessible DOM structure](/x/react-date-pickers/fields/#accessible-dom-structure).
-:::
+### Wrapping `PickersTextField`
You can import the `PickersTextField` component to create custom wrappers:
@@ -101,55 +80,50 @@ This approach is only recommended if you need complex customizations on your `Pi
If you just need to set some default props, you can use [the `slotProps` prop](/x/react-date-pickers/custom-field/#customize-the-textfield).
:::
-## Usage with Joy UI
+### Using Material `TextField`
-### Using Joy `Input`
+Pass the `enableAccessibleFieldDOMStructure={false}` to any Field or Picker component to use an `` for the editing instead of the new accessible DOM structure:
-You can use the [Joy UI](https://mui.com/joy-ui/getting-started/) components instead of the Material UI ones:
+{{"demo": "MaterialV6Field.js"}}
-:::info
-A higher-level solution for _Joy UI_ will be provided in the near future for even simpler usage.
+:::warning
+The non-accessible DOM structure will be deprecated in a follow up minor version and remove in `v9.x`.
+If you are unable to migrate for some reason, please open an issue to describe what is missing from the new DOM structure so that we can improve it before dropping the old one.
:::
-{{"demo": "JoyV6Field.js", "defaultCodeOpen": false}}
-
-{{"demo": "JoyV6SingleInputRangeField.js", "defaultCodeOpen": false}}
-
-{{"demo": "JoyV6MultiInputRangeField.js", "defaultCodeOpen": false}}
+## With another Design System
-### Using Joy `PickersTextField`
+### Using a custom input
:::warning
-This component is not available yet.
+You will need to use a component that supports the `sx` prop as a wrapper for your input
+to be able to benefit from the **hover** and **focus** behavior of the clear button.
+You will have access to the `clearable` and `onClear` props using native HTML elements,
+but the on **focus** and **hover** behavior depends on styles applied via the `sx` prop.
:::
-## Usage with an unstyled input
-
-### Using the browser input
+{{"demo": "BrowserV7Field.js", "defaultCodeOpen": false}}
-{{"demo": "BrowserV6Field.js", "defaultCodeOpen": false}}
+{{"demo": "BrowserV7SingleInputRangeField.js", "defaultCodeOpen": false}}
-{{"demo": "BrowserV6SingleInputRangeField.js", "defaultCodeOpen": false}}
+{{"demo": "BrowserV7MultiInputRangeField.js", "defaultCodeOpen": false}}
-{{"demo": "BrowserV6MultiInputRangeField.js", "defaultCodeOpen": false}}
+### Using Joy UI
-:::warning
-You will need to use a component that supports the `sx` prop as a wrapper for your input, in order to be able to benefit from the **hover** and **focus** behavior of the clear button. You will have access to the `clearable` and `onClear` props using native HTML elements, but the on **focus** and **hover** behavior depends on styles applied via the `sx` prop.
-:::
-
-### Using custom `PickersTextField`
+You can use the [Joy UI](https://mui.com/joy-ui/getting-started/) components instead of the Material UI ones:
-:::success
-Learn more about the accessible DOM structure and its difference compared to the current one on the [dedicated doc section](/x/react-date-pickers/fields/#accessible-dom-structure).
-:::
+{{"demo": "JoyV6Field.js", "defaultCodeOpen": false}}
-{{"demo": "BrowserV7Field.js", "defaultCodeOpen": false}}
+{{"demo": "JoyV6SingleInputRangeField.js", "defaultCodeOpen": false}}
-{{"demo": "BrowserV7SingleInputRangeField.js", "defaultCodeOpen": false}}
+{{"demo": "JoyV6MultiInputRangeField.js", "defaultCodeOpen": false}}
-{{"demo": "BrowserV7MultiInputRangeField.js", "defaultCodeOpen": false}}
+:::warning
+All the Joy UI examples use the non-accessible DOM structure.
+The new accessible DOM structure will become compatible with Joy UI in the future.
+:::
-## Usage with another UI
+## With a custom editing experience
### Using an `Autocomplete`
@@ -158,6 +132,12 @@ you can replace the field with an `Autocomplete` listing those dates:
{{"demo": "PickerWithAutocompleteField.js", "defaultCodeOpen": false}}
+### Using a masked Text Field
+
+If you want to use a simple mask approach for the field editing instead of the built-in logic, you can replace the default field with a Text Field using a masked input value built with the [rifm](https://github.com/realadvisor/rifm) package.
+
+{{"demo": "custom-behavior/MaskedMaterialTextField.js", "defaultCodeOpen": false}}
+
### Using a read-only `TextField`
If you want users to select a value exclusively through the views
@@ -184,22 +164,22 @@ On the examples below, you can see that the typing of the props received by a cu
```tsx
interface JoyDateFieldProps
- extends UseDateFieldProps, // The headless field props
+ extends UseDateFieldProps, // The headless field props
BaseSingleInputFieldProps<
Dayjs | null,
Dayjs,
FieldSection,
- false, // `true` for `enableAccessibleFieldDOMStructure`
+ true, // `false` for `enableAccessibleFieldDOMStructure={false}`
DateValidationError
> {} // The DOM field props
interface JoyDateTimeFieldProps
- extends UseDateTimeFieldProps, // The headless field props
+ extends UseDateTimeFieldProps, // The headless field props
BaseSingleInputFieldProps<
Dayjs | null,
Dayjs,
FieldSection,
- false, // `true` for `enableAccessibleFieldDOMStructure`
+ true, // `false` for `enableAccessibleFieldDOMStructure={false}`
DateTimeValidationError
> {} // The DOM field props
```
diff --git a/docs/data/date-pickers/fields/BasicV7DOMStructure.js b/docs/data/date-pickers/fields/BasicV7DOMStructure.js
index 1f32eca967da..62c0924c3c90 100644
--- a/docs/data/date-pickers/fields/BasicV7DOMStructure.js
+++ b/docs/data/date-pickers/fields/BasicV7DOMStructure.js
@@ -8,7 +8,7 @@ export default function BasicV7DOMStructure() {
return (
-
+
);
diff --git a/docs/data/date-pickers/fields/BasicV7DOMStructure.tsx b/docs/data/date-pickers/fields/BasicV7DOMStructure.tsx
index 1f32eca967da..62c0924c3c90 100644
--- a/docs/data/date-pickers/fields/BasicV7DOMStructure.tsx
+++ b/docs/data/date-pickers/fields/BasicV7DOMStructure.tsx
@@ -8,7 +8,7 @@ export default function BasicV7DOMStructure() {
return (
-
+
);
diff --git a/docs/data/date-pickers/fields/BasicV7DOMStructure.tsx.preview b/docs/data/date-pickers/fields/BasicV7DOMStructure.tsx.preview
index f33bc6c8fdc7..2dc079345c09 100644
--- a/docs/data/date-pickers/fields/BasicV7DOMStructure.tsx.preview
+++ b/docs/data/date-pickers/fields/BasicV7DOMStructure.tsx.preview
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/docs/data/date-pickers/fields/fields.md b/docs/data/date-pickers/fields/fields.md
index 5f54b1411f66..9bd7260fff46 100644
--- a/docs/data/date-pickers/fields/fields.md
+++ b/docs/data/date-pickers/fields/fields.md
@@ -25,201 +25,6 @@ All fields to edit a range are available in a single input version and in a mult
{{"demo": "DateRangeFieldExamples.js", "defaultCodeOpen": false}}
-## Accessible DOM structure
-
-By default, the fields' DOM structure consists of an ``, which holds the whole value for the component, but unfortunately presents a few limitations in terms of accessibility when managing multiple section values.
-
-From v7 version, you can opt-in for a new and experimental DOM structure on any field or picker component using the `enableAccessibleFieldDOMStructure` prop.
-
-```tsx
-
-
-
-```
-
-This new feature allows the field component to set aria attributes on individual sections, providing a far better experience with screen readers.
-
-{{"demo": "BasicV7DOMStructure.js", "defaultCodeOpen": false }}
-
-### Usage with `slotProps.field`
-
-When using `slotProps.field` to pass props to your field component,
-the field consumes some props (e.g: `shouldRespectLeadingZeros`) and forwards the rest to the `TextField`.
-
-- For the props consumed by the field, the behavior should remain exactly the same with both DOM structures.
-
- Both components below will respect the leading zeroes on digit sections:
-
- ```js
-
-
- ```
-
-- For the props forwarded to the `TextField`,
- you can have a look at the next section to see how the migration impact them.
-
- Both components below will render a small size UI:
-
- ```js
-
-
- ```
-
-### Usage with `slotProps.textField`
-
-If you are passing props to `slotProps.textField`,
-these props will now be received by `PickersTextField` and should keep working the same way as before.
-
-Both components below will render a small size UI:
-
-```js
-
-
-```
-
-:::info
-If you are passing `inputProps` to `slotProps.textField`,
-these props will now be passed to the hidden `` element.
-:::
-
-### Usage with `slots.field`
-
-If you are passing a custom field component to your pickers, you need to create a new one that is using the accessible DOM structure.
-This new component will need to use the `PickersSectionList` component instead of an `` HTML element.
-
-You can have a look at the [custom PickersTextField](/x/react-date-pickers/custom-field/#using-custom-pickerstextfield) to have a concrete example.
-
-:::info
-If your custom field was used to create a Joy UI design component,
-you may want to wait a few weeks for the release of an out-of-the-box Joy `PickersTextField` component instead of implementing it yourself.
-:::
-
-### Usage with `slots.textField`
-
-If you are passing a custom `TextField` component to your fields and pickers,
-you need to create a new one that is using the accessible DOM structure.
-
-You can have a look at the second demo of the [Material PickersTextField section](/x/react-date-pickers/custom-field/#using-material-pickerstextfield) to have a concrete example.
-
-:::info
-If your custom `TextField` was used to apply a totally different input that did not use `@mui/material/TextField`,
-please consider having a look at the [custom PickersTextField](/x/react-date-pickers/custom-field/#using-custom-pickerstextfield) section which uses `slots.field`.
-This approach can be more appropriate for deeper changes.
-:::
-
-### Usage with theme
-
-If you are using the theme to customize `MuiTextField`,
-you need to pass the same config to `MuiPickersTextField`:
-
-```js
-const theme = createTheme({
- components: {
- MuiTextField: {
- defaultProps: {
- variant: 'outlined',
- },
- styleOverrides: {
- root: {
- '& .MuiInputLabel-outlined.Mui-focused': {
- color: 'red',
- },
- },
- },
- },
- MuiPickersTextField: {
- defaultProps: {
- variant: 'outlined',
- },
- styleOverrides: {
- root: {
- '& .MuiInputLabel-outlined.Mui-focused': {
- color: 'red',
- },
- },
- },
- },
- },
-});
-```
-
-If you are using the theme to customize `MuiInput`, `MuiOutlinedInput` or `MuiFilledInput`,
-you need to pass the same config to `MuiPickersInput`, `MuiPickersOutlinedInput` or `MuiPickersFilledInput`:
-
-```js
-const theme = createTheme({
- components: {
- // Replace with `MuiOutlinedInput` or `MuiFilledInput` if needed
- MuiInput: {
- defaultProps: {
- margin: 'dense',
- },
- styleOverrides: {
- root: {
- color: 'red',
- },
- },
- },
- // Replace with `MuiPickersOutlinedInput` or `MuiPickersFilledInput` if needed
- MuiPickersInput: {
- defaultProps: {
- margin: 'dense',
- },
- styleOverrides: {
- root: {
- color: 'red',
- },
- },
- },
- },
-});
-```
-
-If you are using the theme to customize `MuiInputBase`,
-you need to pass the same config to `MuiPickersInputBase`:
-
-```js
-const theme = createTheme({
- components: {
- MuiInputBase: {
- defaultProps: {
- margin: 'dense',
- },
- styleOverrides: {
- root: {
- color: 'red',
- },
- },
- },
- MuiPickersInputBase: {
- defaultProps: {
- margin: 'dense',
- },
- styleOverrides: {
- root: {
- color: 'red',
- },
- },
- },
- },
-});
-```
-
## Advanced
### What is a section?
diff --git a/docs/data/date-pickers/localization/localization.md b/docs/data/date-pickers/localization/localization.md
index 9c17517d832a..dab97f4bcb5d 100644
--- a/docs/data/date-pickers/localization/localization.md
+++ b/docs/data/date-pickers/localization/localization.md
@@ -46,7 +46,7 @@ function App({ children }) {
}
```
-Note that `createTheme` accepts any number of arguments.
+Note that `createTheme()` accepts any number of arguments.
If you are already using the [translations of the core components](/material-ui/guides/localization/#locale-text) or the [translations of the Data Grid](/x/react-data-grid/localization/#locale-text), you can add `deDE` as a new argument.
```jsx
@@ -73,7 +73,7 @@ function App({ children }) {
### Using LocalizationProvider
-If you want to pass language translations without using `createTheme` and `ThemeProvider`,
+If you want to pass language translations without using `createTheme()` and `ThemeProvider`,
you can directly load the language translations from the `@mui/x-date-pickers` or `@mui/x-date-pickers-pro` package and pass them to the `LocalizationProvider`.
```jsx
diff --git a/docs/data/date-pickers-component-api-pages.ts b/docs/data/datePickersApiPages.ts
similarity index 98%
rename from docs/data/date-pickers-component-api-pages.ts
rename to docs/data/datePickersApiPages.ts
index f7d4b339ac4f..339472cbea73 100644
--- a/docs/data/date-pickers-component-api-pages.ts
+++ b/docs/data/datePickersApiPages.ts
@@ -1,6 +1,6 @@
import type { MuiPage } from 'docs/src/MuiPage';
-const apiPages: MuiPage[] = [
+const datePickersApiPages: MuiPage[] = [
{
pathname: '/x/api/date-pickers/date-calendar',
title: 'DateCalendar',
@@ -233,4 +233,4 @@ const apiPages: MuiPage[] = [
title: 'YearCalendar',
},
];
-export default apiPages;
+export default datePickersApiPages;
diff --git a/docs/data/introduction/support/support.md b/docs/data/introduction/support/support.md
index 3f65903d7dfb..ebba1a99214b 100644
--- a/docs/data/introduction/support/support.md
+++ b/docs/data/introduction/support/support.md
@@ -42,7 +42,7 @@ You can browse the documentation, find an example close to your use case, and th
- [Data Grid](/x/react-data-grid/#mit-license-free-forever)
- [Date Pickers](/x/react-date-pickers/getting-started/#render-your-first-component)
-- [Charts](/x/react-charts/getting-started/#single-charts)
+- [Charts](/x/react-charts/getting-started/#self-contained-charts)
- [Tree View](/x/react-tree-view/#simple-tree-view)
#### Use starter templates
diff --git a/docs/data/migration/migration-charts-v7/migration-charts-v7.md b/docs/data/migration/migration-charts-v7/migration-charts-v7.md
new file mode 100644
index 000000000000..a23f9406feff
--- /dev/null
+++ b/docs/data/migration/migration-charts-v7/migration-charts-v7.md
@@ -0,0 +1,34 @@
+---
+productId: x-charts
+---
+
+# Migration from v7 to v8
+
+
This guide describes the changes needed to migrate Charts from v7 to v8.
+
+## Introduction
+
+This is a reference guide for upgrading `@mui/x-charts` from v7 to v8.
+The change between v7 and v8 is mostly here to match the version with other MUI X packages.
+No big breaking changes are expected.
+
+## Start using the new release
+
+In `package.json`, change the version of the charts package to `next`.
+
+```diff
+-"@mui/x-charts": "^7.0.0",
++"@mui/x-charts": "next",
+```
+
+Using `next` ensures that it will always use the latest v8 pre-release version, but you can also use a fixed version, like `8.0.0-alpha.0`.
+
+## Breaking changes
+
+Since v8 is a major release, it contains some changes that affect the public API.
+These changes were done for consistency, improve stability and make room for new features.
+Below are described the steps you need to make to migrate from v7 to v8.
+
+:::info
+The list is currently empty, but as we move forward with development during the alpha and beta phases, we'll feed this page with all changes in the API.
+:::
diff --git a/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md b/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md
new file mode 100644
index 000000000000..eea548d0fbc0
--- /dev/null
+++ b/docs/data/migration/migration-data-grid-v7/migration-data-grid-v7.md
@@ -0,0 +1,78 @@
+---
+productId: x-data-grid
+---
+
+# Migration from v7 to v8
+
+
This guide describes the changes needed to migrate the Data Grid from v7 to v8.
+
+## Introduction
+
+This is a reference guide for upgrading `@mui/x-data-grid` from v7 to v8.
+
+## Start using the new release
+
+In `package.json`, change the version of the Data Grid package to `next`.
+
+```diff
+-"@mui/x-data-grid": "^7.0.0",
++"@mui/x-data-grid": "next",
+
+-"@mui/x-data-grid-pro": "^7.0.0",
++"@mui/x-data-grid-pro": "next",
+
+-"@mui/x-data-grid-premium": "^7.0.0",
++"@mui/x-data-grid-premium": "next",
+```
+
+Using `next` ensures that it will always use the latest v8 pre-release version, but you can also use a fixed version, like `8.0.0-alpha.0`.
+
+## Breaking changes
+
+Since v8 is a major release, it contains some changes that affect the public API.
+These changes were done for consistency, improve stability and make room for new features.
+Below are described the steps you need to make to migrate from v7 to v8.
+
+:::info
+The list is currently empty, but as we move forward with development during the alpha and beta phases, we'll feed this page with all changes in the API.
+:::
+
+
diff --git a/docs/data/migration/migration-pickers-v6/migration-pickers-v6.md b/docs/data/migration/migration-pickers-v6/migration-pickers-v6.md
index 787bbefb3182..ab73ca9e1900 100644
--- a/docs/data/migration/migration-pickers-v6/migration-pickers-v6.md
+++ b/docs/data/migration/migration-pickers-v6/migration-pickers-v6.md
@@ -440,7 +440,7 @@ The headless field hooks (e.g.: `useDateField`) now return a new prop called `en
This is used to know if the current UI expected is built using the accessible DOM structure or not.
:::info
-See [Fields—Accessible DOM structure](/x/react-date-pickers/fields/#accessible-dom-structure) for more details.
+See [Migration from v7 to v8—New DOM structure for the field](/x/migration/migration-pickers-v7/#new-dom-structure-for-the-field) for more details.
:::
When building a custom UI, you are most-likely only supporting one DOM structure, so you can remove `enableAccessibleFieldDOMStructure` before it is passed to the DOM:
diff --git a/docs/data/migration/migration-pickers-v7/migration-pickers-v7.md b/docs/data/migration/migration-pickers-v7/migration-pickers-v7.md
new file mode 100644
index 000000000000..18a1f57af80f
--- /dev/null
+++ b/docs/data/migration/migration-pickers-v7/migration-pickers-v7.md
@@ -0,0 +1,316 @@
+---
+productId: x-date-pickers
+---
+
+# Migration from v7 to v8
+
+
This guide describes the changes needed to migrate the Date and Time Pickers from v7 to v8.
+
+## Introduction
+
+This is a reference guide for upgrading `@mui/x-date-pickers` from v7 to v8.
+
+## Start using the new release
+
+In `package.json`, change the version of the date pickers package to `next`.
+
+```diff
+-"@mui/x-date-pickers": "7.x.x",
++"@mui/x-date-pickers": "next",
+```
+
+Using `next` ensures that it will always use the latest v8 pre-release version, but you can also use a fixed version, like `8.0.0-alpha.0`.
+
+Since `v8` is a major release, it contains changes that affect the public API.
+These changes were done for consistency, improved stability and to make room for new features.
+Described below are the steps needed to migrate from v7 to v8.
+
+## Run codemods
+
+The `preset-safe` codemod will automatically adjust the bulk of your code to account for breaking changes in v8. You can run `v8.0.0/pickers/preset-safe` targeting only Date and Time Pickers or `v8.0.0/preset-safe` to target the other packages as well.
+
+You can either run it on a specific file, folder, or your entire codebase when choosing the `` argument.
+
+
+
+```bash
+// Date and Time Pickers specific
+npx @mui/x-codemod@latest v8.0.0/pickers/preset-safe
+
+// Target the other packages as well
+npx @mui/x-codemod@latest v8.0.0/preset-safe
+```
+
+:::info
+If you want to run the transformers one by one, check out the transformers included in the [preset-safe codemod for pickers](https://github.com/mui/mui-x/blob/HEAD/packages/x-codemod/README.md#preset-safe-for-pickers-v800) for more details.
+:::
+
+Breaking changes that are handled by this codemod are denoted by a ✅ emoji in the table of contents on the right side of the screen.
+
+If you have already applied the `v8.0.0/pickers/preset-safe` (or `v8.0.0/preset-safe`) codemod, then you should not need to take any further action on these items.
+
+All other changes must be handled manually.
+
+:::warning
+Not all use cases are covered by codemods. In some scenarios, like props spreading, cross-file dependencies, etc., the changes are not properly identified and therefore must be handled manually.
+
+For example, if a codemod tries to rename a prop, but this prop is hidden with the spread operator, it won't be transformed as expected.
+
+```tsx
+
+```
+
+After running the codemods, make sure to test your application and that you don't have any console errors.
+
+Feel free to [open an issue](https://github.com/mui/mui-x/issues/new/choose) for support if you need help to proceed with your migration.
+:::
+
+## New DOM structure for the field
+
+Before version `v8.x`, the fields' DOM structure consisted of an ``, which held the whole value for the component,
+but unfortunately presents a few limitations in terms of accessibility when managing multiple section values.
+
+Starting with version `v8.x`, all the field and picker components come with a new DOM structure that allows the field component to set aria attributes on individual sections, providing a far better experience with screen readers.
+
+### Fallback to the non-accessible DOM structure
+
+```tsx
+
+
+
+```
+
+### Migrate `slotProps.field`
+
+When using `slotProps.field` to pass props to your field component,
+the field consumes some props (e.g: `shouldRespectLeadingZeros`) and forwards the rest to the `TextField`.
+
+- For the props consumed by the field, the behavior should remain exactly the same with both DOM structures.
+
+ Both components below will respect the leading zeroes on digit sections:
+
+ ```js
+
+
+ ```
+
+- For the props forwarded to the `TextField`,
+ you can have a look at the next section to see how the migration impact them.
+
+ Both components below will render a small size UI:
+
+ ```js
+
+
+ ```
+
+### Migrate `slotProps.textField`
+
+If you are passing props to `slotProps.textField`,
+these props will now be received by `PickersTextField` and should keep working the same way as before.
+
+Both components below will render a small size UI:
+
+```js
+
+
+```
+
+:::info
+If you are passing `inputProps` to `slotProps.textField`,
+these props will now be passed to the hidden `` element.
+:::
+
+### Migrate `slots.field`
+
+If you are passing a custom field component to your pickers, you need to create a new one that is using the accessible DOM structure.
+This new component will need to use the `PickersSectionList` component instead of an `` HTML element.
+
+You can have a look at the [Using a custom input](/x/react-date-pickers/custom-field/#using-a-custom-input) to have a concrete example.
+
+:::info
+If your custom field was used to create a Joy UI design component,
+you may want to wait a few weeks for the release of an out-of-the-box Joy `PickersTextField` component instead of implementing it yourself.
+:::
+
+### Migrate `slots.textField`
+
+If you are passing a custom `TextField` component to your fields and pickers,
+you need to create a new one that is using the accessible DOM structure.
+
+You can have a look at the second demo of the [Wrapping PickersTextField](/x/react-date-pickers/custom-field/#wrapping-pickerstextfield) to have a concrete example.
+
+:::info
+If your custom `TextField` was used to apply a totally different input that did not use `@mui/material/TextField`,
+please consider having a look at the [Using a custom input](/x/react-date-pickers/custom-field/#using-a-custom-input) section which uses `slots.field`.
+This approach can be more appropriate for deeper changes.
+:::
+
+### Migrate the theme
+
+If you are using the theme to customize `MuiTextField`,
+you need to pass the same config to `MuiPickersTextField`:
+
+```js
+const theme = createTheme({
+ components: {
+ MuiTextField: {
+ defaultProps: {
+ variant: 'outlined',
+ },
+ styleOverrides: {
+ root: {
+ '& .MuiInputLabel-outlined.Mui-focused': {
+ color: 'red',
+ },
+ },
+ },
+ },
+ MuiPickersTextField: {
+ defaultProps: {
+ variant: 'outlined',
+ },
+ styleOverrides: {
+ root: {
+ '& .MuiInputLabel-outlined.Mui-focused': {
+ color: 'red',
+ },
+ },
+ },
+ },
+ },
+});
+```
+
+If you are using the theme to customize `MuiInput`, `MuiOutlinedInput` or `MuiFilledInput`,
+you need to pass the same config to `MuiPickersInput`, `MuiPickersOutlinedInput` or `MuiPickersFilledInput`:
+
+```js
+const theme = createTheme({
+ components: {
+ // Replace with `MuiOutlinedInput` or `MuiFilledInput` if needed
+ MuiInput: {
+ defaultProps: {
+ margin: 'dense',
+ },
+ styleOverrides: {
+ root: {
+ color: 'red',
+ },
+ },
+ },
+ // Replace with `MuiPickersOutlinedInput` or `MuiPickersFilledInput` if needed
+ MuiPickersInput: {
+ defaultProps: {
+ margin: 'dense',
+ },
+ styleOverrides: {
+ root: {
+ color: 'red',
+ },
+ },
+ },
+ },
+});
+```
+
+If you are using the theme to customize `MuiInputBase`,
+you need to pass the same config to `MuiPickersInputBase`:
+
+```js
+const theme = createTheme({
+ components: {
+ MuiInputBase: {
+ defaultProps: {
+ margin: 'dense',
+ },
+ styleOverrides: {
+ root: {
+ color: 'red',
+ },
+ },
+ },
+ MuiPickersInputBase: {
+ defaultProps: {
+ margin: 'dense',
+ },
+ styleOverrides: {
+ root: {
+ color: 'red',
+ },
+ },
+ },
+ },
+});
+```
+
+## Removed types
+
+The following types are no longer exported by `@mui/x-date-pickers` and/or `@mui/x-date-pickers-pro`.
+If you were using them, you need to replace them with the following code:
+
+- `UseDateFieldComponentProps`
+
+ ```ts
+ import { UseDateFieldProps } from '@mui/x-date-pickers/DateField';
+ import { PickerValidDate } from '@mui/x-date-pickers/models';
+
+ type UseDateFieldComponentProps<
+ TDate extends PickerValidDate,
+ TEnableAccessibleFieldDOMStructure extends boolean,
+ TChildProps extends {},
+ > = Omit<
+ TChildProps,
+ keyof UseDateFieldProps
+ > &
+ UseDateFieldProps;
+ ```
+
+- `UseTimeFieldComponentProps`
+
+ ```ts
+ import { UseTimeFieldProps } from '@mui/x-date-pickers/TimeField';
+ import { PickerValidDate } from '@mui/x-date-pickers/models';
+
+ type UseTimeFieldComponentProps<
+ TDate extends PickerValidDate,
+ TEnableAccessibleFieldDOMStructure extends boolean,
+ TChildProps extends {},
+ > = Omit<
+ TChildProps,
+ keyof UseTimeFieldProps
+ > &
+ UseTimeFieldProps;
+ ```
+
+- `UseDateTimeFieldComponentProps`
+
+ ```ts
+ import { UseDateTimeFieldProps } from '@mui/x-date-pickers/DateTimeField';
+ import { PickerValidDate } from '@mui/x-date-pickers/models';
+
+ type UseDateTimeFieldComponentProps<
+ TDate extends PickerValidDate,
+ TEnableAccessibleFieldDOMStructure extends boolean,
+ TChildProps extends {},
+ > = Omit<
+ TChildProps,
+ keyof UseDateTimeFieldProps
+ > &
+ UseDateTimeFieldProps;
+ ```
diff --git a/docs/data/migration/migration-tree-view-lab/migration-tree-view-lab.md b/docs/data/migration/migration-tree-view-lab/migration-tree-view-lab.md
index 2b1a932e33ff..3fc640a64832 100644
--- a/docs/data/migration/migration-tree-view-lab/migration-tree-view-lab.md
+++ b/docs/data/migration/migration-tree-view-lab/migration-tree-view-lab.md
@@ -8,7 +8,7 @@ productId: x-tree-view
## Introduction
-This is a reference for migrating your site's tree view from `@mui/lab` to `@mui/x-tree-view`.
+This is a reference for migrating your site's Tree View from `@mui/lab` to `@mui/x-tree-view`.
This migration is about the npm packages used, it **does not** affect the behavior of the components in your application.
[//]: # 'You can find why we are moving in this direction in the [announcement blog post](/blog/lab-tree-view-to-mui-x/).'
diff --git a/docs/data/migration/migration-tree-view-v6/migration-tree-view-v6.md b/docs/data/migration/migration-tree-view-v6/migration-tree-view-v6.md
index 7d979f8af087..2efbd13455fd 100644
--- a/docs/data/migration/migration-tree-view-v6/migration-tree-view-v6.md
+++ b/docs/data/migration/migration-tree-view-v6/migration-tree-view-v6.md
@@ -13,7 +13,7 @@ To read more about the changes from the new major, check out [the blog post abou
## Start using the new release
-In `package.json`, change the version of the tree view package to `^7.0.0`.
+In `package.json`, change the version of the Tree View package to `^7.0.0`.
```diff
-"@mui/x-tree-view": "^6.0.0",
@@ -113,7 +113,7 @@ Here is an example of how you can transpile these features on Webpack 4 using th
### ✅ Rename `nodeId` to `itemId`
-The required `nodeId` prop used by the `TreeItem` has been renamed to `itemId` for consistency:
+The required `nodeId` prop used by the Tree Item has been renamed to `itemId` for consistency:
```diff
@@ -140,10 +140,10 @@ The same change has been applied to the `ContentComponent` prop:
}
```
-### ✅ Use `SimpleTreeView` instead of `TreeView`
+### ✅ Use Simple Tree View instead of Tree View
-The `TreeView` component has been deprecated and will be removed in the next major.
-You can start replacing it with the new `SimpleTreeView` component which has exactly the same API:
+The `` component has been deprecated and will be removed in the next major.
+You can start replacing it with the new `` component which has exactly the same API:
```diff
-import { TreeView } from '@mui/x-tree-view';
@@ -193,7 +193,7 @@ If you were using the `treeViewClasses` object, you can replace it with the new
#### Define `expandIcon`
The icon used to expand the children of an item (rendered when this item is collapsed)
-is now defined as a slot both on the Tree View and the `TreeItem` components.
+is now defined as a slot both on the `` and the `` components.
If you were using the `ChevronRight` icon from `@mui/icons-material`,
you can stop passing it to your component because it is now the default value:
@@ -224,7 +224,7 @@ you need to use the new `expandIcon` slot on this component:
Note that the `slots` prop expects a React component, not the JSX element returned when rendering this component.
:::
-If you were passing another icon to your `TreeItem` component,
+If you were passing another icon to your `` component,
you need to use the new `expandIcon` slot on this component:
```diff
@@ -241,7 +241,7 @@ you need to use the new `expandIcon` slot on this component:
#### Define `collapseIcon`
The icon used to collapse the children of an item (rendered when this item is expanded)
-is now defined as a slot both on the Tree View and the `TreeItem` components.
+is now defined as a slot both on the `` and `` components.
If you were using the `ExpandMore` icon from `@mui/icons-material`,
you can stop passing it to your component because it is now the default value:
@@ -272,7 +272,7 @@ you need to use the new `collapseIcon` slot on this component:
Note that the `slots` prop expects a React component, not the JSX element returned when rendering this component.
:::
-If you were passing another icon to your `TreeItem` component,
+If you were passing another icon to your `` component,
you need to use the new `collapseIcon` slot on this component:
```diff
@@ -306,7 +306,7 @@ by passing the same icon to both the `collapseIcon` and the `expandIcon` slots o
#### Define `endIcon`
The icon rendered next to an item without children
-is now defined as a slot both on the Tree View and the `TreeItem` components.
+is now defined as a slot both on the `` and `` components.
If you were passing an icon to your Tree View component,
you need to use the new `endIcon` slot on this component:
@@ -324,7 +324,7 @@ you need to use the new `endIcon` slot on this component:
Note that the `slots` prop expects a React component, not the JSX element returned when rendering this component.
:::
-If you were passing an icon to your `TreeItem` component,
+If you were passing an icon to your `` component,
you need to use the new `endIcon` slot on this component:
```diff
@@ -341,9 +341,9 @@ you need to use the new `endIcon` slot on this component:
#### Define `icon`
The icon rendered next to an item
-is now defined as a slot on the `TreeItem` component.
+is now defined as a slot on the `` component.
-If you were passing an icon to your `TreeItem` component,
+If you were passing an icon to your `` component,
you need to use the new `icon` slot on this component:
```diff
@@ -364,9 +364,9 @@ Note that the `slots` prop expects a React component, not the JSX element return
### ✅ Use slots to define the group transition
The component used to animate the item children
-is now defined as a slot on the `TreeItem` component.
+is now defined as a slot on the `` component.
-If you were passing a `TransitionComponent` or `TransitionProps` to your `TreeItem` component,
+If you were passing a `TransitionComponent` or `TransitionProps` to your `` component,
you need to use the new `groupTransition` slot on this component:
```diff
@@ -382,9 +382,9 @@ you need to use the new `groupTransition` slot on this component:
```
-### Rename the `group` class of the `TreeItem` component
+### Rename the `group` class of the Tree Item component
-The `group` class of the `TreeItem` component has been renamed to `groupTransition` to match with its new slot name.
+The `group` class of the `` component has been renamed to `groupTransition` to match with its new slot name.
```diff
const StyledTreeItem = styled(TreeItem)({
@@ -423,7 +423,7 @@ If you were using the `onNodeToggle` prop to react to the expansion or collapse
you can use the new `onItemExpansionToggle` prop which is called whenever an item is expanded or collapsed with its id and expansion status
```tsx
-// It is also available on the deprecated `TreeView` component
+// It is also available on the deprecated Tree View component
console.log(itemId, isExpanded)
@@ -461,7 +461,7 @@ If you were using the `onNodeSelect` prop to react to the selection or deselecti
you can use the new `onItemSelectionToggle` prop which is called whenever an item is selected or deselected with its id and selection status.
```tsx
-// It is also available on the deprecated `TreeView` component
+// It is also available on the deprecated `` component
console.log(itemId, isSelected)
@@ -512,7 +512,7 @@ For example, if you were writing a test with `react-testing-library`, here is wh
### ✅ Use `useTreeItemState` instead of `useTreeItem`
The `useTreeItem` hook has been renamed `useTreeItemState`.
-This will help create a new headless version of the `TreeItem` component based on a future `useTreeItem` hook.
+This will help create a new headless version of the Tree Item component based on a future `useTreeItem` hook.
```diff
-import { TreeItem, useTreeItem } from '@mui/x-tree-view/TreeItem';
diff --git a/docs/data/migration/migration-tree-view-v7/migration-tree-view-v7.md b/docs/data/migration/migration-tree-view-v7/migration-tree-view-v7.md
new file mode 100644
index 000000000000..c76698100726
--- /dev/null
+++ b/docs/data/migration/migration-tree-view-v7/migration-tree-view-v7.md
@@ -0,0 +1,180 @@
+---
+productId: x-tree-view
+---
+
+# Migration from v7 to v8
+
+
This guide describes the changes needed to migrate the Tree View from v7 to v8.
+
+## Introduction
+
+This is a reference guide for upgrading `@mui/x-tree-view` from v7 to v8.
+
+## Start using the new release
+
+In `package.json`, change the version of the Tree View package to `next`.
+
+```diff
+-"@mui/x-tree-view": "7.x.x",
++"@mui/x-tree-view": "next",
+```
+
+Using `next` ensures that it will always use the latest v8 pre-release version, but you can also use a fixed version, like `8.0.0-alpha.0`.
+
+Since `v8` is a major release, it contains changes that affect the public API.
+These changes were done for consistency, improved stability and to make room for new features.
+Described below are the steps needed to migrate from v7 to v8.
+
+## Run codemods
+
+The `preset-safe` codemod will automatically adjust the bulk of your code to account for breaking changes in v8. You can run `v8.0.0/tree-view/preset-safe` targeting only Tree View or `v8.0.0/preset-safe` to target the other packages as well.
+
+You can either run it on a specific file, folder, or your entire codebase when choosing the `` argument.
+
+
+
+```bash
+// Tree View specific
+npx @mui/x-codemod@latest v8.0.0/tree-view/preset-safe
+
+// Target the other packages as well
+npx @mui/x-codemod@latest v8.0.0/preset-safe
+```
+
+:::info
+If you want to run the transformers one by one, check out the transformers included in the [preset-safe codemod for the Tree View](https://github.com/mui/mui-x/blob/HEAD/packages/x-codemod/README.md#preset-safe-for-tree-view-v800) for more details.
+:::
+
+Breaking changes that are handled by this codemod are denoted by a ✅ emoji in the table of contents on the right side of the screen.
+
+If you have already applied the `v8.0.0/tree-view/preset-safe` (or `v8.0.0/preset-safe`) codemod, then you should not need to take any further action on these items.
+
+All other changes must be handled manually.
+
+:::warning
+Not all use cases are covered by codemods. In some scenarios, like props spreading, cross-file dependencies, etc., the changes are not properly identified and therefore must be handled manually.
+
+For example, if a codemod tries to rename a prop, but this prop is hidden with the spread operator, it won't be transformed as expected.
+
+```tsx
+
+```
+
+After running the codemods, make sure to test your application and that you don't have any console errors.
+
+Feel free to [open an issue](https://github.com/mui/mui-x/issues/new/choose) for support if you need help to proceed with your migration.
+:::
+
+## New API to customize the Tree Item
+
+The `ContentComponent` or `ContentProps` props of the `TreeItem` component have been removed in favor of the new `slots`, `slotProps` props and of the `useTreeItem` hook.
+
+Learn more about the anatomy of the Tree Items and the customization utilities provided on the [Tree Item Customization page](/x/react-tree-view/tree-item-customization/).
+
+## Behavior change on the `onClick` and `onMouseDown` props of `TreeItem`
+
+The `onClick` and `onMouseDown` were the only event callback that were passed to the content of the Tree Item instead of its root.
+The goal was to make sure that the callback was not fired when clicking on a descendant of a giving item.
+This inconsistency has been solved, all the event manager now target the root of the item, and you can use the `onItemClick` prop on the Tree View component to target the content of an item:
+
+```diff
+-
++
+-
++
+
+```
+
+## Rename the `TreeItem2` (and related utils)
+
+All the new Tree Item-related components and utils (introduced in the previous major to improve the DX of the Tree Item component) are becoming the default way of using the Tree Item and are therefore losing their `2` suffix:
+
+```diff
+ import * as React from 'react';
+ import {
+- TreeItem2,
++ TreeItem,
+- TreeItem2Root,
++ TreeItemRoot,
+- TreeItem2Content,
++ TreeItemContent,
+- TreeItem2IconContainer,
++ TreeItemIconContainer,
+- TreeItem2GroupTransition,
++ TreeItemGroupTransition,
+- TreeItem2Checkbox,
++ TreeItemCheckbox,
+- TreeItem2Label,
++ TreeItemLabel,
+- TreeItem2Props,
++ TreeItemProps,
+- TreeItem2Slots,
++ TreeItemSlots,
+- TreeItem2SlotProps,
++ TreeItemSlotProps,
+- } from '@mui/x-tree-view/TreeItem2';
++ } from '@mui/x-tree-view/TreeItem';
+ import {
+- useTreeItem2,
++ useTreeItem,
+- unstable_useTreeItem2 as useAliasedTreeItem,
++ unstable_useTreeItem as useAliasedTreeItem,
+- UseTreeItem2Parameters,
++ UseTreeItemParameters,
+- UseTreeItem2ReturnValue,
++ UseTreeItemReturnValue,
+- UseTreeItem2Status,
++ UseTreeItemStatus,
+- UseTreeItem2RootSlotOwnProps,
++ UseTreeItemRootSlotOwnProps,
+- UseTreeItem2ContentSlotOwnProps,
++ UseTreeItemContentSlotOwnProps,
+- UseTreeItem2LabelInputSlotOwnProps,
++ UseTreeItemLabelInputSlotOwnProps,
+- UseTreeItem2LabelSlotOwnProps,
++ UseTreeItemLabelSlotOwnProps,
+- UseTreeItem2CheckboxSlotOwnProps,
++ UseTreeItemCheckboxSlotOwnProps,
+- UseTreeItem2IconContainerSlotOwnProps,
++ UseTreeItemIconContainerSlotOwnProps,
+- UseTreeItem2GroupTransitionSlotOwnProps,
++ UseTreeItemGroupTransitionSlotOwnProps,
+- UseTreeItem2DragAndDropOverlaySlotOwnProps,
++ UseTreeItemDragAndDropOverlaySlotOwnProps,
+- } from '@mui/x-tree-view/useTreeItem2';
++ } from '@mui/x-tree-view/useTreeItem';
+- import { useTreeItem2Utils } from '@mui/x-tree-view/hooks';
++ import { useTreeItemUtils } from '@mui/x-tree-view/hooks';
+ import {
+- TreeItem2Provider,
++ TreeItemProvider,
+- TreeItem2ProviderProps,
++ TreeItemProviderProps,
+- } from '@mui/x-tree-view/TreeItem2Provider';
++ } from '@mui/x-tree-view/TreeItemProvider';
+ import {
+- TreeItem2Icon,
++ TreeItemIcon,
+- TreeItem2IconProps,
++ TreeItemIconProps,
+- TreeItem2IconSlots,
++ TreeItemIconSlots,
+- TreeItem2IconSlotProps,
++ TreeItemIconSlotProps,
+- } from '@mui/x-tree-view/TreeItem2Icon';
++ } from '@mui/x-tree-view/TreeItemIcon';
+ import {
+- TreeItem2DragAndDropOverlay,
++ TreeItemDragAndDropOverlay,
+- TreeItem2DragAndDropOverlayProps,
++ TreeItemDragAndDropOverlayProps,
+- } from '@mui/x-tree-view/TreeItem2DragAndDropOverlay';
++ } from '@mui/x-tree-view/TreeItemDragAndDropOverlay';
+ import {
+- TreeItem2LabelInput,
++ TreeItemLabelInput,
+- TreeItem2LabelInputProps,
++ TreeItemLabelInputProps,
+- } from '@mui/x-tree-view/TreeItem2LabelInput';
++ } from '@mui/x-tree-view/TreeItemLabelInput';
+```
diff --git a/docs/data/pages.ts b/docs/data/pages.ts
index b952b8a5b722..361b46837c94 100644
--- a/docs/data/pages.ts
+++ b/docs/data/pages.ts
@@ -1,8 +1,8 @@
import type { MuiPage } from 'docs/src/MuiPage';
-import chartsComponentApi from './charts-component-api-pages';
-import dataGridComponentApi from './data-grid-component-api-pages';
-import pickersComponentApi from './date-pickers-component-api-pages';
-import treeViewComponentApi from './tree-view-component-api-pages';
+import chartsComponentApi from './chartsApiPages';
+import dataGridComponentApi from './dataGridApiPages';
+import pickersComponentApi from './datePickersApiPages';
+import treeViewComponentApi from './treeViewApiPages';
const pages: MuiPage[] = [
{
@@ -120,8 +120,9 @@ const pages: MuiPage[] = [
pathname: '/x/react-data-grid/server-side-data-group',
title: 'Server-side data',
plan: 'pro',
+ newFeature: true,
children: [
- { pathname: '/x/react-data-grid/server-side-data', title: 'Overview' },
+ { pathname: '/x/react-data-grid/server-side-data', title: 'Overview', plan: 'pro' },
{ pathname: '/x/react-data-grid/server-side-data/tree-data', plan: 'pro' },
{
pathname: '/x/react-data-grid/server-side-data/lazy-loading',
@@ -135,8 +136,7 @@ const pages: MuiPage[] = [
},
{
pathname: '/x/react-data-grid/server-side-data/row-grouping',
- plan: 'pro',
- planned: true,
+ plan: 'premium',
},
{
pathname: '/x/react-data-grid/server-side-data/aggregation',
@@ -537,9 +537,28 @@ const pages: MuiPage[] = [
pathname: '/x/migration-group',
title: 'Migration',
children: [
+ {
+ pathname: '/x/migration-v8',
+ subheader: 'Upgrade to v8',
+ children: [
+ { pathname: '/x/migration/migration-data-grid-v7', title: 'Breaking changes: Data Grid' },
+ {
+ pathname: '/x/migration/migration-pickers-v7',
+ title: 'Breaking changes: Date and Time Pickers',
+ },
+ {
+ pathname: '/x/migration/migration-tree-view-v7',
+ title: 'Breaking changes: Tree View',
+ },
+ {
+ pathname: '/x/migration/migration-charts-v7',
+ title: 'Breaking changes: Charts',
+ },
+ ],
+ },
{
pathname: '/x/migration-v7',
- subheader: 'Upgrade to v7',
+ title: 'Upgrade to v7',
children: [
{ pathname: '/x/migration/migration-data-grid-v6', title: 'Breaking changes: Data Grid' },
{
diff --git a/docs/data/tree-view/accessibility/accessibility.md b/docs/data/tree-view/accessibility/accessibility.md
index b1fc45bfc690..cc9c2306612b 100644
--- a/docs/data/tree-view/accessibility/accessibility.md
+++ b/docs/data/tree-view/accessibility/accessibility.md
@@ -54,7 +54,7 @@ Type-ahead is supported for single characters. When typing a character, focus mo
## Selection
-The tree view supports both single and multi-selection. To learn more about the selection API, visit the dedicated page for the [Simple Tree View](/x/react-tree-view/simple-tree-view/selection/) or the [Rich Tree View](/x/react-tree-view/rich-tree-view/selection/).
+The Tree View supports both single and multi-selection. To learn more about the selection API, visit the dedicated page for the [Simple Tree View](/x/react-tree-view/simple-tree-view/selection/) or the [Rich Tree View](/x/react-tree-view/rich-tree-view/selection/).
To read more about the distinction between selection and focus, you can refer to the [WAI-ARIA Authoring Practices guide](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_focus_vs_selection).
diff --git a/docs/data/tree-view/datasets/employees.ts b/docs/data/tree-view/datasets/employees.ts
new file mode 100644
index 000000000000..2af62416f36e
--- /dev/null
+++ b/docs/data/tree-view/datasets/employees.ts
@@ -0,0 +1,40 @@
+import { TreeViewBaseItem } from '@mui/x-tree-view/models';
+
+export const EMPLOYEES_DATASET: TreeViewBaseItem[] = [
+ {
+ id: '0',
+ label: 'Sarah',
+ },
+ {
+ id: '1',
+ label: 'Thomas',
+ children: [
+ { id: '2', label: 'Robert' },
+ { id: '3', label: 'Karen' },
+ { id: '4', label: 'Nancy' },
+ { id: '5', label: 'Daniel' },
+ { id: '6', label: 'Christopher' },
+ { id: '7', label: 'Donald' },
+ ],
+ },
+ {
+ id: '8',
+ label: 'Mary',
+ children: [
+ {
+ id: '9',
+ label: 'Jennifer',
+ children: [{ id: '10', label: 'Anna' }],
+ },
+ { id: '11', label: 'Michael' },
+ {
+ id: '12',
+ label: 'Linda',
+ children: [
+ { id: '13', label: 'Elizabeth' },
+ { id: '14', label: 'William' },
+ ],
+ },
+ ],
+ },
+];
diff --git a/docs/data/tree-view/getting-started/getting-started.md b/docs/data/tree-view/getting-started/getting-started.md
index 79dc191bdc92..6acc9e5382c1 100644
--- a/docs/data/tree-view/getting-started/getting-started.md
+++ b/docs/data/tree-view/getting-started/getting-started.md
@@ -72,7 +72,7 @@ Take a look at the [Styled engine guide](/material-ui/integrations/styled-compon
## Render your first component
-To make sure that everything is set up correctly, try rendering a `SimpleTreeView` component:
+To make sure that everything is set up correctly, try rendering a Simple Tree View component:
{{"demo": "FirstComponent.js"}}
@@ -82,7 +82,7 @@ To make sure that everything is set up correctly, try rendering a `SimpleTreeVie
The component follows the WAI-ARIA authoring practices.
-To have an accessible tree view you must use `aria-labelledby`
+To have an accessible Tree View you must use `aria-labelledby`
or `aria-label` to reference or provide a label on the TreeView,
otherwise, screen readers will announce it as "tree", making it hard to understand the context of a specific tree item.
diff --git a/docs/data/tree-view/overview/overview.md b/docs/data/tree-view/overview/overview.md
index 64c374965652..e1c49a7e2bd6 100644
--- a/docs/data/tree-view/overview/overview.md
+++ b/docs/data/tree-view/overview/overview.md
@@ -41,75 +41,3 @@ This is the recommended version for larger trees, as well as those that require
:::info
At the moment, the Simple and Rich Tree Views are similar in terms of feature support. But as the component grows, you can expect to see the more advanced ones appear primarily on the Rich Tree View.
:::
-
-### Tree Item components
-
-The `@mui/x-tree-view` package exposes two different components to define your tree items:
-
-- `TreeItem`
-- `TreeItem2`
-
-#### `TreeItem`
-
-This is the long-standing component that is very similar to the one used in previous versions (`@mui/x-tree-view@6` and `@mui/lab`).
-
-When using `SimpleTreeView`,
-you can import it from `@mui/x-tree-view/TreeItem` and use it as a child of the `SimpleTreeView` component:
-
-```tsx
-import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView';
-import { TreeItem } from '@mui/x-tree-view/TreeItem';
-
-export default function App() {
- return (
-
-
-
-
- );
-}
-```
-
-When using `RichTreeView`,
-you don't have to import anything; it's the default component used to render the items:
-
-```tsx
-import { RichTreeView } from '@mui/x-tree-view/RichTreeView';
-
-export default function App() {
- return ;
-}
-```
-
-#### `TreeItem2`
-
-This is a new component that provides a more powerful customization API, and will eventually replace `TreeItem`.
-
-When using `SimpleTreeView`,
-you can import it from `@mui/x-tree-view/TreeItem2` and use it as a child of the `SimpleTreeView` component:
-
-```tsx
-import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView';
-import { TreeItem2 } from '@mui/x-tree-view/TreeItem2';
-
-export default function App() {
- return (
-
-
-
-
- );
-}
-```
-
-When using `RichTreeView`,
-you can import it from `@mui/x-tree-view/TreeItem2` and pass it as a slot of the `RichTreeView` component:
-
-```tsx
-import { RichTreeView } from '@mui/x-tree-view/RichTreeView';
-import { TreeItem2 } from '@mui/x-tree-view/TreeItem2';
-
-export default function App() {
- return ;
-}
-```
diff --git a/docs/data/tree-view/rich-tree-view/customization/FileExplorer.js b/docs/data/tree-view/rich-tree-view/customization/FileExplorer.js
index 305d77fc61a3..304f82faaf74 100644
--- a/docs/data/tree-view/rich-tree-view/customization/FileExplorer.js
+++ b/docs/data/tree-view/rich-tree-view/customization/FileExplorer.js
@@ -14,18 +14,18 @@ import ImageIcon from '@mui/icons-material/Image';
import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf';
import VideoCameraBackIcon from '@mui/icons-material/VideoCameraBack';
import { RichTreeView } from '@mui/x-tree-view/RichTreeView';
-import { treeItemClasses } from '@mui/x-tree-view/TreeItem';
-import { useTreeItem2 } from '@mui/x-tree-view/useTreeItem2';
+import { useTreeItem } from '@mui/x-tree-view/useTreeItem';
import {
- TreeItem2Checkbox,
- TreeItem2Content,
- TreeItem2IconContainer,
- TreeItem2Label,
- TreeItem2Root,
-} from '@mui/x-tree-view/TreeItem2';
-import { TreeItem2Icon } from '@mui/x-tree-view/TreeItem2Icon';
-import { TreeItem2Provider } from '@mui/x-tree-view/TreeItem2Provider';
-import { TreeItem2DragAndDropOverlay } from '@mui/x-tree-view/TreeItem2DragAndDropOverlay';
+ TreeItemCheckbox,
+ TreeItemContent,
+ TreeItemIconContainer,
+ TreeItemLabel,
+ TreeItemRoot,
+ treeItemClasses,
+} from '@mui/x-tree-view/TreeItem';
+import { TreeItemIcon } from '@mui/x-tree-view/TreeItemIcon';
+import { TreeItemProvider } from '@mui/x-tree-view/TreeItemProvider';
+import { TreeItemDragAndDropOverlay } from '@mui/x-tree-view/TreeItemDragAndDropOverlay';
const ITEMS = [
{
@@ -79,7 +79,7 @@ function DotIcon() {
);
}
-const StyledTreeItemRoot = styled(TreeItem2Root)(({ theme }) => ({
+const StyledTreeItemRoot = styled(TreeItemRoot)(({ theme }) => ({
color: theme.palette.grey[400],
position: 'relative',
[`& .${treeItemClasses.groupTransition}`]: {
@@ -90,7 +90,7 @@ const StyledTreeItemRoot = styled(TreeItem2Root)(({ theme }) => ({
}),
}));
-const CustomTreeItemContent = styled(TreeItem2Content)(({ theme }) => ({
+const CustomTreeItemContent = styled(TreeItemContent)(({ theme }) => ({
flexDirection: 'row-reverse',
borderRadius: theme.spacing(0.7),
marginBottom: theme.spacing(0.5),
@@ -156,7 +156,7 @@ const StyledTreeItemLabelText = styled(Typography)({
function CustomLabel({ icon: Icon, expandable, children, ...other }) {
return (
- {children}
{expandable && }
-
+
);
}
@@ -219,7 +219,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) {
getDragAndDropOverlayProps,
status,
publicAPI,
- } = useTreeItem2({ id, itemId, children, label, disabled, rootRef: ref });
+ } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref });
const item = publicAPI.getItem(itemId);
const expandable = isExpandable(children);
@@ -231,7 +231,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) {
}
return (
-
+
-
-
-
-
+
+
+
+
-
+
{children && }
-
+
);
});
diff --git a/docs/data/tree-view/rich-tree-view/customization/FileExplorer.tsx b/docs/data/tree-view/rich-tree-view/customization/FileExplorer.tsx
index 6711c554ba9d..09291542de68 100644
--- a/docs/data/tree-view/rich-tree-view/customization/FileExplorer.tsx
+++ b/docs/data/tree-view/rich-tree-view/customization/FileExplorer.tsx
@@ -14,18 +14,18 @@ import ImageIcon from '@mui/icons-material/Image';
import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf';
import VideoCameraBackIcon from '@mui/icons-material/VideoCameraBack';
import { RichTreeView } from '@mui/x-tree-view/RichTreeView';
-import { treeItemClasses } from '@mui/x-tree-view/TreeItem';
-import { useTreeItem2, UseTreeItem2Parameters } from '@mui/x-tree-view/useTreeItem2';
+import { useTreeItem, UseTreeItemParameters } from '@mui/x-tree-view/useTreeItem';
import {
- TreeItem2Checkbox,
- TreeItem2Content,
- TreeItem2IconContainer,
- TreeItem2Label,
- TreeItem2Root,
-} from '@mui/x-tree-view/TreeItem2';
-import { TreeItem2Icon } from '@mui/x-tree-view/TreeItem2Icon';
-import { TreeItem2Provider } from '@mui/x-tree-view/TreeItem2Provider';
-import { TreeItem2DragAndDropOverlay } from '@mui/x-tree-view/TreeItem2DragAndDropOverlay';
+ TreeItemCheckbox,
+ TreeItemContent,
+ TreeItemIconContainer,
+ TreeItemLabel,
+ TreeItemRoot,
+ treeItemClasses,
+} from '@mui/x-tree-view/TreeItem';
+import { TreeItemIcon } from '@mui/x-tree-view/TreeItemIcon';
+import { TreeItemProvider } from '@mui/x-tree-view/TreeItemProvider';
+import { TreeItemDragAndDropOverlay } from '@mui/x-tree-view/TreeItemDragAndDropOverlay';
import { TreeViewBaseItem } from '@mui/x-tree-view/models';
type FileType = 'image' | 'pdf' | 'doc' | 'video' | 'folder' | 'pinned' | 'trash';
@@ -94,7 +94,7 @@ declare module 'react' {
}
}
-const StyledTreeItemRoot = styled(TreeItem2Root)(({ theme }) => ({
+const StyledTreeItemRoot = styled(TreeItemRoot)(({ theme }) => ({
color: theme.palette.grey[400],
position: 'relative',
[`& .${treeItemClasses.groupTransition}`]: {
@@ -103,9 +103,9 @@ const StyledTreeItemRoot = styled(TreeItem2Root)(({ theme }) => ({
...theme.applyStyles('light', {
color: theme.palette.grey[800],
}),
-})) as unknown as typeof TreeItem2Root;
+})) as unknown as typeof TreeItemRoot;
-const CustomTreeItemContent = styled(TreeItem2Content)(({ theme }) => ({
+const CustomTreeItemContent = styled(TreeItemContent)(({ theme }) => ({
flexDirection: 'row-reverse',
borderRadius: theme.spacing(0.7),
marginBottom: theme.spacing(0.5),
@@ -182,7 +182,7 @@ function CustomLabel({
...other
}: CustomLabelProps) {
return (
- {children}
{expandable && }
-
+
);
}
@@ -233,7 +233,7 @@ const getIconFromFileType = (fileType: FileType) => {
};
interface CustomTreeItemProps
- extends Omit,
+ extends Omit,
Omit, 'onFocus'> {}
const CustomTreeItem = React.forwardRef(function CustomTreeItem(
@@ -252,7 +252,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(
getDragAndDropOverlayProps,
status,
publicAPI,
- } = useTreeItem2({ id, itemId, children, label, disabled, rootRef: ref });
+ } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref });
const item = publicAPI.getItem(itemId);
const expandable = isExpandable(children);
@@ -264,7 +264,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(
}
return (
-
+
-
-
-
-
+
+
+
+
-
+
{children && }
-
+
);
});
diff --git a/docs/data/tree-view/rich-tree-view/customization/HeadlessAPI.js b/docs/data/tree-view/rich-tree-view/customization/HeadlessAPI.js
index afb1f90aec17..5619fbf9b31d 100644
--- a/docs/data/tree-view/rich-tree-view/customization/HeadlessAPI.js
+++ b/docs/data/tree-view/rich-tree-view/customization/HeadlessAPI.js
@@ -4,18 +4,18 @@ import Box from '@mui/material/Box';
import Avatar from '@mui/material/Avatar';
import { RichTreeView } from '@mui/x-tree-view/RichTreeView';
-import { useTreeItem2 } from '@mui/x-tree-view/useTreeItem2';
+import { useTreeItem } from '@mui/x-tree-view/useTreeItem';
import {
- TreeItem2Content,
- TreeItem2IconContainer,
- TreeItem2GroupTransition,
- TreeItem2Label,
- TreeItem2Root,
- TreeItem2Checkbox,
-} from '@mui/x-tree-view/TreeItem2';
-import { TreeItem2Icon } from '@mui/x-tree-view/TreeItem2Icon';
-import { TreeItem2Provider } from '@mui/x-tree-view/TreeItem2Provider';
-import { TreeItem2DragAndDropOverlay } from '@mui/x-tree-view/TreeItem2DragAndDropOverlay';
+ TreeItemContent,
+ TreeItemIconContainer,
+ TreeItemGroupTransition,
+ TreeItemLabel,
+ TreeItemRoot,
+ TreeItemCheckbox,
+} from '@mui/x-tree-view/TreeItem';
+import { TreeItemIcon } from '@mui/x-tree-view/TreeItemIcon';
+import { TreeItemProvider } from '@mui/x-tree-view/TreeItemProvider';
+import { TreeItemDragAndDropOverlay } from '@mui/x-tree-view/TreeItemDragAndDropOverlay';
const ITEMS = [
{
@@ -37,7 +37,7 @@ const ITEMS = [
},
];
-const CustomTreeItemContent = styled(TreeItem2Content)(({ theme }) => ({
+const CustomTreeItemContent = styled(TreeItemContent)(({ theme }) => ({
padding: theme.spacing(0.5, 1),
}));
@@ -53,15 +53,15 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) {
getGroupTransitionProps,
getDragAndDropOverlayProps,
status,
- } = useTreeItem2({ id, itemId, children, label, disabled, rootRef: ref });
+ } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref });
return (
-
-
+
+
-
-
-
+
+
+ ({
@@ -73,14 +73,14 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) {
>
{label[0]}
-
-
+
+
-
+
- {children && }
-
-
+ {children && }
+
+
);
});
diff --git a/docs/data/tree-view/rich-tree-view/customization/HeadlessAPI.tsx b/docs/data/tree-view/rich-tree-view/customization/HeadlessAPI.tsx
index d07cd21249f8..c4ac1965cf83 100644
--- a/docs/data/tree-view/rich-tree-view/customization/HeadlessAPI.tsx
+++ b/docs/data/tree-view/rich-tree-view/customization/HeadlessAPI.tsx
@@ -4,18 +4,18 @@ import Box from '@mui/material/Box';
import Avatar from '@mui/material/Avatar';
import { RichTreeView } from '@mui/x-tree-view/RichTreeView';
import { TreeViewBaseItem } from '@mui/x-tree-view/models';
-import { useTreeItem2, UseTreeItem2Parameters } from '@mui/x-tree-view/useTreeItem2';
+import { useTreeItem, UseTreeItemParameters } from '@mui/x-tree-view/useTreeItem';
import {
- TreeItem2Content,
- TreeItem2IconContainer,
- TreeItem2GroupTransition,
- TreeItem2Label,
- TreeItem2Root,
- TreeItem2Checkbox,
-} from '@mui/x-tree-view/TreeItem2';
-import { TreeItem2Icon } from '@mui/x-tree-view/TreeItem2Icon';
-import { TreeItem2Provider } from '@mui/x-tree-view/TreeItem2Provider';
-import { TreeItem2DragAndDropOverlay } from '@mui/x-tree-view/TreeItem2DragAndDropOverlay';
+ TreeItemContent,
+ TreeItemIconContainer,
+ TreeItemGroupTransition,
+ TreeItemLabel,
+ TreeItemRoot,
+ TreeItemCheckbox,
+} from '@mui/x-tree-view/TreeItem';
+import { TreeItemIcon } from '@mui/x-tree-view/TreeItemIcon';
+import { TreeItemProvider } from '@mui/x-tree-view/TreeItemProvider';
+import { TreeItemDragAndDropOverlay } from '@mui/x-tree-view/TreeItemDragAndDropOverlay';
const ITEMS: TreeViewBaseItem[] = [
{
@@ -37,12 +37,12 @@ const ITEMS: TreeViewBaseItem[] = [
},
];
-const CustomTreeItemContent = styled(TreeItem2Content)(({ theme }) => ({
+const CustomTreeItemContent = styled(TreeItemContent)(({ theme }) => ({
padding: theme.spacing(0.5, 1),
}));
interface CustomTreeItemProps
- extends Omit,
+ extends Omit,
Omit, 'onFocus'> {}
const CustomTreeItem = React.forwardRef(function CustomTreeItem(
@@ -60,15 +60,15 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(
getGroupTransitionProps,
getDragAndDropOverlayProps,
status,
- } = useTreeItem2({ id, itemId, children, label, disabled, rootRef: ref });
+ } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref });
return (
-
-
+
+
-
-
-
+
+
+ ({
@@ -80,14 +80,14 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(
>
{(label as string)[0]}
-
-
+
+
-
+
- {children && }
-
-
+ {children && }
+
+
);
});
diff --git a/docs/data/tree-view/rich-tree-view/customization/customization.md b/docs/data/tree-view/rich-tree-view/customization/customization.md
index adfe395f9c19..506acec5ae8c 100644
--- a/docs/data/tree-view/rich-tree-view/customization/customization.md
+++ b/docs/data/tree-view/rich-tree-view/customization/customization.md
@@ -1,7 +1,7 @@
---
productId: x-tree-view
title: Rich Tree View - Customization
-components: RichTreeView, TreeItem, TreeItem2
+components: RichTreeView, TreeItem
packageName: '@mui/x-tree-view'
githubLabel: 'component: tree view'
waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/
@@ -26,7 +26,7 @@ The demo below shows how to add icons using both an existing icon library, such
### Custom toggle animations
-Use the `groupTransition` slot on the `TreeItem` to pass a component that handles your animation.
+Use the `groupTransition` slot on the `` to pass a component that handles your animation.
The demo below is animated using Material UI's [Collapse](/material-ui/transitions/#collapse) component together with the [react-spring](https://www.react-spring.dev/) library.
@@ -45,7 +45,7 @@ Learn more about the anatomy of the Tree Item components and the customization u
### Headless API
-Use the `useTreeItem2` hook to create your own component.
+Use the `useTreeItem` hook to create your own component.
The demo below shows how to add an avatar and custom typography elements.
{{"demo": "HeadlessAPI.js", "defaultCodeOpen": false}}
@@ -54,13 +54,6 @@ The demo below shows how to add an avatar and custom typography elements.
### File explorer
-:::warning
-This example is built using the new `TreeItem2` component
-which adds several slots to modify the content of the Tree Item or change its behavior.
-
-You can learn more about this new component in the [Overview page](/x/react-tree-view/#tree-item-components).
-:::
-
The demo below shows many of the previous customization examples brought together to make the Tree View component look completely different than its default design.
{{"demo": "FileExplorer.js", "defaultCodeOpen": false}}
diff --git a/docs/data/tree-view/rich-tree-view/editing/CustomBehavior.js b/docs/data/tree-view/rich-tree-view/editing/CustomBehavior.js
index 4c52e4c94ec8..e6ed064a1613 100644
--- a/docs/data/tree-view/rich-tree-view/editing/CustomBehavior.js
+++ b/docs/data/tree-view/rich-tree-view/editing/CustomBehavior.js
@@ -1,13 +1,13 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import { RichTreeView } from '@mui/x-tree-view/RichTreeView';
-import { useTreeItem2Utils } from '@mui/x-tree-view/hooks';
-import { TreeItem2 } from '@mui/x-tree-view/TreeItem2';
+import { useTreeItemUtils } from '@mui/x-tree-view/hooks';
+import { TreeItem } from '@mui/x-tree-view/TreeItem';
import { MUI_X_PRODUCTS } from './products';
-const CustomTreeItem2 = React.forwardRef(function CustomTreeItem2(props, ref) {
- const { interactions } = useTreeItem2Utils({
+const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) {
+ const { interactions } = useTreeItemUtils({
itemId: props.itemId,
children: props.children,
});
@@ -17,7 +17,7 @@ const CustomTreeItem2 = React.forwardRef(function CustomTreeItem2(props, ref) {
};
return (
- ,
) {
- const { interactions } = useTreeItem2Utils({
+ const { interactions } = useTreeItemUtils({
itemId: props.itemId,
children: props.children,
});
- const handleInputBlur: UseTreeItem2LabelInputSlotOwnProps['onBlur'] = (event) => {
+ const handleInputBlur: UseTreeItemLabelInputSlotOwnProps['onBlur'] = (event) => {
interactions.handleCancelItemLabelEditing(event);
};
return (
- ({
...theme.typography.body1,
@@ -53,7 +53,7 @@ export const ITEMS = [
function Label({ children, ...other }) {
return (
-
{children}
-
+
);
}
@@ -136,12 +136,12 @@ const LabelInput = React.forwardRef(function LabelInput(
);
});
-const CustomTreeItem2 = React.forwardRef(function CustomTreeItem2(props, ref) {
- const { interactions } = useTreeItem2Utils({
+const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) {
+ const { interactions } = useTreeItemUtils({
itemId: props.itemId,
children: props.children,
});
- const { publicAPI } = useTreeItem2(props);
+ const { publicAPI } = useTreeItem(props);
const handleInputBlur = (event) => {
event.defaultMuiPrevented = true;
@@ -152,7 +152,7 @@ const CustomTreeItem2 = React.forwardRef(function CustomTreeItem2(props, ref) {
};
return (
- ({
@@ -67,9 +63,9 @@ export const ITEMS: TreeViewBaseItem[] = [
},
];
-function Label({ children, ...other }: UseTreeItem2LabelSlotOwnProps) {
+function Label({ children, ...other }: UseTreeItemLabelSlotOwnProps) {
return (
-
{children}
-
+
);
}
-interface CustomLabelInputProps extends UseTreeItem2LabelInputSlotOwnProps {
+interface CustomLabelInputProps extends UseTreeItemLabelInputSlotOwnProps {
handleCancelItemLabelEditing: (event: React.SyntheticEvent) => void;
handleSaveItemLabel: (event: React.SyntheticEvent, label: string) => void;
item: TreeViewBaseItem;
@@ -163,28 +159,28 @@ const LabelInput = React.forwardRef(function LabelInput(
);
});
-const CustomTreeItem2 = React.forwardRef(function CustomTreeItem2(
- props: TreeItem2Props,
+const CustomTreeItem = React.forwardRef(function CustomTreeItem(
+ props: TreeItemProps,
ref: React.Ref,
) {
- const { interactions } = useTreeItem2Utils({
+ const { interactions } = useTreeItemUtils({
itemId: props.itemId,
children: props.children,
});
- const { publicAPI } = useTreeItem2(props);
+ const { publicAPI } = useTreeItem(props);
- const handleInputBlur: UseTreeItem2LabelInputSlotOwnProps['onBlur'] = (event) => {
+ const handleInputBlur: UseTreeItemLabelInputSlotOwnProps['onBlur'] = (event) => {
event.defaultMuiPrevented = true;
};
- const handleInputKeyDown: UseTreeItem2LabelInputSlotOwnProps['onKeyDown'] = (
+ const handleInputKeyDown: UseTreeItemLabelInputSlotOwnProps['onKeyDown'] = (
event,
) => {
event.defaultMuiPrevented = true;
};
return (
-
)}
-
+
);
}
@@ -43,7 +43,7 @@ function CustomLabelInput(props) {
return (
-
+ void;
@@ -32,7 +28,7 @@ function CustomLabel({
...other
}: CustomLabelProps) {
return (
-
)}
-
+
);
}
-interface CustomLabelInputProps extends UseTreeItem2LabelInputSlotOwnProps {
+interface CustomLabelInputProps extends UseTreeItemLabelInputSlotOwnProps {
handleCancelItemLabelEditing: (event: React.SyntheticEvent) => void;
handleSaveItemLabel: (event: React.SyntheticEvent, label: string) => void;
value: string;
@@ -68,7 +64,7 @@ function CustomLabelInput(props: Omit) {
return (
-
+ ) {
);
}
-const CustomTreeItem2 = React.forwardRef(function CustomTreeItem2(
- props: TreeItem2Props,
+const CustomTreeItem = React.forwardRef(function CustomTreeItem(
+ props: TreeItemProps,
ref: React.Ref,
) {
- const { interactions, status } = useTreeItem2Utils({
+ const { interactions, status } = useTreeItemUtils({
itemId: props.itemId,
children: props.children,
});
- const handleContentDoubleClick: UseTreeItem2LabelSlotOwnProps['onDoubleClick'] = (
+ const handleContentDoubleClick: UseTreeItemLabelSlotOwnProps['onDoubleClick'] = (
event,
) => {
event.defaultMuiPrevented = true;
};
- const handleInputBlur: UseTreeItem2LabelInputSlotOwnProps['onBlur'] = (event) => {
+ const handleInputBlur: UseTreeItemLabelInputSlotOwnProps['onBlur'] = (event) => {
event.defaultMuiPrevented = true;
};
- const handleInputKeyDown: UseTreeItem2LabelInputSlotOwnProps['onKeyDown'] = (
+ const handleInputKeyDown: UseTreeItemLabelInputSlotOwnProps['onKeyDown'] = (
event,
) => {
event.defaultMuiPrevented = true;
};
return (
-
-
+
{error ? (
@@ -34,9 +34,9 @@ function CustomLabelInput(props) {
);
}
-const CustomTreeItem2 = React.forwardRef(function CustomTreeItem2(props, ref) {
+const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) {
const [error, setError] = React.useState(null);
- const { interactions } = useTreeItem2Utils({
+ const { interactions } = useTreeItemUtils({
itemId: props.itemId,
children: props.children,
});
@@ -77,7 +77,7 @@ const CustomTreeItem2 = React.forwardRef(function CustomTreeItem2(props, ref) {
};
return (
- ) {
return (
-
+
{error ? (
@@ -38,12 +38,12 @@ function CustomLabelInput(props: Omit) {
);
}
-const CustomTreeItem2 = React.forwardRef(function CustomTreeItem2(
- props: TreeItem2Props,
+const CustomTreeItem = React.forwardRef(function CustomTreeItem(
+ props: TreeItemProps,
ref: React.Ref,
) {
const [error, setError] = React.useState(null);
- const { interactions } = useTreeItem2Utils({
+ const { interactions } = useTreeItemUtils({
itemId: props.itemId,
children: props.children,
});
@@ -57,13 +57,13 @@ const CustomTreeItem2 = React.forwardRef(function CustomTreeItem2(
}
};
- const handleInputBlur: UseTreeItem2LabelInputSlotOwnProps['onBlur'] = (event) => {
+ const handleInputBlur: UseTreeItemLabelInputSlotOwnProps['onBlur'] = (event) => {
if (error) {
event.defaultMuiPrevented = true;
}
};
- const handleInputKeyDown: UseTreeItem2LabelInputSlotOwnProps['onKeyDown'] = (
+ const handleInputKeyDown: UseTreeItemLabelInputSlotOwnProps['onKeyDown'] = (
event,
) => {
event.defaultMuiPrevented = true;
@@ -86,7 +86,7 @@ const CustomTreeItem2 = React.forwardRef(function CustomTreeItem2(
};
return (
- Create your custom tree view.
+
Create your custom Tree View.
:::warning
The `useTreeView` hook is not public API for now,
@@ -143,7 +143,7 @@ Once `focusedItemId` becomes a model, we could consider removing the notion of s
### Populate the Tree View instance
-The Tree View instance is an object accessible in all the plugins and in the `TreeItem`.
+The Tree View instance is an object accessible in all the plugins and in the Tree Item.
It is the main way a plugin can provide features to the rest of the component.
```ts
@@ -268,7 +268,7 @@ type UseCustomPluginSignature = TreeViewPluginSignature<{
params: UseCustomPluginParams;
// The params specific to your plugins after running `getDefaultizedParams`
defaultizedParams: UseCustomPluginDefaultizedParams;
- // The methods added to the tree view instance by your plugin
+ // The methods added to the Tree View instance by your plugin
instance: UseCustomPluginInstance;
// The events emitted by your plugin
events: UseCustomPluginEvents;
@@ -325,6 +325,6 @@ type UseCustomPluginSignature = TreeViewPluginSignature<{
### Log expanded items
-Interact with the tree view to see the expanded items being logged:
+Interact with the Tree View to see the expanded items being logged:
{{"demo": "LogExpandedItems.js"}}
diff --git a/docs/data/tree-view/rich-tree-view/items/items.md b/docs/data/tree-view/rich-tree-view/items/items.md
index fbf179e3685e..49db9da0a4e2 100644
--- a/docs/data/tree-view/rich-tree-view/items/items.md
+++ b/docs/data/tree-view/rich-tree-view/items/items.md
@@ -28,7 +28,7 @@ Each item must have a unique identifier.
This identifier is used internally to identify the item in the various models and to track the item across updates.
-By default, the `RichTreeView` component looks for a property named `id` in the data set to get that identifier:
+By default, the Rich Tree View component looks for a property named `id` in the data set to get that identifier:
```tsx
const ITEMS = [{ id: 'tree-view-community' }];
@@ -36,7 +36,7 @@ const ITEMS = [{ id: 'tree-view-community' }];
;
```
-If the item's identifier is not called `id`, then you need to use the `getItemId` prop to tell the `RichTreeView` component where it is located.
+If the item's identifier is not called `id`, then you need to use the `getItemId` prop to tell the Rich Tree View component where it is located.
The following demo shows how to use `getItemId` to grab the unique identifier from a property named `internalId`:
@@ -63,7 +63,7 @@ It could be achieved by either defining the prop outside the component scope or
Each item must have a label which does not need to be unique.
-By default, the `RichTreeView` component looks for a property named `label` in the data set to get that label:
+By default, the Rich Tree View component looks for a property named `label` in the data set to get that label:
```tsx
const ITEMS = [{ label: '@mui/x-tree-view' }];
@@ -71,7 +71,7 @@ const ITEMS = [{ label: '@mui/x-tree-view' }];
;
```
-If the item's label is not called `label`, then you need to use the `getItemLabel` prop to tell the `RichTreeView` component where it's located:
+If the item's label is not called `label`, then you need to use the `getItemLabel` prop to tell the Rich Tree View component where it's located:
The following demo shows how to use `getItemLabel` to grab the unique identifier from a property named `name`:
@@ -95,7 +95,7 @@ It could be achieved by either defining the prop outside the component scope or
:::
:::warning
-Unlike the `SimpleTreeView` component, the `RichTreeView` component only supports string labels, you cannot pass React nodes to it.
+Unlike the Simple Tree View component, the Rich Tree View component only supports string labels, you cannot pass React nodes to it.
:::
## Disabled items
@@ -179,7 +179,7 @@ const item = apiRef.current.getItem(
### Get an item's DOM element by ID
-Use the `getItemDOMElement` API method to get an item's DOM element by its ID.
+Use the `getItemDOMElement()` API method to get an item's DOM element by its ID.
```ts
const itemElement = apiRef.current.getItemDOMElement(
diff --git a/docs/data/tree-view/rich-tree-view/ordering/FileExplorer.js b/docs/data/tree-view/rich-tree-view/ordering/FileExplorer.js
index 9a05f402be2c..423926095ed7 100644
--- a/docs/data/tree-view/rich-tree-view/ordering/FileExplorer.js
+++ b/docs/data/tree-view/rich-tree-view/ordering/FileExplorer.js
@@ -10,19 +10,19 @@ import ImageIcon from '@mui/icons-material/Image';
import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf';
import VideoCameraBackIcon from '@mui/icons-material/VideoCameraBack';
import { RichTreeViewPro } from '@mui/x-tree-view-pro/RichTreeViewPro';
-import { treeItemClasses } from '@mui/x-tree-view/TreeItem';
-import { useTreeItem2 } from '@mui/x-tree-view/useTreeItem2';
+import { useTreeItem } from '@mui/x-tree-view/useTreeItem';
import {
- TreeItem2Checkbox,
- TreeItem2Content,
- TreeItem2IconContainer,
- TreeItem2Label,
- TreeItem2Root,
- TreeItem2GroupTransition,
-} from '@mui/x-tree-view/TreeItem2';
-import { TreeItem2Icon } from '@mui/x-tree-view/TreeItem2Icon';
-import { TreeItem2Provider } from '@mui/x-tree-view/TreeItem2Provider';
-import { TreeItem2DragAndDropOverlay } from '@mui/x-tree-view/TreeItem2DragAndDropOverlay';
+ TreeItemCheckbox,
+ TreeItemContent,
+ TreeItemIconContainer,
+ TreeItemLabel,
+ TreeItemRoot,
+ TreeItemGroupTransition,
+ treeItemClasses,
+} from '@mui/x-tree-view/TreeItem';
+import { TreeItemIcon } from '@mui/x-tree-view/TreeItemIcon';
+import { TreeItemProvider } from '@mui/x-tree-view/TreeItemProvider';
+import { TreeItemDragAndDropOverlay } from '@mui/x-tree-view/TreeItemDragAndDropOverlay';
import { useTreeViewApiRef } from '@mui/x-tree-view/hooks';
@@ -80,7 +80,7 @@ function DotIcon() {
);
}
-const StyledTreeItemRoot = styled(TreeItem2Root)(({ theme }) => ({
+const StyledTreeItemRoot = styled(TreeItemRoot)(({ theme }) => ({
color: theme.palette.grey[400],
position: 'relative',
[`& .${treeItemClasses.groupTransition}`]: {
@@ -90,7 +90,7 @@ const StyledTreeItemRoot = styled(TreeItem2Root)(({ theme }) => ({
color: theme.palette.grey[800],
}),
}));
-const CustomTreeItemContent = styled(TreeItem2Content)(({ theme }) => ({
+const CustomTreeItemContent = styled(TreeItemContent)(({ theme }) => ({
flexDirection: 'row-reverse',
borderRadius: theme.spacing(0.7),
marginBottom: theme.spacing(0.5),
@@ -142,7 +142,7 @@ const StyledTreeItemLabelText = styled(Typography)({
function CustomLabel({ icon: Icon, expandable, children, ...other }) {
return (
- {children}
{expandable && }
-
+
);
}
@@ -203,14 +203,14 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) {
getDragAndDropOverlayProps,
status,
publicAPI,
- } = useTreeItem2({ id, itemId, children, label, disabled, rootRef: ref });
+ } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref });
const item = publicAPI.getItem(itemId);
const expandable = isExpandable(children);
const icon = getIconFromFileType(item.fileType);
return (
-
+
-
-
-
-
+
+
+
+
-
+
- {children && }
+ {children && }
-
+
);
});
diff --git a/docs/data/tree-view/rich-tree-view/ordering/FileExplorer.tsx b/docs/data/tree-view/rich-tree-view/ordering/FileExplorer.tsx
index f555c2afd64b..5f5a0434956b 100644
--- a/docs/data/tree-view/rich-tree-view/ordering/FileExplorer.tsx
+++ b/docs/data/tree-view/rich-tree-view/ordering/FileExplorer.tsx
@@ -10,19 +10,19 @@ import ImageIcon from '@mui/icons-material/Image';
import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf';
import VideoCameraBackIcon from '@mui/icons-material/VideoCameraBack';
import { RichTreeViewPro } from '@mui/x-tree-view-pro/RichTreeViewPro';
-import { treeItemClasses } from '@mui/x-tree-view/TreeItem';
-import { useTreeItem2, UseTreeItem2Parameters } from '@mui/x-tree-view/useTreeItem2';
+import { useTreeItem, UseTreeItemParameters } from '@mui/x-tree-view/useTreeItem';
import {
- TreeItem2Checkbox,
- TreeItem2Content,
- TreeItem2IconContainer,
- TreeItem2Label,
- TreeItem2Root,
- TreeItem2GroupTransition,
-} from '@mui/x-tree-view/TreeItem2';
-import { TreeItem2Icon } from '@mui/x-tree-view/TreeItem2Icon';
-import { TreeItem2Provider } from '@mui/x-tree-view/TreeItem2Provider';
-import { TreeItem2DragAndDropOverlay } from '@mui/x-tree-view/TreeItem2DragAndDropOverlay';
+ TreeItemCheckbox,
+ TreeItemContent,
+ TreeItemIconContainer,
+ TreeItemLabel,
+ TreeItemRoot,
+ TreeItemGroupTransition,
+ treeItemClasses,
+} from '@mui/x-tree-view/TreeItem';
+import { TreeItemIcon } from '@mui/x-tree-view/TreeItemIcon';
+import { TreeItemProvider } from '@mui/x-tree-view/TreeItemProvider';
+import { TreeItemDragAndDropOverlay } from '@mui/x-tree-view/TreeItemDragAndDropOverlay';
import { TreeViewBaseItem } from '@mui/x-tree-view/models';
import { useTreeViewApiRef } from '@mui/x-tree-view/hooks';
@@ -94,7 +94,7 @@ declare module 'react' {
}
}
-const StyledTreeItemRoot = styled(TreeItem2Root)(({ theme }) => ({
+const StyledTreeItemRoot = styled(TreeItemRoot)(({ theme }) => ({
color: theme.palette.grey[400],
position: 'relative',
[`& .${treeItemClasses.groupTransition}`]: {
@@ -103,8 +103,8 @@ const StyledTreeItemRoot = styled(TreeItem2Root)(({ theme }) => ({
...theme.applyStyles('light', {
color: theme.palette.grey[800],
}),
-})) as unknown as typeof TreeItem2Root;
-const CustomTreeItemContent = styled(TreeItem2Content)(({ theme }) => ({
+})) as unknown as typeof TreeItemRoot;
+const CustomTreeItemContent = styled(TreeItemContent)(({ theme }) => ({
flexDirection: 'row-reverse',
borderRadius: theme.spacing(0.7),
marginBottom: theme.spacing(0.5),
@@ -167,7 +167,7 @@ function CustomLabel({
...other
}: CustomLabelProps) {
return (
- {children}
{expandable && }
-
+
);
}
@@ -216,7 +216,7 @@ const getIconFromFileType = (fileType: FileType) => {
};
interface CustomTreeItemProps
- extends Omit,
+ extends Omit,
Omit, 'onFocus'> {}
const CustomTreeItem = React.forwardRef(function CustomTreeItem(
@@ -235,14 +235,14 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(
getDragAndDropOverlayProps,
status,
publicAPI,
- } = useTreeItem2({ id, itemId, children, label, disabled, rootRef: ref });
+ } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref });
const item = publicAPI.getItem(itemId);
const expandable = isExpandable(children);
const icon = getIconFromFileType(item.fileType);
return (
-
+
-
-
-
-
+
+
+
+
-
+
- {children && }
+ {children && }
-
+
);
});
diff --git a/docs/data/tree-view/rich-tree-view/ordering/OnlyReorderFromDragHandle.js b/docs/data/tree-view/rich-tree-view/ordering/OnlyReorderFromDragHandle.js
index c9f03403a38f..500411bd806c 100644
--- a/docs/data/tree-view/rich-tree-view/ordering/OnlyReorderFromDragHandle.js
+++ b/docs/data/tree-view/rich-tree-view/ordering/OnlyReorderFromDragHandle.js
@@ -3,18 +3,18 @@ import Box from '@mui/material/Box';
import DragIndicatorIcon from '@mui/icons-material/DragIndicator';
import { RichTreeViewPro } from '@mui/x-tree-view-pro/RichTreeViewPro';
-import { useTreeItem2 } from '@mui/x-tree-view/useTreeItem2';
+import { useTreeItem } from '@mui/x-tree-view/useTreeItem';
import {
- TreeItem2Content,
- TreeItem2IconContainer,
- TreeItem2GroupTransition,
- TreeItem2Label,
- TreeItem2Root,
- TreeItem2Checkbox,
-} from '@mui/x-tree-view/TreeItem2';
-import { TreeItem2Icon } from '@mui/x-tree-view/TreeItem2Icon';
-import { TreeItem2Provider } from '@mui/x-tree-view/TreeItem2Provider';
-import { TreeItem2DragAndDropOverlay } from '@mui/x-tree-view/TreeItem2DragAndDropOverlay';
+ TreeItemContent,
+ TreeItemIconContainer,
+ TreeItemGroupTransition,
+ TreeItemLabel,
+ TreeItemRoot,
+ TreeItemCheckbox,
+} from '@mui/x-tree-view/TreeItem';
+import { TreeItemIcon } from '@mui/x-tree-view/TreeItemIcon';
+import { TreeItemProvider } from '@mui/x-tree-view/TreeItemProvider';
+import { TreeItemDragAndDropOverlay } from '@mui/x-tree-view/TreeItemDragAndDropOverlay';
const MUI_X_PRODUCTS = [
{
@@ -58,7 +58,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) {
getGroupTransitionProps,
getDragAndDropOverlayProps,
status,
- } = useTreeItem2({ id, itemId, children, label, disabled, rootRef: ref });
+ } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref });
const { draggable, onDragStart, onDragOver, onDragEnd, ...otherRootProps } =
getRootProps(other);
@@ -73,27 +73,27 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) {
};
return (
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
- {children && }
-
-
+
+
+
+
+
+ {children && }
+
+
);
});
diff --git a/docs/data/tree-view/rich-tree-view/ordering/OnlyReorderFromDragHandle.tsx b/docs/data/tree-view/rich-tree-view/ordering/OnlyReorderFromDragHandle.tsx
index 8780d381c49b..8b0395890c15 100644
--- a/docs/data/tree-view/rich-tree-view/ordering/OnlyReorderFromDragHandle.tsx
+++ b/docs/data/tree-view/rich-tree-view/ordering/OnlyReorderFromDragHandle.tsx
@@ -3,18 +3,18 @@ import Box from '@mui/material/Box';
import DragIndicatorIcon from '@mui/icons-material/DragIndicator';
import { RichTreeViewPro } from '@mui/x-tree-view-pro/RichTreeViewPro';
import { TreeViewBaseItem } from '@mui/x-tree-view/models';
-import { useTreeItem2, UseTreeItem2Parameters } from '@mui/x-tree-view/useTreeItem2';
+import { useTreeItem, UseTreeItemParameters } from '@mui/x-tree-view/useTreeItem';
import {
- TreeItem2Content,
- TreeItem2IconContainer,
- TreeItem2GroupTransition,
- TreeItem2Label,
- TreeItem2Root,
- TreeItem2Checkbox,
-} from '@mui/x-tree-view/TreeItem2';
-import { TreeItem2Icon } from '@mui/x-tree-view/TreeItem2Icon';
-import { TreeItem2Provider } from '@mui/x-tree-view/TreeItem2Provider';
-import { TreeItem2DragAndDropOverlay } from '@mui/x-tree-view/TreeItem2DragAndDropOverlay';
+ TreeItemContent,
+ TreeItemIconContainer,
+ TreeItemGroupTransition,
+ TreeItemLabel,
+ TreeItemRoot,
+ TreeItemCheckbox,
+} from '@mui/x-tree-view/TreeItem';
+import { TreeItemIcon } from '@mui/x-tree-view/TreeItemIcon';
+import { TreeItemProvider } from '@mui/x-tree-view/TreeItemProvider';
+import { TreeItemDragAndDropOverlay } from '@mui/x-tree-view/TreeItemDragAndDropOverlay';
const MUI_X_PRODUCTS: TreeViewBaseItem[] = [
{
@@ -47,7 +47,7 @@ const MUI_X_PRODUCTS: TreeViewBaseItem[] = [
];
interface CustomTreeItemProps
- extends Omit,
+ extends Omit,
Omit, 'onFocus'> {}
const CustomTreeItem = React.forwardRef(function CustomTreeItem(
@@ -65,7 +65,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(
getGroupTransitionProps,
getDragAndDropOverlayProps,
status,
- } = useTreeItem2({ id, itemId, children, label, disabled, rootRef: ref });
+ } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref });
const { draggable, onDragStart, onDragOver, onDragEnd, ...otherRootProps } =
getRootProps(other);
@@ -84,27 +84,27 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(
};
return (
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
- {children && }
-
-
+
+
+
+
+
+ {children && }
+
+
);
});
diff --git a/docs/data/tree-view/rich-tree-view/ordering/ordering.md b/docs/data/tree-view/rich-tree-view/ordering/ordering.md
index ed28ace0806b..be62d10fd51b 100644
--- a/docs/data/tree-view/rich-tree-view/ordering/ordering.md
+++ b/docs/data/tree-view/rich-tree-view/ordering/ordering.md
@@ -1,7 +1,7 @@
---
productId: x-tree-view
title: Rich Tree View - Ordering
-components: TreeItem2, TreeItem, RichTreeViewPro
+components: TreeItem, RichTreeViewPro, TreeItemDragAndDropOverlay
packageName: '@mui/x-tree-view'
githubLabel: 'component: tree view'
waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/
@@ -50,7 +50,7 @@ You can use the `onItemPositionChange` to send the new position of an item to yo
{{"demo": "OnItemPositionChange.js"}}
If you want to send the entire dataset to your backend, you can use the [`getItemTree`](/x/react-tree-view/rich-tree-view/items/#get-the-current-item-tree) API method.
-The following demo demonstrates it by synchronizing the first tree view with the second one whenever you do a re-ordering:
+The following demo demonstrates it by synchronizing the first Tree View with the second one whenever you do a re-ordering:
{{"demo": "SendAllItemsToServer.js"}}
diff --git a/docs/data/tree-view/rich-tree-view/selection/ParentChildrenSelectionRelationship.js b/docs/data/tree-view/rich-tree-view/selection/ParentChildrenSelectionRelationship.js
deleted file mode 100644
index 8f9dd61e4df9..000000000000
--- a/docs/data/tree-view/rich-tree-view/selection/ParentChildrenSelectionRelationship.js
+++ /dev/null
@@ -1,98 +0,0 @@
-import * as React from 'react';
-import Box from '@mui/material/Box';
-import { RichTreeView } from '@mui/x-tree-view/RichTreeView';
-import { useTreeViewApiRef } from '@mui/x-tree-view/hooks';
-
-const MUI_X_PRODUCTS = [
- {
- id: 'grid',
- label: 'Data Grid',
- children: [
- { id: 'grid-community', label: '@mui/x-data-grid' },
- { id: 'grid-pro', label: '@mui/x-data-grid-pro' },
- { id: 'grid-premium', label: '@mui/x-data-grid-premium' },
- ],
- },
- {
- id: 'pickers',
- label: 'Date and Time Pickers',
- children: [
- { id: 'pickers-community', label: '@mui/x-date-pickers' },
- { id: 'pickers-pro', label: '@mui/x-date-pickers-pro' },
- ],
- },
- {
- id: 'charts',
- label: 'Charts',
- children: [{ id: 'charts-community', label: '@mui/x-charts' }],
- },
- {
- id: 'tree-view',
- label: 'Tree View',
- children: [{ id: 'tree-view-community', label: '@mui/x-tree-view' }],
- },
-];
-
-function getItemDescendantsIds(item) {
- const ids = [];
- item.children?.forEach((child) => {
- ids.push(child.id);
- ids.push(...getItemDescendantsIds(child));
- });
-
- return ids;
-}
-
-export default function ParentChildrenSelectionRelationship() {
- const [selectedItems, setSelectedItems] = React.useState([]);
- const toggledItemRef = React.useRef({});
- const apiRef = useTreeViewApiRef();
-
- const handleItemSelectionToggle = (event, itemId, isSelected) => {
- toggledItemRef.current[itemId] = isSelected;
- };
-
- const handleSelectedItemsChange = (event, newSelectedItems) => {
- setSelectedItems(newSelectedItems);
-
- // Select / unselect the children of the toggled item
- const itemsToSelect = [];
- const itemsToUnSelect = {};
- Object.entries(toggledItemRef.current).forEach(([itemId, isSelected]) => {
- const item = apiRef.current.getItem(itemId);
- if (isSelected) {
- itemsToSelect.push(...getItemDescendantsIds(item));
- } else {
- getItemDescendantsIds(item).forEach((descendantId) => {
- itemsToUnSelect[descendantId] = true;
- });
- }
- });
-
- const newSelectedItemsWithChildren = Array.from(
- new Set(
- [...newSelectedItems, ...itemsToSelect].filter(
- (itemId) => !itemsToUnSelect[itemId],
- ),
- ),
- );
-
- setSelectedItems(newSelectedItemsWithChildren);
-
- toggledItemRef.current = {};
- };
-
- return (
-
-
-
- );
-}
diff --git a/docs/data/tree-view/rich-tree-view/selection/ParentChildrenSelectionRelationship.tsx b/docs/data/tree-view/rich-tree-view/selection/ParentChildrenSelectionRelationship.tsx
deleted file mode 100644
index e45bdbb4fb3c..000000000000
--- a/docs/data/tree-view/rich-tree-view/selection/ParentChildrenSelectionRelationship.tsx
+++ /dev/null
@@ -1,106 +0,0 @@
-import * as React from 'react';
-import Box from '@mui/material/Box';
-import { RichTreeView } from '@mui/x-tree-view/RichTreeView';
-import { useTreeViewApiRef } from '@mui/x-tree-view/hooks';
-import { TreeViewBaseItem } from '@mui/x-tree-view/models';
-
-const MUI_X_PRODUCTS: TreeViewBaseItem[] = [
- {
- id: 'grid',
- label: 'Data Grid',
- children: [
- { id: 'grid-community', label: '@mui/x-data-grid' },
- { id: 'grid-pro', label: '@mui/x-data-grid-pro' },
- { id: 'grid-premium', label: '@mui/x-data-grid-premium' },
- ],
- },
- {
- id: 'pickers',
- label: 'Date and Time Pickers',
- children: [
- { id: 'pickers-community', label: '@mui/x-date-pickers' },
- { id: 'pickers-pro', label: '@mui/x-date-pickers-pro' },
- ],
- },
- {
- id: 'charts',
- label: 'Charts',
- children: [{ id: 'charts-community', label: '@mui/x-charts' }],
- },
- {
- id: 'tree-view',
- label: 'Tree View',
- children: [{ id: 'tree-view-community', label: '@mui/x-tree-view' }],
- },
-];
-
-function getItemDescendantsIds(item: TreeViewBaseItem) {
- const ids: string[] = [];
- item.children?.forEach((child) => {
- ids.push(child.id);
- ids.push(...getItemDescendantsIds(child));
- });
-
- return ids;
-}
-
-export default function ParentChildrenSelectionRelationship() {
- const [selectedItems, setSelectedItems] = React.useState([]);
- const toggledItemRef = React.useRef<{ [itemId: string]: boolean }>({});
- const apiRef = useTreeViewApiRef();
-
- const handleItemSelectionToggle = (
- event: React.SyntheticEvent,
- itemId: string,
- isSelected: boolean,
- ) => {
- toggledItemRef.current[itemId] = isSelected;
- };
-
- const handleSelectedItemsChange = (
- event: React.SyntheticEvent,
- newSelectedItems: string[],
- ) => {
- setSelectedItems(newSelectedItems);
-
- // Select / unselect the children of the toggled item
- const itemsToSelect: string[] = [];
- const itemsToUnSelect: { [itemId: string]: boolean } = {};
- Object.entries(toggledItemRef.current).forEach(([itemId, isSelected]) => {
- const item = apiRef.current!.getItem(itemId);
- if (isSelected) {
- itemsToSelect.push(...getItemDescendantsIds(item));
- } else {
- getItemDescendantsIds(item).forEach((descendantId) => {
- itemsToUnSelect[descendantId] = true;
- });
- }
- });
-
- const newSelectedItemsWithChildren = Array.from(
- new Set(
- [...newSelectedItems, ...itemsToSelect].filter(
- (itemId) => !itemsToUnSelect[itemId],
- ),
- ),
- );
-
- setSelectedItems(newSelectedItemsWithChildren);
-
- toggledItemRef.current = {};
- };
-
- return (
-
-
-
- );
-}
diff --git a/docs/data/tree-view/rich-tree-view/selection/ParentChildrenSelectionRelationship.tsx.preview b/docs/data/tree-view/rich-tree-view/selection/ParentChildrenSelectionRelationship.tsx.preview
deleted file mode 100644
index 6fa38db9c231..000000000000
--- a/docs/data/tree-view/rich-tree-view/selection/ParentChildrenSelectionRelationship.tsx.preview
+++ /dev/null
@@ -1,9 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/data/tree-view/rich-tree-view/selection/SelectionPropagation.js b/docs/data/tree-view/rich-tree-view/selection/SelectionPropagation.js
new file mode 100644
index 000000000000..2c54a087f326
--- /dev/null
+++ b/docs/data/tree-view/rich-tree-view/selection/SelectionPropagation.js
@@ -0,0 +1,59 @@
+import * as React from 'react';
+import FormControlLabel from '@mui/material/FormControlLabel';
+import Checkbox from '@mui/material/Checkbox';
+import Stack from '@mui/material/Stack';
+import Box from '@mui/material/Box';
+import { RichTreeView } from '@mui/x-tree-view/RichTreeView';
+
+import { EMPLOYEES_DATASET } from '../../datasets/employees';
+
+export default function SelectionPropagation() {
+ const [selectionPropagation, setSelectionPropagation] = React.useState({
+ parents: true,
+ descendants: true,
+ });
+
+ return (
+