diff --git a/.circleci/config.yml b/.circleci/config.yml index a5685e260757c..96f5576c4b6d8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -13,6 +13,14 @@ parameters: description: The name of the workflow to run type: string default: pipeline + with-material-ui-6: + description: Use material-ui v6 for additional checks and tests + type: boolean + default: false + with-react-version: + description: The version of react to be used for the additional tests + type: string + default: stable e2e-base-url: description: The base url for running end-to-end test type: string @@ -90,11 +98,10 @@ commands: git --no-pager diff HEAD - when: - condition: - equal: [material-ui-v6, << pipeline.parameters.workflow >>] + condition: << pipeline.parameters.with-material-ui-6 >> steps: - run: - name: Install @mui/material@next + name: Install @mui/material v6 command: pnpm use-material-ui-v6 jobs: @@ -225,7 +232,7 @@ jobs: test_browser: <<: *default-job docker: - - image: mcr.microsoft.com/playwright:v1.44.1-focal + - image: mcr.microsoft.com/playwright:v1.49.0-noble steps: - checkout - install_js: @@ -256,7 +263,7 @@ jobs: test_e2e: <<: *default-job docker: - - image: mcr.microsoft.com/playwright:v1.44.1-focal + - image: mcr.microsoft.com/playwright:v1.49.0-noble steps: - checkout - install_js: @@ -267,7 +274,7 @@ jobs: test_e2e_website: <<: *default-job docker: - - image: mcr.microsoft.com/playwright:v1.44.1-focal + - image: mcr.microsoft.com/playwright:v1.49.0-noble steps: - checkout - install_js: @@ -280,11 +287,14 @@ jobs: test_regressions: <<: *default-job docker: - - image: mcr.microsoft.com/playwright:v1.44.1-focal + - image: mcr.microsoft.com/playwright:v1.49.0-noble steps: - checkout - install_js: browsers: true + - run: + name: Install ffmpeg + command: apt update && apt upgrade -y && apt install ffmpeg -y - run: name: Run visual regression tests command: xvfb-run pnpm test:regressions @@ -349,50 +359,38 @@ workflows: requires: - checkout - react-next: + additional-tests: when: - equal: [react-next, << pipeline.parameters.workflow >>] - # triggers: - # - schedule: - # cron: '0 0 * * *' - # filters: - # branches: - # only: - # - master + and: + - equal: [additional, << pipeline.parameters.workflow >>] + - or: + - equal: [true, << pipeline.parameters.with-material-ui-6 >>] + - not: + equal: ['stable', << pipeline.parameters.with-react-version >>] jobs: - test_unit: <<: *default-context - react-version: next - name: test_unit-react@next + name: test_unit_additional + react-version: << pipeline.parameters.with-react-version >> - test_browser: <<: *default-context - react-version: next - name: test_browser-react@next + name: test_browser_additional + react-version: << pipeline.parameters.with-react-version >> - test_regressions: <<: *default-context - react-version: next - name: test_regressions-react@next + name: test_regressions_additional + react-version: << pipeline.parameters.with-react-version >> - test_e2e: <<: *default-context - react-version: next - name: test_e2e-react@next + name: test_e2e_additional + react-version: << pipeline.parameters.with-react-version >> - material-ui-v6: + additional-checks: when: - equal: [material-ui-v6, << pipeline.parameters.workflow >>] + and: + - equal: [additional, << pipeline.parameters.workflow >>] + - equal: [true, << pipeline.parameters.with-material-ui-6 >>] jobs: - - test_unit: - <<: *default-context - name: test_unit-material@next - - test_browser: - <<: *default-context - name: test_browser-material@next - - test_regressions: - <<: *default-context - name: test_regressions-material@next - - test_e2e: - <<: *default-context - name: test_e2e-material@next - test_types: <<: *default-context - name: test_types-material@next + name: test_types_additional diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json index 91008eca7dc2b..46d665df1ad28 100644 --- a/.codesandbox/ci.json +++ b/.codesandbox/ci.json @@ -32,6 +32,6 @@ "@mui/x-tree-view-pro": "packages/x-tree-view-pro/build", "@mui/x-internals": "packages/x-internals/build" }, - "sandboxes": ["/bug-reproductions/x-data-grid"], + "sandboxes": ["/bug-reproductions/x-data-grid", "/bug-reproductions/x-charts"], "silent": true } diff --git a/.eslintrc.js b/.eslintrc.js index 86ca180db6c83..fac05b6d0e35d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -59,21 +59,22 @@ const RESTRICTED_TOP_LEVEL_IMPORTS = [ const buildPackageRestrictedImports = (packageName, root, allowRootImports = true) => [ { files: [`packages/${root}/src/**/*{.ts,.tsx,.js}`], - excludedFiles: ['*.d.ts', '*.spec.ts', '*.spec.tsx', '**.test.tx', '**.test.tsx'], + excludedFiles: [ + '*.d.ts', + '*.spec.ts', + '*.spec.tsx', + '**.test.tx', + '**.test.tsx', + `packages/${root}/src/index{.ts,.tsx,.js}`, + ], rules: { 'no-restricted-imports': [ 'error', { - paths: [ - { - name: packageName, - message: 'Use relative import instead', - }, - { - name: '@mui/material', - message: 'Use @mui/utils or a more specific import instead', - }, - ], + paths: RESTRICTED_TOP_LEVEL_IMPORTS.map((pkName) => ({ + name: pkName, + message: 'Use relative import instead', + })), patterns: [ // TODO move rule into main repo to allow deep @mui/monorepo imports { @@ -136,6 +137,7 @@ module.exports = { ...(ENABLE_REACT_COMPILER_PLUGIN ? { 'react-compiler/react-compiler': 'error' } : {}), // TODO move to @mui/monorepo, codebase is moving away from default exports https://github.com/mui/material-ui/issues/21862 'import/prefer-default-export': 'off', + 'import/no-relative-packages': 'error', 'import/no-restricted-paths': [ 'error', { diff --git a/.github/ISSUE_TEMPLATE/1.bug.yml b/.github/ISSUE_TEMPLATE/1.bug.yml index f450370788a1e..0d6d9de328bf6 100644 --- a/.github/ISSUE_TEMPLATE/1.bug.yml +++ b/.github/ISSUE_TEMPLATE/1.bug.yml @@ -38,10 +38,8 @@ body: Please provide a link to a live example and an unambiguous set of steps to reproduce this bug. See our [documentation](https://mui.com/x/introduction/support/#bug-reproductions) on how to build a reproduction case. value: | - Link to live example: (required) - Steps: - 1. + 1. Open this link to live example: (required) 2. 3. - type: textarea diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index b8649980cc3aa..e04b01f36ead3 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,3 +1,5 @@ + + - [ ] I have followed (at least) the [PR section of the contributing guide](https://github.com/mui/mui-x/blob/HEAD/CONTRIBUTING.md#sending-a-pull-request). diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 99c62e16f892d..e32d3c4ead251 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0 + uses: github/codeql-action/init@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6 with: languages: typescript # If you wish to specify custom queries, you can do so here or in a config file. @@ -29,4 +29,4 @@ jobs: # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs # queries: security-extended,security-and-quality - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0 + uses: github/codeql-action/analyze@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6 diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml index c0df4ca87ef7b..9cb68e53e4831 100644 --- a/.github/workflows/codspeed.yml +++ b/.github/workflows/codspeed.yml @@ -50,7 +50,7 @@ jobs: - run: pnpm --filter @mui/x-charts build - run: pnpm --filter @mui/x-charts-pro build - name: Run benchmarks - uses: CodSpeedHQ/action@b587655f756aab640e742fec141261bc6f0a569d + uses: CodSpeedHQ/action@513a19673a831f139e8717bf45ead67e47f00044 with: run: pnpm --filter @mui-x-internal/performance-charts test:performance token: ${{ secrets.CODSPEED_TOKEN }} diff --git a/.github/workflows/create-cherry-pick-pr.yml b/.github/workflows/create-cherry-pick-pr.yml index 0d5381c25b9da..fdfe07ff19c31 100644 --- a/.github/workflows/create-cherry-pick-pr.yml +++ b/.github/workflows/create-cherry-pick-pr.yml @@ -2,6 +2,7 @@ name: Create cherry-pick PR on: pull_request_target: branches: + - 'next' - 'v*.x' - 'master' types: ['closed'] @@ -14,5 +15,4 @@ jobs: uses: mui/mui-public/.github/workflows/prs_create-cherry-pick-pr.yml@master permissions: contents: write - issues: write pull-requests: write diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 0868a58d28b90..486634ffc2645 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -44,6 +44,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: Upload to code-scanning - uses: github/codeql-action/upload-sarif@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0 + uses: github/codeql-action/upload-sarif@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6 with: sarif_file: results.sarif diff --git a/CHANGELOG.md b/CHANGELOG.md index d533a40da0cac..eeee378b0778c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,948 @@ # Changelog +> For full v7 changelog, please refer to the [v.7x branch](https://github.com/mui/mui-x/blob/v7.x/CHANGELOG.md). + All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 8.0.0-alpha.3 + +_Dec 5, 2024_ + +We'd like to offer a big thanks to the 9 contributors who made this release possible. Here are some highlights ✨: + +- 💫 Support [Server-side lazy loading](https://mui.com/x/react-data-grid/server-side-data/lazy-loading/) on the Data Grid. Use [data source](https://mui.com/x/react-data-grid/server-side-data/#data-source) to fetch a range of rows on demand and update the rows in the same way as described in [Infinite loading](https://mui.com/x/react-data-grid/row-updates/#infinite-loading) and [Lazy loading](https://mui.com/x/react-data-grid/row-updates/#lazy-loading) without the need to use any additional event listeners and callbacks. +- 🎯 Improved [data caching](https://mui.com/x/react-data-grid/server-side-data/#data-caching). Check out our [recommendations](https://mui.com/x/react-data-grid/server-side-data/#improving-the-cache-hit-rate) for improving the cache hit rate. + +Special thanks go out to the community contributors who have helped make this release possible: +@ihsanberkozcan, @k-rajat19, @perezShaked. +Following are all team members who have contributed to this release: +@arminmeh, @cherniavskii, @flaviendelangle, @JCQuintas, @MBilalShafi, @noraleonte. + + + +### Data Grid + +#### Breaking changes + +- The "Select all" checkbox is now checked when all the selectable rows are selected, ignoring rows that are not selectable because of the `isRowSelectable` prop. +- The `rowPositionsDebounceMs` prop was removed. +- The `gridRowsDataRowIdToIdLookupSelector` selector was removed. Use the `gridRowsLookupSelector` selector in combination with the `getRowId()` API method instead. + ```diff + -const idToIdLookup = gridRowsDataRowIdToIdLookupSelector(apiRef); + -const rowId = idToIdLookup[id] + +const rowsLookup = gridRowsLookupSelector(apiRef); + +const rowId = apiRef.current.getRowId(rowsLookup[id]) + ``` +- The Grid is now more aligned with the WAI-ARIA authoring practices and sets the `role` attribute to `treegrid` if the Data Grid is used with row grouping feature. + +#### `@mui/x-data-grid@8.0.0-alpha.3` + +- [DataGrid] Fix deselection not working with `isRowSelectable` (#15692) @MBilalShafi +- [DataGrid] Make column autosizing work with flex columns (#15465) @cherniavskii +- [DataGrid] Remove `gridRowsDataRowIdToIdLookupSelector` selector (#15698) @arminmeh +- [DataGrid] Remove `rowPositionsDebounceMs` prop (#15482) @k-rajat19 +- [l10n] Improve Hebrew (he-IL) locale (#15699) @perezShaked +- [l10n] Improve Turkish (tr-TR) locale (#15734) @ihsanberkozcan + +#### `@mui/x-data-grid-pro@8.0.0-alpha.3` [![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@8.0.0-alpha.3`, plus: + +- [DataGridPro] Cleanup pinned rows on removal (#15697) @cherniavskii +- [DataGridPro] Server-side lazy loading (#13878) @arminmeh + +#### `@mui/x-data-grid-premium@8.0.0-alpha.3` [![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@8.0.0-alpha.3`, plus: + +- [DataGridPremium] Remove the `ariaV8` experimental flag (#15694) @arminmeh + +### Date and Time Pickers + +#### Breaking changes + +- The `onOpen()` and `onClose()` methods of the `usePickerContext()` hook have been replaced with a single `setOpen` method — [Learn more](https://next.mui.com/x/migration/migration-pickers-v7/#usepickercontext). + +#### `@mui/x-date-pickers@8.0.0-alpha.3` + +- [pickers] Replace the `onOpen()` and `onClose()` methods of `usePickerContext()` with a single `setOpen()` method. (#15701) @flaviendelangle + +#### `@mui/x-date-pickers-pro@8.0.0-alpha.3` [![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@8.0.0-alpha.3`. + +### Charts + +#### `@mui/x-charts@8.0.0-alpha.3` + +- [charts] Improve SVG `pattern` and `gradient` support (#15720) @JCQuintas + +#### `@mui/x-charts-pro@8.0.0-alpha.3` [![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@8.0.0-alpha.3`. + +### Tree View + +#### `@mui/x-tree-view@8.0.0-alpha.3` + +No changes since `@mui/x-tree-view-pro@v8.0.0-alpha.2`. + +#### `@mui/x-tree-view-pro@8.0.0-alpha.3` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan') + +Same changes as in `@mui/x-tree-view@8.0.0-alpha.3`. + +### Docs + +- [docs] Add a customization demo for the Date and Time Pickers overview page (#15118) @noraleonte +- [docs] Fix typo in charts axis documentation (#15743) @JCQuintas +- [docs] Improve SEO titles for the Data Grid (#15695) @MBilalShafi + +### Core + +- [core] Add `@mui/x-tree-view-pro` to `releaseChangelog` (#15316) @flaviendelangle +- [code-infra] Lock file maintenance (#11894) +- [code-infra] Check if `preset-safe` folder exists in codemod test (#15703) @JCQuintas +- [code-infra] Import Pickers `preset-safe` into global codemod config (#15659) @JCQuintas +- [code-infra] Playwright 1.49 (#15493) @JCQuintas +- [test] Force hover in headless Chrome (#15710) @cherniavskii + +## v8.0.0-alpha.2 + +_Nov 29, 2024_ + +We'd like to offer a big thanks to the 17 contributors who made this release possible. Here are some highlights ✨: + +- 👨🏽‍💻 Improve resize performance on the Data Gird. +- `` and `` components are now fully divided — [Learn more](https://next.mui.com/x/react-charts/composition/#overview). +- Users can create their own HTML components using chart data — [Learn more](https://next.mui.com/x/react-charts/components/#html-components). +- 🌍 Improve Spanish, Portuguese, Chinese locales on the Data Grid component. +- 🌍 Improve Dutch locale on the Date and Time Pickers components. +- 🐞 Bugfixes +- 📚 Documentation improvements + +Special thanks go out to the community contributors who have helped make this release possible: +@dloeda, @headironc, @jedesroches, @k-rajat19, @lauri865, @mathzdev, @nphmuller, @zinoroman. +Following are all team members who have contributed to this release: +@arminmeh, @alexfauquette, @cherniavskii, @flaviendelangle, @JCQuintas, @KenanYusuf, @LukasTy, @MBilalShafi, @oliviertassinari. + + + +### Data Grid + +#### Breaking changes + +- The `` component is not exported anymore. +- The `indeterminateCheckboxAction` prop has been removed. Clicking on an indeterminate checkbox "selects" the unselected descendants. +- The `apiRef.current.resize()` method was removed. +- The default value of the `rowSelectionPropagation` prop has been changed to `{ parents: true, descendants: true }` which means that the selection will be propagated to the parents and descendants by default. + To revert to the previous behavior, pass `rowSelectionPropagation` as `{ parents: false, descendants: false }`. +- If `estimatedRowCount` is used, the text provided to the [Table Pagination](/material-ui/api/table-pagination/) component from the Material UI library is updated and requires additional translations. Check the example at the end of [Index-based pagination section](/x/react-data-grid/pagination/#index-based-pagination). + +#### `@mui/x-data-grid@v8.0.0-alpha.2` + +- [DataGrid] Change test dom check from `/jsdom/` to `/jsdom|HappyDOM/`. (#15634) @jedesroches +- [DataGrid] Clear timers on unmount (#15620) @cherniavskii +- [DataGrid] Fix order of spread props on toolbar items (#15556) @KenanYusuf +- [DataGrid] Improve resize performance (#15549) @lauri865 +- [DataGrid] Make estimation label more accurate (#15632) @arminmeh +- [DataGrid] Remove `` export (#15573) @k-rajat19 +- [DataGrid] Remove `indeterminateCheckboxAction` prop (#15522) @MBilalShafi +- [DataGrid] Remove try/catch from `` due to performance issues (#15616) @lauri865 +- [DataGrid] Remove unused `resize` method (#15599) @cherniavskii +- [DataGrid] Support column virtualization with dynamic row height (#15541) @cherniavskii +- [DataGrid] Update the default value for `rowSelectionPropagation` (#15523) @MBilalShafi +- [l10n] Improve Chinese (zh-CN) locale (#15570) @headironc +- [l10n] Improve Portuguese (pt-PT) locale (#15561) @mathzdev + +#### `@mui/x-data-grid-pro@v8.0.0-alpha.2` [![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@v8.0.0-alpha.2`, plus: + +- [DataGridPro] Fix header filtering with `boolean` column type (#15528) @k-rajat19 +- [DataGridPro] Fix pagination state not updating if the data source response has no rows (#15622) @zinoroman +- [DataGridPro] Fix selection propagation issue on initialization (#15461) @MBilalShafi + +#### `@mui/x-data-grid-premium@v8.0.0-alpha.2` [![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@v8.0.0-alpha.2`. + +### Date and Time Pickers + +#### Breaking changes + +- The props received by the `layout` and the `toolbar` slots have been reworked — [Learn more](https://next.mui.com/x/migration/migration-pickers-v7/#do-not-pass-the-section-type-as-a-generic). + +- The `TSection` generic of the `FieldRef` type has been replaced with the `TValue` generic — [Learn more](https://next.mui.com/x/migration/migration-pickers-v7/#slots-breaking-changes). + +#### `@mui/x-date-pickers@v8.0.0-alpha.2` + +- [l10n] Improve Dutch (nl-NL) locale (#15564) @nphmuller +- [pickers] Fix DST issue with `America/Asuncion` timezone and `AdapterMoment` (#15552) @flaviendelangle +- [pickers] Improve validation internals (#15419) @flaviendelangle +- [pickers] Remove `TSection` and strictly type `TValue` (#15434) @flaviendelangle +- [pickers] Remove `orientation`, `isLandscape`, `isRtl`, `wrapperVariant` and `disabled` props from `PickersLayout` (#15494) @flaviendelangle +- [pickers] Use the new `ownerState` in ``, `` and `` (#15499) @flaviendelangle +- [pickers] Use the new `ownerState` object in all the field components (#15510) @flaviendelangle + +#### `@mui/x-date-pickers-pro@v8.0.0-alpha.2` [![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@v8.0.0-alpha.2`. + +### Charts + +#### Breaking changes + +- Charts Container don't have a `
` wrapping them anymore. All props are now passed to the root `` instead of the `
`. + +#### `@mui/x-charts@v8.0.0-alpha.2` + +- [charts] Allow the creation of custom HTML components using charts data (#15511) @JCQuintas +- [charts] Flatten imports from `@mui/utils` and `@mui/system` (#15603) @alexfauquette +- [charts] Introduce the plugin system (#15513) @alexfauquette +- [charts] Prevent invalid `releasePointerCapture` (#15602) @alexfauquette +- [charts] Fix custom Tooltip demos (#15631) @alexfauquette + +#### `@mui/x-charts-pro@v8.0.0-alpha.2` [![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@v8.0.0-alpha.2`. + +### Tree View + +#### `@mui/x-tree-view@v8.0.0-alpha.2` + +- [TreeView] Flatten import from `@mui/utils` and `@mui/system` (#15604) @alexfauquette + +#### `@mui/x-tree-view-pro@v8.0.0-alpha.2` + +Same changes as in `@mui/x-tree-view@v8.0.0-alpha.2`. + +### Docs + +- [docs] Fix 404 links (#15575) @oliviertassinari +- [docs] Fix bash comments (#15571) @oliviertassinari +- [docs] Fix Pickers theme augmentation example (#15672) @LukasTy +- [docs] Replace use of "e.g." with "for example" (#15572) @oliviertassinari +- [docs] Update stale `new` and `preview` tags in v8 docs (#15547) @JCQuintas +- [docs] Fix layout shift image on Tree View docs (#15626) @oliviertassinari +- [docs] Fix `anchorEl` API page for charts (#15625) @oliviertassinari +- [docs] Add documentation for the list view feature (#15344) @KenanYusuf + +### Core + +- [core] Follow `()` function convention for docs @oliviertassinari +- [core] Remove dead translation key (#15566) @oliviertassinari +- [code-infra] Auto-merge `@types/node` bumps (#15591) @LukasTy + +## v8.0.0-alpha.1 + +_Nov 22, 2024_ + +We'd like to offer a big thanks to the 16 contributors who made this release possible. Here are some highlights ✨: + +- 🔧 Refactor Tooltip customisation for charts — [Learn more](https://next.mui.com/x/react-charts/tooltip/#overriding-content). +- ⚛️ React 19 support +- 🌍 Improve Chinese, Spanish, and Swedish locale on the Data Grid component +- 🐞 Bugfixes +- 📚 Documentation improvements + +Special thanks go out to the community contributors who have helped make this release possible: +@CarlosLopezLg, @headironc, @hendrikpeilke, @k-rajat19, @lhilgert9, @viktormelin. +Following are all team members who have contributed to this release: +@alexfauquette, @arthurbalduini, @cherniavskii, @flaviendelangle, @JCQuintas, @LukasTy, @MBilalShafi, @oliviertassinari, @KenanYusuf, @arminmeh. + + + +### Data Grid + +#### `@mui/x-data-grid@v8.0.0-alpha.1` + +- [DataGrid] React 19 support (#15342) @arminmeh +- [DataGrid] Add prop to override search input props in `GridColumnsManagement` (#15347) @k-rajat19 +- [DataGrid] Add test coverage for issues fixed in #15184 (#15282) @MBilalShafi +- [DataGrid] Change default loading overlay variants (#15504) @KenanYusuf +- [DataGrid] Fix last separator not being hidden when grid is scrollable (#15543) @KenanYusuf +- [DataGrid] Fix right column group header border with virtualization (#15470) @hendrikpeilke +- [DataGrid] Fix row-spanning in combination with column-pinning (#15368) @lhilgert9 +- [l10n] Improve Chinese (zh-CN) locale (#15365) @headironc +- [l10n] Improve Spanish (es-ES) locale (#15369) @CarlosLopezLg +- [l10n] Improve Swedish (sv-SE) locale (#15371) @viktormelin + +#### `@mui/x-data-grid-pro@v8.0.0-alpha.1` [![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@v8.0.0-alpha.1`. + +#### `@mui/x-data-grid-premium@v8.0.0-alpha.1` [![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@v8.0.0-alpha.1`, plus: + +- [DataGridPremium] Prompt input control (#15401) @arminmeh + +### Date and Time Pickers + +#### Breaking change + +- The `FieldValueType` type has been renamed to `PickerValueType` — [Learn more](https://next.mui.com/x/migration/migration-pickers-v7/#renamed-variables). +- The `toolbar` and `layout` slots no longer receive the `disabled` and `readOnly` props — [Learn more](https://next.mui.com/x/migration/migration-pickers-v7/#slots-breaking-changes). + +#### `@mui/x-date-pickers@v8.0.0-alpha.1` + +- [fields] Fix focus management with new DOM structure (#15475) @flaviendelangle +- [pickers] React 19 support (#15342) @arminmeh +- [pickers] Add new properties to `PickerOwnerState` and `PickerContextValue` (#15415) @flaviendelangle +- [pickers] Always use `props.value` when it changes (#15490) @flaviendelangle +- [pickers] Ensure internal value timezone is updated (#15435) @LukasTy +- [pickers] Fix unused code in `` component (#15515) @LukasTy +- [pickers] Remove `FieldValueType` in favor of `PickerValueType` (#15259) @arthurbalduini +- [pickers] Remove the form props from the layout and the toolbar slots (#15492) @flaviendelangle +- [pickers] Use `props.referenceDate` timezone when `props.value` and `props.defaultValue` are not defined (#15532) @flaviendelangle +- [TimePicker] Prevent mouse events after `touchend` event (#15346) @arthurbalduini + +#### `@mui/x-date-pickers-pro@v8.0.0-alpha.1` [![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@v8.0.0-alpha.1`, plus: + +- [DateTimeRangePicker] Use time in `referenceDate` when selecting date (#15429) @LukasTy + +### Charts + +#### Breaking change + +- The DX of the Tooltip customization has been refactored + + - The `tooltip` prop has been removed in favor of `slotProps.tooltip` for consistency. + - The `popper`, `axisContent`, and `itemContent` slots have been removed in favor of the `tooltip` slot which overrides the entire tooltip. + - To override the tooltip content, use the `useItemTooltip` or `useAxisTooltip` hook to get the data, and wrap your component in `ChartsTooltipContainer` to follow the pointer position. + - To override the tooltip placement, use the `ChartsItemTooltipContent` or `ChartsItemTooltipContent` to get default data and place them in your custom tooltip. + +- The library now uses the SVG `filter` attribute instead of `d3-color` for color manipulation. + + - This modification impacts the `LinePlot`, `AreaPlot`, and `BarPlot` components. + If you've customized the `fill` of those elements, you might need to override it by using the CSS `filter`. + - The `theme.styleOverride` is removed for `MuiLineElement`, `MuiAreaElement`, and `MuiBarElement` to improve performance. + You can still target those elements by using the `MuiLinePlot`, `MuiAreaPlot`, and `MuiBarPlot` and target the appropriate classes `lineElementClasses.root`, `areaElementClasses.root`, `barElementClasses.root` + +- Removed the `resolveSizeBeforeRender` prop from all chart components — [Learn more](https://next.mui.com/x/migration/migration-charts-v7/#remove-resolvesizebeforerender-prop). +- Removed `width` and `height` props from the `ChartsSurface` component. +- Removed the `viewport` prop from all charts. + +#### `@mui/x-charts@v8.0.0-alpha.1` + +- [charts] React 19 support (#15342) @arminmeh +- [charts] Decouple `` and `` (#15375) @JCQuintas +- [charts] Fix Scatter Chart tooltip wrong defaults (#15537) @JCQuintas +- [charts] Fix key generation for the `` component (#15463) @alexfauquette +- [charts] Improve `` to split the received ref (#15424) @JCQuintas +- [charts] Move interaction state in store (#15426) @alexfauquette +- [charts] Refactor Tooltip customisation (#15154) @alexfauquette +- [charts] Remove intrinsic size requirement (#15471) @JCQuintas +- [charts] Replace `d3-color` with CSS filter for highlight (#15084) @alexfauquette +- [charts] Split `` into `` and `` (#15417) @JCQuintas + +#### `@mui/x-charts-pro@v8.0.0-alpha.1` [![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@v8.0.0-alpha.1`. + +### Tree View + +#### Breaking changes + +- The Tree Item component can no longer use `publicAPI` methods in the `render` because they are now memoized — [Learn more](https://next.mui.com/x/migration/migration-tree-view-v7/#stop-using-publicapi-methods-in-the-render). + +#### `@mui/x-tree-view@v8.0.0-alpha.1` + +- [TreeView] React 19 support (#15342) @arminmeh +- [TreeView] Do not re-render every Tree Item when the Rich Tree View re-renders (introduce selectors) (#14210) @flaviendelangle +- [TreeView] Remove `treeId` from the item context (#15542) @flaviendelangle +- [TreeView] Remove state mutation in `moveItemInTree()` (#15539) @flaviendelangle +- [TreeItem] Correct the typing of `slotProps.groupTransition` (#15534) @flaviendelangle + +### Docs + +- [docs] Fix some migration typos (#15422) @LukasTy +- [docs] Fix typo in migration guide (#15508) @flaviendelangle +- [docs] Fix 301 redirection in docs @oliviertassinari +- [docs] Polish Server-side data section (#15330) @oliviertassinari +- [docs] Use loading state in the demos (#15512) @cherniavskii + +### Core + +- [core] Keep OpenSSF badge up-to-date @oliviertassinari +- [code-infra] Add `'DensitySelectorGrid'` to time-sensitive argos tests (#15425) @JCQuintas +- [code-infra] Add documentation to internal types (#15540) @JCQuintas +- [code-infra] Prevent relative imports across packages (#15437) @JCQuintas +- [code-infra] Update renovate config to merge `action` pins (#15462) @LukasTy +- [docs-infra] Fix version tooltip (#15468) @alexfauquette +- [docs-infra] Transpile `.ts` demo files (#15345) @KenanYusuf +- [infra] Remove cherry-pick issue write permission (#15456) @oliviertassinari + +## 8.0.0-alpha.0 + +MUI X v8 Alpha is live + +_Nov 14, 2024_ + +We'd like to offer a big thanks to the 22 contributors who made this release possible. Here are some highlights ✨: + +- 🔁 Support [automatic parents and children selection](https://next.mui.com/x/react-tree-view/rich-tree-view/selection/#automatic-parents-and-children-selection) for the Rich Tree View components. +- 🌍 Improve Greek (el-GR) locale on the Date and Time Pickers components +- 🌍 Improve Polish (pl-PL) locale on the Data Grid component +- 🐞 Bugfixes +- 📚 Documentation improvements + + Special thanks go out to the community contributors who have helped make this release possible: + @belkocik, @GeorgiosDrivas, @k-rajat19, @kalyan90, @DungTiger, @fxnoob, @GuillaumeMeheut + Following are all team members who have contributed to this release: + @alexfauquette, @arminmeh, @arthurbalduini, @cherniavskii, @flaviendelangle, @JCQuintas, @KenanYusuf, @LukasTy, @MBilalShafi, @michelengelen, @noraleonte, @oliviertassinari, @romgrk, @samuelsycamore, @joserodolfofreitas. + + + +### Data Grid + +#### `@mui/x-data-grid@8.0.0-alpha.0` + +- [DataGrid] Fix grid overlay aligment with scroll for rtl (#15072) @kalyan90 +- [DataGrid] Fix resizing right pinned column (#15107) @KenanYusuf +- [DataGrid] Pass the reason to the `onPaginationModelChange` callback (#13959) @DungTiger +- [DataGrid] Set default overlay height in flex parent layout (#15202) @cherniavskii +- [DataGrid] Refactor `baseMenuList` and `baseMenuItem` (#15049) @romgrk +- [DataGrid] Remove more material imports (#15063) @romgrk +- [l10n] Improve Polish (pl-PL) locale (#15227) @belkocik + +#### `@mui/x-data-grid-pro@8.0.0-alpha.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@8.0.0-alpha.0`, plus: + +- [DataGridPro] Fix column pinning layout (#14966) @cherniavskii + +#### `@mui/x-data-grid-premium@8.0.0-alpha.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@8.0.0-alpha.0`, plus: + +- [DataGridPremium] Server-side data source with row grouping (#13826) @MBilalShafi + +### Date and Time Pickers + +#### Breaking changes + +- The default DOM structure of the field has changed [Learn more](https://next.mui.com/x/migration/migration-pickers-v7/#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. + +- Some translation keys no longer require `utils` and the date object as parameters, but only the formatted value as a string. The keys affected by this changes are: `clockLabelText`, `openDatePickerDialogue` and `openTimePickerDialogue` — [Learn more](https://next.mui.com/x/migration/migration-pickers-v7/#stop-passing-utils-and-the-date-object-to-some-translation-keys). + +- The following types are no longer exported by `@mui/x-date-pickers` and `@mui/x-date-pickers-pro` — [Learn more](https://next.mui.com/x/migration/migration-pickers-v7/#removed-types). + + - `UseDateFieldComponentProps` + - `UseTimeFieldComponentProps` + - `UseDateTimeFieldComponentProps` + - `BaseSingleInputFieldProps` + - `BaseMultiInputFieldProps` + - `BasePickersTextFieldProps` + +- The `TDate` generic has been removed from all the types, interfaces, and variables of the `@mui/x-date-pickers` and `@mui/x-date-pickers-pro` packages — [Learn more](https://next.mui.com/x/migration/migration-pickers-v7/#remove-tdate-generic). + +- Renamed `usePickersTranslations` and `usePickersContext` hooks to have a coherent `Picker` prefix instead of `Pickers` — [Learn more](https://next.mui.com/x/migration/migration-pickers-v7/#renamed-variables). + +- The `LicenseInfo` object is no longer exported from the `@mui/x-date-pickers-pro` package — [Learn more](https://next.mui.com/x/migration/migration-pickers-v7/#stop-using-licenseinfo-from-mui-x-date-pickers-pro). + +#### `@mui/x-date-pickers@8.0.0-alpha.0` + +- [fields] Enable the new field DOM structure by default (#14651) @flaviendelangle +- [fields] Remove `UseDateFieldComponentProps` and equivalent interfaces (#15053) @flaviendelangle +- [fields] Remove clear button from the tab sequence (#14616) @k-rajat19 +- [l10n] Improve Greek (el-GR) locale (#15250) @GeorgiosDrivas +- [pickers] Clean definition of validation props (#15198) @flaviendelangle +- [pickers] Clean the new `ownerState` object (#15056) @flaviendelangle +- [pickers] Correctly type the `ownerState` of the `field` and `actionBar` slots when resolved in a picker component (#15162) @flaviendelangle +- [pickers] Fix `DateCalendar` timezone management (#12321) @LukasTy +- [pickers] Fix `DateTimeRangePicker` error when using format without time (#14917) @fxnoob +- [pickers] Fix `DigitalClock` time options on a `DST` switch day (#10793) @LukasTy +- [pickers] Remove `TDate` generics in favor of `PickerValidDate` direct usage (#15001) @flaviendelangle +- [pickers] Remove `utils` and `value` params from translations (#14986) @arthurbalduini +- [pickers] Remove plural in "Pickers" on recently introduced APIs (#15297) @flaviendelangle +- [pickers] Remove the re-export from `@mui/x-license` (#14487) @k-rajat19 +- [pickers] Strictly type the props a picker passes to its field, and migrate all the custom field demos accordingly (#15197) @flaviendelangle +- [pickers] Unify JSDoc for all the `disabled` and `readOnly` props (#15304) @flaviendelangle +- [pickers] Use the new `ownerState` in `DateCalendar`, `DateRangeCalendar`, `MonthCalendar` and `YearCalendar` (#15171) @flaviendelangle +- [pickers] Use the new `ownerState` in `usePickersLayout` and `useXXXPicker` (#14994) @flaviendelangle + +#### `@mui/x-date-pickers-pro@8.0.0-alpha.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@8.0.0-alpha.0`. + +### Charts + +#### Breaking changes + +- The `legend` prop has been removed. To pass props to the legend, use `slotProps={{ legend: { ... } }}` instead. This can be automatically done with the codemod as long as the `legend` prop does not come from a destructured object — [Learn more](https://next.mui.com/x/migration/migration-charts-v7/#legend-props-propagation-✅). + +- The `slots.legend` does not receive the `drawingArea` prop. You can still access your custom legend with the `useDrawingArea()` hook if your custom legend needs it. + +- Removed or renamed multiple props from Series — [Learn more](https://next.mui.com/x/migration/migration-charts-v7/#series-properties-renaming). + + - The `highlighted` and `faded` properties of highlightScope have been deprecated in favor of `highlight` and `fade`. + The deprecated ones are now removed. + - The `xAxisKey`, `yAxisKey`, and `zAxisKey` properties have been deprecated in favor of `xAxisId`, `yAxisId`, and `zAxisId`. + +- The Pie Chart lost all props and renderer linked to axes because pie chart does not need cartesian axes. If you used it, you can still add them back with composition. Please consider opening an issue to share your use case with us — [Learn more](https://next.mui.com/x/migration/migration-charts-v7/#remove-pie-chart-axes). + +#### `@mui/x-charts@8.0.0-alpha.0` + +- [charts] Introduce `hideLegend` prop (#15277) @alexfauquette +- [charts] Filter items outside the drawing area for performance (#14281) @alexfauquette +- [charts] Fix log scale with `null` data (#15337) @alexfauquette +- [charts] Fix tooltip follow mouse (#15189) @alexfauquette +- [charts] Remove `xAxisKey`, `yAxisKey`, and `zAxisKey` series keys (#15192) @alexfauquette +- [charts] Remove axis from the pie chart (#15187) @alexfauquette +- [charts] Remove deprecated `legend` props (#15081) @alexfauquette +- [charts] Remove deprecated highlight properties (#15191) @alexfauquette +- [charts] Update Popper position outside of React (#15003) @alexfauquette +- [charts] Improve the performance of the `getSymbol` method (#15233) @romgrk + +#### `@mui/x-charts-pro@8.0.0-alpha.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-charts@8.0.0-alpha.0`. + +### Tree View + +#### Breaking changes + +- The `ContentComponent` or `ContentProps` props of the `` component have been removed in favor of the new `slots`, `slotProps` props and of the `useTreeItem` hook — [Learn more](https://next.mui.com/x/migration/migration-tree-view-v7/#new-api-to-customize-the-tree-item). + +- The `onClick` and `onMouseDown` callbacks of the Tree Item component are now passed to the root element instead of the content — [Learn more](https://next.mui.com/x/migration/migration-tree-view-v7/#behavior-change-on-the-onclick-and-onmousedown-props-of-treeitem). + +- Rename the `` component (and related utils) — [Learn more](https://next.mui.com/x/migration/migration-tree-view-v7/#✅-rename-the-treeitem2-and-related-utils). + +- The `` component has been renamed `` which has exactly the same API — [Learn more](https://next.mui.com/x/migration/migration-tree-view-v7/#✅-use-simple-tree-view-instead-of-tree-view). + +- The indentation of nested Tree Items is now applied on the content of the element — [Learn more](https://next.mui.com/x/migration/migration-tree-view-v7/#apply-the-indentation-on-the-item-content-instead-of-its-parents-group). + +#### `@mui/x-tree-view@8.0.0-alpha.0` + +- [TreeView] Always apply the indentation on the item content instead of its parent's group (#15089) @flaviendelangle +- [TreeView] Automatic parents and children selection (#14899) @flaviendelangle +- [TreeView] Remove deprecated `TreeView` component (#15093) @flaviendelangle +- [TreeView] Replace `` with `` and migrate all the components and utils (#14913) @flaviendelangle + +### Docs + +- [docs] Add docs for rounded symbol (#15324) @GuillaumeMeheut +- [docs] Add migration guide for the removal of `LicenseInfo` from `@mui/x-date-pickers-pro` (#15321) @flaviendelangle +- [docs] Add migration guide for the first breaking changes of charts (#15276) @alexfauquette +- [docs] Add `PickersPopper` component to the Date Picker customization playground (#15305) @LukasTy +- [docs] Add v8 to supported releases table (#15384) @joserodolfofreitas +- [docs] Apply the new DX to the Button Field demos (#14860) @flaviendelangle +- [docs] Apply the new DX to the `Autocomplete` Field demo (#15165) @flaviendelangle +- [docs] Cleanup the pickers migration guide (#15310) @flaviendelangle +- [docs] Copyedit the Charts Getting Started sequence (#14962) @samuelsycamore +- [docs] Create Pickers masked field recipe (#13515) @flaviendelangle +- [docs] Fix `applyDomain` docs for the charts (#15332) @JCQuintas +- [docs] Fix link to private notion page (#15396) @michelengelen +- [docs] Fix missing punctuation on descriptions (#15229) @oliviertassinari +- [docs] Fix peer dependency range (#15281) @oliviertassinari +- [docs] Fix small Tree View typo (#15390) @oliviertassinari +- [docs] Fix the `AdapterMomentHijri` doc section (#15312) @flaviendelangle +- [docs] Replace the Tree Item anatomy images (#15066) @noraleonte +- [docs] Start v8 migration guides (#15096) @MBilalShafi +- [docs] Subdivide and reorganize navigation bar (#15014) @samuelsycamore +- [docs] Use `PickersTextField` in the customization playground (#15288) @LukasTy +- [docs] Use `next` instead of `^8.0.0` in the migration guides (#15091) @flaviendelangle + +### Core + +- [core] Adjust the `cherry-pick` GitHub actions (#15099) @LukasTy +- [core] Add `()` at the name of function name in the doc (#15075) @oliviertassinari +- [core] Clarify release version bump strategy (#15219) @cherniavskii +- [core] Fix CodeSandbox and StackBlitz for next doc-infra sync @oliviertassinari +- [core] Fix Vale error on `master` @oliviertassinari +- [core] Fix changelog reference to VoiceOver @oliviertassinari +- [core] Fix `tools-public.mui.com` redirection @oliviertassinari +- [core] Fix webpack capitalization (#15353) @oliviertassinari +- [core] Move `helpers` to `@mui/x-internals` package (#15188) @LukasTy +- [code-infra] Set renovate to automerge devDependencies (#13463) @JCQuintas +- [infra] Reintroduce the cherry pick workflow (#15293) @michelengelen +- [core] Remove duplicate title header (#15389) @oliviertassinari +- [release] v8 preparation (#15054) @michelengelen +- [test] Fix advanced list view regression test snapshot (#15260) @KenanYusuf + +## 7.23.0 + +_Nov 29, 2024_ + +We'd like to offer a big thanks to the 10 contributors who made this release possible. Here are some highlights ✨: + +- ✨ Support for a new display mode on the Data Grid with the [List View feature](https://mui.com/x/react-data-grid/list-view/), offering an extremely flexible way to render datasets and enabling developers to adapt how data is displayed across different screen sizes. + + https://github.com/user-attachments/assets/61286adc-03fc-4323-9739-8ca726fcc16c + +- ⚛️ React 19 support +- 📚 Documentation improvements +- 🌍 Improve Spanish, Portuguese, Chinese locales on the Data Grid component. +- 🌍 Improve Dutch locale on the Date and Time Picker components. +- 🐞 Bugfixes + +Special thanks go out to the community contributors who have helped make this release possible: +@dloeda, @headironc, @mathzdev, @nphmuller, @lhilgert9, @lauri865. +Following are all team members who have contributed to this release: +@oliviertassinari, @arminmeh, @KenanYusuf, @flaviendelangle, @MBilalShafi. + + + +### Data Grid + +#### `@mui/x-data-grid@v7.23.0` + +- [DataGrid] React 19 support (#15557) @arminmeh +- [DataGrid] Change test dom check from `/jsdom/` to `/jsdom|HappyDOM/`. (#15642) @jedesroches +- [DataGrid] Fix last separator not being hidden when grid is scrollable (#15551) @KenanYusuf +- [DataGrid] Fix order of spread props on toolbar items (#15556) @KenanYusuf +- [DataGrid] Fix row-spanning in combination with column-pinning (#15460) @lhilgert9 +- [DataGrid] Improve resize performance (#15592) @lauri865 +- [DataGrid] Support column virtualization with dynamic row height (#15567) @cherniavskii +- [DataGrid] Improve `GridCell` performance (#15621) @lauri865 +- [l10n] Improve Chinese (zh-CN) locale (#15570) @headironc +- [l10n] Improve Portuguese (pt-PT) locale (#15561) @mathzdev + +#### `@mui/x-data-grid-pro@v7.23.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@v7.23.0`, plus: + +- [DataGridPro] Fix header filtering with `boolean` column type (#15640) @k-rajat19 +- [DataGridPro] Fix pagination state not updating if the data source response has no rows (#15643) @zinoroman +- [DataGridPro] Fix selection propagation issue on initialization (#15593) @MBilalShafi + +#### `@mui/x-data-grid-premium@v7.23.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@v7.23.0`. + +### Date and Time Pickers + +#### `@mui/x-date-pickers@v7.23.0` + +- [pickers] React 19 support (#15557) @arminmeh +- [pickers] Fix DST issue with `America/Asuncion` timezone and `AdapterMoment` (#15653) @flaviendelangle +- [pickers] Use `props.referenceDate` timezone when `props.value` and `props.defaultValue` are not defined (#15544) @flaviendelangle +- [l10n] Improve Dutch (nl-NL) locale (#15564) @nphmuller + +#### `@mui/x-date-pickers-pro@v7.23.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@v7.23.0`. + +### Charts + +#### `@mui/x-charts@v7.23.0` + +- [charts] React 19 support (#15557) @arminmeh +- [charts] Prevent invalid `releasePointerCapture` (#15609) @alexfauquette + +#### `@mui/x-charts-pro@v7.23.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-charts@v7.23.0`. + +### Tree View + +#### `@mui/x-tree-view@v7.23.0` + +- [TreeView] React 19 support (#15557) @arminmeh + +#### `@mui/x-tree-view-pro@7.23.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-tree-view@7.23.0`. + +### Docs + +- [docs] Add data caching to lazy loaded detail panel demo (#15555) @cherniavskii +- [docs] Remove selectors section from list view docs (#15639) @KenanYusuf +- [docs] Add documentation for the list view feature (#15344) @KenanYusuf + +### Core + +- [core] Update @mui/monorepo (#15574) @oliviertassinari + +## v7.22.3 + +_Nov 21, 2024_ + +We'd like to offer a big thanks to the 10 contributors who made this release possible. Here are some highlights ✨: + +- 📊 Charts Pro get stable. The [zoom](https://mui.com/x/react-charts/zoom-and-pan/) and [Heatmap](https://mui.com/x/react-charts/heatmap/) are now stable. +- 🌍 Improve Chinese, Spanish, Swedish, and Turkish locales on the Data Grid +- 🐞 Bugfixes + +Special thanks go out to the community contributors who have helped make this release possible: +@CarlosLopezLg, @headironc, @viktormelin, @qerkules, @DungTiger, @hendrikpeilke, @k-rajat19. +Following are all team members who have contributed to this release: +@alexfauquette, @LukasTy, @MBilalShafi, @flaviendelangle. + + + +### Data Grid + +#### `@mui/x-data-grid@7.22.3` + +- [DataGrid] Add prop to override search input props in `GridColumnsManagement` (#15476) @k-rajat19 +- [DataGrid] Add test coverage for issues fixed in #15184 @MBilalShafi +- [DataGrid] Fix memoized selectors with arguments (#15336) @MBilalShafi +- [DataGrid] Fix right column group header border with virtualization (#15503) @hendrikpeilke +- [DataGrid] Pass reason to `onPaginationModelChange` (#15402) @DungTiger +- [DataGrid] Set default overlay height in flex parent layout (#15535) @cherniavskii +- [l10n] Improve Chinese (zh-CN) locale (#15365) @headironc +- [l10n] Improve Spanish (es-ES) locale (#15369) @CarlosLopezLg +- [l10n] Improve Swedish (sv-SE) locale (#15371) @viktormelin +- [l10n] Improve Turkish (tr-TR) locale (#15414) @qerkules + +#### `@mui/x-data-grid-pro@7.22.3` [![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.22.3`. + +#### `@mui/x-data-grid-premium@7.22.3` [![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.22.3`. + +### Date and Time Pickers + +#### `@mui/x-date-pickers@7.22.3` + +- [pickers] Always use `props.value` when it changes (#15500) @flaviendelangle +- [pickers] Ensure internal value timezone is updated (#15491) @LukasTy +- [pickers] Fix `DateTimeRangePicker` error when using format without time (#15341) @fxnoob +- [pickers] Fix unused code in `PickersToolbar` component (#15525) @LukasTy + +#### `@mui/x-date-pickers-pro@7.22.3` [![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.22.3`, plus: + +- [DateTimeRangePicker] Use time in `referenceDate` when selecting date (#15431) @LukasTy + +### Charts + +#### `@mui/x-charts@7.22.3` + +No changes since `@mui/x-charts@7.22.2`. + +#### `@mui/x-charts-pro@7.22.3` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan') + +- [charts-pro] Fix missing typeOverload (#15400) @alexfauquette + +### Docs + +- [docs] Add `PickersPopper` component to customization playground (#15397) @LukasTy +- [docs] Add `next` version links (#15423) @LukasTy +- [docs] Use the `loading` state in the demos (#15538) @cherniavskii +- [docs] Add data caching to lazy loaded detail panel demo (#15506) @cherniavskii + +- [code-infra] Tentative fix for Argos flaky screenshot tests (#15399) @JCQuintas +- [docs-infra] Transpile `.ts` demo files (#15421) @KenanYusuf +- [core] Clarify release version bump strategy (#15536) @cherniavskii + +## 7.22.2 + +_Nov 8, 2024_ + +We'd like to offer a big thanks to the 7 contributors who made this release possible. Here are some highlights ✨: + +- 👨🏽‍💻 API enhancements +- 🐞 Bugfixes + +Special thanks go out to the community contributors who have helped make this release possible: +@clins1994, @GuillaumeMeheut, @k-rajat19. +Following are all team members who have contributed to this release: +@LukasTy, @MBilalShafi, @KenanYusuf, @arminmeh. + +### Upcoming alpha + +Keep an eye out for the MUI⠀X `v8.0.0-aplha.0` release soon. It will follow a weekly release schedule as always until it is stable. + + + +### Data Grid + +#### `@mui/x-data-grid@7.22.2` + +- [DataGrid] Fix `null` reference error in `GridVirtualScrollbar` (#15289) @MBilalShafi +- [DataGrid] Fix filtering with `boolean` column type (#15257) @k-rajat19 +- [DataGrid] Improve row selection propagation trigger (#15274) @MBilalShafi +- [DataGrid] Preprocess edit cell props on backspace/delete (#15223) @KenanYusuf +- [DataGrid] Add a recipe to persist column width and order (#15309) @MBilalShafi + +#### `@mui/x-data-grid-pro@7.22.2` [![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.22.2`, plus: + +- [DataGridPro] Apply default properties if they are not passed in a reorder column (#15320) @k-rajat19 +- [DataGridPro] Toggle row expansion with `Enter` key in Tree data (#15313) @k-rajat19 + +#### `@mui/x-data-grid-premium@7.22.2` [![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.22.2`, plus: + +- [DataGridPremium] Fix incorrect rows selection count when selection propagation is enabled with row grouping (#15222) @arminmeh + +### Date and Time Pickers + +#### `@mui/x-date-pickers@7.22.2` + +- [pickers] Add support for `moment-hijri@3.0.0` (#15248) @LukasTy + +#### `@mui/x-date-pickers-pro@7.22.2` [![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.22.2`. + +### Charts + +#### `@mui/x-charts@7.22.2` + +- [charts] Allow `SeriesValueFormatter` to return `null` value (#15295) @clins1994 +- [charts] Allow configuring the `domainLimit` for each axis. (#15325) @GuillaumeMeheut + +#### `@mui/x-charts-pro@7.0.0-beta.7` [![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.22.2`. + +## 7.22.1 + +_Nov 1, 2024_ + +We'd like to offer a big thanks to the 7 contributors who made this release possible. Here are some highlights ✨: + +- 🐞 Bugfixes +- 📚 Documentation improvements +- 🌍 Improve Polish (pl-PL) locale on the Date Pickers + +Special thanks go out to the community contributors who have helped make this release possible: +@wojtkolos, @dpak-maurya, @k-rajat19. +Following are all team members who have contributed to this release: +@LukasTy, @arminmeh, @MBilalShafi, @KenanYusuf, @flaviendelangle. + + + +### Data Grid + +#### `@mui/x-data-grid@7.22.1` + +- [DataGrid] Fix right column group header border (#15152) @KenanYusuf +- [DataGrid] Fix scroll jump when holding down arrow keys (#15167) @arminmeh +- [DataGrid] Move `rowGroupingModelChange` handler to respective hook (#15127) @MBilalShafi +- [DataGrid] Prevent error when deleting the last row (#15153) @dpak-maurya +- [DataGrid] Fix overlay height in autoHeight mode (#15205) @cherniavskii + +#### `@mui/x-data-grid-pro@7.22.1` [![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.22.1`, plus: + +- [DataGridPro] Add list view tests (#15166) @KenanYusuf + +#### `@mui/x-data-grid-premium@7.22.1` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan') + +- [DataGridPremium] Keep focus on the grouping cell on space bar press #15155 @k-rajat19 + +### Date and Time Pickers + +#### `@mui/x-date-pickers@7.22.1` + +- [l10n] Improve Polish (pl-PL) locale (#15177) @wojtkolos + +#### `@mui/x-date-pickers-pro@7.22.1` [![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.22.1`. + +### Tree View + +#### `@mui/x-tree-view@7.22.1` + +- [TreeView] Export `TreeItem2DragAndDropOverlay` and `TreeItem2LabelInput` from the root of each package (#15208) @flaviendelangle +- [TreeView] Fix drag and drop color usage (#15149) @LukasTy + +#### `@mui/x-tree-view-pro@7.22.1` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan') + +Same changes as in `@mui/x-tree-view@7.22.1`. + +### Docs + +- [docs] Add section explaining how to keep the selection while filtering in Data grid docs (#15199) @arminmeh + +## 7.22.0 + +_Oct 25, 2024_ + +We'd like to offer a big thanks to the 11 contributors who made this release possible. Here are some highlights ✨: + +- 🛰 Introduce [server-side support for Data Grid row grouping](https://mui.com/x/react-data-grid/server-side-data/row-grouping/) +- 🐞 Bugfixes +- 📚 Documentation improvements +- 🌍 Improve Portuguese (pt-BR) locale on the Data Grid component + +Special thanks go out to the community contributors who have helped make this release possible: +@clins1994, @GITPHLAP, @k-rajat19, @kalyan90, @merotosc, @yash49. +Following are all team members who have contributed to this release: +@cherniavskii, @flaviendelangle, @LukasTy, @MBilalShafi, @romgrk. + + + +### Data Grid + +#### `@mui/x-data-grid@7.22.0` + +- [DataGrid] Fix `GridPanelAnchor` positioning (#15022) @k-rajat19 +- [DataGrid] Fix ugly prop-types for the `pageStyle` prop of the `GridPrintExportMenuItem` component (#15015) @flaviendelangle +- [DataGrid] Fix value type in filter model for number and boolean column type (#14733) @k-rajat19 +- [DataGrid] Focus next row when the focused row is deleted (#15067) @cherniavskii +- [DataGrid] Remove some usages of `` and `` (#15013) @romgrk +- [DataGrid] Fix number of rows to display for page size options with negative value (#14890) @kalyan90 +- [l10n] Improve Portuguese (pt-BR) locale (#15021) @k-rajat19 + +#### `@mui/x-data-grid-pro@7.22.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.22.0`, plus: + +- [DataGridPro] Fix column pinning layout (#15073) @cherniavskii + +#### `@mui/x-data-grid-premium@7.22.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.22.0`, plus: + +- [DataGridPremium] Server-side data source with row grouping (#15109) @MBilalShafi + +### Date and Time Pickers + +#### `@mui/x-date-pickers@7.22.0` + +- [pickers] Fix `DateCalendar` timezone management (#15119) @LukasTy +- [pickers] Fix `DigitalClock` time options on a `DST` switch day (#15092) @LukasTy + +#### `@mui/x-date-pickers-pro@7.22.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.22.0`. + +### Charts + +#### `@mui/x-charts@7.22.0` + +- [charts] Export data type in `onAxisClick(_, data)` callback (#15038) @clins1994 + +#### `@mui/x-charts-pro@7.0.0-beta.6` [![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.22.0`. + +### Tree View + +#### `@mui/x-tree-view@7.22.0` + +- [TreeView] Make the cancellable event types public (#14992) @flaviendelangle + +### Docs + +- [docs] Fix typo in Tree View docs (#15047) @yash49 + +### Core + +- [core] Adjust cherry-pick GH actions (#15101) @LukasTy +- [core] Update prettier target branch (#15100) @MBilalShafi +- [core] Update some `default-branch-switch` instances for `v7.x` (#15085) @MBilalShafi +- [test] Revert to using `fireEvent` instead of `userEvent` (#14927) @LukasTy + ## 7.21.0 _Oct 17, 2024_ @@ -4117,7 +5057,7 @@ Same changes as in `@mui/x-data-grid-pro@7.0.0-alpha.5`. #### Breaking changes -- The slot interfaces got renamed to match with `@mui/base` naming. +- The slot interfaces have been renamed to match with `@mui/base` naming. The `SlotsComponent` suffix has been replaced with `Slots` and `SlotsComponentsProps` with `SlotProps`. ```diff @@ -4186,7 +5126,7 @@ Same changes as in `@mui/x-data-grid-pro@7.0.0-alpha.5`. The `useClearableField` hook API has been simplified to now take a `props` parameter instead of a `fieldProps`, `InputProps`, `clearable`, `onClear`, `slots` and `slotProps` parameters. - You should now be able to directly pass the returned value from your field hook (e.g: `useDateField`) to `useClearableField` + You should now be able to directly pass the returned value from your field hook (for example `useDateField`) to `useClearableField` ```diff const fieldResponse = useDateField(props); @@ -5159,7 +6099,7 @@ Same changes as in `@mui/x-date-pickers@7.0.0-alpha.0`. #### Breaking changes -Types for `slots` and `slotProps` got renamed by removing the "Component" which is meaningless for charts. +Types for `slots` and `slotProps` have been renamed by removing the "Component" which is meaningless for charts. Unless you imported those types, to create a wrapper, you should not be impacted by this breaking change. Here is an example of the renaming for the `` component. diff --git a/README.md b/README.md index d22304111b44d..b2e30d211bdc1 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,7 @@ [![Renovate status](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://github.com/mui/mui-x/issues/2081) [![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/mui/mui-x.svg)](https://isitmaintained.com/project/mui/mui-x 'Average time to resolve an issue') [![Open Collective backers and sponsors](https://img.shields.io/opencollective/all/mui-org)](https://opencollective.com/mui-org) -[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6293/badge)](https://bestpractices.coreinfrastructure.org/projects/6293) - - +[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/6293/badge)](https://www.bestpractices.dev/projects/6293)
diff --git a/bug-reproductions/x-charts/package.json b/bug-reproductions/x-charts/package.json new file mode 100644 index 0000000000000..a493ca3742c53 --- /dev/null +++ b/bug-reproductions/x-charts/package.json @@ -0,0 +1,25 @@ +{ + "dependencies": { + "@emotion/react": "latest", + "@emotion/styled": "latest", + "@mui/icons-material": "latest", + "@mui/material": "latest", + "@mui/x-charts": "latest", + "@mui/x-charts-pro": "latest", + "@types/react": "latest", + "@types/react-dom": "latest", + "react": "latest", + "react-dom": "latest", + "typescript": "latest" + }, + "devDependencies": { + "react-scripts": "latest" + }, + "main": "src/index.tsx", + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + } +} diff --git a/bug-reproductions/x-charts/public/index.html b/bug-reproductions/x-charts/public/index.html new file mode 100644 index 0000000000000..8e1bd85f807c0 --- /dev/null +++ b/bug-reproductions/x-charts/public/index.html @@ -0,0 +1,19 @@ + + + + Charts — MUI X + + + + + + + + + +
+ + diff --git a/bug-reproductions/x-charts/src/demo.tsx b/bug-reproductions/x-charts/src/demo.tsx new file mode 100644 index 0000000000000..fd022479b8780 --- /dev/null +++ b/bug-reproductions/x-charts/src/demo.tsx @@ -0,0 +1,20 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { BarChart } from '@mui/x-charts'; + +export default function Demo() { + return ( + + + + ); +} diff --git a/bug-reproductions/x-charts/src/index.tsx b/bug-reproductions/x-charts/src/index.tsx new file mode 100644 index 0000000000000..863f9ac4a3c38 --- /dev/null +++ b/bug-reproductions/x-charts/src/index.tsx @@ -0,0 +1,12 @@ +import * as React from 'react'; +import * as ReactDOM from 'react-dom/client'; +import { StyledEngineProvider } from '@mui/material/styles'; +import Demo from './demo'; + +ReactDOM.createRoot(document.querySelector('#root')!).render( + + + + + , +); diff --git a/bug-reproductions/x-charts/template.json b/bug-reproductions/x-charts/template.json new file mode 100644 index 0000000000000..7d4b5f453224b --- /dev/null +++ b/bug-reproductions/x-charts/template.json @@ -0,0 +1,6 @@ +{ + "title": "MUI X Charts template", + "description": "Base template for reporting a bug", + "tags": ["react", "typescript"], + "published": true +} diff --git a/bug-reproductions/x-charts/tsconfig.json b/bug-reproductions/x-charts/tsconfig.json new file mode 100644 index 0000000000000..af10394b4c375 --- /dev/null +++ b/bug-reproductions/x-charts/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react" + }, + "include": ["src"] +} diff --git a/docs/data/charts/areas-demo/AreaChartFillByValue.js b/docs/data/charts/areas-demo/AreaChartFillByValue.js index 7561daa0e7a6a..3ff670df251f2 100644 --- a/docs/data/charts/areas-demo/AreaChartFillByValue.js +++ b/docs/data/charts/areas-demo/AreaChartFillByValue.js @@ -45,6 +45,7 @@ export default function AreaChartFillByValue() { sx={{ [`& .${areaElementClasses.root}`]: { fill: 'url(#swich-color-id-1)', + filter: 'none', // Remove the default filter. }, }} > @@ -66,6 +67,7 @@ export default function AreaChartFillByValue() { sx={{ [`& .${areaElementClasses.root}`]: { fill: 'url(#swich-color-id-2)', + filter: 'none', // Remove the default filter. }, }} > diff --git a/docs/data/charts/areas-demo/AreaChartFillByValue.tsx b/docs/data/charts/areas-demo/AreaChartFillByValue.tsx index 97fc2f78ff596..dfc4844544645 100644 --- a/docs/data/charts/areas-demo/AreaChartFillByValue.tsx +++ b/docs/data/charts/areas-demo/AreaChartFillByValue.tsx @@ -52,6 +52,7 @@ export default function AreaChartFillByValue() { sx={{ [`& .${areaElementClasses.root}`]: { fill: 'url(#swich-color-id-1)', + filter: 'none', // Remove the default filter. }, }} > @@ -73,6 +74,7 @@ export default function AreaChartFillByValue() { sx={{ [`& .${areaElementClasses.root}`]: { fill: 'url(#swich-color-id-2)', + filter: 'none', // Remove the default filter. }, }} > diff --git a/docs/data/charts/axis/AxisWithComposition.js b/docs/data/charts/axis/AxisWithComposition.js index 725eb3d112a0c..339d380b08ea8 100644 --- a/docs/data/charts/axis/AxisWithComposition.js +++ b/docs/data/charts/axis/AxisWithComposition.js @@ -53,7 +53,11 @@ export default function AxisWithComposition() { > - + diff --git a/docs/data/charts/axis/AxisWithComposition.tsx b/docs/data/charts/axis/AxisWithComposition.tsx index 725eb3d112a0c..339d380b08ea8 100644 --- a/docs/data/charts/axis/AxisWithComposition.tsx +++ b/docs/data/charts/axis/AxisWithComposition.tsx @@ -53,7 +53,11 @@ export default function AxisWithComposition() { > - + diff --git a/docs/data/charts/axis/axis.md b/docs/data/charts/axis/axis.md index 7f8098d27120c..d213ff6b3bd32 100644 --- a/docs/data/charts/axis/axis.md +++ b/docs/data/charts/axis/axis.md @@ -206,7 +206,7 @@ The x-axis label placement is based on the axis configuration, and the y-axis is ### Position Charts components provide 4 props: `topAxis`, `rightAxis`, `bottomAxis`, and `leftAxis` allowing to define the 4 axes of the chart. -Those pros can accept three type of value: +Those props can accept three type of value: - `null` to not display the axis - `string` which should correspond to the id of a `xAxis` for top and bottom. Or to the id of a `yAxis` for left and right. diff --git a/docs/data/charts/bars/netflixsBalanceSheet.js b/docs/data/charts/bars/netflixsBalanceSheet.js new file mode 100644 index 0000000000000..753f3e013532c --- /dev/null +++ b/docs/data/charts/bars/netflixsBalanceSheet.js @@ -0,0 +1,82 @@ +// Data from https://finance.yahoo.com/quote/NFLX/financials/ + +const translations = { + totAss: 'Total Assets', + currAss: 'Current Assets', + nCurrAss: 'non-Current Assets', + totLia: 'Total Liabilities', + curLia: 'Current Liabilities', + nCurLia: 'non-Current Liabilities', + totEq: 'Total Equity', + capStock: 'Capital Stock', + retEarn: 'Retained Earning', + treas: 'Treasury', + nonAffect: 'non Affected', +}; + +export function addLabels(series) { + return series.map((item) => ({ + ...item, + label: translations[item.dataKey], + valueFormatter: (v) => (v ? `$ ${v.toLocaleString()}k` : '-'), + })); +} + +export const balanceSheet = [ + { + year: '2020', + totAss: 39280359, + currAss: 9761580, + nCurrAss: 29518779, + totLia: 28215119, + curLia: 7805785, + nCurLia: 20409334, + totEq: 11065240, + capStock: 3447698, + retEarn: 7573144, + treas: null, + nonAffect: 44398, + }, + { + year: '2021', + totAss: 44584663, + currAss: 8069825, + nCurrAss: 36514838, + totLia: 28735415, + curLia: 8488966, + nCurLia: 20246449, + totEq: 15849248, + capStock: 4024561, + retEarn: 12689372, + treas: 824190, + nonAffect: -40495, + }, + { + year: '2022', + totAss: 48594768, + currAss: 9266473, + nCurrAss: 39328295, + totLia: 27817367, + curLia: 7930974, + nCurLia: 19886393, + totEq: 20777401, + capStock: 4637601, + retEarn: 17181296, + treas: 824190, + nonAffect: -217306, + }, + { + year: '2023', + totAss: 48731992, + currAss: 9918133, + nCurrAss: 38813859, + totLia: 28143679, + curLia: 8860655, + nCurLia: 19283024, + totEq: 20588313, + capStock: 5145172, + retEarn: 22589286, + treas: 6922200, + nonAffect: -223945, + }, +]; diff --git a/docs/data/charts/components/HtmlLegend.js b/docs/data/charts/components/HtmlLegend.js new file mode 100644 index 0000000000000..a58701b379a8f --- /dev/null +++ b/docs/data/charts/components/HtmlLegend.js @@ -0,0 +1,66 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { unstable_useBarSeries } from '@mui/x-charts/hooks'; +import { ChartDataProvider } from '@mui/x-charts/context'; +import { ChartsSurface } from '@mui/x-charts/ChartsSurface'; +import { BarPlot } from '@mui/x-charts/BarChart'; +import { ChartsXAxis } from '@mui/x-charts/ChartsXAxis'; +import { ChartsYAxis } from '@mui/x-charts/ChartsYAxis'; + +function MyCustomLegend() { + const s = unstable_useBarSeries(); + return ( + + + {Object.values(s?.series ?? []).map((v) => { + return ( + + + + + ); + })} + +
+
+
{`${v.label}`}
+ ); +} + +const veryLongText = + "Second Series. You should always try to avoid long sentences. But oftentimes, it's not possible. So, we need to handle them gracefully. This is a very long sentence that should be fully readable."; + +export default function HtmlLegend() { + return ( + + + + + + + + + + + ); +} diff --git a/docs/data/charts/components/HtmlLegend.tsx b/docs/data/charts/components/HtmlLegend.tsx new file mode 100644 index 0000000000000..a58701b379a8f --- /dev/null +++ b/docs/data/charts/components/HtmlLegend.tsx @@ -0,0 +1,66 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { unstable_useBarSeries } from '@mui/x-charts/hooks'; +import { ChartDataProvider } from '@mui/x-charts/context'; +import { ChartsSurface } from '@mui/x-charts/ChartsSurface'; +import { BarPlot } from '@mui/x-charts/BarChart'; +import { ChartsXAxis } from '@mui/x-charts/ChartsXAxis'; +import { ChartsYAxis } from '@mui/x-charts/ChartsYAxis'; + +function MyCustomLegend() { + const s = unstable_useBarSeries(); + return ( + + + {Object.values(s?.series ?? []).map((v) => { + return ( + + + + + ); + })} + +
+
+
{`${v.label}`}
+ ); +} + +const veryLongText = + "Second Series. You should always try to avoid long sentences. But oftentimes, it's not possible. So, we need to handle them gracefully. This is a very long sentence that should be fully readable."; + +export default function HtmlLegend() { + return ( + + + + + + + + + + + ); +} diff --git a/docs/data/charts/components/HtmlLegend.tsx.preview b/docs/data/charts/components/HtmlLegend.tsx.preview new file mode 100644 index 0000000000000..3f05cd43a0a0e --- /dev/null +++ b/docs/data/charts/components/HtmlLegend.tsx.preview @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/docs/data/charts/components/components.md b/docs/data/charts/components/components.md index be2f67d72870d..791c338ced4fe 100644 --- a/docs/data/charts/components/components.md +++ b/docs/data/charts/components/components.md @@ -76,3 +76,22 @@ By using `invert`, the value associated with the current mouse coordinate `y` ca ``` {{"demo": "ScaleDemo.js"}} + +## HTML components + +With the introduction of the `ChartDataProvider` in v8, the chart data can be accessed from any component. +This allows you to create HTML components that interact with the charts data. + +In the next example, notice that `MyCustomLegend` component displays the series names and colors. +This creates an html `table` element, which handles long series names better than the default legend. + +{{"demo": "HtmlLegend.js"}} + +:::warning +Note that the HTML components are not part of the SVG hierarchy. +Hence, they should be: + +- Outside the `` component to avoid mixing HTAM and SVG. +- Inside the `` component to get access to the data. + +::: diff --git a/docs/data/charts/composition/composition.md b/docs/data/charts/composition/composition.md index 657c8724c1355..4bf8606dd5dba 100644 --- a/docs/data/charts/composition/composition.md +++ b/docs/data/charts/composition/composition.md @@ -2,7 +2,7 @@ title: React Chart composition productId: x-charts githubLabel: 'component: charts' -components: ChartContainer, ChartContainerPro, ChartsGrid +components: ChartContainer, ChartContainerPro, ChartsGrid, ChartDataProvider, ChartsSurface packageName: '@mui/x-charts' --- @@ -13,11 +13,75 @@ packageName: '@mui/x-charts' ## Overview The `@mui/x-charts` follows an architecture based on context providers. -The overall idea is to pass your series and axes definitions to a single component: the ``. -This component transforms the data and makes it available to its children. +The overall idea is to pass your series and axes definitions to special components. +This component transforms the data and makes it available to its children, which can be composed. -Based on the data provided by the container, you can render some graphical elements with provided subcomponents, such as `` or ``. -Or you can [create your own components](/x/react-charts/components/). +There are two main classes of components, which are used to create a chart. + +### Structural components + +These are used to define the chart's structure and data. + +#### The Data Provider and Surface components + +As the name suggests, the `ChartDataProvider` provides the data to the children components. +While the `ChartsSurface` renders the SVG elements. + +```jsx + + + {children} + + +``` + +:::info +The demos here are using the `ChartContainer` component. +To see demos using the separate `ChartDataProvider` and `ChartsSurface` components, check the [HTML components documentation](/x/react-charts/components/#html-components). +::: + +#### The `ChartContainer` helper + +This component is a composition of the two previous components. +It can be used instead of them when there is no need to customize anything outside the chart's graphical elements. + +```jsx + + {children} + +``` + +### Graphical components + +These are any component that render the graphical elements of the chart. +They are the children of the **Structural components** shown above. +There are many of them, so they won't all be listed here. +You can even [create your own components](/x/react-charts/components/). + +Some examples of graphical components are: + +- `LinePlot` +- `BarPlot` +- `ChartsXAxis` +- `ChartsLegend` +- `ChartsTooltip` ## Container options diff --git a/docs/data/charts/dataset/weather.js b/docs/data/charts/dataset/weather.js new file mode 100644 index 0000000000000..9eb2105690f83 --- /dev/null +++ b/docs/data/charts/dataset/weather.js @@ -0,0 +1,90 @@ +export const dataset = [ + { + london: 59, + paris: 57, + newYork: 86, + seoul: 21, + month: 'Jan', + }, + { + london: 50, + paris: 52, + newYork: 78, + seoul: 28, + month: 'Feb', + }, + { + london: 47, + paris: 53, + newYork: 106, + seoul: 41, + month: 'Mar', + }, + { + london: 54, + paris: 56, + newYork: 92, + seoul: 73, + month: 'Apr', + }, + { + london: 57, + paris: 69, + newYork: 92, + seoul: 99, + month: 'May', + }, + { + london: 60, + paris: 63, + newYork: 103, + seoul: 144, + month: 'June', + }, + { + london: 59, + paris: 60, + newYork: 105, + seoul: 319, + month: 'July', + }, + { + london: 65, + paris: 60, + newYork: 106, + seoul: 249, + month: 'Aug', + }, + { + london: 51, + paris: 51, + newYork: 95, + seoul: 131, + month: 'Sept', + }, + { + london: 60, + paris: 65, + newYork: 97, + seoul: 55, + month: 'Oct', + }, + { + london: 67, + paris: 64, + newYork: 76, + seoul: 48, + month: 'Nov', + }, + { + london: 61, + paris: 70, + newYork: 103, + seoul: 25, + month: 'Dec', + }, +]; + +export function valueFormatter(value) { + return `${value}mm`; +} diff --git a/docs/data/charts/getting-started/getting-started.md b/docs/data/charts/getting-started/getting-started.md index 83dbff7001c70..7efdf925eebfa 100644 --- a/docs/data/charts/getting-started/getting-started.md +++ b/docs/data/charts/getting-started/getting-started.md @@ -41,15 +41,15 @@ yarn add @mui/material @emotion/react @emotion/styled ```json "peerDependencies": { - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" }, ``` ### 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`. +You can import D3 functions from `@mui/x-charts-vendor/d3-scale`. ## Rendering Charts diff --git a/docs/data/charts/heatmap/dumbData.js b/docs/data/charts/heatmap/dumbData.js new file mode 100644 index 0000000000000..7af927d58c60b --- /dev/null +++ b/docs/data/charts/heatmap/dumbData.js @@ -0,0 +1,22 @@ +export const data = [ + [0, 0, 10], + [0, 1, 20], + [0, 2, 40], + [0, 3, 90], + [0, 4, 70], + [1, 0, 30], + [1, 1, 50], + [1, 2, 10], + [1, 3, 70], + [1, 4, 40], + [2, 0, 50], + [2, 1, 20], + [2, 2, 90], + [2, 3, 20], + [2, 4, 70], + [3, 0, 40], + [3, 1, 50], + [3, 2, 20], + [3, 3, 70], + [3, 4, 90], +]; diff --git a/docs/data/charts/heatmap/heatmap.md b/docs/data/charts/heatmap/heatmap.md index f33f20a988aab..a5b6321f1e392 100644 --- a/docs/data/charts/heatmap/heatmap.md +++ b/docs/data/charts/heatmap/heatmap.md @@ -1,7 +1,7 @@ --- title: React Heatmap chart productId: x-charts -components: Heatmap, HeatmapPlot, DefaultHeatmapTooltip +components: Heatmap, HeatmapPlot, HeatmapTooltip --- # Charts - Heatmap [](/x/introduction/licensing/#pro-plan 'Pro plan') diff --git a/docs/data/charts/legend/tempAnomaly.js b/docs/data/charts/legend/tempAnomaly.js new file mode 100644 index 0000000000000..fe651b02323fa --- /dev/null +++ b/docs/data/charts/legend/tempAnomaly.js @@ -0,0 +1,177 @@ +export const dataset = [ + { year: new Date(1850, 0, 1), anomaly: -0.4177114 }, + { year: new Date(1851, 0, 1), anomaly: -0.2333498 }, + { year: new Date(1852, 0, 1), anomaly: -0.22939907 }, + { year: new Date(1853, 0, 1), anomaly: -0.27035445 }, + { year: new Date(1854, 0, 1), anomaly: -0.29152083 }, + { year: new Date(1855, 0, 1), anomaly: -0.29691675 }, + { year: new Date(1856, 0, 1), anomaly: -0.32035372 }, + { year: new Date(1857, 0, 1), anomaly: -0.46723005 }, + { year: new Date(1858, 0, 1), anomaly: -0.3887657 }, + { year: new Date(1859, 0, 1), anomaly: -0.28126517 }, + { year: new Date(1860, 0, 1), anomaly: -0.39016518 }, + { year: new Date(1861, 0, 1), anomaly: -0.42911294 }, + { year: new Date(1862, 0, 1), anomaly: -0.5363694 }, + { year: new Date(1863, 0, 1), anomaly: -0.34424406 }, + { year: new Date(1864, 0, 1), anomaly: -0.46546507 }, + { year: new Date(1865, 0, 1), anomaly: -0.33248132 }, + { year: new Date(1866, 0, 1), anomaly: -0.3412875 }, + { year: new Date(1867, 0, 1), anomaly: -0.35699412 }, + { year: new Date(1868, 0, 1), anomaly: -0.35182714 }, + { year: new Date(1869, 0, 1), anomaly: -0.31659195 }, + { year: new Date(1870, 0, 1), anomaly: -0.32792753 }, + { year: new Date(1871, 0, 1), anomaly: -0.36856276 }, + { year: new Date(1872, 0, 1), anomaly: -0.32811058 }, + { year: new Date(1873, 0, 1), anomaly: -0.3412969 }, + { year: new Date(1874, 0, 1), anomaly: -0.3732512 }, + { year: new Date(1875, 0, 1), anomaly: -0.37562594 }, + { year: new Date(1876, 0, 1), anomaly: -0.4241099 }, + { year: new Date(1877, 0, 1), anomaly: -0.10110884 }, + { year: new Date(1878, 0, 1), anomaly: -0.011315192 }, + { year: new Date(1879, 0, 1), anomaly: -0.30363432 }, + { year: new Date(1880, 0, 1), anomaly: -0.31583205 }, + { year: new Date(1881, 0, 1), anomaly: -0.23224552 }, + { year: new Date(1882, 0, 1), anomaly: -0.29553008 }, + { year: new Date(1883, 0, 1), anomaly: -0.3464744 }, + { year: new Date(1884, 0, 1), anomaly: -0.49232006 }, + { year: new Date(1885, 0, 1), anomaly: -0.47112358 }, + { year: new Date(1886, 0, 1), anomaly: -0.42090362 }, + { year: new Date(1887, 0, 1), anomaly: -0.49878576 }, + { year: new Date(1888, 0, 1), anomaly: -0.37937889 }, + { year: new Date(1889, 0, 1), anomaly: -0.24989556 }, + { year: new Date(1890, 0, 1), anomaly: -0.50685817 }, + { year: new Date(1891, 0, 1), anomaly: -0.40131494 }, + { year: new Date(1892, 0, 1), anomaly: -0.5075585 }, + { year: new Date(1893, 0, 1), anomaly: -0.49461922 }, + { year: new Date(1894, 0, 1), anomaly: -0.48376393 }, + { year: new Date(1895, 0, 1), anomaly: -0.4487516 }, + { year: new Date(1896, 0, 1), anomaly: -0.28400728 }, + { year: new Date(1897, 0, 1), anomaly: -0.25980017 }, + { year: new Date(1898, 0, 1), anomaly: -0.48579213 }, + { year: new Date(1899, 0, 1), anomaly: -0.35543364 }, + { year: new Date(1900, 0, 1), anomaly: -0.2344939 }, + { year: new Date(1901, 0, 1), anomaly: -0.29341024 }, + { year: new Date(1902, 0, 1), anomaly: -0.43895653 }, + { year: new Date(1903, 0, 1), anomaly: -0.5332871 }, + { year: new Date(1904, 0, 1), anomaly: -0.59751105 }, + { year: new Date(1905, 0, 1), anomaly: -0.40779322 }, + { year: new Date(1906, 0, 1), anomaly: -0.31910878 }, + { year: new Date(1907, 0, 1), anomaly: -0.5040763 }, + { year: new Date(1908, 0, 1), anomaly: -0.5138197 }, + { year: new Date(1909, 0, 1), anomaly: -0.53568715 }, + { year: new Date(1910, 0, 1), anomaly: -0.5309095 }, + { year: new Date(1911, 0, 1), anomaly: -0.539079 }, + { year: new Date(1912, 0, 1), anomaly: -0.47553864 }, + { year: new Date(1913, 0, 1), anomaly: -0.4670111 }, + { year: new Date(1914, 0, 1), anomaly: -0.26243657 }, + { year: new Date(1915, 0, 1), anomaly: -0.19167219 }, + { year: new Date(1916, 0, 1), anomaly: -0.42002314 }, + { year: new Date(1917, 0, 1), anomaly: -0.5428197 }, + { year: new Date(1918, 0, 1), anomaly: -0.4243641 }, + { year: new Date(1919, 0, 1), anomaly: -0.32528907 }, + { year: new Date(1920, 0, 1), anomaly: -0.29835507 }, + { year: new Date(1921, 0, 1), anomaly: -0.24044435 }, + { year: new Date(1922, 0, 1), anomaly: -0.3390137 }, + { year: new Date(1923, 0, 1), anomaly: -0.31768188 }, + { year: new Date(1924, 0, 1), anomaly: -0.3118017 }, + { year: new Date(1925, 0, 1), anomaly: -0.28214198 }, + { year: new Date(1926, 0, 1), anomaly: -0.122555 }, + { year: new Date(1927, 0, 1), anomaly: -0.2291136 }, + { year: new Date(1928, 0, 1), anomaly: -0.20646581 }, + { year: new Date(1929, 0, 1), anomaly: -0.39244303 }, + { year: new Date(1930, 0, 1), anomaly: -0.17680542 }, + { year: new Date(1931, 0, 1), anomaly: -0.103397675 }, + { year: new Date(1932, 0, 1), anomaly: -0.14546171 }, + { year: new Date(1933, 0, 1), anomaly: -0.32234442 }, + { year: new Date(1934, 0, 1), anomaly: -0.17433685 }, + { year: new Date(1935, 0, 1), anomaly: -0.20605923 }, + { year: new Date(1936, 0, 1), anomaly: -0.16952094 }, + { year: new Date(1937, 0, 1), anomaly: -0.019198947 }, + { year: new Date(1938, 0, 1), anomaly: -0.012200737 }, + { year: new Date(1939, 0, 1), anomaly: -0.040797204 }, + { year: new Date(1940, 0, 1), anomaly: 0.07593582 }, + { year: new Date(1941, 0, 1), anomaly: 0.0381293 }, + { year: new Date(1942, 0, 1), anomaly: 0.0014060677 }, + { year: new Date(1943, 0, 1), anomaly: 0.0064215823 }, + { year: new Date(1944, 0, 1), anomaly: 0.14410514 }, + { year: new Date(1945, 0, 1), anomaly: 0.043088354 }, + { year: new Date(1946, 0, 1), anomaly: -0.11881461 }, + { year: new Date(1947, 0, 1), anomaly: -0.09120561 }, + { year: new Date(1948, 0, 1), anomaly: -0.12466127 }, + { year: new Date(1949, 0, 1), anomaly: -0.14380223 }, + { year: new Date(1950, 0, 1), anomaly: -0.2266218 }, + { year: new Date(1951, 0, 1), anomaly: -0.06115396 }, + { year: new Date(1952, 0, 1), anomaly: 0.015354548 }, + { year: new Date(1953, 0, 1), anomaly: 0.07763075 }, + { year: new Date(1954, 0, 1), anomaly: -0.11675023 }, + { year: new Date(1955, 0, 1), anomaly: -0.19730994 }, + { year: new Date(1956, 0, 1), anomaly: -0.26316562 }, + { year: new Date(1957, 0, 1), anomaly: -0.035334915 }, + { year: new Date(1958, 0, 1), anomaly: -0.017632563 }, + { year: new Date(1959, 0, 1), anomaly: -0.048004813 }, + { year: new Date(1960, 0, 1), anomaly: -0.11545958 }, + { year: new Date(1961, 0, 1), anomaly: -0.019999769 }, + { year: new Date(1962, 0, 1), anomaly: -0.06404272 }, + { year: new Date(1963, 0, 1), anomaly: -0.036810614 }, + { year: new Date(1964, 0, 1), anomaly: -0.30586153 }, + { year: new Date(1965, 0, 1), anomaly: -0.20442048 }, + { year: new Date(1966, 0, 1), anomaly: -0.1488976 }, + { year: new Date(1967, 0, 1), anomaly: -0.117539294 }, + { year: new Date(1968, 0, 1), anomaly: -0.16864756 }, + { year: new Date(1969, 0, 1), anomaly: -0.03138624 }, + { year: new Date(1970, 0, 1), anomaly: -0.08506408 }, + { year: new Date(1971, 0, 1), anomaly: -0.20588905 }, + { year: new Date(1972, 0, 1), anomaly: -0.09379131 }, + { year: new Date(1973, 0, 1), anomaly: 0.04995016 }, + { year: new Date(1974, 0, 1), anomaly: -0.17252657 }, + { year: new Date(1975, 0, 1), anomaly: -0.110754214 }, + { year: new Date(1976, 0, 1), anomaly: -0.2158369 }, + { year: new Date(1977, 0, 1), anomaly: 0.1030885 }, + { year: new Date(1978, 0, 1), anomaly: 0.0052559716 }, + { year: new Date(1979, 0, 1), anomaly: 0.09085814 }, + { year: new Date(1980, 0, 1), anomaly: 0.19607204 }, + { year: new Date(1981, 0, 1), anomaly: 0.25001204 }, + { year: new Date(1982, 0, 1), anomaly: 0.034268282 }, + { year: new Date(1983, 0, 1), anomaly: 0.22380984 }, + { year: new Date(1984, 0, 1), anomaly: 0.04799352 }, + { year: new Date(1985, 0, 1), anomaly: 0.049729742 }, + { year: new Date(1986, 0, 1), anomaly: 0.09568698 }, + { year: new Date(1987, 0, 1), anomaly: 0.2430264 }, + { year: new Date(1988, 0, 1), anomaly: 0.2821517 }, + { year: new Date(1989, 0, 1), anomaly: 0.1792503 }, + { year: new Date(1990, 0, 1), anomaly: 0.36058238 }, + { year: new Date(1991, 0, 1), anomaly: 0.33889654 }, + { year: new Date(1992, 0, 1), anomaly: 0.12489683 }, + { year: new Date(1993, 0, 1), anomaly: 0.16570719 }, + { year: new Date(1994, 0, 1), anomaly: 0.23354979 }, + { year: new Date(1995, 0, 1), anomaly: 0.37686613 }, + { year: new Date(1996, 0, 1), anomaly: 0.27668938 }, + { year: new Date(1997, 0, 1), anomaly: 0.4223085 }, + { year: new Date(1998, 0, 1), anomaly: 0.5773417 }, + { year: new Date(1999, 0, 1), anomaly: 0.32448497 }, + { year: new Date(2000, 0, 1), anomaly: 0.33108476 }, + { year: new Date(2001, 0, 1), anomaly: 0.48928034 }, + { year: new Date(2002, 0, 1), anomaly: 0.5434665 }, + { year: new Date(2003, 0, 1), anomaly: 0.54417014 }, + { year: new Date(2004, 0, 1), anomaly: 0.46737072 }, + { year: new Date(2005, 0, 1), anomaly: 0.6068625 }, + { year: new Date(2006, 0, 1), anomaly: 0.5725527 }, + { year: new Date(2007, 0, 1), anomaly: 0.5917013 }, + { year: new Date(2008, 0, 1), anomaly: 0.46564984 }, + { year: new Date(2009, 0, 1), anomaly: 0.5967816 }, + { year: new Date(2010, 0, 1), anomaly: 0.6803714 }, + { year: new Date(2011, 0, 1), anomaly: 0.53769773 }, + { year: new Date(2012, 0, 1), anomaly: 0.57760704 }, + { year: new Date(2013, 0, 1), anomaly: 0.6235753 }, + { year: new Date(2014, 0, 1), anomaly: 0.67287165 }, + { year: new Date(2015, 0, 1), anomaly: 0.8251144 }, + { year: new Date(2016, 0, 1), anomaly: 0.9329271 }, + { year: new Date(2017, 0, 1), anomaly: 0.84517425 }, + { year: new Date(2018, 0, 1), anomaly: 0.76265407 }, + { year: new Date(2019, 0, 1), anomaly: 0.8910726 }, + { year: new Date(2020, 0, 1), anomaly: 0.9229205 }, + { year: new Date(2021, 0, 1), anomaly: 0.76190555 }, + { year: new Date(2022, 0, 1), anomaly: 0.8013053 }, + { year: new Date(2023, 0, 1), anomaly: 1.1003127 }, + { year: new Date(2024, 0, 1), anomaly: 1.2314565 }, +]; diff --git a/docs/data/charts/line-demo/LineWithPrediction.js b/docs/data/charts/line-demo/LineWithPrediction.js index 277ce031aeb0a..1e5858c5ddf6b 100644 --- a/docs/data/charts/line-demo/LineWithPrediction.js +++ b/docs/data/charts/line-demo/LineWithPrediction.js @@ -40,11 +40,11 @@ function CustomAnimatedLine(props) { height={top + height + bottom} /> - - + + - - + + ); @@ -64,7 +64,8 @@ export default function LineWithPrediction() { height={200} width={400} slots={{ line: CustomAnimatedLine }} - slotProps={{ line: { limit: 5, sxAfter: { strokeDasharray: '10 5' } } }} + slotProps={{ line: { limit: 5 } }} + sx={{ '& .line-after path': { strokeDasharray: '10 5' } }} /> ); } diff --git a/docs/data/charts/line-demo/LineWithPrediction.tsx b/docs/data/charts/line-demo/LineWithPrediction.tsx index 55fd42deb2443..981c7805dd3eb 100644 --- a/docs/data/charts/line-demo/LineWithPrediction.tsx +++ b/docs/data/charts/line-demo/LineWithPrediction.tsx @@ -47,11 +47,11 @@ function CustomAnimatedLine(props: CustomAnimatedLineProps) { height={top + height + bottom} /> - - + + - - + + ); @@ -71,7 +71,8 @@ export default function LineWithPrediction() { height={200} width={400} slots={{ line: CustomAnimatedLine }} - slotProps={{ line: { limit: 5, sxAfter: { strokeDasharray: '10 5' } } as any }} + slotProps={{ line: { limit: 5 } as any }} + sx={{ '& .line-after path': { strokeDasharray: '10 5' } }} /> ); } diff --git a/docs/data/charts/line-demo/LineWithPrediction.tsx.preview b/docs/data/charts/line-demo/LineWithPrediction.tsx.preview index 1dc0a8f94a59e..f15f69543aae0 100644 --- a/docs/data/charts/line-demo/LineWithPrediction.tsx.preview +++ b/docs/data/charts/line-demo/LineWithPrediction.tsx.preview @@ -10,5 +10,6 @@ height={200} width={400} slots={{ line: CustomAnimatedLine }} - slotProps={{ line: { limit: 5, sxAfter: { strokeDasharray: '10 5' } } as any }} + slotProps={{ line: { limit: 5 } as any }} + sx={{ '& .line-after path': { strokeDasharray: '10 5' } }} /> \ No newline at end of file diff --git a/docs/data/charts/lines/CSSCustomization.js b/docs/data/charts/lines/CSSCustomization.js index 5e5fe62608213..b647eaa27f14d 100644 --- a/docs/data/charts/lines/CSSCustomization.js +++ b/docs/data/charts/lines/CSSCustomization.js @@ -13,6 +13,7 @@ export default function CSSCustomization() { }, '& .MuiAreaElement-series-Germany': { fill: "url('#myGradient')", + filter: 'none', // Remove the default filtering }, }} xAxis={[ diff --git a/docs/data/charts/lines/CSSCustomization.tsx b/docs/data/charts/lines/CSSCustomization.tsx index 5e5fe62608213..b647eaa27f14d 100644 --- a/docs/data/charts/lines/CSSCustomization.tsx +++ b/docs/data/charts/lines/CSSCustomization.tsx @@ -13,6 +13,7 @@ export default function CSSCustomization() { }, '& .MuiAreaElement-series-Germany': { fill: "url('#myGradient')", + filter: 'none', // Remove the default filtering }, }} xAxis={[ diff --git a/docs/data/charts/lines/GDPperCapita.js b/docs/data/charts/lines/GDPperCapita.js new file mode 100644 index 0000000000000..eb5babd81d4dc --- /dev/null +++ b/docs/data/charts/lines/GDPperCapita.js @@ -0,0 +1,31 @@ +export const dataset = [ + { date: new Date(1990, 0, 1), fr: 28129, gb: 26189, dl: 25391 }, + { date: new Date(1991, 0, 1), fr: 28294.264, gb: 25792.014, dl: 26769.96 }, + { date: new Date(1992, 0, 1), fr: 28619.805, gb: 25790.186, dl: 27385.055 }, + { date: new Date(1993, 0, 1), fr: 28336.16, gb: 26349.342, dl: 27250.701 }, + { date: new Date(1994, 0, 1), fr: 28907.977, gb: 27277.543, dl: 28140.057 }, + { date: new Date(1995, 0, 1), fr: 29418.863, gb: 27861.215, dl: 28868.945 }, + { date: new Date(1996, 0, 1), fr: 29736.645, gb: 28472.248, dl: 29349.982 }, + { date: new Date(1997, 0, 1), fr: 30341.807, gb: 29259.764, dl: 30186.945 }, + { date: new Date(1998, 0, 1), fr: 31323.078, gb: 30077.385, dl: 31129.584 }, + { date: new Date(1999, 0, 1), fr: 32284.611, gb: 30932.537, dl: 32087.604 }, + { date: new Date(2000, 0, 1), fr: 33409.68, gb: 31946.037, dl: 33367.285 }, + { date: new Date(2001, 0, 1), fr: 33920.098, gb: 32660.441, dl: 34260.29 }, + { date: new Date(2002, 0, 1), fr: 34152.773, gb: 33271.3, dl: 34590.93 }, + { date: new Date(2003, 0, 1), fr: 34292.03, gb: 34232.426, dl: 34716.44 }, + { date: new Date(2004, 0, 1), fr: 35093.824, gb: 34865.78, dl: 35528.715 }, + { date: new Date(2005, 0, 1), fr: 35495.465, gb: 35623.625, dl: 36205.574 }, + { date: new Date(2006, 0, 1), fr: 36166.16, gb: 36214.07, dl: 38014.137 }, + { date: new Date(2007, 0, 1), fr: 36845.684, gb: 36816.676, dl: 39752.207 }, + { date: new Date(2008, 0, 1), fr: 36761.793, gb: 36264.79, dl: 40715.434 }, + { date: new Date(2009, 0, 1), fr: 35534.926, gb: 34402.36, dl: 38962.938 }, + { date: new Date(2010, 0, 1), fr: 36086.727, gb: 34754.473, dl: 41109.582 }, + { date: new Date(2011, 0, 1), fr: 36691, gb: 34971, dl: 43189 }, + { date: new Date(2012, 0, 1), fr: 36571, gb: 35185, dl: 43320 }, + { date: new Date(2013, 0, 1), fr: 36632, gb: 35618, dl: 43413 }, + { date: new Date(2014, 0, 1), fr: 36527, gb: 36436, dl: 43922 }, + { date: new Date(2015, 0, 1), fr: 36827, gb: 36941, dl: 44293 }, + { date: new Date(2016, 0, 1), fr: 37124, gb: 37334, dl: 44689 }, + { date: new Date(2017, 0, 1), fr: 37895, gb: 37782.83, dl: 45619.785 }, + { date: new Date(2018, 0, 1), fr: 38515.918, gb: 38058.086, dl: 46177.617 }, +]; diff --git a/docs/data/charts/lines/basicDataset.js b/docs/data/charts/lines/basicDataset.js new file mode 100644 index 0000000000000..ef59c6d6d807e --- /dev/null +++ b/docs/data/charts/lines/basicDataset.js @@ -0,0 +1,8 @@ +export const dataset = [ + { x: 1, y: 2 }, + { x: 2, y: 5.5 }, + { x: 3, y: 2 }, + { x: 5, y: 8.5 }, + { x: 8, y: 1.5 }, + { x: 10, y: 5 }, +]; diff --git a/docs/data/charts/lines/worldElectricityProduction.js b/docs/data/charts/lines/worldElectricityProduction.js new file mode 100644 index 0000000000000..4807f7ef87fff --- /dev/null +++ b/docs/data/charts/lines/worldElectricityProduction.js @@ -0,0 +1,520 @@ +export const keyToLabel = { + coal: 'Electricity from coal (TWh)', + gas: 'Electricity from gas (TWh)', + oil: 'Electricity from oil (TWh)', + nuclear: 'Electricity from nuclear (TWh)', + hydro: 'Electricity from hydro (TWh)', + wind: 'Electricity from wind (TWh)', + solar: 'Electricity from solar (TWh)', + bio: 'Electricity from bioenergy (TWh)', + other: 'Other renewables excluding bioenergy (TWh)', +}; + +export const colors = { + other: 'lightgray', + bio: 'lightgreen', + solar: 'yellow', + wind: 'lightblue', + hydro: 'blue', + nuclear: 'orange', + oil: 'darkgrey', + gas: 'gray', + coal: 'black', +}; + +export const worldElectricityProduction = [ + { + country: 'World', + year: 1985, + other: 0, + bio: 0, + solar: 0.011747475, + wind: 0.064220205, + hydro: 1979.2446, + nuclear: 1488.9216, + oil: 1110.7847, + gas: 1426.3086, + coal: 3748.3848, + }, + { + country: 'World', + year: 1986, + other: 0, + bio: 0, + solar: 0.015183838, + wind: 0.13883132, + hydro: 2006.0651, + nuclear: 1594.7357, + oil: 1168.3097, + gas: 1432.6683, + coal: 3839.0095, + }, + { + country: 'World', + year: 1987, + other: 0, + bio: 0, + solar: 0.01060303, + wind: 0.19537677, + hydro: 2033.1884, + nuclear: 1734.7332, + oil: 1183.1947, + gas: 1516.4941, + coal: 4058.0767, + }, + { + country: 'World', + year: 1988, + other: 0, + bio: 0, + solar: 0.01019596, + wind: 0.3315798, + hydro: 2098.3518, + nuclear: 1891.2493, + oil: 1256.5684, + gas: 1540.9414, + coal: 4200.6743, + }, + { + country: 'World', + year: 1989, + other: 0, + bio: 0, + solar: 0.26222324, + wind: 2.6497767, + hydro: 2087.588, + nuclear: 1945.0106, + oil: 1350.2358, + gas: 1728.5189, + coal: 4376.982, + }, + { + country: 'World', + year: 1990, + other: 0, + bio: 0, + solar: 0.38834995, + wind: 3.6324706, + hydro: 2158.854, + nuclear: 2000.596, + oil: 1364.6844, + gas: 1789.7031, + coal: 4460.2417, + }, + { + country: 'World', + year: 1991, + other: 0, + bio: 0, + solar: 0.5053229, + wind: 4.086107, + hydro: 2208.702, + nuclear: 2096.3098, + oil: 1349.9071, + gas: 1815.2444, + coal: 4557.0664, + }, + { + country: 'World', + year: 1992, + other: 0, + bio: 0, + solar: 0.4666791, + wind: 4.732812, + hydro: 2208.4592, + nuclear: 2112.223, + oil: 1328.2163, + gas: 1829.3868, + coal: 4649.9165, + }, + { + country: 'World', + year: 1993, + other: 0, + bio: 0, + solar: 0.5566775, + wind: 5.704169, + hydro: 2341.4597, + nuclear: 2184.9646, + oil: 1266.6155, + gas: 1863.8153, + coal: 4727.899, + }, + { + country: 'World', + year: 1994, + other: 0, + bio: 0, + solar: 0.5969829, + wind: 7.13173, + hydro: 2356.203, + nuclear: 2225.9788, + oil: 1302.1187, + gas: 1925.1002, + coal: 4891.904, + }, + { + country: 'World', + year: 1995, + other: 0, + bio: 0, + solar: 0.63888276, + wind: 8.272123, + hydro: 2483.6868, + nuclear: 2322.5298, + oil: 1259.9452, + gas: 2036.3821, + coal: 5038.9316, + }, + { + country: 'World', + year: 1996, + other: 0, + bio: 0, + solar: 0.69922996, + wind: 9.215601, + hydro: 2517.03, + nuclear: 2406.615, + oil: 1245.6957, + gas: 2101.594, + coal: 5279.661, + }, + { + country: 'World', + year: 1997, + other: 0, + bio: 0, + solar: 0.7496558, + wind: 12.028216, + hydro: 2561.359, + nuclear: 2390.0642, + oil: 1244.647, + gas: 2271.0615, + coal: 5395.626, + }, + { + country: 'World', + year: 1998, + other: 0, + bio: 0, + solar: 0.811852, + wind: 15.92926, + hydro: 2581.1204, + nuclear: 2431.1948, + oil: 1294.6146, + gas: 2408.5476, + coal: 5511.2935, + }, + { + country: 'World', + year: 1999, + other: 0, + bio: 0, + solar: 0.9052879, + wind: 21.226898, + hydro: 2600.65, + nuclear: 2523.7056, + oil: 1266.6599, + gas: 2600.75, + coal: 5630.859, + }, + { + country: 'World', + year: 2000, + other: 52.37, + bio: 148.65, + solar: 1.08, + wind: 31.16, + hydro: 2621.36, + nuclear: 2507.43, + oil: 1209.51, + gas: 2681.11, + coal: 5719.12, + }, + { + country: 'World', + year: 2001, + other: 52.6, + bio: 143.1, + solar: 1.35, + wind: 38.16, + hydro: 2561.04, + nuclear: 2573.71, + oil: 1197.6, + gas: 2827.65, + coal: 5801.14, + }, + { + country: 'World', + year: 2002, + other: 54.08, + bio: 156.61, + solar: 1.69, + wind: 52.04, + hydro: 2601.39, + nuclear: 2601.89, + oil: 1175.58, + gas: 3033.78, + coal: 6056.12, + }, + { + country: 'World', + year: 2003, + other: 56.07, + bio: 167.91, + solar: 2.07, + wind: 63.43, + hydro: 2602.33, + nuclear: 2577.71, + oil: 1198.2, + gas: 3165.78, + coal: 6458.61, + }, + { + country: 'World', + year: 2004, + other: 57.94, + bio: 184.54, + solar: 2.71, + wind: 85.26, + hydro: 2796.69, + nuclear: 2682.73, + oil: 1177.47, + gas: 3408.19, + coal: 6697.61, + }, + { + country: 'World', + year: 2005, + other: 58.74, + bio: 208.44, + solar: 3.78, + wind: 103.89, + hydro: 2895.17, + nuclear: 2686.95, + oil: 1186.13, + gas: 3579.99, + coal: 7040.85, + }, + { + country: 'World', + year: 2006, + other: 60.11, + bio: 220.96, + solar: 5.11, + wind: 132.79, + hydro: 3001.53, + nuclear: 2721.42, + oil: 1097.06, + gas: 3792.38, + coal: 7439.88, + }, + { + country: 'World', + year: 2007, + other: 62.87, + bio: 243.14, + solar: 6.92, + wind: 170.91, + hydro: 3046.18, + nuclear: 2666.92, + oil: 1119.39, + gas: 4109.47, + coal: 7931.82, + }, + { + country: 'World', + year: 2008, + other: 65.97, + bio: 258.44, + solar: 11.36, + wind: 220.07, + hydro: 3231.07, + nuclear: 2656.04, + oil: 1078.99, + gas: 4210.51, + coal: 7927.59, + }, + { + country: 'World', + year: 2009, + other: 68.02, + bio: 279.55, + solar: 19.19, + wind: 275.88, + hydro: 3229.55, + nuclear: 2619, + oil: 1005.12, + gas: 4247.72, + coal: 7817.32, + }, + { + country: 'World', + year: 2010, + other: 68.38, + bio: 322.22, + solar: 31.05, + wind: 345.99, + hydro: 3412.33, + nuclear: 2686.44, + oil: 1011.78, + gas: 4701.27, + coal: 8358.6, + }, + { + country: 'World', + year: 2011, + other: 69.67, + bio: 342.44, + solar: 61.85, + wind: 440.39, + hydro: 3479.25, + nuclear: 2575.35, + oil: 1103.87, + gas: 4767.24, + coal: 8814.17, + }, + { + country: 'World', + year: 2012, + other: 70.88, + bio: 370.87, + solar: 95.18, + wind: 529.11, + hydro: 3645.02, + nuclear: 2403.21, + oil: 1157.13, + gas: 5042.66, + coal: 8855.83, + }, + { + country: 'World', + year: 2013, + other: 72.58, + bio: 402.92, + solar: 131.42, + wind: 641.17, + hydro: 3776.88, + nuclear: 2418.44, + oil: 1118.61, + gas: 4939.52, + coal: 9306.75, + }, + { + country: 'World', + year: 2014, + other: 77.68, + bio: 438.47, + solar: 196.46, + wind: 716.51, + hydro: 3865.63, + nuclear: 2472.7, + oil: 1063.74, + gas: 5096.07, + coal: 9495.57, + }, + { + country: 'World', + year: 2015, + other: 81.57, + bio: 475.79, + solar: 254.87, + wind: 828.37, + hydro: 3870.04, + nuclear: 2502.45, + oil: 1068.09, + gas: 5418.55, + coal: 9160.63, + }, + { + country: 'World', + year: 2016, + other: 83.91, + bio: 483.77, + solar: 329.15, + wind: 959.65, + hydro: 3996.54, + nuclear: 2540.48, + oil: 1004.96, + gas: 5669.08, + coal: 9226.85, + }, + { + country: 'World', + year: 2017, + other: 86.39, + bio: 515.07, + solar: 444.54, + wind: 1136.41, + hydro: 4053.96, + nuclear: 2566.22, + oil: 913.07, + gas: 5791.83, + coal: 9518.91, + }, + { + country: 'World', + year: 2018, + other: 89.54, + bio: 546.21, + solar: 570.57, + wind: 1265.29, + hydro: 4174.81, + nuclear: 2619.57, + oil: 841.34, + gas: 6015.24, + coal: 9899.44, + }, + { + country: 'World', + year: 2019, + other: 91.15, + bio: 575.5, + solar: 701.19, + wind: 1419.51, + hydro: 4220.11, + nuclear: 2724.08, + oil: 776.78, + gas: 6176.34, + coal: 9680.92, + }, + { + country: 'World', + year: 2020, + other: 94.16, + bio: 602.57, + solar: 850.89, + wind: 1587.13, + hydro: 4341.1, + nuclear: 2634.69, + oil: 741, + gas: 6132.47, + coal: 9292.9, + }, + { + country: 'World', + year: 2021, + other: 95, + bio: 663.78, + solar: 1040.06, + wind: 1849.4, + hydro: 4244.57, + nuclear: 2740.78, + oil: 793.53, + gas: 6326, + coal: 10081.8, + }, + { + country: 'World', + year: 2022, + other: 99.74, + bio: 677.57, + solar: 1289.27, + wind: 2139.23, + hydro: 4326.76, + nuclear: 2610.04, + oil: 884.98, + gas: 6309.46, + coal: 10190.71, + }, +]; diff --git a/docs/data/charts/pie/webUsageStats.js b/docs/data/charts/pie/webUsageStats.js new file mode 100644 index 0000000000000..b8a888253dcf4 --- /dev/null +++ b/docs/data/charts/pie/webUsageStats.js @@ -0,0 +1,70 @@ +// Data derived from https://gs.statcounter.com/os-market-share/desktop/worldwide/2023 +// And https://gs.statcounter.com/os-market-share/mobile/worldwide/2023 +// And https://gs.statcounter.com/platform-market-share/desktop-mobile-tablet/worldwide/2023 +// For the month of December 2023 + +export const desktopOS = [ + { + label: 'Windows', + value: 72.72, + }, + { + label: 'OS X', + value: 16.38, + }, + { + label: 'Linux', + value: 3.83, + }, + { + label: 'Chrome OS', + value: 2.42, + }, + { + label: 'Other', + value: 4.65, + }, +]; + +export const mobileOS = [ + { + label: 'Android', + value: 70.48, + }, + { + label: 'iOS', + value: 28.8, + }, + { + label: 'Other', + value: 0.71, + }, +]; + +export const platforms = [ + { + label: 'Mobile', + value: 59.12, + }, + { + label: 'Desktop', + value: 40.88, + }, +]; + +const normalize = (v, v2) => Number.parseFloat(((v * v2) / 100).toFixed(2)); + +export const mobileAndDesktopOS = [ + ...mobileOS.map((v) => ({ + ...v, + label: v.label === 'Other' ? 'Other (Mobile)' : v.label, + value: normalize(v.value, platforms[0].value), + })), + ...desktopOS.map((v) => ({ + ...v, + label: v.label === 'Other' ? 'Other (Desktop)' : v.label, + value: normalize(v.value, platforms[1].value), + })), +]; + +export const valueFormatter = (item) => `${item.value}%`; diff --git a/docs/data/charts/styling/GradientTooltip.js b/docs/data/charts/styling/GradientTooltip.js new file mode 100644 index 0000000000000..91d3f04fdbacd --- /dev/null +++ b/docs/data/charts/styling/GradientTooltip.js @@ -0,0 +1,37 @@ +import * as React from 'react'; +import { BarChart } from '@mui/x-charts/BarChart'; + +export default function GradientTooltip() { + return ( + + + + + + + ); +} diff --git a/docs/data/charts/styling/GradientTooltip.tsx b/docs/data/charts/styling/GradientTooltip.tsx new file mode 100644 index 0000000000000..91d3f04fdbacd --- /dev/null +++ b/docs/data/charts/styling/GradientTooltip.tsx @@ -0,0 +1,37 @@ +import * as React from 'react'; +import { BarChart } from '@mui/x-charts/BarChart'; + +export default function GradientTooltip() { + return ( + + + + + + + ); +} diff --git a/docs/data/charts/styling/PatternPie.js b/docs/data/charts/styling/PatternPie.js new file mode 100644 index 0000000000000..02f53eebf0161 --- /dev/null +++ b/docs/data/charts/styling/PatternPie.js @@ -0,0 +1,44 @@ +import * as React from 'react'; +import { PieChart } from '@mui/x-charts/PieChart'; + +export default function PatternPie() { + return ( + + + + + + + ); +} diff --git a/docs/data/charts/styling/PatternPie.tsx b/docs/data/charts/styling/PatternPie.tsx new file mode 100644 index 0000000000000..02f53eebf0161 --- /dev/null +++ b/docs/data/charts/styling/PatternPie.tsx @@ -0,0 +1,44 @@ +import * as React from 'react'; +import { PieChart } from '@mui/x-charts/PieChart'; + +export default function PatternPie() { + return ( + + + + + + + ); +} diff --git a/docs/data/charts/styling/styling.md b/docs/data/charts/styling/styling.md index 9f795806ee5d0..fc64c9cb923d9 100644 --- a/docs/data/charts/styling/styling.md +++ b/docs/data/charts/styling/styling.md @@ -164,3 +164,22 @@ Chart components accept the `sx` props. From here, you can target any subcomponents with its class name. {{"demo": "SxStyling.js"}} + +### Gradients and patterns + +It is possible to use gradients and patterns to fill the charts. +This can be done by passing your gradient or pattern definition as children of the chart component. + +Note that the gradient or pattern defined that way is only usable for SVG. +So a direct definition like `color: "url(#Pattern)'` would cause undefined colors in HTML elements such as the tooltip. +The demo solves this issue by using a CSS variable `'--my-custom-pattern': 'url(#Pattern)'` to specify fallback color with `color: 'var(--my-custom-pattern, #123456)'`. + +{{"demo": "PatternPie.js"}} + +#### Using gradients on tooltips + +Gradients defined as SVG elements are not directly supported in HTML. +However you can use the [gradient functions](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions#gradient_functions) to define a gradient in CSS. +This gradient can be used in the tooltip by setting the `sx` prop on the tooltip component, instead of the fallback color used in the previous examples. + +{{"demo": "GradientTooltip.js"}} diff --git a/docs/data/charts/tooltip/CustomAxisTooltip.js b/docs/data/charts/tooltip/CustomAxisTooltip.js index b65f7d3df4b23..9689757aa66a9 100644 --- a/docs/data/charts/tooltip/CustomAxisTooltip.js +++ b/docs/data/charts/tooltip/CustomAxisTooltip.js @@ -1,184 +1,79 @@ import * as React from 'react'; -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 } from '@mui/x-charts/ChartsTooltip'; -import { useSvgRef } from '@mui/x-charts/hooks'; - -function usePointer() { - const svgRef = useSvgRef(); - const popperRef = React.useRef(null); - const positionRef = React.useRef({ 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) => { - positionRef.current = { - 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: { - getBoundingClientRect: () => ({ - x: positionRef.current.x, - y: positionRef.current.y, - top: positionRef.current.y, - left: positionRef.current.x, - right: positionRef.current.x, - bottom: positionRef.current.y, - width: 0, - height: 0, - toJSON: () => '', - }), - }, - }; -} export function CustomAxisTooltip() { const tooltipData = useAxisTooltip(); - const { isActive, isMousePointer, pointerHeight, popperRef, anchorEl } = - usePointer(); - if (!tooltipData || !isActive) { - // No data to display + if (tooltipData === null) { return null; } - - // The pointer type can be used to have different behavior based on pointer type. - // Adapt the tooltip offset to the size of the pointer. - const yOffset = isMousePointer ? 0 : 40 - pointerHeight; - return ( - - theme.zIndex.modal, - }} - open - placement={isMousePointer ? 'top-end' : 'top'} - anchorEl={anchorEl} - popperRef={popperRef} - modifiers={[ - { - name: 'offset', - options: { - offset: [0, yOffset], - }, - }, - ]} - > - - - - - - - - - {tooltipData.seriesItems.map((seriesItem) => ( - - - - - - ))} - -
- {tooltipData.axisFormattedValue} -
-
-
- - {seriesItem.formattedLabel} - - - {seriesItem.formattedValue} -
-
-
-
+ }, + }, + }} + > + + + + + + + + {tooltipData.seriesItems.map((seriesItem) => ( + + + + + + ))} + +
+ {tooltipData.axisFormattedValue} +
+
+
+ + {seriesItem.formattedLabel} + + + {seriesItem.formattedValue} +
+ ); } diff --git a/docs/data/charts/tooltip/CustomAxisTooltip.tsx b/docs/data/charts/tooltip/CustomAxisTooltip.tsx index 010af780809fe..9689757aa66a9 100644 --- a/docs/data/charts/tooltip/CustomAxisTooltip.tsx +++ b/docs/data/charts/tooltip/CustomAxisTooltip.tsx @@ -1,190 +1,79 @@ import * as React from 'react'; -import NoSsr from '@mui/material/NoSsr'; -import Popper, { PopperProps } from '@mui/material/Popper'; import Paper from '@mui/material/Paper'; import Typography from '@mui/material/Typography'; import { useAxisTooltip } from '@mui/x-charts/ChartsTooltip'; -import { useSvgRef } from '@mui/x-charts/hooks'; - -type PointerState = { - isActive: boolean; - isMousePointer: boolean; - pointerHeight: number; -}; - -function usePointer(): PointerState & Pick { - const svgRef = useSvgRef(); - const popperRef: PopperProps['popperRef'] = React.useRef(null); - const positionRef = React.useRef({ 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) => { - positionRef.current = { - 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: { - getBoundingClientRect: () => ({ - x: positionRef.current.x, - y: positionRef.current.y, - top: positionRef.current.y, - left: positionRef.current.x, - right: positionRef.current.x, - bottom: positionRef.current.y, - width: 0, - height: 0, - toJSON: () => '', - }), - }, - }; -} export function CustomAxisTooltip() { const tooltipData = useAxisTooltip(); - const { isActive, isMousePointer, pointerHeight, popperRef, anchorEl } = - usePointer(); - if (!tooltipData || !isActive) { - // No data to display + if (tooltipData === null) { return null; } - - // The pointer type can be used to have different behavior based on pointer type. - // Adapt the tooltip offset to the size of the pointer. - const yOffset = isMousePointer ? 0 : 40 - pointerHeight; - return ( - - theme.zIndex.modal, - }} - open - placement={isMousePointer ? 'top-end' : 'top'} - anchorEl={anchorEl} - popperRef={popperRef} - modifiers={[ - { - name: 'offset', - options: { - offset: [0, yOffset], - }, - }, - ]} - > - - - - - - - - - {tooltipData.seriesItems.map((seriesItem) => ( - - - - - - ))} - -
- {tooltipData.axisFormattedValue} -
-
-
- - {seriesItem.formattedLabel} - - - {seriesItem.formattedValue} -
-
-
-
+ }, + }, + }} + > + + + + + + + + {tooltipData.seriesItems.map((seriesItem) => ( + + + + + + ))} + +
+ {tooltipData.axisFormattedValue} +
+
+
+ + {seriesItem.formattedLabel} + + + {seriesItem.formattedValue} +
+ ); } diff --git a/docs/data/charts/tooltip/CustomAxisTooltipContent.js b/docs/data/charts/tooltip/CustomAxisTooltipContent.js index db5e269c6bd9e..f2b5f5c4d649d 100644 --- a/docs/data/charts/tooltip/CustomAxisTooltipContent.js +++ b/docs/data/charts/tooltip/CustomAxisTooltipContent.js @@ -4,6 +4,7 @@ import { BarPlot } from '@mui/x-charts/BarChart'; import { ChartsXAxis } from '@mui/x-charts/ChartsXAxis'; import { ChartsClipPath } from '@mui/x-charts/ChartsClipPath'; import { ChartsYAxis } from '@mui/x-charts/ChartsYAxis'; +import { ChartsTooltipContainer } from '@mui/x-charts/ChartsTooltip'; import { CustomAxisTooltip } from './CustomAxisTooltip'; import { dataset, valueFormatter } from '../dataset/weather'; @@ -27,7 +28,9 @@ export default function CustomAxisTooltipContent() {
- + + +
); diff --git a/docs/data/charts/tooltip/CustomAxisTooltipContent.tsx b/docs/data/charts/tooltip/CustomAxisTooltipContent.tsx index 9a791ace90ea9..34e94004d86c5 100644 --- a/docs/data/charts/tooltip/CustomAxisTooltipContent.tsx +++ b/docs/data/charts/tooltip/CustomAxisTooltipContent.tsx @@ -4,6 +4,7 @@ import { BarPlot } from '@mui/x-charts/BarChart'; import { ChartsXAxis } from '@mui/x-charts/ChartsXAxis'; import { ChartsClipPath } from '@mui/x-charts/ChartsClipPath'; import { ChartsYAxis } from '@mui/x-charts/ChartsYAxis'; +import { ChartsTooltipContainer } from '@mui/x-charts/ChartsTooltip'; import { CustomAxisTooltip } from './CustomAxisTooltip'; import { dataset, valueFormatter } from '../dataset/weather'; @@ -28,7 +29,9 @@ export default function CustomAxisTooltipContent() { - + + + ); diff --git a/docs/data/charts/tooltip/CustomItemTooltip.js b/docs/data/charts/tooltip/CustomItemTooltip.js index 2f7c2310c5d53..88833ca76d354 100644 --- a/docs/data/charts/tooltip/CustomItemTooltip.js +++ b/docs/data/charts/tooltip/CustomItemTooltip.js @@ -1,144 +1,39 @@ import * as React from 'react'; -import NoSsr from '@mui/material/NoSsr'; -import Popper from '@mui/material/Popper'; import Paper from '@mui/material/Paper'; import Stack from '@mui/material/Stack'; import Typography from '@mui/material/Typography'; import { useItemTooltip } from '@mui/x-charts/ChartsTooltip'; -import { useSvgRef } from '@mui/x-charts/hooks'; - -function usePointer() { - const svgRef = useSvgRef(); - const popperRef = React.useRef(null); - const positionRef = React.useRef({ 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) => { - positionRef.current = { - 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: { - getBoundingClientRect: () => ({ - x: positionRef.current.x, - y: positionRef.current.y, - top: positionRef.current.y, - left: positionRef.current.x, - right: positionRef.current.x, - bottom: positionRef.current.y, - width: 0, - height: 0, - toJSON: () => '', - }), - }, - }; -} export function CustomItemTooltip() { const tooltipData = useItemTooltip(); - const { isActive, isMousePointer, pointerHeight, popperRef, anchorEl } = - usePointer(); - - if (!tooltipData || !isActive) { - // No data to display + if (!tooltipData) { return null; } - - // Adapt the tooltip offset to the size of the pointer. - const yOffset = isMousePointer ? 0 : 40 - pointerHeight; - return ( - - theme.zIndex.modal, - }} - open - placement={isMousePointer ? 'top-end' : 'top'} - anchorEl={anchorEl} - popperRef={popperRef} - modifiers={[ - { - name: 'offset', - options: { - offset: [0, yOffset], - }, - }, - ]} - > - + +
- -
- - {tooltipData.label} - - {tooltipData.formattedValue} - - - - + /> + + {tooltipData.label} + + {tooltipData.formattedValue} + + ); } diff --git a/docs/data/charts/tooltip/CustomItemTooltip.tsx b/docs/data/charts/tooltip/CustomItemTooltip.tsx index 077243411c5d3..88833ca76d354 100644 --- a/docs/data/charts/tooltip/CustomItemTooltip.tsx +++ b/docs/data/charts/tooltip/CustomItemTooltip.tsx @@ -1,150 +1,39 @@ import * as React from 'react'; -import NoSsr from '@mui/material/NoSsr'; -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 } from '@mui/x-charts/ChartsTooltip'; -import { useSvgRef } from '@mui/x-charts/hooks'; - -type PointerState = { - isActive: boolean; - isMousePointer: boolean; - pointerHeight: number; -}; - -function usePointer(): PointerState & Pick { - const svgRef = useSvgRef(); - const popperRef: PopperProps['popperRef'] = React.useRef(null); - const positionRef = React.useRef({ 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) => { - positionRef.current = { - 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: { - getBoundingClientRect: () => ({ - x: positionRef.current.x, - y: positionRef.current.y, - top: positionRef.current.y, - left: positionRef.current.x, - right: positionRef.current.x, - bottom: positionRef.current.y, - width: 0, - height: 0, - toJSON: () => '', - }), - }, - }; -} export function CustomItemTooltip() { const tooltipData = useItemTooltip(); - const { isActive, isMousePointer, pointerHeight, popperRef, anchorEl } = - usePointer(); - - if (!tooltipData || !isActive) { - // No data to display + if (!tooltipData) { return null; } - - // Adapt the tooltip offset to the size of the pointer. - const yOffset = isMousePointer ? 0 : 40 - pointerHeight; - return ( - - theme.zIndex.modal, - }} - open - placement={isMousePointer ? 'top-end' : 'top'} - anchorEl={anchorEl} - popperRef={popperRef} - modifiers={[ - { - name: 'offset', - options: { - offset: [0, yOffset], - }, - }, - ]} - > - + +
- -
- - {tooltipData.label} - - {tooltipData.formattedValue} - - - - + /> + + {tooltipData.label} + + {tooltipData.formattedValue} + + ); } diff --git a/docs/data/charts/tooltip/CustomItemTooltipContent.js b/docs/data/charts/tooltip/CustomItemTooltipContent.js deleted file mode 100644 index 6cda5693841c5..0000000000000 --- a/docs/data/charts/tooltip/CustomItemTooltipContent.js +++ /dev/null @@ -1,37 +0,0 @@ -import * as React from 'react'; -import Stack from '@mui/material/Stack'; -import Typography from '@mui/material/Typography'; -import Paper from '@mui/material/Paper'; - -/** - * Render a basic tooltip content for an item. - */ -export function CustomItemTooltipContent(props) { - return ( - - -
- - {props.label} - - {props.formattedValue} - - - ); -} diff --git a/docs/data/charts/tooltip/CustomItemTooltipContent.tsx b/docs/data/charts/tooltip/CustomItemTooltipContent.tsx deleted file mode 100644 index a85a7ec3fe28b..0000000000000 --- a/docs/data/charts/tooltip/CustomItemTooltipContent.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import * as React from 'react'; -import Stack from '@mui/material/Stack'; -import Typography from '@mui/material/Typography'; -import Paper from '@mui/material/Paper'; -import { UseItemTooltipReturnValue } from '@mui/x-charts/ChartsTooltip'; -import { ChartSeriesType } from '@mui/x-charts/internals'; - -/** - * Render a basic tooltip content for an item. - */ -export function CustomItemTooltipContent( - props: Pick< - UseItemTooltipReturnValue, - 'color' | 'label' | 'formattedValue' - >, -) { - return ( - - -
- - {props.label} - - {props.formattedValue} - - - ); -} diff --git a/docs/data/charts/tooltip/CustomTooltipContent.js b/docs/data/charts/tooltip/CustomTooltipContent.js index 72d4b2d839d2d..70661ea5c4362 100644 --- a/docs/data/charts/tooltip/CustomTooltipContent.js +++ b/docs/data/charts/tooltip/CustomTooltipContent.js @@ -4,6 +4,7 @@ import { BarPlot } from '@mui/x-charts/BarChart'; import { ChartsXAxis } from '@mui/x-charts/ChartsXAxis'; import { ChartsClipPath } from '@mui/x-charts/ChartsClipPath'; import { ChartsYAxis } from '@mui/x-charts/ChartsYAxis'; +import { ChartsTooltipContainer } from '@mui/x-charts/ChartsTooltip'; import { CustomItemTooltip } from './CustomItemTooltip'; import { dataset, valueFormatter } from '../dataset/weather'; @@ -27,7 +28,9 @@ export default function CustomTooltipContent() { - + + +
); diff --git a/docs/data/charts/tooltip/CustomTooltipContent.tsx b/docs/data/charts/tooltip/CustomTooltipContent.tsx index a40570a7d032e..70661ea5c4362 100644 --- a/docs/data/charts/tooltip/CustomTooltipContent.tsx +++ b/docs/data/charts/tooltip/CustomTooltipContent.tsx @@ -4,6 +4,7 @@ import { BarPlot } from '@mui/x-charts/BarChart'; import { ChartsXAxis } from '@mui/x-charts/ChartsXAxis'; import { ChartsClipPath } from '@mui/x-charts/ChartsClipPath'; import { ChartsYAxis } from '@mui/x-charts/ChartsYAxis'; +import { ChartsTooltipContainer } from '@mui/x-charts/ChartsTooltip'; import { CustomItemTooltip } from './CustomItemTooltip'; import { dataset, valueFormatter } from '../dataset/weather'; @@ -27,8 +28,9 @@ export default function CustomTooltipContent() { - - + + +
); diff --git a/docs/data/charts/tooltip/CustomTooltipPosition.js b/docs/data/charts/tooltip/CustomTooltipPosition.js index 7bb8180ba629a..0853674803a2d 100644 --- a/docs/data/charts/tooltip/CustomTooltipPosition.js +++ b/docs/data/charts/tooltip/CustomTooltipPosition.js @@ -9,6 +9,10 @@ import { BarPlot } from '@mui/x-charts/BarChart'; import { ChartsXAxis } from '@mui/x-charts/ChartsXAxis'; import { ChartsClipPath } from '@mui/x-charts/ChartsClipPath'; import { ChartsYAxis } from '@mui/x-charts/ChartsYAxis'; +import { + ChartsTooltipContainer, + ChartsItemTooltipContent, +} from '@mui/x-charts/ChartsTooltip'; import { ItemTooltip } from './ItemTooltip'; import { ItemTooltipFixedY } from './ItemTooltipFixedY'; import { ItemTooltipTopElement } from './ItemTooltipTopElement'; @@ -19,6 +23,14 @@ export default function CustomTooltipPosition() { const id = React.useId(); const clipPathId = `${id}-clip-path`; + + // Pick one of the custom tooltip wrapper according to the state. + const TooltipPlacement = + (tooltipType === 'mouse' && ItemTooltip) || + (tooltipType === 'fixedY' && ItemTooltipFixedY) || + (tooltipType === 'itemTop' && ItemTooltipTopElement) || + ChartsTooltipContainer; + return (
@@ -55,9 +67,11 @@ export default function CustomTooltipPosition() { - {tooltipType === 'mouse' && } - {tooltipType === 'fixedY' && } - {tooltipType === 'itemTop' && } + {/* Our custom tooltip wrapper with the default item content. */} + + + +
diff --git a/docs/data/charts/tooltip/CustomTooltipPosition.tsx b/docs/data/charts/tooltip/CustomTooltipPosition.tsx index 49596ca4ed65b..4f0deaf7bcd5e 100644 --- a/docs/data/charts/tooltip/CustomTooltipPosition.tsx +++ b/docs/data/charts/tooltip/CustomTooltipPosition.tsx @@ -9,6 +9,10 @@ import { BarPlot } from '@mui/x-charts/BarChart'; import { ChartsXAxis } from '@mui/x-charts/ChartsXAxis'; import { ChartsClipPath } from '@mui/x-charts/ChartsClipPath'; import { ChartsYAxis } from '@mui/x-charts/ChartsYAxis'; +import { + ChartsTooltipContainer, + ChartsItemTooltipContent, +} from '@mui/x-charts/ChartsTooltip'; import { ItemTooltip } from './ItemTooltip'; import { ItemTooltipFixedY } from './ItemTooltipFixedY'; import { ItemTooltipTopElement } from './ItemTooltipTopElement'; @@ -21,6 +25,14 @@ export default function CustomTooltipPosition() { const id = React.useId(); const clipPathId = `${id}-clip-path`; + + // Pick one of the custom tooltip wrapper according to the state. + const TooltipPlacement = + (tooltipType === 'mouse' && ItemTooltip) || + (tooltipType === 'fixedY' && ItemTooltipFixedY) || + (tooltipType === 'itemTop' && ItemTooltipTopElement) || + ChartsTooltipContainer; + return (
@@ -60,9 +72,11 @@ export default function CustomTooltipPosition() { - {tooltipType === 'mouse' && } - {tooltipType === 'fixedY' && } - {tooltipType === 'itemTop' && } + {/* Our custom tooltip wrapper with the default item content. */} + + + +
diff --git a/docs/data/charts/tooltip/Interaction.js b/docs/data/charts/tooltip/Interaction.js index aa9cfe094a799..d99346368b884 100644 --- a/docs/data/charts/tooltip/Interaction.js +++ b/docs/data/charts/tooltip/Interaction.js @@ -21,8 +21,8 @@ const barChartsParams = { export default function Interaction() { return ( - - + + ); } diff --git a/docs/data/charts/tooltip/Interaction.tsx b/docs/data/charts/tooltip/Interaction.tsx index cacdca34fd5a1..5443660027f8e 100644 --- a/docs/data/charts/tooltip/Interaction.tsx +++ b/docs/data/charts/tooltip/Interaction.tsx @@ -21,8 +21,8 @@ const barChartsParams = { export default function Interaction() { return ( - - + + ); } diff --git a/docs/data/charts/tooltip/Interaction.tsx.preview b/docs/data/charts/tooltip/Interaction.tsx.preview index dee07e073af07..09da31b473bbf 100644 --- a/docs/data/charts/tooltip/Interaction.tsx.preview +++ b/docs/data/charts/tooltip/Interaction.tsx.preview @@ -1,2 +1,2 @@ - - \ No newline at end of file + + \ No newline at end of file diff --git a/docs/data/charts/tooltip/ItemTooltip.js b/docs/data/charts/tooltip/ItemTooltip.js index 4e3b52476e277..17e9e2b3cf774 100644 --- a/docs/data/charts/tooltip/ItemTooltip.js +++ b/docs/data/charts/tooltip/ItemTooltip.js @@ -3,7 +3,6 @@ import NoSsr from '@mui/material/NoSsr'; import Popper from '@mui/material/Popper'; import { useItemTooltip } from '@mui/x-charts/ChartsTooltip'; import { useSvgRef } from '@mui/x-charts/hooks'; -import { CustomItemTooltipContent } from './CustomItemTooltipContent'; function usePointer() { const svgRef = useSvgRef(); @@ -78,7 +77,7 @@ function usePointer() { }; } -export function ItemTooltip() { +export function ItemTooltip({ children }) { const tooltipData = useItemTooltip(); const { isActive, isMousePointer, pointerHeight, popperRef, anchorEl } = usePointer(); @@ -111,7 +110,7 @@ export function ItemTooltip() { }, ]} > - + {children} ); diff --git a/docs/data/charts/tooltip/ItemTooltip.tsx b/docs/data/charts/tooltip/ItemTooltip.tsx index 1f4277d578c7f..682e0e9d300b2 100644 --- a/docs/data/charts/tooltip/ItemTooltip.tsx +++ b/docs/data/charts/tooltip/ItemTooltip.tsx @@ -3,7 +3,6 @@ import NoSsr from '@mui/material/NoSsr'; 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'; type PointerState = { isActive: boolean; @@ -84,7 +83,7 @@ function usePointer(): PointerState & Pick - + {children} ); diff --git a/docs/data/charts/tooltip/ItemTooltipFixedY.js b/docs/data/charts/tooltip/ItemTooltipFixedY.js index aa11e750dc8dd..93f94d31c0e80 100644 --- a/docs/data/charts/tooltip/ItemTooltipFixedY.js +++ b/docs/data/charts/tooltip/ItemTooltipFixedY.js @@ -3,7 +3,6 @@ import NoSsr from '@mui/material/NoSsr'; import Popper from '@mui/material/Popper'; import { useItemTooltip } from '@mui/x-charts/ChartsTooltip'; import { useDrawingArea, useSvgRef } from '@mui/x-charts/hooks'; -import { CustomItemTooltipContent } from './CustomItemTooltipContent'; function usePointer() { const svgRef = useSvgRef(); @@ -50,7 +49,7 @@ function usePointer() { return pointer; } -export function ItemTooltipFixedY() { +export function ItemTooltipFixedY({ children }) { const tooltipData = useItemTooltip(); const { isActive } = usePointer(); @@ -109,7 +108,7 @@ export function ItemTooltipFixedY() { }} popperRef={popperRef} > - + {children} ); diff --git a/docs/data/charts/tooltip/ItemTooltipFixedY.tsx b/docs/data/charts/tooltip/ItemTooltipFixedY.tsx index 925b27453789c..70c7bf29ec7db 100644 --- a/docs/data/charts/tooltip/ItemTooltipFixedY.tsx +++ b/docs/data/charts/tooltip/ItemTooltipFixedY.tsx @@ -3,7 +3,6 @@ import NoSsr from '@mui/material/NoSsr'; 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'; type PointerState = { isActive: boolean; @@ -56,7 +55,7 @@ function usePointer(): PointerState { return pointer; } -export function ItemTooltipFixedY() { +export function ItemTooltipFixedY({ children }: React.PropsWithChildren) { const tooltipData = useItemTooltip(); const { isActive } = usePointer(); @@ -115,7 +114,7 @@ export function ItemTooltipFixedY() { }} popperRef={popperRef} > - + {children} ); diff --git a/docs/data/charts/tooltip/ItemTooltipTopElement.js b/docs/data/charts/tooltip/ItemTooltipTopElement.js index 538a729564c9b..a601caee56d57 100644 --- a/docs/data/charts/tooltip/ItemTooltipTopElement.js +++ b/docs/data/charts/tooltip/ItemTooltipTopElement.js @@ -4,7 +4,6 @@ import NoSsr from '@mui/material/NoSsr'; import Popper from '@mui/material/Popper'; import { useItemTooltip } from '@mui/x-charts/ChartsTooltip'; import { useSvgRef, useXAxis, useXScale, useYScale } from '@mui/x-charts/hooks'; -import { CustomItemTooltipContent } from './CustomItemTooltipContent'; function usePointer() { const svgRef = useSvgRef(); @@ -51,7 +50,7 @@ function usePointer() { return pointer; } -export function ItemTooltipTopElement() { +export function ItemTooltipTopElement({ children }) { const tooltipData = useItemTooltip(); const { isActive } = usePointer(); // Get xAxis config to access its data array. @@ -73,7 +72,8 @@ export function ItemTooltipTopElement() { if ( tooltipData.identifier.type !== 'bar' || tooltipData.identifier.dataIndex === undefined || - tooltipData.value === null + tooltipData.value === null || + svgRef.current === null ) { // This demo is only about bar charts return null; @@ -115,7 +115,7 @@ export function ItemTooltipTopElement() { }), }} > - + {children} ); diff --git a/docs/data/charts/tooltip/ItemTooltipTopElement.tsx b/docs/data/charts/tooltip/ItemTooltipTopElement.tsx index 9c73fa1d43831..a36f5048d00f5 100644 --- a/docs/data/charts/tooltip/ItemTooltipTopElement.tsx +++ b/docs/data/charts/tooltip/ItemTooltipTopElement.tsx @@ -4,7 +4,6 @@ import NoSsr from '@mui/material/NoSsr'; import Popper from '@mui/material/Popper'; import { useItemTooltip } from '@mui/x-charts/ChartsTooltip'; import { useSvgRef, useXAxis, useXScale, useYScale } from '@mui/x-charts/hooks'; -import { CustomItemTooltipContent } from './CustomItemTooltipContent'; type PointerState = { isActive: boolean; @@ -57,7 +56,7 @@ function usePointer(): PointerState { return pointer; } -export function ItemTooltipTopElement() { +export function ItemTooltipTopElement({ children }: React.PropsWithChildren) { const tooltipData = useItemTooltip<'bar'>(); const { isActive } = usePointer(); // Get xAxis config to access its data array. @@ -79,7 +78,8 @@ export function ItemTooltipTopElement() { if ( tooltipData.identifier.type !== 'bar' || tooltipData.identifier.dataIndex === undefined || - tooltipData.value === null + tooltipData.value === null || + svgRef.current === null ) { // This demo is only about bar charts return null; @@ -123,7 +123,7 @@ export function ItemTooltipTopElement() { }), }} > - + {children} ); diff --git a/docs/data/charts/tooltip/tooltip.md b/docs/data/charts/tooltip/tooltip.md index f53171fca6e52..9433e90b68f69 100644 --- a/docs/data/charts/tooltip/tooltip.md +++ b/docs/data/charts/tooltip/tooltip.md @@ -1,24 +1,26 @@ --- title: Charts - Tooltip productId: x-charts -components: ChartsTooltip, DefaultChartsAxisTooltipContent, DefaultChartsItemTooltipContent +components: ChartsTooltip, ChartsAxisTooltipContent, ChartsItemTooltipContent, ChartsTooltipContainer --- # Charts - Tooltip

Tooltip provides extra data on charts item.

-In all charts components, you can pass props to the tooltip by using `tooltip={{...}}`. -If you are using composition, you can add the `` component and pass props directly. +In all charts components, the tooltip is accessible via the slot `tooltip`. +If you are using composition, you can use the `` component. ## Tooltip trigger -The tooltip can be triggered by two kinds of events: +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 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. +To pass this trigger attribute to the tooltip use `slotProps.tooltip.trigger`. + {{"demo": "Interaction.js"}} ## Customization @@ -90,30 +92,66 @@ It removes the header showing the x-axis value from the tooltip. ### Overriding content -To modify the tooltip content, use `slots.itemContent` or `slots.axisContent`. -The first one is rendered when tooltip trigger is set to `"item"`. -The second one when trigger is set to `"axis"`. +To override tooltip content, provide a custom component to `slots.tooltip`. +Some helper are provided, such as: + +- `` which provide a tooltip with built-in open and position management. +- `useItemTooltip()` which provides all basic information associated to the current item. +- `useAxisTooltip()` which provides all basic information associated to the current axis. + +Here is the basic scheme to follow. +Examples about helpers are provided in the composition section. ```jsx -// With single component +import { ChartsTooltipContainer } from '@mui/x-charts/ChartsTooltip'; + +function CustomItemTooltipContent() { + const tooltipData = useItemTooltip(); + + if (!tooltipData) { // No data to display + return null; + } + + return
{/** Your custom content **/}
; +} + // With composition // ... - + + + ``` +:::warning +Do not skip ChartsTooltipContainer rendering if the tooltip has no data to display. +For example the following code does not work. + +```jsx +if (tooltipData === null) { + return null; +} + +return ( + + {/** My content **/} + +); +``` + +The ChartsTooltipContainer must render before the pointer enters the SVG because it uses this event to get the pointer type. +::: + +### Overriding placement + +To override tooltip placement, override to the tooltip with `slots.tooltip`. +If you want to keep the default content, you can place the `ChartsItemTooltipContent` or `ChartsAxisTooltipContent` in your custom tooltip. + ## Composition If you're using composition, by default, the axis listens for mouse events to get its current x/y values. diff --git a/docs/data/charts/zoom-and-pan/letterFrequency.js b/docs/data/charts/zoom-and-pan/letterFrequency.js new file mode 100644 index 0000000000000..43e294a10c55e --- /dev/null +++ b/docs/data/charts/zoom-and-pan/letterFrequency.js @@ -0,0 +1,37 @@ +export const letterFrequency = [ + { letter: 'A', frequency: 8.2 }, + { letter: 'B', frequency: 1.5 }, + { letter: 'C', frequency: 2.8 }, + { letter: 'D', frequency: 4.3 }, + { letter: 'E', frequency: 12.7 }, + { letter: 'F', frequency: 2.2 }, + { letter: 'G', frequency: 2.0 }, + { letter: 'H', frequency: 6.1 }, + { letter: 'I', frequency: 7.0 }, + { letter: 'J', frequency: 0.15 }, + { letter: 'K', frequency: 0.77 }, + { letter: 'L', frequency: 4.0 }, + { letter: 'M', frequency: 2.4 }, + { letter: 'N', frequency: 6.7 }, + { letter: 'O', frequency: 7.5 }, + { letter: 'P', frequency: 1.9 }, + { letter: 'Q', frequency: 0.095 }, + { letter: 'R', frequency: 6.0 }, + { letter: 'S', frequency: 6.3 }, + { letter: 'T', frequency: 9.1 }, + { letter: 'U', frequency: 2.8 }, + { letter: 'V', frequency: 0.98 }, + { letter: 'W', frequency: 2.4 }, + { letter: 'X', frequency: 0.15 }, + { letter: 'Y', frequency: 2.0 }, + { letter: 'Z', frequency: 0.074 }, +]; + +export const dataset = letterFrequency.sort((a, b) => b.frequency - a.frequency); + +export function valueFormatter(value) { + if (value === null) { + return `?`; + } + return `${(value / 100).toLocaleString(undefined, { style: 'percent', maximumFractionDigits: 2 })}`; +} diff --git a/docs/data/chartsApiPages.ts b/docs/data/chartsApiPages.ts index 0cb3b0977674f..c4ec485b59c66 100644 --- a/docs/data/chartsApiPages.ts +++ b/docs/data/chartsApiPages.ts @@ -47,6 +47,10 @@ const chartsApiPages: MuiPage[] = [ title: 'ChartContainerPro', plan: 'pro', }, + { + pathname: '/x/api/charts/chart-data-provider', + title: 'ChartDataProvider', + }, { pathname: '/x/api/charts/charts-axis', title: 'ChartsAxis', @@ -55,6 +59,10 @@ const chartsApiPages: MuiPage[] = [ pathname: '/x/api/charts/charts-axis-highlight', title: 'ChartsAxisHighlight', }, + { + pathname: '/x/api/charts/charts-axis-tooltip-content', + title: 'ChartsAxisTooltipContent', + }, { pathname: '/x/api/charts/charts-clip-path', title: 'ChartsClipPath', @@ -63,6 +71,10 @@ const chartsApiPages: MuiPage[] = [ pathname: '/x/api/charts/charts-grid', title: 'ChartsGrid', }, + { + pathname: '/x/api/charts/charts-item-tooltip-content', + title: 'ChartsItemTooltipContent', + }, { pathname: '/x/api/charts/charts-legend', title: 'ChartsLegend', @@ -87,6 +99,10 @@ const chartsApiPages: MuiPage[] = [ pathname: '/x/api/charts/charts-tooltip', title: 'ChartsTooltip', }, + { + pathname: '/x/api/charts/charts-tooltip-container', + title: 'ChartsTooltipContainer', + }, { pathname: '/x/api/charts/charts-voronoi-handler', title: 'ChartsVoronoiHandler', @@ -103,23 +119,10 @@ const chartsApiPages: MuiPage[] = [ pathname: '/x/api/charts/continuous-color-legend', title: 'ContinuousColorLegend', }, - { - pathname: '/x/api/charts/default-charts-axis-tooltip-content', - title: 'DefaultChartsAxisTooltipContent', - }, - { - pathname: '/x/api/charts/default-charts-item-tooltip-content', - title: 'DefaultChartsItemTooltipContent', - }, { pathname: '/x/api/charts/default-charts-legend', title: 'DefaultChartsLegend', }, - { - pathname: '/x/api/charts/default-heatmap-tooltip', - title: 'DefaultHeatmapTooltip', - plan: 'pro', - }, { pathname: '/x/api/charts/gauge', title: 'Gauge', @@ -138,6 +141,11 @@ const chartsApiPages: MuiPage[] = [ title: 'HeatmapPlot', plan: 'pro', }, + { + pathname: '/x/api/charts/heatmap-tooltip', + title: 'HeatmapTooltip', + plan: 'pro', + }, { pathname: '/x/api/charts/line-chart', title: 'LineChart', diff --git a/docs/data/data-grid/api-object/UseGridApiContext.js b/docs/data/data-grid/api-object/UseGridApiContext.js index 563cd1eced4d2..8a4f71eb6f133 100644 --- a/docs/data/data-grid/api-object/UseGridApiContext.js +++ b/docs/data/data-grid/api-object/UseGridApiContext.js @@ -17,7 +17,7 @@ function CustomToolbar() { } export default function UseGridApiContext() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, maxColumns: 6, @@ -27,6 +27,7 @@ export default function UseGridApiContext() { - +
); } diff --git a/docs/data/data-grid/components/ToolbarGrid.tsx b/docs/data/data-grid/components/ToolbarGrid.tsx index 5ea22ba9b00a4..b1161800220a8 100644 --- a/docs/data/data-grid/components/ToolbarGrid.tsx +++ b/docs/data/data-grid/components/ToolbarGrid.tsx @@ -3,7 +3,7 @@ import { DataGrid, GridToolbar } from '@mui/x-data-grid'; import { useDemoData } from '@mui/x-data-grid-generator'; export default function ToolbarGrid() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, maxColumns: 6, @@ -11,12 +11,7 @@ export default function ToolbarGrid() { return (
- +
); } diff --git a/docs/data/data-grid/components/ToolbarGrid.tsx.preview b/docs/data/data-grid/components/ToolbarGrid.tsx.preview index 218f7646f92a6..b414c69135f2c 100644 --- a/docs/data/data-grid/components/ToolbarGrid.tsx.preview +++ b/docs/data/data-grid/components/ToolbarGrid.tsx.preview @@ -1,6 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/data-grid/custom-columns/cell-renderers/rating.tsx b/docs/data/data-grid/custom-columns/cell-renderers/rating.tsx index 9eb9c68ce767d..56160cf6caf68 100644 --- a/docs/data/data-grid/custom-columns/cell-renderers/rating.tsx +++ b/docs/data/data-grid/custom-columns/cell-renderers/rating.tsx @@ -46,7 +46,7 @@ function EditRating(props: GridRenderEditCellParams) { changedThroughKeyboard.current = false; }; - const handleRef = (element: HTMLElement | undefined) => { + const handleRef = (element: HTMLElement | null) => { if (element) { if (value !== 0) { element.querySelector(`input[value="${value}"]`)!.focus(); diff --git a/docs/data/data-grid/editing/FullFeaturedCrudGrid.js b/docs/data/data-grid/editing/FullFeaturedCrudGrid.js index 9481818e7896b..6c30f7ad2b9ee 100644 --- a/docs/data/data-grid/editing/FullFeaturedCrudGrid.js +++ b/docs/data/data-grid/editing/FullFeaturedCrudGrid.js @@ -226,9 +226,7 @@ export default function FullFeaturedCrudGrid() { onRowModesModelChange={handleRowModesModelChange} onRowEditStop={handleRowEditStop} processRowUpdate={processRowUpdate} - slots={{ - toolbar: EditToolbar, - }} + slots={{ toolbar: EditToolbar }} slotProps={{ toolbar: { setRows, setRowModesModel }, }} diff --git a/docs/data/data-grid/editing/FullFeaturedCrudGrid.tsx b/docs/data/data-grid/editing/FullFeaturedCrudGrid.tsx index ca1f3daaf5940..b74a768045cba 100644 --- a/docs/data/data-grid/editing/FullFeaturedCrudGrid.tsx +++ b/docs/data/data-grid/editing/FullFeaturedCrudGrid.tsx @@ -18,7 +18,7 @@ import { GridRowId, GridRowModel, GridRowEditStopReasons, - GridSlots, + GridSlotProps, } from '@mui/x-data-grid'; import { randomCreatedDate, @@ -70,14 +70,16 @@ const initialRows: GridRowsProp = [ }, ]; -interface EditToolbarProps { - setRows: (newRows: (oldRows: GridRowsProp) => GridRowsProp) => void; - setRowModesModel: ( - newModel: (oldModel: GridRowModesModel) => GridRowModesModel, - ) => void; +declare module '@mui/x-data-grid' { + interface ToolbarPropsOverrides { + setRows: (newRows: (oldRows: GridRowsProp) => GridRowsProp) => void; + setRowModesModel: ( + newModel: (oldModel: GridRowModesModel) => GridRowModesModel, + ) => void; + } } -function EditToolbar(props: EditToolbarProps) { +function EditToolbar(props: GridSlotProps['toolbar']) { const { setRows, setRowModesModel } = props; const handleClick = () => { @@ -240,9 +242,7 @@ export default function FullFeaturedCrudGrid() { onRowModesModelChange={handleRowModesModelChange} onRowEditStop={handleRowEditStop} processRowUpdate={processRowUpdate} - slots={{ - toolbar: EditToolbar as GridSlots['toolbar'], - }} + slots={{ toolbar: EditToolbar }} slotProps={{ toolbar: { setRows, setRowModesModel }, }} diff --git a/docs/data/data-grid/editing/FullFeaturedCrudGrid.tsx.preview b/docs/data/data-grid/editing/FullFeaturedCrudGrid.tsx.preview index 2693093092106..6077d2531ba8f 100644 --- a/docs/data/data-grid/editing/FullFeaturedCrudGrid.tsx.preview +++ b/docs/data/data-grid/editing/FullFeaturedCrudGrid.tsx.preview @@ -6,9 +6,7 @@ onRowModesModelChange={handleRowModesModelChange} onRowEditStop={handleRowEditStop} processRowUpdate={processRowUpdate} - slots={{ - toolbar: EditToolbar as GridSlots['toolbar'], - }} + slots={{ toolbar: EditToolbar }} slotProps={{ toolbar: { setRows, setRowModesModel }, }} diff --git a/docs/data/data-grid/editing/StartEditButtonGrid.js b/docs/data/data-grid/editing/StartEditButtonGrid.js index e533d375bd4ea..f0a4713cac67e 100644 --- a/docs/data/data-grid/editing/StartEditButtonGrid.js +++ b/docs/data/data-grid/editing/StartEditButtonGrid.js @@ -119,14 +119,11 @@ export default function StartEditButtonGrid() { cellModesModel={cellModesModel} onCellEditStop={handleCellEditStop} onCellModesModelChange={(model) => setCellModesModel(model)} - slots={{ - toolbar: EditToolbar, - }} + slots={{ toolbar: EditToolbar }} slotProps={{ toolbar: { cellMode, selectedCellParams, - setSelectedCellParams, cellModesModel, setCellModesModel, }, diff --git a/docs/data/data-grid/editing/StartEditButtonGrid.tsx b/docs/data/data-grid/editing/StartEditButtonGrid.tsx index 98f848fd4e14e..a1e7a86e69cb3 100644 --- a/docs/data/data-grid/editing/StartEditButtonGrid.tsx +++ b/docs/data/data-grid/editing/StartEditButtonGrid.tsx @@ -9,7 +9,7 @@ import { GridCellModes, GridEventListener, GridCellModesModel, - GridSlots, + GridSlotProps, } from '@mui/x-data-grid'; import { randomCreatedDate, @@ -22,14 +22,16 @@ interface SelectedCellParams { field: string; } -interface EditToolbarProps { - selectedCellParams?: SelectedCellParams; - cellModesModel: GridCellModesModel; - setCellModesModel: (value: GridCellModesModel) => void; - cellMode: 'view' | 'edit'; +declare module '@mui/x-data-grid' { + interface ToolbarPropsOverrides { + selectedCellParams: SelectedCellParams | null; + cellModesModel: GridCellModesModel; + setCellModesModel: (value: GridCellModesModel) => void; + cellMode: 'view' | 'edit'; + } } -function EditToolbar(props: EditToolbarProps) { +function EditToolbar(props: GridSlotProps['toolbar']) { const { selectedCellParams, cellMode, cellModesModel, setCellModesModel } = props; const handleSaveOrEdit = () => { @@ -147,14 +149,11 @@ export default function StartEditButtonGrid() { cellModesModel={cellModesModel} onCellEditStop={handleCellEditStop} onCellModesModelChange={(model) => setCellModesModel(model)} - slots={{ - toolbar: EditToolbar as GridSlots['toolbar'], - }} + slots={{ toolbar: EditToolbar }} slotProps={{ toolbar: { cellMode, selectedCellParams, - setSelectedCellParams, cellModesModel, setCellModesModel, }, diff --git a/docs/data/data-grid/events/DoubleClickWithCtrlToEdit.js b/docs/data/data-grid/events/DoubleClickWithCtrlToEdit.js index 07c081a3fad7d..95f4e39077bc8 100644 --- a/docs/data/data-grid/events/DoubleClickWithCtrlToEdit.js +++ b/docs/data/data-grid/events/DoubleClickWithCtrlToEdit.js @@ -3,7 +3,7 @@ import { DataGrid } from '@mui/x-data-grid'; import { useDemoData } from '@mui/x-data-grid-generator'; export default function DoubleClickWithCtrlToEdit() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, maxColumns: 6, @@ -19,6 +19,7 @@ export default function DoubleClickWithCtrlToEdit() { } }} {...data} + loading={loading} />
); diff --git a/docs/data/data-grid/events/DoubleClickWithCtrlToEdit.tsx b/docs/data/data-grid/events/DoubleClickWithCtrlToEdit.tsx index 07c081a3fad7d..95f4e39077bc8 100644 --- a/docs/data/data-grid/events/DoubleClickWithCtrlToEdit.tsx +++ b/docs/data/data-grid/events/DoubleClickWithCtrlToEdit.tsx @@ -3,7 +3,7 @@ import { DataGrid } from '@mui/x-data-grid'; import { useDemoData } from '@mui/x-data-grid-generator'; export default function DoubleClickWithCtrlToEdit() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, maxColumns: 6, @@ -19,6 +19,7 @@ export default function DoubleClickWithCtrlToEdit() { } }} {...data} + loading={loading} />
); diff --git a/docs/data/data-grid/events/DoubleClickWithCtrlToEdit.tsx.preview b/docs/data/data-grid/events/DoubleClickWithCtrlToEdit.tsx.preview index 4fc2e62f01655..0503cabf8d121 100644 --- a/docs/data/data-grid/events/DoubleClickWithCtrlToEdit.tsx.preview +++ b/docs/data/data-grid/events/DoubleClickWithCtrlToEdit.tsx.preview @@ -5,4 +5,5 @@ } }} {...data} + loading={loading} /> \ No newline at end of file diff --git a/docs/data/data-grid/events/events.json b/docs/data/data-grid/events/events.json index a2831d2974c28..fedd745dd5c45 100644 --- a/docs/data/data-grid/events/events.json +++ b/docs/data/data-grid/events/events.json @@ -227,7 +227,7 @@ { "projects": ["x-data-grid-pro", "x-data-grid-premium"], "name": "fetchRows", - "description": "Fired when a new batch of rows is requested to be loaded. Called with a GridFetchRowsParams object.", + "description": "Fired when a new batch of rows is requested to be loaded. Called with a GridFetchRowsParams object. Used to trigger onFetchRows.", "params": "GridFetchRowsParams", "event": "MuiEvent<{}>", "componentProp": "onFetchRows" diff --git a/docs/data/data-grid/export/ExcelCustomExport.js b/docs/data/data-grid/export/ExcelCustomExport.js index 5c6f8c51b6893..621088852f8be 100644 --- a/docs/data/data-grid/export/ExcelCustomExport.js +++ b/docs/data/data-grid/export/ExcelCustomExport.js @@ -236,7 +236,7 @@ const groupingColDef = { headerName: 'Feature', }; -const exceljsPreProcess = ({ workbook, worksheet }) => { +const exceljsPreProcess = async ({ workbook, worksheet }) => { // Set document meta data workbook.creator = 'MUI-X team'; workbook.created = new Date(); @@ -264,14 +264,17 @@ const exceljsPreProcess = ({ workbook, worksheet }) => { }; worksheet.addRow([]); }; -const exceljsPostProcess = ({ worksheet }) => { +const exceljsPostProcess = async ({ worksheet }) => { // add a text after the data worksheet.addRow({}); // Add empty row worksheet.addRow(['Those data are for internal use only']); }; -const excelOptions = { exceljsPreProcess, exceljsPostProcess }; +const excelOptions = { + exceljsPreProcess, + exceljsPostProcess, +}; const getTreeDataPath = (row) => row.path; diff --git a/docs/data/data-grid/export/ExcelCustomExport.tsx b/docs/data/data-grid/export/ExcelCustomExport.tsx index 3f491db331dbc..e904ae78a84ba 100644 --- a/docs/data/data-grid/export/ExcelCustomExport.tsx +++ b/docs/data/data-grid/export/ExcelCustomExport.tsx @@ -5,6 +5,7 @@ import { GridExceljsProcessInput, GridColDef, DataGridPremiumProps, + GridExcelExportOptions, } from '@mui/x-data-grid-premium'; const rows = [ @@ -243,7 +244,10 @@ const groupingColDef = { headerName: 'Feature', }; -const exceljsPreProcess = ({ workbook, worksheet }: GridExceljsProcessInput) => { +const exceljsPreProcess = async ({ + workbook, + worksheet, +}: GridExceljsProcessInput) => { // Set document meta data workbook.creator = 'MUI-X team'; workbook.created = new Date(); @@ -271,14 +275,17 @@ const exceljsPreProcess = ({ workbook, worksheet }: GridExceljsProcessInput) => }; worksheet.addRow([]); }; -const exceljsPostProcess = ({ worksheet }: GridExceljsProcessInput) => { +const exceljsPostProcess = async ({ worksheet }: GridExceljsProcessInput) => { // add a text after the data worksheet.addRow({}); // Add empty row worksheet.addRow(['Those data are for internal use only']); }; -const excelOptions = { exceljsPreProcess, exceljsPostProcess }; +const excelOptions: GridExcelExportOptions = { + exceljsPreProcess, + exceljsPostProcess, +}; const getTreeDataPath: DataGridPremiumProps['getTreeDataPath'] = (row) => row.path; diff --git a/docs/data/data-grid/export/ExcelExportWithWebWorker.js b/docs/data/data-grid/export/ExcelExportWithWebWorker.js index 43d5b3f78e176..a286931a6d791 100644 --- a/docs/data/data-grid/export/ExcelExportWithWebWorker.js +++ b/docs/data/data-grid/export/ExcelExportWithWebWorker.js @@ -31,7 +31,7 @@ function SlideTransition(props) { export default function ExcelExportWithWebWorker() { const [inProgress, setInProgress] = React.useState(false); - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 10000, editable: true, @@ -46,7 +46,7 @@ export default function ExcelExportWithWebWorker() { - +
); diff --git a/docs/data/data-grid/filtering-recipes/FilteredRowCount.tsx b/docs/data/data-grid/filtering-recipes/FilteredRowCount.tsx index df925c75a800a..e96ca3ac73d6a 100644 --- a/docs/data/data-grid/filtering-recipes/FilteredRowCount.tsx +++ b/docs/data/data-grid/filtering-recipes/FilteredRowCount.tsx @@ -31,7 +31,7 @@ const predefinedFilters: { label: string; filterModel: GridFilterModel }[] = [ ]; export default function FilteredRowCount() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 1000, maxColumns: 10, @@ -81,7 +81,7 @@ export default function FilteredRowCount() { })}
- + ); diff --git a/docs/data/data-grid/filtering-recipes/FilteringLocalStorage.js b/docs/data/data-grid/filtering-recipes/FilteringLocalStorage.js index 290e5ce9e6084..a4bbed18007c5 100644 --- a/docs/data/data-grid/filtering-recipes/FilteringLocalStorage.js +++ b/docs/data/data-grid/filtering-recipes/FilteringLocalStorage.js @@ -57,7 +57,7 @@ const usePersistedFilterModel = () => { }; export default function FilteringLocalStorage() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -76,6 +76,7 @@ export default function FilteringLocalStorage() {
{ }; export default function FilteringLocalStorage() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -85,6 +85,7 @@ export default function FilteringLocalStorage() {
- +
); } diff --git a/docs/data/data-grid/filtering/BasicExampleDataGrid.tsx b/docs/data/data-grid/filtering/BasicExampleDataGrid.tsx index 9dd4226da1d95..bf7640d13181a 100644 --- a/docs/data/data-grid/filtering/BasicExampleDataGrid.tsx +++ b/docs/data/data-grid/filtering/BasicExampleDataGrid.tsx @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function BasicExampleDataGrid() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -13,7 +13,7 @@ export default function BasicExampleDataGrid() { return (
- +
); } diff --git a/docs/data/data-grid/filtering/BasicExampleDataGrid.tsx.preview b/docs/data/data-grid/filtering/BasicExampleDataGrid.tsx.preview index 2f5d7ee7b32ab..b414c69135f2c 100644 --- a/docs/data/data-grid/filtering/BasicExampleDataGrid.tsx.preview +++ b/docs/data/data-grid/filtering/BasicExampleDataGrid.tsx.preview @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/data-grid/filtering/BasicExampleDataGridPro.js b/docs/data/data-grid/filtering/BasicExampleDataGridPro.js index cc2e668aeb8d9..99def1d9f8098 100644 --- a/docs/data/data-grid/filtering/BasicExampleDataGridPro.js +++ b/docs/data/data-grid/filtering/BasicExampleDataGridPro.js @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function BasicExampleDataGridPro() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -13,7 +13,7 @@ export default function BasicExampleDataGridPro() { return (
- +
); } diff --git a/docs/data/data-grid/filtering/BasicExampleDataGridPro.tsx b/docs/data/data-grid/filtering/BasicExampleDataGridPro.tsx index cc2e668aeb8d9..99def1d9f8098 100644 --- a/docs/data/data-grid/filtering/BasicExampleDataGridPro.tsx +++ b/docs/data/data-grid/filtering/BasicExampleDataGridPro.tsx @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function BasicExampleDataGridPro() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -13,7 +13,7 @@ export default function BasicExampleDataGridPro() { return (
- +
); } diff --git a/docs/data/data-grid/filtering/BasicExampleDataGridPro.tsx.preview b/docs/data/data-grid/filtering/BasicExampleDataGridPro.tsx.preview index d16153b32fe20..8e8049c8fe953 100644 --- a/docs/data/data-grid/filtering/BasicExampleDataGridPro.tsx.preview +++ b/docs/data/data-grid/filtering/BasicExampleDataGridPro.tsx.preview @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/data-grid/filtering/ControlledFilters.js b/docs/data/data-grid/filtering/ControlledFilters.js index ed220311051af..106417658a800 100644 --- a/docs/data/data-grid/filtering/ControlledFilters.js +++ b/docs/data/data-grid/filtering/ControlledFilters.js @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function ControlledFilters() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -25,6 +25,7 @@ export default function ControlledFilters() {
diff --git a/docs/data/data-grid/filtering/CustomFilterPanelPosition.tsx b/docs/data/data-grid/filtering/CustomFilterPanelPosition.tsx index 2f686357b240a..ddfa49a3ae380 100644 --- a/docs/data/data-grid/filtering/CustomFilterPanelPosition.tsx +++ b/docs/data/data-grid/filtering/CustomFilterPanelPosition.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { DataGrid, - GridSlots, + GridSlotProps, GridToolbarContainer, GridToolbarFilterButton, } from '@mui/x-data-grid'; @@ -9,11 +9,15 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; -interface CustomToolbarProps { - setFilterButtonEl: React.Dispatch>; +declare module '@mui/x-data-grid' { + interface ToolbarPropsOverrides { + setFilterButtonEl: React.Dispatch< + React.SetStateAction + >; + } } -function CustomToolbar({ setFilterButtonEl }: CustomToolbarProps) { +function CustomToolbar({ setFilterButtonEl }: GridSlotProps['toolbar']) { return ( @@ -22,7 +26,7 @@ function CustomToolbar({ setFilterButtonEl }: CustomToolbarProps) { } export default function CustomFilterPanelPosition() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -35,16 +39,13 @@ export default function CustomFilterPanelPosition() {
diff --git a/docs/data/data-grid/filtering/CustomFilterPanelPosition.tsx.preview b/docs/data/data-grid/filtering/CustomFilterPanelPosition.tsx.preview index ded969e1fd1e9..026d280ebcba5 100644 --- a/docs/data/data-grid/filtering/CustomFilterPanelPosition.tsx.preview +++ b/docs/data/data-grid/filtering/CustomFilterPanelPosition.tsx.preview @@ -1,14 +1,11 @@ \ No newline at end of file diff --git a/docs/data/data-grid/filtering/CustomHeaderFilterDataGridPro.js b/docs/data/data-grid/filtering/CustomHeaderFilterDataGridPro.js index 294ebacdbea2c..4cd9c80e0acde 100644 --- a/docs/data/data-grid/filtering/CustomHeaderFilterDataGridPro.js +++ b/docs/data/data-grid/filtering/CustomHeaderFilterDataGridPro.js @@ -99,7 +99,7 @@ function CustomHeaderFilter(props) { } export default function CustomHeaderFilterDataGridPro() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', rowLength: 100, }); @@ -108,6 +108,7 @@ export default function CustomHeaderFilterDataGridPro() {
\ No newline at end of file diff --git a/docs/data/data-grid/filtering/CustomHeaderFilterOperatorDataGridPro.js b/docs/data/data-grid/filtering/CustomHeaderFilterOperatorDataGridPro.js index 29219dffa319f..50463279c37d7 100644 --- a/docs/data/data-grid/filtering/CustomHeaderFilterOperatorDataGridPro.js +++ b/docs/data/data-grid/filtering/CustomHeaderFilterOperatorDataGridPro.js @@ -49,7 +49,7 @@ function RatingInputValue(props) { } export default function CustomHeaderFilterOperatorDataGridPro() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', rowLength: 100, visibleFields: VISIBLE_FIELDS, @@ -79,7 +79,7 @@ export default function CustomHeaderFilterOperatorDataGridPro() { return (
- +
); } diff --git a/docs/data/data-grid/filtering/CustomHeaderFilterOperatorDataGridPro.tsx b/docs/data/data-grid/filtering/CustomHeaderFilterOperatorDataGridPro.tsx index d15aeab0e7809..0276f0e9e4299 100644 --- a/docs/data/data-grid/filtering/CustomHeaderFilterOperatorDataGridPro.tsx +++ b/docs/data/data-grid/filtering/CustomHeaderFilterOperatorDataGridPro.tsx @@ -58,7 +58,7 @@ function RatingInputValue( } export default function CustomHeaderFilterOperatorDataGridPro() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', rowLength: 100, visibleFields: VISIBLE_FIELDS, @@ -88,7 +88,7 @@ export default function CustomHeaderFilterOperatorDataGridPro() { return (
- +
); } diff --git a/docs/data/data-grid/filtering/CustomHeaderFilterOperatorDataGridPro.tsx.preview b/docs/data/data-grid/filtering/CustomHeaderFilterOperatorDataGridPro.tsx.preview index 5742bdcb33294..f68808f59d882 100644 --- a/docs/data/data-grid/filtering/CustomHeaderFilterOperatorDataGridPro.tsx.preview +++ b/docs/data/data-grid/filtering/CustomHeaderFilterOperatorDataGridPro.tsx.preview @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/data-grid/filtering/CustomHeaderFilterSingleDataGridPro.js b/docs/data/data-grid/filtering/CustomHeaderFilterSingleDataGridPro.js index ede0923b1ce08..0ed5ea252ea16 100644 --- a/docs/data/data-grid/filtering/CustomHeaderFilterSingleDataGridPro.js +++ b/docs/data/data-grid/filtering/CustomHeaderFilterSingleDataGridPro.js @@ -62,7 +62,7 @@ function AdminFilter(props) { } export default function CustomHeaderFilterSingleDataGridPro() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', rowLength: 100, visibleFields: ['name', 'website', 'phone', 'isAdmin', 'salary'], @@ -89,7 +89,13 @@ export default function CustomHeaderFilterSingleDataGridPro() { return (
- +
); } diff --git a/docs/data/data-grid/filtering/CustomHeaderFilterSingleDataGridPro.tsx b/docs/data/data-grid/filtering/CustomHeaderFilterSingleDataGridPro.tsx index 3f591c64efe94..ecd9ccf8be2a1 100644 --- a/docs/data/data-grid/filtering/CustomHeaderFilterSingleDataGridPro.tsx +++ b/docs/data/data-grid/filtering/CustomHeaderFilterSingleDataGridPro.tsx @@ -63,7 +63,7 @@ function AdminFilter(props: GridRenderHeaderFilterProps) { } export default function CustomHeaderFilterSingleDataGridPro() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', rowLength: 100, visibleFields: ['name', 'website', 'phone', 'isAdmin', 'salary'], @@ -92,7 +92,13 @@ export default function CustomHeaderFilterSingleDataGridPro() { return (
- +
); } diff --git a/docs/data/data-grid/filtering/CustomHeaderFilterSingleDataGridPro.tsx.preview b/docs/data/data-grid/filtering/CustomHeaderFilterSingleDataGridPro.tsx.preview index 747656ecf9315..9a2921144cc61 100644 --- a/docs/data/data-grid/filtering/CustomHeaderFilterSingleDataGridPro.tsx.preview +++ b/docs/data/data-grid/filtering/CustomHeaderFilterSingleDataGridPro.tsx.preview @@ -1 +1,7 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/data-grid/filtering/CustomInputComponent.js b/docs/data/data-grid/filtering/CustomInputComponent.js index d4e1d119dcdbc..57678e242f83f 100644 --- a/docs/data/data-grid/filtering/CustomInputComponent.js +++ b/docs/data/data-grid/filtering/CustomInputComponent.js @@ -44,7 +44,7 @@ function RatingInputValue(props) { const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function CustomInputComponent() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -76,6 +76,7 @@ export default function CustomInputComponent() { setFilterModel(model)} diff --git a/docs/data/data-grid/filtering/CustomMultiValueOperator.tsx b/docs/data/data-grid/filtering/CustomMultiValueOperator.tsx index 2245dc2ced32c..0ac2080fb364b 100644 --- a/docs/data/data-grid/filtering/CustomMultiValueOperator.tsx +++ b/docs/data/data-grid/filtering/CustomMultiValueOperator.tsx @@ -111,7 +111,7 @@ const quantityOnlyOperators: GridFilterOperator[] = [ ]; export default function CustomMultiValueOperator() { - const { data } = useDemoData({ dataSet: 'Commodity', rowLength: 100 }); + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100 }); const [filterModel, setFilterModel] = React.useState({ items: [ @@ -144,6 +144,7 @@ export default function CustomMultiValueOperator() {
setFilterModel(model)} diff --git a/docs/data/data-grid/filtering/CustomMultiValueOperator.tsx.preview b/docs/data/data-grid/filtering/CustomMultiValueOperator.tsx.preview index 3e72a809ee8af..512bcf6fded3d 100644 --- a/docs/data/data-grid/filtering/CustomMultiValueOperator.tsx.preview +++ b/docs/data/data-grid/filtering/CustomMultiValueOperator.tsx.preview @@ -1,5 +1,6 @@ setFilterModel(model)} diff --git a/docs/data/data-grid/filtering/CustomRatingOperator.js b/docs/data/data-grid/filtering/CustomRatingOperator.js index 5132bf4c9d6bd..f3d7d4c720c58 100644 --- a/docs/data/data-grid/filtering/CustomRatingOperator.js +++ b/docs/data/data-grid/filtering/CustomRatingOperator.js @@ -70,7 +70,7 @@ const ratingOnlyOperators = [ const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function CustomRatingOperator() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -93,6 +93,7 @@ export default function CustomRatingOperator() {
[] = [ const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function CustomRatingOperator() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -98,6 +98,7 @@ export default function CustomRatingOperator() {
- +
); } diff --git a/docs/data/data-grid/filtering/DisableFilteringGridAllColumns.tsx b/docs/data/data-grid/filtering/DisableFilteringGridAllColumns.tsx index e542265edf9b6..bf1b157a280ba 100644 --- a/docs/data/data-grid/filtering/DisableFilteringGridAllColumns.tsx +++ b/docs/data/data-grid/filtering/DisableFilteringGridAllColumns.tsx @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function DisableFilteringGridAllColumns() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -13,7 +13,7 @@ export default function DisableFilteringGridAllColumns() { return (
- +
); } diff --git a/docs/data/data-grid/filtering/DisableFilteringGridAllColumns.tsx.preview b/docs/data/data-grid/filtering/DisableFilteringGridAllColumns.tsx.preview index b5d88f3e8fb04..3270c8deea719 100644 --- a/docs/data/data-grid/filtering/DisableFilteringGridAllColumns.tsx.preview +++ b/docs/data/data-grid/filtering/DisableFilteringGridAllColumns.tsx.preview @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/data-grid/filtering/DisableFilteringGridSomeColumns.js b/docs/data/data-grid/filtering/DisableFilteringGridSomeColumns.js index a6913fd319ac5..f05775052d77f 100644 --- a/docs/data/data-grid/filtering/DisableFilteringGridSomeColumns.js +++ b/docs/data/data-grid/filtering/DisableFilteringGridSomeColumns.js @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function DisableFilteringGridSomeColumns() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -21,7 +21,7 @@ export default function DisableFilteringGridSomeColumns() { return (
- +
); } diff --git a/docs/data/data-grid/filtering/DisableFilteringGridSomeColumns.tsx b/docs/data/data-grid/filtering/DisableFilteringGridSomeColumns.tsx index a6913fd319ac5..f05775052d77f 100644 --- a/docs/data/data-grid/filtering/DisableFilteringGridSomeColumns.tsx +++ b/docs/data/data-grid/filtering/DisableFilteringGridSomeColumns.tsx @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function DisableFilteringGridSomeColumns() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -21,7 +21,7 @@ export default function DisableFilteringGridSomeColumns() { return (
- +
); } diff --git a/docs/data/data-grid/filtering/DisableFilteringGridSomeColumns.tsx.preview b/docs/data/data-grid/filtering/DisableFilteringGridSomeColumns.tsx.preview index 50c4ffdb6a38b..6991c5aded8e7 100644 --- a/docs/data/data-grid/filtering/DisableFilteringGridSomeColumns.tsx.preview +++ b/docs/data/data-grid/filtering/DisableFilteringGridSomeColumns.tsx.preview @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/data-grid/filtering/DisableMultiFiltersDataGridPro.js b/docs/data/data-grid/filtering/DisableMultiFiltersDataGridPro.js index 43358973e6330..e70aa737de030 100644 --- a/docs/data/data-grid/filtering/DisableMultiFiltersDataGridPro.js +++ b/docs/data/data-grid/filtering/DisableMultiFiltersDataGridPro.js @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function DisableMultiFiltersDataGridPro() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -37,6 +37,7 @@ export default function DisableMultiFiltersDataGridPro() {
{ }; export default function QuickFilteringCustomLogic() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -65,6 +65,7 @@ export default function QuickFilteringCustomLogic() { diff --git a/docs/data/data-grid/filtering/QuickFilteringCustomLogic.tsx b/docs/data/data-grid/filtering/QuickFilteringCustomLogic.tsx index 5baf7a7ab05d1..127d4ddcd18e3 100644 --- a/docs/data/data-grid/filtering/QuickFilteringCustomLogic.tsx +++ b/docs/data/data-grid/filtering/QuickFilteringCustomLogic.tsx @@ -38,7 +38,7 @@ const getApplyQuickFilterFnSameYear: GetApplyQuickFilterFn = ( }; export default function QuickFilteringCustomLogic() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -71,6 +71,7 @@ export default function QuickFilteringCustomLogic() { diff --git a/docs/data/data-grid/filtering/QuickFilteringCustomLogic.tsx.preview b/docs/data/data-grid/filtering/QuickFilteringCustomLogic.tsx.preview index 1ad531b31d6f6..6f1ec40747d6f 100644 --- a/docs/data/data-grid/filtering/QuickFilteringCustomLogic.tsx.preview +++ b/docs/data/data-grid/filtering/QuickFilteringCustomLogic.tsx.preview @@ -1,5 +1,6 @@ \ No newline at end of file diff --git a/docs/data/data-grid/filtering/QuickFilteringCustomizedGrid.js b/docs/data/data-grid/filtering/QuickFilteringCustomizedGrid.js index 83b8904505ef2..ac1caf7220429 100644 --- a/docs/data/data-grid/filtering/QuickFilteringCustomizedGrid.js +++ b/docs/data/data-grid/filtering/QuickFilteringCustomizedGrid.js @@ -30,7 +30,7 @@ function QuickSearchToolbar() { const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function QuickFilteringCustomizedGrid() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -46,6 +46,7 @@ export default function QuickFilteringCustomizedGrid() { setFilterModel(newFilterModel)} /> diff --git a/docs/data/data-grid/filtering/ReadOnlyFilters.tsx b/docs/data/data-grid/filtering/ReadOnlyFilters.tsx index 86abce911eea2..bfd38d01ccf23 100644 --- a/docs/data/data-grid/filtering/ReadOnlyFilters.tsx +++ b/docs/data/data-grid/filtering/ReadOnlyFilters.tsx @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function ReadOnlyFilters() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -34,10 +34,9 @@ export default function ReadOnlyFilters() {
setFilterModel(newFilterModel)} /> diff --git a/docs/data/data-grid/filtering/ReadOnlyFilters.tsx.preview b/docs/data/data-grid/filtering/ReadOnlyFilters.tsx.preview index 056a5447e7e3e..e9b7d2ebdca5f 100644 --- a/docs/data/data-grid/filtering/ReadOnlyFilters.tsx.preview +++ b/docs/data/data-grid/filtering/ReadOnlyFilters.tsx.preview @@ -1,9 +1,8 @@ setFilterModel(newFilterModel)} /> \ No newline at end of file diff --git a/docs/data/data-grid/filtering/RemoveBuiltInOperators.js b/docs/data/data-grid/filtering/RemoveBuiltInOperators.js index 4b70d9d16ce48..c463b4b95706e 100644 --- a/docs/data/data-grid/filtering/RemoveBuiltInOperators.js +++ b/docs/data/data-grid/filtering/RemoveBuiltInOperators.js @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function RemoveBuiltInOperators() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', rowLength: 100, visibleFields: VISIBLE_FIELDS, @@ -32,6 +32,7 @@ export default function RemoveBuiltInOperators() {
setNbRows((x) => Math.max(0, x - 1)); const addRow = () => setNbRows((x) => Math.min(100, x + 1)); - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, maxColumns: 6, @@ -26,7 +26,12 @@ export default function AutoHeightGrid() { Add a row - + ); } diff --git a/docs/data/data-grid/layout/AutoHeightGrid.tsx b/docs/data/data-grid/layout/AutoHeightGrid.tsx index eb2f2f3cd666b..95ec1e0146d0e 100644 --- a/docs/data/data-grid/layout/AutoHeightGrid.tsx +++ b/docs/data/data-grid/layout/AutoHeightGrid.tsx @@ -10,7 +10,7 @@ export default function AutoHeightGrid() { const removeRow = () => setNbRows((x) => Math.max(0, x - 1)); const addRow = () => setNbRows((x) => Math.min(100, x + 1)); - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, maxColumns: 6, @@ -26,7 +26,12 @@ export default function AutoHeightGrid() { Add a row - + ); } diff --git a/docs/data/data-grid/layout/AutoHeightGrid.tsx.preview b/docs/data/data-grid/layout/AutoHeightGrid.tsx.preview index bd3e48b450e66..5e51b75f7bdd7 100644 --- a/docs/data/data-grid/layout/AutoHeightGrid.tsx.preview +++ b/docs/data/data-grid/layout/AutoHeightGrid.tsx.preview @@ -6,4 +6,9 @@ Add a row - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/data-grid/list-view/ListView.js b/docs/data/data-grid/list-view/ListView.js index a7ab930852afe..f4bc0524e74b0 100644 --- a/docs/data/data-grid/list-view/ListView.js +++ b/docs/data/data-grid/list-view/ListView.js @@ -1,17 +1,19 @@ import * as React from 'react'; -import { DataGridPro } from '@mui/x-data-grid-pro'; -import Box from '@mui/material/Box'; +import { DataGridPro, GridToolbarContainer } from '@mui/x-data-grid-pro'; import { useDemoData } from '@mui/x-data-grid-generator'; import Stack from '@mui/material/Stack'; import Avatar from '@mui/material/Avatar'; import Typography from '@mui/material/Typography'; -import Checkbox from '@mui/material/Checkbox'; -import FormControlLabel from '@mui/material/FormControlLabel'; import IconButton from '@mui/material/IconButton'; import MessageIcon from '@mui/icons-material/Message'; +import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'; +import ToggleButton from '@mui/material/ToggleButton'; +import GridViewIcon from '@mui/icons-material/ViewModule'; +import ListViewIcon from '@mui/icons-material/ViewList'; function MessageAction(params) { - const handleMessage = () => { + const handleMessage = (event) => { + event.stopPropagation(); console.log(`send message to ${params.row.phone}`); }; return ( @@ -52,10 +54,50 @@ const listColDef = { const VISIBLE_FIELDS = ['avatar', 'name', 'position']; +function Toolbar({ view, onChangeView }) { + return ( + + { + if (newView) { + onChangeView(newView); + } + }} + > + + Grid + + + List + + + + ); +} + export default function ListView() { - const [isListView, setIsListView] = React.useState(true); + const [view, setView] = React.useState('list'); + const isListView = view === 'list'; - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', rowLength: 20, visibleFields: VISIBLE_FIELDS, @@ -76,32 +118,25 @@ export default function ListView() { const rowHeight = isListView ? 64 : 52; return ( - - setIsListView(event.target.checked)} - /> - } - label="Enable list view" - /> - + - - - + slotProps={{ + toolbar: { + view, + onChangeView: setView, + }, + }} + sx={{ backgroundColor: 'background.paper' }} + /> +
); } diff --git a/docs/data/data-grid/list-view/ListView.tsx b/docs/data/data-grid/list-view/ListView.tsx index 40239d5a8e41a..64550e4d653c6 100644 --- a/docs/data/data-grid/list-view/ListView.tsx +++ b/docs/data/data-grid/list-view/ListView.tsx @@ -5,19 +5,29 @@ import { GridListColDef, GridColDef, GridRowParams, + GridToolbarContainer, } from '@mui/x-data-grid-pro'; -import Box from '@mui/material/Box'; import { useDemoData } from '@mui/x-data-grid-generator'; import Stack from '@mui/material/Stack'; import Avatar from '@mui/material/Avatar'; import Typography from '@mui/material/Typography'; -import Checkbox from '@mui/material/Checkbox'; -import FormControlLabel from '@mui/material/FormControlLabel'; import IconButton from '@mui/material/IconButton'; import MessageIcon from '@mui/icons-material/Message'; +import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'; +import ToggleButton from '@mui/material/ToggleButton'; +import GridViewIcon from '@mui/icons-material/ViewModule'; +import ListViewIcon from '@mui/icons-material/ViewList'; + +declare module '@mui/x-data-grid' { + interface ToolbarPropsOverrides { + view: 'grid' | 'list'; + onChangeView: (view: 'grid' | 'list') => void; + } +} function MessageAction(params: Pick) { - const handleMessage = () => { + const handleMessage = (event: React.MouseEvent) => { + event.stopPropagation(); console.log(`send message to ${params.row.phone}`); }; return ( @@ -58,10 +68,55 @@ const listColDef: GridListColDef = { const VISIBLE_FIELDS = ['avatar', 'name', 'position']; +type ToolbarProps = { + view: 'grid' | 'list'; + onChangeView: (view: 'grid' | 'list') => void; +}; + +function Toolbar({ view, onChangeView }: ToolbarProps) { + return ( + + { + if (newView) { + onChangeView(newView); + } + }} + > + + Grid + + + List + + + + ); +} + export default function ListView() { - const [isListView, setIsListView] = React.useState(true); + const [view, setView] = React.useState<'grid' | 'list'>('list'); + const isListView = view === 'list'; - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', rowLength: 20, visibleFields: VISIBLE_FIELDS, @@ -82,32 +137,25 @@ export default function ListView() { const rowHeight = isListView ? 64 : 52; return ( - - setIsListView(event.target.checked)} - /> - } - label="Enable list view" - /> - + - - - + slotProps={{ + toolbar: { + view, + onChangeView: setView, + }, + }} + sx={{ backgroundColor: 'background.paper' }} + /> +
); } diff --git a/docs/data/data-grid/list-view/ListViewAdvanced.js b/docs/data/data-grid/list-view/ListViewAdvanced.js index 2185d42a142d7..cc3beaeeabe32 100644 --- a/docs/data/data-grid/list-view/ListViewAdvanced.js +++ b/docs/data/data-grid/list-view/ListViewAdvanced.js @@ -13,6 +13,7 @@ import OpenIcon from '@mui/icons-material/Visibility'; import useMediaQuery from '@mui/material/useMediaQuery'; import CSSBaseline from '@mui/material/CssBaseline'; import { randomId } from '@mui/x-data-grid-generator'; +import { useTheme } from '@mui/material/styles'; import { FileIcon } from './components/FileIcon'; import { DetailsDrawer } from './components/DetailsDrawer'; import { ListCell } from './components/ListCell'; @@ -24,16 +25,18 @@ import { formatDate, formatSize, stringAvatar } from './utils'; import { ActionDrawer } from './components/ActionDrawer'; import { RenameDialog } from './components/RenameDialog'; -export default function ListViewAdvanced() { +export default function ListViewAdvanced(props) { // This is used only for the example - renders the drawer inside the container const containerRef = React.useRef(null); const container = () => containerRef.current; - const isListView = useMediaQuery('(min-width: 700px)'); + const theme = useTheme(); + const isBelowMd = useMediaQuery(theme.breakpoints.down('md')); - const apiRef = useGridApiRef(); + const isDocsDemo = props.window !== undefined; + const isListView = isDocsDemo ? true : isBelowMd; - const [rows, setRows] = React.useState(INITIAL_ROWS); + const apiRef = useGridApiRef(); const [loading, setLoading] = React.useState(false); @@ -46,65 +49,67 @@ export default function ListViewAdvanced() { setOverlayState({ overlay: null, params: null }); }; - const handleDelete = React.useCallback((ids) => { - setRows((prevRows) => prevRows.filter((row) => !ids.includes(row.id))); - }, []); + const handleDelete = React.useCallback( + (ids) => { + apiRef.current.updateRows(ids.map((id) => ({ id, _action: 'delete' }))); + }, + [apiRef], + ); - const handleUpdate = React.useCallback((id, field, value) => { - setRows((prevRows) => - prevRows.map((row) => - row.id === id - ? { ...row, [field]: value, updatedAt: new Date().toISOString() } - : row, - ), - ); - }, []); + const handleUpdate = React.useCallback( + (id, field, value) => { + const updatedAt = new Date().toISOString(); + apiRef.current.updateRows([{ id, [field]: value, updatedAt }]); + }, + [apiRef], + ); - const handleUpload = React.useCallback((event) => { - if (!event.target.files) { - return; - } + const handleUpload = React.useCallback( + (event) => { + if (!event.target.files) { + return; + } - const file = event.target.files[0]; - const createdAt = new Date().toISOString(); + const file = event.target.files[0]; + const createdAt = new Date().toISOString(); - const fileType = file.type.split('/')[1]; + const fileType = file.type.split('/')[1]; - // validate file type - if (!FILE_TYPES.includes(fileType)) { - alert('Invalid file type'); - return; - } + // validate file type + if (!FILE_TYPES.includes(fileType)) { + alert('Invalid file type'); + return; + } - const row = { - id: randomId(), - name: file.name, - description: '', - type: fileType, - size: file.size, - createdBy: 'Kenan Yusuf', - createdAt, - updatedAt: createdAt, - state: 'pending', - }; + const row = { + id: randomId(), + name: file.name, + description: '', + type: fileType, + size: file.size, + createdBy: 'Kenan Yusuf', + createdAt, + updatedAt: createdAt, + state: 'pending', + }; - event.target.value = ''; + event.target.value = ''; - // Add temporary row - setLoading(true); - setRows((prevRows) => [...prevRows, row]); + // Add temporary row + setLoading(true); + apiRef.current.updateRows([row]); - // Simulate server response time - const timeout = Math.floor(Math.random() * 3000) + 2000; - setTimeout(() => { - const uploadedRow = { ...row, state: 'uploaded' }; - setRows((prevRows) => - prevRows.map((r) => (r.id === row.id ? uploadedRow : r)), - ); - setOverlayState({ overlay: 'actions', params: { row } }); - setLoading(false); - }, timeout); - }, []); + // Simulate server response time + const timeout = Math.floor(Math.random() * 3000) + 2000; + setTimeout(() => { + const uploadedRow = { ...row, state: 'uploaded' }; + apiRef.current.updateRows([uploadedRow]); + setOverlayState({ overlay: 'actions', params: { row } }); + setLoading(false); + }, timeout); + }, + [apiRef], + ); const columns = React.useMemo( () => [ @@ -267,7 +272,7 @@ export default function ListViewAdvanced() { > HTMLElement; + handleDelete: (ids: GridRowId[]) => void; + handleUpload: (event: React.ChangeEvent) => void; + } +} + +interface Props { + // Injected by the documentation to work in an iframe. + window?: () => Window; +} + +export default function ListViewAdvanced(props: Props) { // This is used only for the example - renders the drawer inside the container const containerRef = React.useRef(null); const container = () => containerRef.current as HTMLElement; - const isListView = useMediaQuery('(min-width: 700px)'); + const theme = useTheme(); + const isBelowMd = useMediaQuery(theme.breakpoints.down('md')); - const apiRef = useGridApiRef(); + const isDocsDemo = props.window !== undefined; + const isListView = isDocsDemo ? true : isBelowMd; - const [rows, setRows] = React.useState[]>(INITIAL_ROWS); + const apiRef = useGridApiRef(); const [loading, setLoading] = React.useState(false); @@ -53,9 +69,12 @@ export default function ListViewAdvanced() { setOverlayState({ overlay: null, params: null }); }; - const handleDelete = React.useCallback((ids: GridRowId[]) => { - setRows((prevRows) => prevRows.filter((row) => !ids.includes(row.id))); - }, []); + const handleDelete = React.useCallback( + (ids: GridRowId[]) => { + apiRef.current.updateRows(ids.map((id) => ({ id, _action: 'delete' }))); + }, + [apiRef], + ); const handleUpdate = React.useCallback( ( @@ -63,15 +82,10 @@ export default function ListViewAdvanced() { field: GridRowParams['columns'][number]['field'], value: string, ) => { - setRows((prevRows) => - prevRows.map((row) => - row.id === id - ? { ...row, [field]: value, updatedAt: new Date().toISOString() } - : row, - ), - ); + const updatedAt = new Date().toISOString(); + apiRef.current.updateRows([{ id, [field]: value, updatedAt }]); }, - [], + [apiRef], ); const handleUpload = React.useCallback( @@ -107,20 +121,18 @@ export default function ListViewAdvanced() { // Add temporary row setLoading(true); - setRows((prevRows) => [...prevRows, row]); + apiRef.current.updateRows([row]); // Simulate server response time const timeout = Math.floor(Math.random() * 3000) + 2000; setTimeout(() => { const uploadedRow: RowModel = { ...row, state: 'uploaded' }; - setRows((prevRows) => - prevRows.map((r) => (r.id === row.id ? uploadedRow : r)), - ); + apiRef.current.updateRows([uploadedRow]); setOverlayState({ overlay: 'actions', params: { row } }); setLoading(false); }, timeout); }, - [], + [apiRef], ); const columns: GridColDef[] = React.useMemo( @@ -284,7 +296,7 @@ export default function ListViewAdvanced() { > { + return randomArrayItem(roles); +}; + +const rows = [ + { + id: randomId(), + name: randomTraderName(), + position: randomRole(), + avatar: '#4caf50', + }, + { + id: randomId(), + name: randomTraderName(), + position: randomRole(), + avatar: '#2196f3', + }, + { + id: randomId(), + name: randomTraderName(), + position: randomRole(), + avatar: '#ff9800', + }, + { + id: randomId(), + name: randomTraderName(), + position: randomRole(), + avatar: '#9c27b0', + }, + { + id: randomId(), + name: randomTraderName(), + position: randomRole(), + avatar: '#f44336', + }, +]; + +const columns = [ + { field: 'name', headerName: 'Name', width: 180 }, + { + field: 'position', + headerName: 'Department', + width: 220, + type: 'singleSelect', + valueOptions: roles, + }, +]; + +function EditAction(props) { + const { row } = props; + const [editing, setEditing] = React.useState(false); + const [name, setName] = React.useState(row.name); + const [position, setPosition] = React.useState(row.position); + const apiRef = useGridApiContext(); + + const handleEdit = (event) => { + event.stopPropagation(); + setEditing(true); + }; + + const handleClose = () => { + setEditing(false); + }; + + const handleSave = (event) => { + event.preventDefault(); + apiRef.current.updateRows([{ id: row.id, name, position }]); + handleClose(); + }; + + React.useEffect(() => { + setName(row.name); + setPosition(row.position); + }, [row]); + + return ( + + + + + + + Edit Employee + + + Make changes to the employee's information. + + setName(event.target.value)} + /> + + Position + + + + + + + + + + ); +} + +function DeleteAction(props) { + const { row } = props; + const apiRef = useGridApiContext(); + + return ( + apiRef.current.updateRows([{ id: row.id, _action: 'delete' }])} + > + + + ); +} + +function ListViewCell(props) { + const { row } = props; + + return ( + + + + + {row.name} + + + {row.position} + + + + + + + + ); +} + +const listColDef = { + field: 'listColumn', + renderCell: (params) => , +}; + +export default function ListViewEdit() { + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/list-view/ListViewEdit.tsx b/docs/data/data-grid/list-view/ListViewEdit.tsx new file mode 100644 index 0000000000000..e63bec02da42e --- /dev/null +++ b/docs/data/data-grid/list-view/ListViewEdit.tsx @@ -0,0 +1,236 @@ +import * as React from 'react'; +import { + DataGridPro, + GridRenderCellParams, + GridListColDef, + GridColDef, + GridRowParams, + GridRowsProp, + useGridApiContext, +} from '@mui/x-data-grid-pro'; +import Stack from '@mui/material/Stack'; +import Avatar from '@mui/material/Avatar'; +import Typography from '@mui/material/Typography'; +import IconButton from '@mui/material/IconButton'; +import EditIcon from '@mui/icons-material/Edit'; +import DeleteIcon from '@mui/icons-material/Delete'; +import Dialog from '@mui/material/Dialog'; +import DialogTitle from '@mui/material/DialogTitle'; +import DialogContent from '@mui/material/DialogContent'; +import DialogContentText from '@mui/material/DialogContentText'; +import TextField from '@mui/material/TextField'; +import Button from '@mui/material/Button'; +import DialogActions from '@mui/material/DialogActions'; +import FormControl from '@mui/material/FormControl'; +import InputLabel from '@mui/material/InputLabel'; +import Select from '@mui/material/Select'; +import MenuItem from '@mui/material/MenuItem'; +import { + randomId, + randomTraderName, + randomArrayItem, +} from '@mui/x-data-grid-generator'; + +const roles = ['Marketing', 'Finance', 'Development']; + +const randomRole = () => { + return randomArrayItem(roles); +}; + +const rows: GridRowsProp = [ + { + id: randomId(), + name: randomTraderName(), + position: randomRole(), + avatar: '#4caf50', + }, + { + id: randomId(), + name: randomTraderName(), + position: randomRole(), + avatar: '#2196f3', + }, + { + id: randomId(), + name: randomTraderName(), + position: randomRole(), + avatar: '#ff9800', + }, + { + id: randomId(), + name: randomTraderName(), + position: randomRole(), + avatar: '#9c27b0', + }, + { + id: randomId(), + name: randomTraderName(), + position: randomRole(), + avatar: '#f44336', + }, +]; + +const columns: GridColDef[] = [ + { field: 'name', headerName: 'Name', width: 180 }, + { + field: 'position', + headerName: 'Department', + width: 220, + type: 'singleSelect', + valueOptions: roles, + }, +]; + +function EditAction(props: Pick) { + const { row } = props; + const [editing, setEditing] = React.useState(false); + const [name, setName] = React.useState(row.name); + const [position, setPosition] = React.useState(row.position); + const apiRef = useGridApiContext(); + + const handleEdit = (event: React.MouseEvent) => { + event.stopPropagation(); + setEditing(true); + }; + + const handleClose = () => { + setEditing(false); + }; + + const handleSave = (event: React.FormEvent) => { + event.preventDefault(); + apiRef.current.updateRows([{ id: row.id, name, position }]); + handleClose(); + }; + + React.useEffect(() => { + setName(row.name); + setPosition(row.position); + }, [row]); + + return ( + + + + + + + Edit Employee + + + Make changes to the employee's information. + + setName(event.target.value)} + /> + + Position + + + + + + + + + + ); +} + +function DeleteAction(props: Pick) { + const { row } = props; + const apiRef = useGridApiContext(); + + return ( + apiRef.current.updateRows([{ id: row.id, _action: 'delete' }])} + > + + + ); +} + +function ListViewCell(props: GridRenderCellParams) { + const { row } = props; + + return ( + + + + + {row.name} + + + {row.position} + + + + + + + + ); +} + +const listColDef: GridListColDef = { + field: 'listColumn', + renderCell: (params) => , +}; + +export default function ListViewEdit() { + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/list-view/ListViewEdit.tsx.preview b/docs/data/data-grid/list-view/ListViewEdit.tsx.preview new file mode 100644 index 0000000000000..09b26a2a275bb --- /dev/null +++ b/docs/data/data-grid/list-view/ListViewEdit.tsx.preview @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/list-view/ListViewMediaQuery.js b/docs/data/data-grid/list-view/ListViewMediaQuery.js new file mode 100644 index 0000000000000..44eae0ccd9cef --- /dev/null +++ b/docs/data/data-grid/list-view/ListViewMediaQuery.js @@ -0,0 +1,70 @@ +import * as React from 'react'; +import { DataGridPro } from '@mui/x-data-grid-pro'; +import { useDemoData } from '@mui/x-data-grid-generator'; +import Stack from '@mui/material/Stack'; +import Avatar from '@mui/material/Avatar'; +import Typography from '@mui/material/Typography'; +import useMediaQuery from '@mui/material/useMediaQuery'; +import { useTheme } from '@mui/material/styles'; + +function ListViewCell(params) { + return ( + + + + + {params.row.name} + + + {params.row.position} + + + + ); +} + +const listColDef = { + field: 'listColumn', + renderCell: ListViewCell, +}; + +const VISIBLE_FIELDS = ['avatar', 'name', 'position']; + +export default function ListViewMediaQuery() { + const theme = useTheme(); + const isListView = useMediaQuery(theme.breakpoints.down('md')); + + const { data, loading } = useDemoData({ + dataSet: 'Employee', + rowLength: 5, + visibleFields: VISIBLE_FIELDS, + }); + + const rowHeight = isListView ? 64 : 52; + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/list-view/ListViewMediaQuery.tsx b/docs/data/data-grid/list-view/ListViewMediaQuery.tsx new file mode 100644 index 0000000000000..21605af8d10c1 --- /dev/null +++ b/docs/data/data-grid/list-view/ListViewMediaQuery.tsx @@ -0,0 +1,74 @@ +import * as React from 'react'; +import { + DataGridPro, + GridRenderCellParams, + GridListColDef, +} from '@mui/x-data-grid-pro'; +import { useDemoData } from '@mui/x-data-grid-generator'; +import Stack from '@mui/material/Stack'; +import Avatar from '@mui/material/Avatar'; +import Typography from '@mui/material/Typography'; +import useMediaQuery from '@mui/material/useMediaQuery'; +import { useTheme } from '@mui/material/styles'; + +function ListViewCell(params: GridRenderCellParams) { + return ( + + + + + {params.row.name} + + + {params.row.position} + + + + ); +} + +const listColDef: GridListColDef = { + field: 'listColumn', + renderCell: ListViewCell, +}; + +const VISIBLE_FIELDS = ['avatar', 'name', 'position']; + +export default function ListViewMediaQuery() { + const theme = useTheme(); + const isListView = useMediaQuery(theme.breakpoints.down('md')); + + const { data, loading } = useDemoData({ + dataSet: 'Employee', + rowLength: 5, + visibleFields: VISIBLE_FIELDS, + }); + + const rowHeight = isListView ? 64 : 52; + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/list-view/ListViewMediaQuery.tsx.preview b/docs/data/data-grid/list-view/ListViewMediaQuery.tsx.preview new file mode 100644 index 0000000000000..7481bb780c233 --- /dev/null +++ b/docs/data/data-grid/list-view/ListViewMediaQuery.tsx.preview @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/list-view/constants.js b/docs/data/data-grid/list-view/constants.js new file mode 100644 index 0000000000000..367df998d6374 --- /dev/null +++ b/docs/data/data-grid/list-view/constants.js @@ -0,0 +1,15 @@ +export const FILE_TYPES = [ + 'pdf', + 'docx', + 'txt', + 'mp4', + 'mov', + 'webm', + 'jpg', + 'jpeg', + 'png', + 'gif', + 'tiff', + 'webp', + 'zip', +]; diff --git a/docs/data/data-grid/list-view/data.js b/docs/data/data-grid/list-view/data.js new file mode 100644 index 0000000000000..39537f00c1f53 --- /dev/null +++ b/docs/data/data-grid/list-view/data.js @@ -0,0 +1,202 @@ +import { randomId } from '@mui/x-data-grid-generator'; + +export const INITIAL_ROWS = [ + { + id: randomId(), + type: 'zip', + name: 'archive.zip', + description: 'Compressed archive of project files', + size: 128_313_213, + createdBy: 'Kenan Yusuf', + createdAt: new Date('2023-09-15T08:30:00').toISOString(), + updatedAt: new Date('2023-09-15T08:30:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'docx', + name: 'invoice-322.docx', + description: 'Invoice document for client 322', + size: 1_694_986, + createdBy: 'José Freitas', + createdAt: new Date('2024-01-18T11:30:00').toISOString(), + updatedAt: new Date().toISOString(), // Today + state: 'uploaded', + }, + { + id: randomId(), + type: 'png', + name: 'screenshot_2024-02-14_12-34-56.png', + description: 'Screenshot of application interface', + size: 522_078, + createdBy: 'José Freitas', + createdAt: new Date('2024-02-14T12:35:16').toISOString(), + updatedAt: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString(), // Last week + state: 'uploaded', + }, + { + id: randomId(), + type: 'mp4', + name: 'strategy-meeting.mp4', + description: 'Recording of the strategy planning meeting', + size: 2_442_044, + createdBy: 'José Freitas', + createdAt: new Date('2023-12-05T15:40:30').toISOString(), + updatedAt: new Date(Date.now() - 20 * 24 * 60 * 60 * 1000).toISOString(), // Last month + state: 'uploaded', + }, + { + id: randomId(), + type: 'docx', + name: 'project-proposal.docx', + description: 'Detailed project proposal document', + size: 3_567_890, + createdBy: 'Olivier Tassinari', + createdAt: new Date('2024-03-01T09:15:00').toISOString(), + updatedAt: new Date('2024-03-02T14:30:45').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'png', + name: 'logo-design-final.png', + description: 'Final version of the company logo design', + size: 1_234_567, + createdBy: 'Kenan Yusuf', + createdAt: new Date('2024-02-28T16:20:00').toISOString(), + updatedAt: new Date('2024-02-28T16:20:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'mp4', + name: 'product-demo.mp4', + description: 'Video demonstration of the new product features', + size: 15_789_012, + createdBy: 'Olivier Tassinari', + createdAt: new Date('2024-02-25T11:45:00').toISOString(), + updatedAt: new Date(Date.now() - 60 * 24 * 60 * 60 * 1000).toISOString(), // Last 3 months + state: 'uploaded', + }, + { + id: randomId(), + type: 'zip', + name: 'project-assets.zip', + description: 'Compressed folder containing all project assets', + size: 87_654_321, + createdBy: 'José Freitas', + createdAt: new Date('2024-03-03T13:00:00').toISOString(), + updatedAt: new Date('2024-03-03T13:00:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'docx', + name: 'meeting-minutes-2024-03-10.docx', + description: 'Minutes from the team meeting on March 10, 2024', + size: 567_890, + createdBy: 'Kenan Yusuf', + createdAt: new Date('2024-03-10T14:00:00').toISOString(), + updatedAt: new Date('2024-03-10T16:30:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'png', + name: 'ui-mockup-v2.png', + description: 'Updated user interface mockup', + size: 3_456_789, + createdBy: 'Olivier Tassinari', + createdAt: new Date('2024-03-05T10:20:00').toISOString(), + updatedAt: new Date('2024-03-05T10:20:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'mp4', + name: 'user-feedback-session.mp4', + description: 'Recording of user feedback session', + size: 234_567_890, + createdBy: 'José Freitas', + createdAt: new Date('2024-03-08T13:45:00').toISOString(), + updatedAt: new Date('2024-03-08T15:30:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'zip', + name: 'legacy-codebase.zip', + description: 'Archive of the legacy project codebase', + size: 567_890_123, + createdBy: 'Kenan Yusuf', + createdAt: new Date('2024-02-20T09:00:00').toISOString(), + updatedAt: new Date('2024-02-20T09:00:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'docx', + name: 'q1-2024-report.docx', + description: 'Quarterly report for Q1 2024', + size: 4_567_890, + createdBy: 'Olivier Tassinari', + createdAt: new Date('2024-03-31T23:59:59').toISOString(), + updatedAt: new Date('2024-04-01T10:15:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'png', + name: 'data-visualization.png', + description: 'Chart showing project progress', + size: 789_012, + createdBy: 'José Freitas', + createdAt: new Date('2024-03-15T11:30:00').toISOString(), + updatedAt: new Date('2024-03-15T11:30:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'mp4', + name: 'code-review-session.mp4', + description: 'Recording of code review meeting', + size: 345_678_901, + createdBy: 'Kenan Yusuf', + createdAt: new Date('2024-03-20T14:00:00').toISOString(), + updatedAt: new Date('2024-03-20T16:45:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'zip', + name: 'design-assets-v3.zip', + description: 'Compressed folder of updated design assets', + size: 98_765_432, + createdBy: 'Olivier Tassinari', + createdAt: new Date('2024-03-25T09:30:00').toISOString(), + updatedAt: new Date('2024-03-25T09:30:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'docx', + name: 'api-documentation.docx', + description: 'Comprehensive API documentation', + size: 2_345_678, + createdBy: 'José Freitas', + createdAt: new Date('2024-03-28T16:20:00').toISOString(), + updatedAt: new Date('2024-03-29T11:45:00').toISOString(), + state: 'uploaded', + }, + { + id: randomId(), + type: 'png', + name: 'error-screenshot.png', + description: 'Screenshot of error message for debugging', + size: 345_678, + createdBy: 'Kenan Yusuf', + createdAt: new Date('2024-03-30T08:15:00').toISOString(), + updatedAt: new Date('2024-03-30T08:15:00').toISOString(), + state: 'uploaded', + }, +]; diff --git a/docs/data/data-grid/list-view/list-view.md b/docs/data/data-grid/list-view/list-view.md index 11f4b7ca3e88c..ed100bb168cab 100644 --- a/docs/data/data-grid/list-view/list-view.md +++ b/docs/data/data-grid/list-view/list-view.md @@ -2,28 +2,78 @@ title: Data Grid - List view --- -# Data Grid - List view [](/x/introduction/licensing/#pro-plan 'Pro plan') +# Data Grid - List view [](/x/introduction/licensing/#pro-plan 'Pro plan')🧪

Display data in a single-column list view. Can be used to present a more compact grid on smaller screens and mobile devices.

+:::warning +This feature is marked as **unstable**. While you can use this feature in production, the API could change in the future. +::: + List view can be enabled by providing the `unstable_listView` prop. Unlike the default grid view, the list view makes no assumptions on how data is presented to end users. In order to display data in a list view, a `unstable_listColumn` prop must be provided with a `renderCell` function. -:::warning -This feature is under development and is marked as **unstable**. While you can use the list view feature in production, the API could change in the future. -::: +```tsx +function ListViewCell(params: GridRenderCellParams) { + return <>{params.row.id}; +} + +const listColDef: GridListColDef = { + field: 'listColumn', + renderCell: ListViewCell, +}; + +; +``` + +{{"demo": "ListView.js", "bg": true}} + +## Enable with a media query + +Use the `useMediaQuery` hook from `@mui/material` to enable the list view feature at a specified breakpoint. + +The demo below automatically switches to a list layout when the viewport width is below the `md` breakpoint. -{{"demo": "ListView.js", "bg": "inline"}} +{{"demo": "ListViewMediaQuery.js", "bg": "inline"}} + +## Editable rows + +The [editing feature](/x/react-data-grid/editing/) is not supported in list view, but it is possible to build an editing experience from within your custom cell renderer, as shown below. + +{{"demo": "ListViewEdit.js", "bg": true}} ## Advanced usage -The list view feature can be combined with [custom subcomponents](/x/react-data-grid/components/) to provide an improved user experience on small screens. +The list view feature can be combined with [custom subcomponents](/x/react-data-grid/components/) to provide an improved user experience on small screens, as shown below. + +{{"demo": "ListViewAdvanced.js", "iframe": true, "maxWidth": 360, "height": 600}} + +## Feature compatibility + +The list view feature can be used in combination with the following features: -{{"demo": "ListViewAdvanced.js", "bg": "inline", "iframe": true, "maxWidth": 360, "height": 600, "hideToolbar": true}} +- ✅ [Sorting](/x/react-data-grid/sorting/) +- ✅ [Filtering](/x/react-data-grid/filtering/) +- ✅ [Pagination](/x/react-data-grid/pagination/) +- ✅ [Row selection](/x/react-data-grid/row-selection/) +- ✅ [Multi filters](/x/react-data-grid/filtering/multi-filters/) [](/x/introduction/licensing/#pro-plan 'Pro plan') +- ✅ [Row pinning](/x/react-data-grid/row-pinning/) [](/x/introduction/licensing/#pro-plan 'Pro plan') +- ✅ [Cell selection](/x/react-data-grid/cell-selection/) [](/x/introduction/licensing/#premium-plan 'Premium plan') -:::info -See the code for this demo in [CodeSandbox](https://codesandbox.io/p/sandbox/x-react-data-grid-list-view-zmkzhz). +:::warning +Features not listed may not work as expected, or may not work at all. + +If you're using a feature that's listed above and it's not working as expected, please [open a bug report](https://github.com/mui/mui-x/issues/new?assignees=&labels=status%3A+waiting+for+maintainer%2Cbug+%F0%9F%90%9B&projects=&template=1.bug.yml). + +If you need to use list view with any other features, please [open a feature request](https://github.com/mui/mui-x/issues/new?assignees=&labels=status%3A+waiting+for+maintainer%2Cnew+feature&projects=&template=2.feature.yml). ::: + +## API + +- [DataGrid](/x/api/data-grid/data-grid/) +- [DataGridPro](/x/api/data-grid/data-grid-pro/) +- [DataGridPremium](/x/api/data-grid/data-grid-premium/) +- [GridListColDef](/x/api/data-grid/grid-list-col-def/) diff --git a/docs/data/data-grid/list-view/utils.js b/docs/data/data-grid/list-view/utils.js new file mode 100644 index 0000000000000..8e75f8418c0ff --- /dev/null +++ b/docs/data/data-grid/list-view/utils.js @@ -0,0 +1,56 @@ +export function formatDate(value) { + if (!value) { + return '—'; + } + const date = new Date(value); + const formatter = new Intl.DateTimeFormat('en-US', { + month: 'short', + day: '2-digit', + year: 'numeric', + hour: '2-digit', + minute: '2-digit', + }); + return formatter.format(date); +} + +export function formatSize(size) { + const units = ['B', 'KB', 'MB', 'GB', 'TB']; + let unitIndex = 0; + let formattedSize = size; + + while (formattedSize >= 1024 && unitIndex < units.length - 1) { + formattedSize /= 1024; + unitIndex += 1; + } + + return `${formattedSize.toFixed(2)} ${units[unitIndex]}`; +} + +export function stringToColor(string) { + let hash = 0; + let i; + + /* eslint-disable no-bitwise */ + for (i = 0; i < string.length; i += 1) { + hash = string.charCodeAt(i) + ((hash << 5) - hash); + } + + let color = '#'; + + for (i = 0; i < 3; i += 1) { + const value = (hash >> (i * 8)) & 0xff; + color += `00${value.toString(16)}`.slice(-2); + } + /* eslint-enable no-bitwise */ + + return color; +} + +export function stringAvatar(name) { + return { + sx: { + bgcolor: stringToColor(name), + }, + children: `${name.split(' ')[0][0]}${name.split(' ')[1][0]}`, + }; +} diff --git a/docs/data/data-grid/localization/data.json b/docs/data/data-grid/localization/data.json index fc9f1657230c3..cc0c430a6377e 100644 --- a/docs/data/data-grid/localization/data.json +++ b/docs/data/data-grid/localization/data.json @@ -3,96 +3,96 @@ "languageTag": "ar-SD", "importName": "arSD", "localeName": "Arabic (Sudan)", - "missingKeysCount": 8, - "totalKeysCount": 122, + "missingKeysCount": 18, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/arSD.ts" }, { "languageTag": "be-BY", "importName": "beBY", "localeName": "Belarusian", - "missingKeysCount": 34, - "totalKeysCount": 122, + "missingKeysCount": 44, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/beBY.ts" }, { "languageTag": "bg-BG", "importName": "bgBG", "localeName": "Bulgarian", - "missingKeysCount": 0, - "totalKeysCount": 122, + "missingKeysCount": 10, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/bgBG.ts" }, { "languageTag": "zh-HK", "importName": "zhHK", "localeName": "Chinese (Hong Kong)", - "missingKeysCount": 8, - "totalKeysCount": 122, + "missingKeysCount": 18, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/zhHK.ts" }, { "languageTag": "zh-CN", "importName": "zhCN", "localeName": "Chinese (Simplified)", - "missingKeysCount": 4, - "totalKeysCount": 122, + "missingKeysCount": 0, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/zhCN.ts" }, { "languageTag": "zh-TW", "importName": "zhTW", "localeName": "Chinese (Taiwan)", - "missingKeysCount": 8, - "totalKeysCount": 122, + "missingKeysCount": 18, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/zhTW.ts" }, { "languageTag": "hr-HR", "importName": "hrHR", "localeName": "Croatian", - "missingKeysCount": 0, - "totalKeysCount": 122, + "missingKeysCount": 10, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/hrHR.ts" }, { "languageTag": "cs-CZ", "importName": "csCZ", "localeName": "Czech", - "missingKeysCount": 4, - "totalKeysCount": 122, + "missingKeysCount": 14, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/csCZ.ts" }, { "languageTag": "da-DK", "importName": "daDK", "localeName": "Danish", - "missingKeysCount": 0, - "totalKeysCount": 122, + "missingKeysCount": 10, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/daDK.ts" }, { "languageTag": "nl-NL", "importName": "nlNL", "localeName": "Dutch", - "missingKeysCount": 4, - "totalKeysCount": 122, + "missingKeysCount": 14, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/nlNL.ts" }, { "languageTag": "fi-FI", "importName": "fiFI", "localeName": "Finnish", - "missingKeysCount": 4, - "totalKeysCount": 122, + "missingKeysCount": 14, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/fiFI.ts" }, { "languageTag": "fr-FR", "importName": "frFR", "localeName": "French", - "missingKeysCount": 0, - "totalKeysCount": 122, + "missingKeysCount": 10, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/frFR.ts" }, { @@ -100,95 +100,95 @@ "importName": "deDE", "localeName": "German", "missingKeysCount": 0, - "totalKeysCount": 122, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/deDE.ts" }, { "languageTag": "el-GR", "importName": "elGR", "localeName": "Greek", - "missingKeysCount": 8, - "totalKeysCount": 122, + "missingKeysCount": 18, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/elGR.ts" }, { "languageTag": "he-IL", "importName": "heIL", "localeName": "Hebrew", - "missingKeysCount": 4, - "totalKeysCount": 122, + "missingKeysCount": 0, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/heIL.ts" }, { "languageTag": "hu-HU", "importName": "huHU", "localeName": "Hungarian", - "missingKeysCount": 6, - "totalKeysCount": 122, + "missingKeysCount": 16, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/huHU.ts" }, { "languageTag": "is-IS", "importName": "isIS", "localeName": "Icelandic", - "missingKeysCount": 8, - "totalKeysCount": 122, + "missingKeysCount": 18, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/isIS.ts" }, { "languageTag": "it-IT", "importName": "itIT", "localeName": "Italian", - "missingKeysCount": 0, - "totalKeysCount": 122, + "missingKeysCount": 10, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/itIT.ts" }, { "languageTag": "ja-JP", "importName": "jaJP", "localeName": "Japanese", - "missingKeysCount": 0, - "totalKeysCount": 122, + "missingKeysCount": 10, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/jaJP.ts" }, { "languageTag": "ko-KR", "importName": "koKR", "localeName": "Korean", - "missingKeysCount": 35, - "totalKeysCount": 122, + "missingKeysCount": 45, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/koKR.ts" }, { "languageTag": "nb-NO", "importName": "nbNO", "localeName": "Norwegian (Bokmål)", - "missingKeysCount": 4, - "totalKeysCount": 122, + "missingKeysCount": 14, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/nbNO.ts" }, { "languageTag": "nn-NO", "importName": "nnNO", "localeName": "Norwegian (Nynorsk)", - "missingKeysCount": 4, - "totalKeysCount": 122, + "missingKeysCount": 14, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/nnNO.ts" }, { "languageTag": "fa-IR", "importName": "faIR", "localeName": "Persian", - "missingKeysCount": 4, - "totalKeysCount": 122, + "missingKeysCount": 14, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/faIR.ts" }, { "languageTag": "pl-PL", "importName": "plPL", "localeName": "Polish", - "missingKeysCount": 11, - "totalKeysCount": 122, + "missingKeysCount": 21, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/plPL.ts" }, { @@ -196,7 +196,7 @@ "importName": "ptPT", "localeName": "Portuguese", "missingKeysCount": 0, - "totalKeysCount": 122, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/ptPT.ts" }, { @@ -204,79 +204,79 @@ "importName": "ptBR", "localeName": "Portuguese (Brazil)", "missingKeysCount": 0, - "totalKeysCount": 122, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/ptBR.ts" }, { "languageTag": "ro-RO", "importName": "roRO", "localeName": "Romanian", - "missingKeysCount": 8, - "totalKeysCount": 122, + "missingKeysCount": 0, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/roRO.ts" }, { "languageTag": "ru-RU", "importName": "ruRU", "localeName": "Russian", - "missingKeysCount": 4, - "totalKeysCount": 122, + "missingKeysCount": 14, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/ruRU.ts" }, { "languageTag": "sk-SK", "importName": "skSK", "localeName": "Slovak", - "missingKeysCount": 5, - "totalKeysCount": 122, + "missingKeysCount": 15, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/skSK.ts" }, { "languageTag": "es-ES", "importName": "esES", "localeName": "Spanish", - "missingKeysCount": 4, - "totalKeysCount": 122, + "missingKeysCount": 0, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/esES.ts" }, { "languageTag": "sv-SE", "importName": "svSE", "localeName": "Swedish", - "missingKeysCount": 5, - "totalKeysCount": 122, + "missingKeysCount": 10, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/svSE.ts" }, { "languageTag": "tr-TR", "importName": "trTR", "localeName": "Turkish", - "missingKeysCount": 4, - "totalKeysCount": 122, + "missingKeysCount": 0, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/trTR.ts" }, { "languageTag": "uk-UA", "importName": "ukUA", "localeName": "Ukrainian", - "missingKeysCount": 8, - "totalKeysCount": 122, + "missingKeysCount": 18, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/ukUA.ts" }, { "languageTag": "ur-PK", "importName": "urPK", "localeName": "Urdu (Pakistan)", - "missingKeysCount": 8, - "totalKeysCount": 122, + "missingKeysCount": 18, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/urPK.ts" }, { "languageTag": "vi-VN", "importName": "viVN", "localeName": "Vietnamese", - "missingKeysCount": 0, - "totalKeysCount": 122, + "missingKeysCount": 10, + "totalKeysCount": 132, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/locales/viVN.ts" } ] diff --git a/docs/data/data-grid/master-detail/LazyLoadingDetailPanel.js b/docs/data/data-grid/master-detail/LazyLoadingDetailPanel.js index b13e7603bbb57..7e136821589c4 100644 --- a/docs/data/data-grid/master-detail/LazyLoadingDetailPanel.js +++ b/docs/data/data-grid/master-detail/LazyLoadingDetailPanel.js @@ -13,6 +13,8 @@ import { randomId, } from '@mui/x-data-grid-generator'; +const DetailPanelDataCache = React.createContext(new Map()); + async function getProducts(orderId) { await new Promise((resolve) => { setTimeout(resolve, 1000); @@ -32,11 +34,18 @@ function DetailPanelContent({ row: rowProp }) { const [isLoading, setLoading] = React.useState(true); const [products, setProducts] = React.useState([]); + const detailPanelDataCache = React.useContext(DetailPanelDataCache); + React.useEffect(() => { let isMounted = true; (async () => { - console.log('fetching detail panel content for row', rowProp.id); - const result = await getProducts(rowProp.id); + if (!detailPanelDataCache.has(rowProp.id)) { + console.log('fetching detail panel content for row', rowProp.id); + const response = await getProducts(rowProp.id); + // Store the data in cache so that when detail panel unmounts due to virtualization, the data is not lost + detailPanelDataCache.set(rowProp.id, response); + } + const result = detailPanelDataCache.get(rowProp.id); if (!isMounted) { return; @@ -49,7 +58,7 @@ function DetailPanelContent({ row: rowProp }) { return () => { isMounted = false; }; - }, [rowProp.id]); + }, [rowProp.id, detailPanelDataCache]); return ( 240; export default function LazyLoadingDetailPanel() { + const detailPanelDataCache = React.useRef(new Map()).current; + + const handleDetailPanelExpansionChange = React.useCallback( + (newExpandedRowIds) => { + // Only keep cached data for detail panels that are still expanded + const preservedEntries = newExpandedRowIds.map((id) => [ + id, + detailPanelDataCache.get(id), + ]); + detailPanelDataCache.clear(); + preservedEntries.forEach( + ([id, value]) => value && detailPanelDataCache.set(id, value), + ); + }, + [detailPanelDataCache], + ); + return ( - + + + ); } diff --git a/docs/data/data-grid/master-detail/LazyLoadingDetailPanel.tsx b/docs/data/data-grid/master-detail/LazyLoadingDetailPanel.tsx index d4e88ac1a15ee..2fbc032ed70f8 100644 --- a/docs/data/data-grid/master-detail/LazyLoadingDetailPanel.tsx +++ b/docs/data/data-grid/master-detail/LazyLoadingDetailPanel.tsx @@ -3,7 +3,7 @@ import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; import Paper from '@mui/material/Paper'; import Stack from '@mui/material/Stack'; -import { DataGridPro, GridColDef } from '@mui/x-data-grid-pro'; +import { DataGridPro, DataGridProProps, GridColDef } from '@mui/x-data-grid-pro'; import { randomEmail, randomInt, @@ -14,6 +14,8 @@ import { } from '@mui/x-data-grid-generator'; import { DataGridProps } from '@mui/x-data-grid'; +const DetailPanelDataCache = React.createContext>(new Map()); + async function getProducts(orderId: Customer['id']) { await new Promise((resolve) => { setTimeout(resolve, 1000); @@ -35,11 +37,18 @@ function DetailPanelContent({ row: rowProp }: { row: Customer }) { Awaited> >([]); + const detailPanelDataCache = React.useContext(DetailPanelDataCache); + React.useEffect(() => { let isMounted = true; (async () => { - console.log('fetching detail panel content for row', rowProp.id); - const result = await getProducts(rowProp.id); + if (!detailPanelDataCache.has(rowProp.id)) { + console.log('fetching detail panel content for row', rowProp.id); + const response = await getProducts(rowProp.id); + // Store the data in cache so that when detail panel unmounts due to virtualization, the data is not lost + detailPanelDataCache.set(rowProp.id, response); + } + const result = detailPanelDataCache.get(rowProp.id); if (!isMounted) { return; @@ -52,7 +61,7 @@ function DetailPanelContent({ row: rowProp }: { row: Customer }) { return () => { isMounted = false; }; - }, [rowProp.id]); + }, [rowProp.id, detailPanelDataCache]); return ( 240; export default function LazyLoadingDetailPanel() { + const detailPanelDataCache = React.useRef(new Map()).current; + + const handleDetailPanelExpansionChange = React.useCallback< + NonNullable + >( + (newExpandedRowIds) => { + // Only keep cached data for detail panels that are still expanded + const preservedEntries = newExpandedRowIds.map((id) => [ + id, + detailPanelDataCache.get(id), + ]); + detailPanelDataCache.clear(); + preservedEntries.forEach( + ([id, value]) => value && detailPanelDataCache.set(id, value), + ); + }, + [detailPanelDataCache], + ); + return ( - + + + ); } diff --git a/docs/data/data-grid/master-detail/LazyLoadingDetailPanel.tsx.preview b/docs/data/data-grid/master-detail/LazyLoadingDetailPanel.tsx.preview index ac41382b6e510..dffb0494ca983 100644 --- a/docs/data/data-grid/master-detail/LazyLoadingDetailPanel.tsx.preview +++ b/docs/data/data-grid/master-detail/LazyLoadingDetailPanel.tsx.preview @@ -1,6 +1,9 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/docs/data/data-grid/overlays/LoadingOverlay.tsx b/docs/data/data-grid/overlays/LoadingOverlayCircularProgress.js similarity index 55% rename from docs/data/data-grid/overlays/LoadingOverlay.tsx rename to docs/data/data-grid/overlays/LoadingOverlayCircularProgress.js index 333a904448f63..cb286b6f1e214 100644 --- a/docs/data/data-grid/overlays/LoadingOverlay.tsx +++ b/docs/data/data-grid/overlays/LoadingOverlayCircularProgress.js @@ -3,7 +3,7 @@ import Box from '@mui/material/Box'; import { DataGrid } from '@mui/x-data-grid'; import { useDemoData } from '@mui/x-data-grid-generator'; -export default function LoadingOverlay() { +export default function LoadingOverlayCircularProgress() { const { data } = useDemoData({ dataSet: 'Commodity', rowLength: 6, @@ -12,7 +12,16 @@ export default function LoadingOverlay() { return ( - + ); } diff --git a/docs/data/data-grid/overlays/LoadingOverlay.tsx.preview b/docs/data/data-grid/overlays/LoadingOverlayCircularProgress.preview similarity index 100% rename from docs/data/data-grid/overlays/LoadingOverlay.tsx.preview rename to docs/data/data-grid/overlays/LoadingOverlayCircularProgress.preview diff --git a/docs/data/data-grid/overlays/LoadingOverlay.js b/docs/data/data-grid/overlays/LoadingOverlayCircularProgress.tsx similarity index 55% rename from docs/data/data-grid/overlays/LoadingOverlay.js rename to docs/data/data-grid/overlays/LoadingOverlayCircularProgress.tsx index 333a904448f63..cb286b6f1e214 100644 --- a/docs/data/data-grid/overlays/LoadingOverlay.js +++ b/docs/data/data-grid/overlays/LoadingOverlayCircularProgress.tsx @@ -3,7 +3,7 @@ import Box from '@mui/material/Box'; import { DataGrid } from '@mui/x-data-grid'; import { useDemoData } from '@mui/x-data-grid-generator'; -export default function LoadingOverlay() { +export default function LoadingOverlayCircularProgress() { const { data } = useDemoData({ dataSet: 'Commodity', rowLength: 6, @@ -12,7 +12,16 @@ export default function LoadingOverlay() { return ( - + ); } diff --git a/docs/data/data-grid/overlays/LoadingOverlayCircularProgress.tsx.preview b/docs/data/data-grid/overlays/LoadingOverlayCircularProgress.tsx.preview new file mode 100644 index 0000000000000..98586c3da7360 --- /dev/null +++ b/docs/data/data-grid/overlays/LoadingOverlayCircularProgress.tsx.preview @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/overlays/LoadingOverlaySkeleton.js b/docs/data/data-grid/overlays/LoadingOverlaySkeleton.js index 0e86a253dfcde..a772ce461b73e 100644 --- a/docs/data/data-grid/overlays/LoadingOverlaySkeleton.js +++ b/docs/data/data-grid/overlays/LoadingOverlaySkeleton.js @@ -1,7 +1,7 @@ import * as React from 'react'; import Box from '@mui/material/Box'; import { useDemoData } from '@mui/x-data-grid-generator'; -import { DataGridPro } from '@mui/x-data-grid-pro'; +import { DataGrid } from '@mui/x-data-grid'; export default function LoadingOverlaySkeleton() { const { data } = useDemoData({ @@ -12,7 +12,7 @@ export default function LoadingOverlaySkeleton() { return ( - ); diff --git a/docs/data/data-grid/overlays/LoadingOverlaySkeleton.tsx b/docs/data/data-grid/overlays/LoadingOverlaySkeleton.tsx index 0e86a253dfcde..a772ce461b73e 100644 --- a/docs/data/data-grid/overlays/LoadingOverlaySkeleton.tsx +++ b/docs/data/data-grid/overlays/LoadingOverlaySkeleton.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import Box from '@mui/material/Box'; import { useDemoData } from '@mui/x-data-grid-generator'; -import { DataGridPro } from '@mui/x-data-grid-pro'; +import { DataGrid } from '@mui/x-data-grid'; export default function LoadingOverlaySkeleton() { const { data } = useDemoData({ @@ -12,7 +12,7 @@ export default function LoadingOverlaySkeleton() { return ( - ); diff --git a/docs/data/data-grid/overlays/LoadingOverlaySkeleton.tsx.preview b/docs/data/data-grid/overlays/LoadingOverlaySkeleton.tsx.preview index 9173142c9f99a..83f974bbdc118 100644 --- a/docs/data/data-grid/overlays/LoadingOverlaySkeleton.tsx.preview +++ b/docs/data/data-grid/overlays/LoadingOverlaySkeleton.tsx.preview @@ -1,4 +1,4 @@ - \ No newline at end of file diff --git a/docs/data/data-grid/overlays/overlays.md b/docs/data/data-grid/overlays/overlays.md index 84334d9a2955d..6a192c478af5b 100644 --- a/docs/data/data-grid/overlays/overlays.md +++ b/docs/data/data-grid/overlays/overlays.md @@ -8,14 +8,14 @@ To display a loading overlay and signify that the Data Grid is in a loading stat The Data Grid supports 3 loading overlay variants out of the box: -- `circular-progress` (default): a circular loading spinner. -- `linear-progress`: an indeterminate linear progress bar. - `skeleton`: an animated placeholder of the Data Grid. +- `linear-progress`: an indeterminate linear progress bar. +- `circular-progress`: a circular loading spinner. The type of loading overlay to display can be set via `slotProps.loadingOverlay` for the following two props: -- `variant`: when `loading` and there are rows in the table. -- `noRowsVariant`: when `loading` and there are not any rows in the table. +- `variant` (default: `linear-progress`): when `loading` and there are rows in the table. +- `noRowsVariant` (default: `skeleton`): when `loading` and there are not any rows in the table. ```tsx ``` -### Circular progress +### Skeleton -A circular loading spinner, the default loading overlay. +An animated placeholder of the Data Grid. -{{"demo": "LoadingOverlay.js", "bg": "inline"}} +{{"demo": "LoadingOverlaySkeleton.js", "bg": "inline"}} ### Linear progress @@ -42,11 +42,11 @@ An indeterminate linear progress bar. {{"demo": "LoadingOverlayLinearProgress.js", "bg": "inline"}} -### Skeleton +### Circular progress -An animated placeholder of the Data Grid. +A circular loading spinner. -{{"demo": "LoadingOverlaySkeleton.js", "bg": "inline"}} +{{"demo": "LoadingOverlayCircularProgress.js", "bg": "inline"}} ### Custom component diff --git a/docs/data/data-grid/overview/DataGridProDemo.js b/docs/data/data-grid/overview/DataGridProDemo.js index 10cc6a348fe17..c112180b37b79 100644 --- a/docs/data/data-grid/overview/DataGridProDemo.js +++ b/docs/data/data-grid/overview/DataGridProDemo.js @@ -4,7 +4,7 @@ import { DataGridPro } from '@mui/x-data-grid-pro'; import { useDemoData } from '@mui/x-data-grid-generator'; export default function DataGridProDemo() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100000, editable: true, @@ -14,7 +14,7 @@ export default function DataGridProDemo() {
- +
); diff --git a/docs/data/data-grid/pagination/PageSizeAuto.tsx b/docs/data/data-grid/pagination/PageSizeAuto.tsx index bb7ccf6c9b9c9..ec8eb62936fec 100644 --- a/docs/data/data-grid/pagination/PageSizeAuto.tsx +++ b/docs/data/data-grid/pagination/PageSizeAuto.tsx @@ -8,7 +8,7 @@ import InputLabel from '@mui/material/InputLabel'; import Select from '@mui/material/Select'; export default function PageSizeAuto() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, maxColumns: 6, @@ -35,7 +35,7 @@ export default function PageSizeAuto() {
- +
); diff --git a/docs/data/data-grid/pagination/PageSizeCustomOptions.js b/docs/data/data-grid/pagination/PageSizeCustomOptions.js index 2cdb2ddfa58bf..bae3ea5a2185e 100644 --- a/docs/data/data-grid/pagination/PageSizeCustomOptions.js +++ b/docs/data/data-grid/pagination/PageSizeCustomOptions.js @@ -3,7 +3,7 @@ import { DataGrid } from '@mui/x-data-grid'; import { useDemoData } from '@mui/x-data-grid-generator'; export default function PageSizeCustomOptions() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, maxColumns: 6, @@ -13,6 +13,7 @@ export default function PageSizeCustomOptions() {
- +
); } diff --git a/docs/data/data-grid/pagination/PaginationCommunityNoSnap.tsx b/docs/data/data-grid/pagination/PaginationCommunityNoSnap.tsx index 2cfcdc798467c..32eab8bbdccc3 100644 --- a/docs/data/data-grid/pagination/PaginationCommunityNoSnap.tsx +++ b/docs/data/data-grid/pagination/PaginationCommunityNoSnap.tsx @@ -3,7 +3,7 @@ import { DataGrid } from '@mui/x-data-grid'; import { useDemoData } from '@mui/x-data-grid-generator'; export default function PaginationCommunityNoSnap() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 500, maxColumns: 6, @@ -11,7 +11,7 @@ export default function PaginationCommunityNoSnap() { return (
- +
); } diff --git a/docs/data/data-grid/pagination/PaginationCommunityNoSnap.tsx.preview b/docs/data/data-grid/pagination/PaginationCommunityNoSnap.tsx.preview index 4eba0f23a52f2..c0970b7369aa3 100644 --- a/docs/data/data-grid/pagination/PaginationCommunityNoSnap.tsx.preview +++ b/docs/data/data-grid/pagination/PaginationCommunityNoSnap.tsx.preview @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/data-grid/pagination/PaginationModelControlled.js b/docs/data/data-grid/pagination/PaginationModelControlled.js index 8249cdf350eba..f9d460df37f5f 100644 --- a/docs/data/data-grid/pagination/PaginationModelControlled.js +++ b/docs/data/data-grid/pagination/PaginationModelControlled.js @@ -3,7 +3,7 @@ import { DataGrid } from '@mui/x-data-grid'; import { useDemoData } from '@mui/x-data-grid-generator'; export default function PaginationModelControlled() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 500, maxColumns: 6, @@ -19,6 +19,7 @@ export default function PaginationModelControlled() { paginationModel={paginationModel} onPaginationModelChange={setPaginationModel} {...data} + loading={loading} />
); diff --git a/docs/data/data-grid/pagination/PaginationModelControlled.tsx b/docs/data/data-grid/pagination/PaginationModelControlled.tsx index 8249cdf350eba..f9d460df37f5f 100644 --- a/docs/data/data-grid/pagination/PaginationModelControlled.tsx +++ b/docs/data/data-grid/pagination/PaginationModelControlled.tsx @@ -3,7 +3,7 @@ import { DataGrid } from '@mui/x-data-grid'; import { useDemoData } from '@mui/x-data-grid-generator'; export default function PaginationModelControlled() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 500, maxColumns: 6, @@ -19,6 +19,7 @@ export default function PaginationModelControlled() { paginationModel={paginationModel} onPaginationModelChange={setPaginationModel} {...data} + loading={loading} />
); diff --git a/docs/data/data-grid/pagination/PaginationModelControlled.tsx.preview b/docs/data/data-grid/pagination/PaginationModelControlled.tsx.preview index c437fac5e31f7..b6479fe9daf61 100644 --- a/docs/data/data-grid/pagination/PaginationModelControlled.tsx.preview +++ b/docs/data/data-grid/pagination/PaginationModelControlled.tsx.preview @@ -2,4 +2,5 @@ paginationModel={paginationModel} onPaginationModelChange={setPaginationModel} {...data} + loading={loading} /> \ No newline at end of file diff --git a/docs/data/data-grid/pagination/PaginationModelInitialState.js b/docs/data/data-grid/pagination/PaginationModelInitialState.js index 10dd9a23849aa..a801f512234c2 100644 --- a/docs/data/data-grid/pagination/PaginationModelInitialState.js +++ b/docs/data/data-grid/pagination/PaginationModelInitialState.js @@ -3,7 +3,7 @@ import { DataGrid } from '@mui/x-data-grid'; import { useDemoData } from '@mui/x-data-grid-generator'; export default function PaginationModelInitialState() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 500, maxColumns: 6, @@ -13,6 +13,7 @@ export default function PaginationModelInitialState() {
{ if (!estimated) { - return `${from}–${to} od ${count !== -1 ? count : `više nego ${to}`}`, + return `${from}–${to} od ${count !== -1 ? count : `više nego ${to}`}`; } - return `${from}–${to} od ${count !== -1 ? count : `više nego ${estimated > to ? estimated : to}`}`; -} + const estimateLabel = + estimated && estimated > to ? `oko ${estimated}` : `više nego ${to}`; + return `${from}–${to} od ${count !== -1 ? count : estimateLabel}`; +}; { labelDisplayedRows, }, }} -/> +/>; ``` For more information, see the [Translation keys](/x/react-data-grid/localization/#translation-keys) section of the localization documentation. diff --git a/docs/data/data-grid/performance/GridVisualization.js b/docs/data/data-grid/performance/GridVisualization.js index 97862557cf5d3..5c69b087fef1d 100644 --- a/docs/data/data-grid/performance/GridVisualization.js +++ b/docs/data/data-grid/performance/GridVisualization.js @@ -35,7 +35,7 @@ const slots = { }; export default function GridVisualization() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, editable: true, @@ -62,6 +62,7 @@ export default function GridVisualization() { > + + + + + + ); +} + +const VISIBLE_FIELDS = [ + 'name', + 'email', + 'position', + 'company', + 'salary', + 'phone', + 'country', + 'dateCreated', + 'isAdmin', +]; + +export default function PromptWithDataSampling() { + const { data } = useDemoData({ + dataSet: 'Employee', + visibleFields: VISIBLE_FIELDS, + rowLength: 10000, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/prompt/PromptWithDataSampling.tsx b/docs/data/data-grid/prompt/PromptWithDataSampling.tsx new file mode 100644 index 0000000000000..b7cb1e9214d4d --- /dev/null +++ b/docs/data/data-grid/prompt/PromptWithDataSampling.tsx @@ -0,0 +1,51 @@ +import * as React from 'react'; +import { + DataGridPremium, + Unstable_GridToolbarPromptControl as GridToolbarPromptControl, + GridToolbar, +} from '@mui/x-data-grid-premium'; +import { mockPromptResolver, useDemoData } from '@mui/x-data-grid-generator'; +import Stack from '@mui/material/Stack'; +import Box from '@mui/material/Box'; + +function ToolbarWithPromptInput() { + return ( + + + + + + + ); +} + +const VISIBLE_FIELDS = [ + 'name', + 'email', + 'position', + 'company', + 'salary', + 'phone', + 'country', + 'dateCreated', + 'isAdmin', +]; + +export default function PromptWithDataSampling() { + const { data } = useDemoData({ + dataSet: 'Employee', + visibleFields: VISIBLE_FIELDS, + rowLength: 10000, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/prompt/PromptWithDataSampling.tsx.preview b/docs/data/data-grid/prompt/PromptWithDataSampling.tsx.preview new file mode 100644 index 0000000000000..c140559bcf94d --- /dev/null +++ b/docs/data/data-grid/prompt/PromptWithDataSampling.tsx.preview @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/prompt/PromptWithDataSource.js b/docs/data/data-grid/prompt/PromptWithDataSource.js new file mode 100644 index 0000000000000..964711a513855 --- /dev/null +++ b/docs/data/data-grid/prompt/PromptWithDataSource.js @@ -0,0 +1,85 @@ +import * as React from 'react'; +import { + DataGridPremium, + Unstable_GridToolbarPromptControl as GridToolbarPromptControl, + GridToolbar, +} from '@mui/x-data-grid-premium'; +import { mockPromptResolver, useMockServer } from '@mui/x-data-grid-generator'; +import Stack from '@mui/material/Stack'; +import Box from '@mui/material/Box'; + +const VISIBLE_FIELDS = [ + 'name', + 'email', + 'position', + 'company', + 'salary', + 'phone', + 'country', + 'dateCreated', + 'isAdmin', +]; + +function ToolbarWithPromptInput() { + return ( + + + + + + + ); +} + +export default function PromptWithDataSource() { + const { columns, initialState, fetchRows } = useMockServer( + { dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, maxColumns: 16 }, + { useCursorPagination: false }, + ); + + const dataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + paginationModel: JSON.stringify(params.paginationModel), + filterModel: JSON.stringify(params.filterModel), + sortModel: JSON.stringify(params.sortModel), + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + }), + [fetchRows], + ); + + const initialStateWithPagination = React.useMemo( + () => ({ + ...initialState, + pagination: { + paginationModel: { pageSize: 10, page: 0 }, + rowCount: 0, + }, + }), + [initialState], + ); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/prompt/PromptWithDataSource.tsx b/docs/data/data-grid/prompt/PromptWithDataSource.tsx new file mode 100644 index 0000000000000..0fb0132a59697 --- /dev/null +++ b/docs/data/data-grid/prompt/PromptWithDataSource.tsx @@ -0,0 +1,86 @@ +import * as React from 'react'; +import { + DataGridPremium, + Unstable_GridToolbarPromptControl as GridToolbarPromptControl, + GridToolbar, + GridDataSource, +} from '@mui/x-data-grid-premium'; +import { mockPromptResolver, useMockServer } from '@mui/x-data-grid-generator'; +import Stack from '@mui/material/Stack'; +import Box from '@mui/material/Box'; + +const VISIBLE_FIELDS = [ + 'name', + 'email', + 'position', + 'company', + 'salary', + 'phone', + 'country', + 'dateCreated', + 'isAdmin', +]; + +function ToolbarWithPromptInput() { + return ( + + + + + + + ); +} + +export default function PromptWithDataSource() { + const { columns, initialState, fetchRows } = useMockServer( + { dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, maxColumns: 16 }, + { useCursorPagination: false }, + ); + + const dataSource: GridDataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + paginationModel: JSON.stringify(params.paginationModel), + filterModel: JSON.stringify(params.filterModel), + sortModel: JSON.stringify(params.sortModel), + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + }), + [fetchRows], + ); + + const initialStateWithPagination = React.useMemo( + () => ({ + ...initialState, + pagination: { + paginationModel: { pageSize: 10, page: 0 }, + rowCount: 0, + }, + }), + [initialState], + ); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/prompt/PromptWithDataSource.tsx.preview b/docs/data/data-grid/prompt/PromptWithDataSource.tsx.preview new file mode 100644 index 0000000000000..1c7559543c28a --- /dev/null +++ b/docs/data/data-grid/prompt/PromptWithDataSource.tsx.preview @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/prompt/PromptWithExamples.js b/docs/data/data-grid/prompt/PromptWithExamples.js new file mode 100644 index 0000000000000..abdd774d0d485 --- /dev/null +++ b/docs/data/data-grid/prompt/PromptWithExamples.js @@ -0,0 +1,98 @@ +import * as React from 'react'; +import { + DataGridPremium, + Unstable_GridToolbarPromptControl as GridToolbarPromptControl, + GridToolbar, +} from '@mui/x-data-grid-premium'; +import { + mockPromptResolver, + randomBoolean, + randomCompanyName, + randomCountry, + randomCreatedDate, + randomEmail, + randomInt, + randomJobTitle, + randomPhoneNumber, + randomTraderName, + useDemoData, +} from '@mui/x-data-grid-generator'; +import Stack from '@mui/material/Stack'; +import Box from '@mui/material/Box'; + +function ToolbarWithPromptInput() { + return ( + + + + + + + ); +} + +const VISIBLE_FIELDS = [ + 'name', + 'email', + 'position', + 'company', + 'salary', + 'phone', + 'country', + 'dateCreated', + 'isAdmin', +]; + +function createExamples(column) { + switch (column) { + case 'name': + return Array.from({ length: 5 }, () => randomTraderName()); + case 'email': + return Array.from({ length: 5 }, () => randomEmail()); + case 'position': + return Array.from({ length: 5 }, () => randomJobTitle()); + case 'company': + return Array.from({ length: 5 }, () => randomCompanyName()); + case 'salary': + return Array.from({ length: 5 }, () => randomInt(30000, 80000)); + case 'phone': + return Array.from({ length: 5 }, () => randomPhoneNumber()); + case 'country': + return Array.from({ length: 5 }, () => randomCountry()); + case 'dateCreated': + return Array.from({ length: 5 }, () => randomCreatedDate()); + case 'isAdmin': + return Array.from({ length: 5 }, () => randomBoolean()); + default: + return []; + } +} + +export default function PromptWithExamples() { + const { data } = useDemoData({ + dataSet: 'Employee', + visibleFields: VISIBLE_FIELDS, + rowLength: 10000, + }); + + const columns = React.useMemo( + () => + data.columns.map((column) => ({ + ...column, + unstable_examples: createExamples(column.field), + })), + [data.columns], + ); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/prompt/PromptWithExamples.tsx b/docs/data/data-grid/prompt/PromptWithExamples.tsx new file mode 100644 index 0000000000000..dacd4e75a6019 --- /dev/null +++ b/docs/data/data-grid/prompt/PromptWithExamples.tsx @@ -0,0 +1,98 @@ +import * as React from 'react'; +import { + DataGridPremium, + Unstable_GridToolbarPromptControl as GridToolbarPromptControl, + GridToolbar, +} from '@mui/x-data-grid-premium'; +import { + mockPromptResolver, + randomBoolean, + randomCompanyName, + randomCountry, + randomCreatedDate, + randomEmail, + randomInt, + randomJobTitle, + randomPhoneNumber, + randomTraderName, + useDemoData, +} from '@mui/x-data-grid-generator'; +import Stack from '@mui/material/Stack'; +import Box from '@mui/material/Box'; + +function ToolbarWithPromptInput() { + return ( + + + + + + + ); +} + +const VISIBLE_FIELDS = [ + 'name', + 'email', + 'position', + 'company', + 'salary', + 'phone', + 'country', + 'dateCreated', + 'isAdmin', +]; + +function createExamples(column: string) { + switch (column) { + case 'name': + return Array.from({ length: 5 }, () => randomTraderName()); + case 'email': + return Array.from({ length: 5 }, () => randomEmail()); + case 'position': + return Array.from({ length: 5 }, () => randomJobTitle()); + case 'company': + return Array.from({ length: 5 }, () => randomCompanyName()); + case 'salary': + return Array.from({ length: 5 }, () => randomInt(30000, 80000)); + case 'phone': + return Array.from({ length: 5 }, () => randomPhoneNumber()); + case 'country': + return Array.from({ length: 5 }, () => randomCountry()); + case 'dateCreated': + return Array.from({ length: 5 }, () => randomCreatedDate()); + case 'isAdmin': + return Array.from({ length: 5 }, () => randomBoolean()); + default: + return []; + } +} + +export default function PromptWithExamples() { + const { data } = useDemoData({ + dataSet: 'Employee', + visibleFields: VISIBLE_FIELDS, + rowLength: 10000, + }); + + const columns = React.useMemo( + () => + data.columns.map((column) => ({ + ...column, + unstable_examples: createExamples(column.field), + })), + [data.columns], + ); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/prompt/PromptWithExamples.tsx.preview b/docs/data/data-grid/prompt/PromptWithExamples.tsx.preview new file mode 100644 index 0000000000000..dc637e4603da1 --- /dev/null +++ b/docs/data/data-grid/prompt/PromptWithExamples.tsx.preview @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/prompt/prompt.md b/docs/data/data-grid/prompt/prompt.md new file mode 100644 index 0000000000000..6148eacf15d4a --- /dev/null +++ b/docs/data/data-grid/prompt/prompt.md @@ -0,0 +1,92 @@ +--- +title: Data Grid - Prompt +--- + +# Data Grid - Prompt [](/x/introduction/licensing/#premium-plan 'Premium plan') + +

Translate natural language into a set of grid state updates and apply them to the Data Grid component.

+ +:::warning +To use this feature, you need to have a prompt processing backend. MUI offers this service as a part of a premium package add-on. Check [licensing page](/x/introduction/licensing/) for more information. +::: + +The prompt feature allows users to interact with the Data Grid component using natural language. The user can type commands like "sort by name" or "show amounts larger than 1000" in the prompt input field, and the Data Grid will update accordingly. + +To increase the accuracy of the prompt processing, the user should provide example values for the available columns. +This can be done in following ways. + +:::info +Prompt demos use a utility function `mockPromptResolver` to simulate the api that resolves the user prompts. +In a real-world scenario, you should replace this with your own api. + +`mockPromptResolver` can handle a predefined set of prompts: + +- `sort by name` +- `sort by company name and employee name` +- `show people from the EU` +- `order companies by amount of people` + + ::: + +## Custom examples + +The user can provide custom examples for the prompt processing through the `unstable_examples` prop of the column in the `columns` array. +The `unstable_examples` prop should be an array of values that are possible values for that column. + +{{"demo": "PromptWithExamples.js", "bg": "inline"}} + +## Use row data for examples + +If you pass `allowDataSampling` flag to the `Unstable_GridToolbarPromptControl`, it uses the row data to generate examples for the prompt processing. +This is useful if you are dealing with non-sensitive data and want to skip creating custom examples for each column. + +{{"demo": "PromptWithDataSampling.js", "bg": "inline"}} + +## Using Server-side data + +An example of combining prompt toolbar with the [Server-side data](/x/react-data-grid/server-side-data/) + +{{"demo": "PromptWithDataSource.js", "bg": "inline"}} + +## Integration with MUI's API + +To integrate with MUI's API, an API key would be needed. +As the key cannot be exposed to the client, a small proxy server could be used that would receive prompt processing requests, add the `x-api-key` header, and pass the request further to the MUI's API. + +This is an example of a Fastify proxy for the prompt requests + +```ts +fastify.register(proxy, { + upstream: process.env.MUI_DATAGRID_API_URL, + prefix: '/api/datagrid/prompt', + rewritePrefix: '/api/v1/datagrid/prompt', + replyOptions: { + rewriteRequestHeaders: (_, headers) => ({ + ...headers, + 'x-api-key': process.env.MUI_DATAGRID_API_KEY, + }), + }, +}); +``` + +To make the integration easier, use the `unstable_gridDefaultPromptResolver` from `@mui/x-data-grid-premium` package. +It will add necessary headers and stringify the body in the right format for you. + +The example below shows a code that adds an additional prompt context for better results and uses `unstable_gridDefaultPromptResolver` to avoid dealing with the request details. + +```ts +const PROMPT_RESOLVER_PROXY_BASE_URL = + process.env.NODE_ENV === 'development' + ? 'http://localhost:3000' + : 'https://api.my-proxy.com'; + +function processPrompt(context: string, query: string) { + const extendedContext = `The rows represent: List of employees with their company, position and start date\n\n${context}`; + + return unstable_gridDefaultPromptResolver( + `${PROMPT_RESOLVER_PROXY_BASE_URL}/api/datagrid/prompt`, + extendedContext, + query, + ); +} +``` diff --git a/docs/data/data-grid/row-grouping/RowGroupingAriaV8.js b/docs/data/data-grid/row-grouping/RowGroupingAriaV8.js deleted file mode 100644 index 6689443db0822..0000000000000 --- a/docs/data/data-grid/row-grouping/RowGroupingAriaV8.js +++ /dev/null @@ -1,32 +0,0 @@ -import * as React from 'react'; -import { - DataGridPremium, - useGridApiRef, - useKeepGroupedColumnsHidden, -} from '@mui/x-data-grid-premium'; -import { useMovieData } from '@mui/x-data-grid-generator'; - -export default function RowGroupingAriaV8() { - const data = useMovieData(); - const apiRef = useGridApiRef(); - - const initialState = useKeepGroupedColumnsHidden({ - apiRef, - initialState: { - rowGrouping: { - model: ['company'], - }, - }, - }); - - return ( -
- -
- ); -} diff --git a/docs/data/data-grid/row-grouping/RowGroupingAriaV8.tsx b/docs/data/data-grid/row-grouping/RowGroupingAriaV8.tsx deleted file mode 100644 index 6689443db0822..0000000000000 --- a/docs/data/data-grid/row-grouping/RowGroupingAriaV8.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import * as React from 'react'; -import { - DataGridPremium, - useGridApiRef, - useKeepGroupedColumnsHidden, -} from '@mui/x-data-grid-premium'; -import { useMovieData } from '@mui/x-data-grid-generator'; - -export default function RowGroupingAriaV8() { - const data = useMovieData(); - const apiRef = useGridApiRef(); - - const initialState = useKeepGroupedColumnsHidden({ - apiRef, - initialState: { - rowGrouping: { - model: ['company'], - }, - }, - }); - - return ( -
- -
- ); -} diff --git a/docs/data/data-grid/row-grouping/RowGroupingAriaV8.tsx.preview b/docs/data/data-grid/row-grouping/RowGroupingAriaV8.tsx.preview deleted file mode 100644 index 303e3b3ef2367..0000000000000 --- a/docs/data/data-grid/row-grouping/RowGroupingAriaV8.tsx.preview +++ /dev/null @@ -1,6 +0,0 @@ - \ No newline at end of file diff --git a/docs/data/data-grid/row-grouping/RowGroupingFullExample.js b/docs/data/data-grid/row-grouping/RowGroupingFullExample.js index 52040b1639af1..4deda985cbd8b 100644 --- a/docs/data/data-grid/row-grouping/RowGroupingFullExample.js +++ b/docs/data/data-grid/row-grouping/RowGroupingFullExample.js @@ -40,7 +40,6 @@ export default function RowGroupingFullExample() { groupingColDef={{ leafField: 'traderEmail', }} - experimentalFeatures={{ ariaV8: true }} />
); diff --git a/docs/data/data-grid/row-grouping/RowGroupingFullExample.tsx b/docs/data/data-grid/row-grouping/RowGroupingFullExample.tsx index 52040b1639af1..4deda985cbd8b 100644 --- a/docs/data/data-grid/row-grouping/RowGroupingFullExample.tsx +++ b/docs/data/data-grid/row-grouping/RowGroupingFullExample.tsx @@ -40,7 +40,6 @@ export default function RowGroupingFullExample() { groupingColDef={{ leafField: 'traderEmail', }} - experimentalFeatures={{ ariaV8: true }} />
); diff --git a/docs/data/data-grid/row-grouping/RowGroupingFullExample.tsx.preview b/docs/data/data-grid/row-grouping/RowGroupingFullExample.tsx.preview index 35a7dd3ccbcd0..b20dbc70dc3ad 100644 --- a/docs/data/data-grid/row-grouping/RowGroupingFullExample.tsx.preview +++ b/docs/data/data-grid/row-grouping/RowGroupingFullExample.tsx.preview @@ -7,5 +7,4 @@ groupingColDef={{ leafField: 'traderEmail', }} - experimentalFeatures={{ ariaV8: true }} /> \ No newline at end of file diff --git a/docs/data/data-grid/row-grouping/RowGroupingPropagateSelection.js b/docs/data/data-grid/row-grouping/RowGroupingPropagateSelection.js index 5baa5839b6f86..89ab855dc45b6 100644 --- a/docs/data/data-grid/row-grouping/RowGroupingPropagateSelection.js +++ b/docs/data/data-grid/row-grouping/RowGroupingPropagateSelection.js @@ -13,8 +13,8 @@ export default function RowGroupingPropagateSelection() { const data = useMovieData(); const apiRef = useGridApiRef(); const [rowSelectionPropagation, setRowSelectionPropagation] = React.useState({ - parents: true, - descendants: true, + parents: false, + descendants: false, }); const initialState = useKeepGroupedColumnsHidden({ diff --git a/docs/data/data-grid/row-grouping/RowGroupingPropagateSelection.tsx b/docs/data/data-grid/row-grouping/RowGroupingPropagateSelection.tsx index 9229e086666ac..03570d1b5a7fe 100644 --- a/docs/data/data-grid/row-grouping/RowGroupingPropagateSelection.tsx +++ b/docs/data/data-grid/row-grouping/RowGroupingPropagateSelection.tsx @@ -15,8 +15,8 @@ export default function RowGroupingPropagateSelection() { const apiRef = useGridApiRef(); const [rowSelectionPropagation, setRowSelectionPropagation] = React.useState({ - parents: true, - descendants: true, + parents: false, + descendants: false, }); const initialState = useKeepGroupedColumnsHidden({ diff --git a/docs/data/data-grid/row-grouping/row-grouping.md b/docs/data/data-grid/row-grouping/row-grouping.md index 13f56a2ebac88..846c08b234395 100644 --- a/docs/data/data-grid/row-grouping/row-grouping.md +++ b/docs/data/data-grid/row-grouping/row-grouping.md @@ -311,15 +311,15 @@ If you are dynamically switching the `leafField` or `mainGroupingCriteria`, the ## Automatic parents and children selection -By default, selecting a parent row does not select its children. -You can override this behavior by using the `rowSelectionPropagation` prop. +By default, selecting a parent row selects all its descendants automatically. +You can customize this behavior by using the `rowSelectionPropagation` prop. Here's how it's structured: ```ts type GridRowSelectionPropagation = { - descendants?: boolean; // default: false - parents?: boolean; // default: false + descendants?: boolean; // default: true + parents?: boolean; // default: true }; ``` @@ -396,22 +396,6 @@ Don't hesitate to leave a comment on the same issue to influence what gets built With this panel, your users will be able to control which columns are used for grouping just by dragging them inside the panel. -## Accessibility changes in v8 - -The Data Grid v8 with row grouping feature will improve the accessibility and will be more aligned with the WAI-ARIA authoring practices. - -You can start using the new accessibility features by enabling `ariaV8` experimental feature flag: - -```tsx - -``` - -:::warning -The value of `ariaV8` should be constant and not change during the lifetime of the Data Grid. -::: - -{{"demo": "RowGroupingAriaV8.js", "bg": "inline", "defaultCodeOpen": false}} - ## Full example {{"demo": "RowGroupingFullExample.js", "bg": "inline", "defaultCodeOpen": false}} diff --git a/docs/data/data-grid/row-height/DenseHeightGrid.js b/docs/data/data-grid/row-height/DenseHeightGrid.js index f2ffa815b28a0..297217a740068 100644 --- a/docs/data/data-grid/row-height/DenseHeightGrid.js +++ b/docs/data/data-grid/row-height/DenseHeightGrid.js @@ -3,7 +3,7 @@ import { DataGrid } from '@mui/x-data-grid'; import { useDemoData } from '@mui/x-data-grid-generator'; export default function DenseHeightGrid() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, maxColumns: 6, @@ -11,7 +11,7 @@ export default function DenseHeightGrid() { return (
- +
); } diff --git a/docs/data/data-grid/row-height/DenseHeightGrid.tsx b/docs/data/data-grid/row-height/DenseHeightGrid.tsx index f2ffa815b28a0..297217a740068 100644 --- a/docs/data/data-grid/row-height/DenseHeightGrid.tsx +++ b/docs/data/data-grid/row-height/DenseHeightGrid.tsx @@ -3,7 +3,7 @@ import { DataGrid } from '@mui/x-data-grid'; import { useDemoData } from '@mui/x-data-grid-generator'; export default function DenseHeightGrid() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, maxColumns: 6, @@ -11,7 +11,7 @@ export default function DenseHeightGrid() { return (
- +
); } diff --git a/docs/data/data-grid/row-height/DenseHeightGrid.tsx.preview b/docs/data/data-grid/row-height/DenseHeightGrid.tsx.preview index bca6f05b95702..294ca01c4b899 100644 --- a/docs/data/data-grid/row-height/DenseHeightGrid.tsx.preview +++ b/docs/data/data-grid/row-height/DenseHeightGrid.tsx.preview @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/data-grid/row-height/RowMarginGrid.js b/docs/data/data-grid/row-height/RowMarginGrid.js index 829650739f586..ce5739b131dac 100644 --- a/docs/data/data-grid/row-height/RowMarginGrid.js +++ b/docs/data/data-grid/row-height/RowMarginGrid.js @@ -4,7 +4,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; import { grey } from '@mui/material/colors'; export default function RowMarginGrid() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 200, maxColumns: 6, @@ -21,6 +21,7 @@ export default function RowMarginGrid() {
{ + const rows = []; + + for (let i = 0; i < rowLength; i += 1) { + const row = { + id: i, + }; + + for (let j = 1; j <= columnLength; j += 1) { + row[`price${j}M`] = `${i.toString()}, ${j} `; + } + + rows.push(row); + } + + const columns = []; + + for (let j = 1; j <= columnLength; j += 1) { + columns.push({ field: `price${j}M`, headerName: `${j}M`, width: 55 }); + } + + setData({ + rows, + columns, + }); + }, [rowLength, columnLength]); + + return data; +} + +export default function VirtualizeColumnsWithAutoRowHeight() { + const data = useData(100, 100); + + return ( +
+ 'auto'} + virtualizeColumnsWithAutoRowHeight + /> +
+ ); +} diff --git a/docs/data/data-grid/row-height/VirtualizeColumnsWithAutoRowHeight.tsx b/docs/data/data-grid/row-height/VirtualizeColumnsWithAutoRowHeight.tsx new file mode 100644 index 0000000000000..1a76b22ee5c97 --- /dev/null +++ b/docs/data/data-grid/row-height/VirtualizeColumnsWithAutoRowHeight.tsx @@ -0,0 +1,59 @@ +import * as React from 'react'; +import { DataGrid, GridColDef, GridRowId } from '@mui/x-data-grid'; + +export interface DataRowModel { + id: GridRowId; + [price: string]: number | string; +} + +export interface GridData { + columns: GridColDef[]; + rows: DataRowModel[]; +} + +function useData(rowLength: number, columnLength: number) { + const [data, setData] = React.useState({ columns: [], rows: [] }); + + React.useEffect(() => { + const rows: DataRowModel[] = []; + + for (let i = 0; i < rowLength; i += 1) { + const row: DataRowModel = { + id: i, + }; + + for (let j = 1; j <= columnLength; j += 1) { + row[`price${j}M`] = `${i.toString()}, ${j} `; + } + + rows.push(row); + } + + const columns: GridColDef[] = []; + + for (let j = 1; j <= columnLength; j += 1) { + columns.push({ field: `price${j}M`, headerName: `${j}M`, width: 55 }); + } + + setData({ + rows, + columns, + }); + }, [rowLength, columnLength]); + + return data; +} + +export default function VirtualizeColumnsWithAutoRowHeight() { + const data = useData(100, 100); + + return ( +
+ 'auto'} + virtualizeColumnsWithAutoRowHeight + /> +
+ ); +} diff --git a/docs/data/data-grid/row-height/VirtualizeColumnsWithAutoRowHeight.tsx.preview b/docs/data/data-grid/row-height/VirtualizeColumnsWithAutoRowHeight.tsx.preview new file mode 100644 index 0000000000000..1f3efbd9e944e --- /dev/null +++ b/docs/data/data-grid/row-height/VirtualizeColumnsWithAutoRowHeight.tsx.preview @@ -0,0 +1,5 @@ + 'auto'} + virtualizeColumnsWithAutoRowHeight +/> \ No newline at end of file diff --git a/docs/data/data-grid/row-height/row-height.md b/docs/data/data-grid/row-height/row-height.md index 0d5790977d894..fa5a34a72a4c5 100644 --- a/docs/data/data-grid/row-height/row-height.md +++ b/docs/data/data-grid/row-height/row-height.md @@ -54,7 +54,6 @@ This side effect happens because a row height estimation is used while a row is You can configure the estimated value used by passing a function to the `getEstimatedRowHeight` prop. If not provided, the default row height of `52px` is used as estimation. It's recommended to pass this prop if the content deviates too much from the default value. -Note that, due to the implementation adopted, the virtualization of the columns is also disabled to force all columns to be rendered at the same time. ```tsx 'auto'} getEstimatedRowHeight={() => 200} /> @@ -78,6 +77,17 @@ Add padding to the cells to increase the space between the content and the cell ::: +### Column virtualization + +By default, the virtualization of the columns is disabled to force all columns to be rendered at the same time and calculate the row height correctly. +However, this can lead to poor performance when rendering a lot of columns. + +If you need column virtualization, you can set the `virtualizeColumnsWithAutoRowHeight` prop to `true`. +With this approach, the Data Grid measures the row height based on the visible columns. +However, the row height might change during horizontal scrolling. + +{{"demo": "VirtualizeColumnsWithAutoRowHeight.js", "bg": "inline" }} + ## Row density Give your users the option to change the default row density to match their preferences—compact, standard, or comfortable. diff --git a/docs/data/data-grid/row-pinning/RowPinningWithPagination.js b/docs/data/data-grid/row-pinning/RowPinningWithPagination.js index bb2874c03d0be..5231174017e21 100644 --- a/docs/data/data-grid/row-pinning/RowPinningWithPagination.js +++ b/docs/data/data-grid/row-pinning/RowPinningWithPagination.js @@ -3,7 +3,7 @@ import { DataGridPro } from '@mui/x-data-grid-pro'; import { useDemoData } from '@mui/x-data-grid-generator'; export default function RowPinningWithPagination() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, maxColumns: 20, @@ -28,6 +28,7 @@ export default function RowPinningWithPagination() {
- -
- ); -} diff --git a/docs/data/data-grid/row-selection/CheckboxSelectionIndeterminateGrid.tsx b/docs/data/data-grid/row-selection/CheckboxSelectionIndeterminateGrid.tsx deleted file mode 100644 index 88493e2bf3a76..0000000000000 --- a/docs/data/data-grid/row-selection/CheckboxSelectionIndeterminateGrid.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as React from 'react'; -import { DataGrid } from '@mui/x-data-grid'; -import { useDemoData } from '@mui/x-data-grid-generator'; - -export default function CheckboxSelectionIndeterminateGrid() { - const { data } = useDemoData({ - dataSet: 'Commodity', - rowLength: 10, - maxColumns: 5, - }); - - return ( -
- -
- ); -} diff --git a/docs/data/data-grid/row-selection/CheckboxSelectionIndeterminateGrid.tsx.preview b/docs/data/data-grid/row-selection/CheckboxSelectionIndeterminateGrid.tsx.preview deleted file mode 100644 index 9091ca3b75cce..0000000000000 --- a/docs/data/data-grid/row-selection/CheckboxSelectionIndeterminateGrid.tsx.preview +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/data/data-grid/row-selection/CheckboxSelectionVisibleOnlyGrid.js b/docs/data/data-grid/row-selection/CheckboxSelectionVisibleOnlyGrid.js index 4b4783735e5c3..7652691d77d76 100644 --- a/docs/data/data-grid/row-selection/CheckboxSelectionVisibleOnlyGrid.js +++ b/docs/data/data-grid/row-selection/CheckboxSelectionVisibleOnlyGrid.js @@ -9,7 +9,7 @@ export default function CheckboxSelectionVisibleOnlyGrid() { const [checkboxSelectionVisibleOnly, setCheckboxSelectionVisibleOnly] = React.useState(false); - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 300, maxColumns: 5, @@ -33,6 +33,7 @@ export default function CheckboxSelectionVisibleOnlyGrid() {
params.row.quantity > 50000} checkboxSelection /> diff --git a/docs/data/data-grid/row-selection/DisableRowSelection.tsx b/docs/data/data-grid/row-selection/DisableRowSelection.tsx index 2282362136813..0f64cb7ab42a5 100644 --- a/docs/data/data-grid/row-selection/DisableRowSelection.tsx +++ b/docs/data/data-grid/row-selection/DisableRowSelection.tsx @@ -3,7 +3,7 @@ import { DataGrid, GridRowParams } from '@mui/x-data-grid'; import { useDemoData } from '@mui/x-data-grid-generator'; export default function DisableRowSelection() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, maxColumns: 6, @@ -13,6 +13,7 @@ export default function DisableRowSelection() {
params.row.quantity > 50000} checkboxSelection /> diff --git a/docs/data/data-grid/row-selection/DisableRowSelection.tsx.preview b/docs/data/data-grid/row-selection/DisableRowSelection.tsx.preview index e35109aebb0f2..d5e8b8d4f54f8 100644 --- a/docs/data/data-grid/row-selection/DisableRowSelection.tsx.preview +++ b/docs/data/data-grid/row-selection/DisableRowSelection.tsx.preview @@ -1,5 +1,6 @@ params.row.quantity > 50000} checkboxSelection /> \ No newline at end of file diff --git a/docs/data/data-grid/row-selection/MultipleRowSelectionGrid.js b/docs/data/data-grid/row-selection/MultipleRowSelectionGrid.js index dc6f2a5a6853a..82cae9ed475cf 100644 --- a/docs/data/data-grid/row-selection/MultipleRowSelectionGrid.js +++ b/docs/data/data-grid/row-selection/MultipleRowSelectionGrid.js @@ -3,7 +3,7 @@ import { DataGridPro } from '@mui/x-data-grid-pro'; import { useDemoData } from '@mui/x-data-grid-generator'; export default function MultipleRowSelectionGrid() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, maxColumns: 6, @@ -13,6 +13,7 @@ export default function MultipleRowSelectionGrid() {
](/x/introduction/licensing/#pro-plan 'Pro plan') By default, when you click the "Select All" checkbox, all rows in the Data Grid are selected. diff --git a/docs/data/data-grid/row-spanning/RowSpanning.js b/docs/data/data-grid/row-spanning/RowSpanning.js index 109566ed72271..58cd4d1223b05 100644 --- a/docs/data/data-grid/row-spanning/RowSpanning.js +++ b/docs/data/data-grid/row-spanning/RowSpanning.js @@ -23,7 +23,7 @@ export default function RowSpanning() { showCellVerticalBorder showColumnVerticalBorder disableRowSelectionOnClick - unstable_rowSpanning={enabled} + rowSpanning={enabled} hideFooter sx={{ '& .MuiDataGrid-row:hover': { diff --git a/docs/data/data-grid/row-spanning/RowSpanning.tsx b/docs/data/data-grid/row-spanning/RowSpanning.tsx index f9ac1d6204460..d871d83e21226 100644 --- a/docs/data/data-grid/row-spanning/RowSpanning.tsx +++ b/docs/data/data-grid/row-spanning/RowSpanning.tsx @@ -23,7 +23,7 @@ export default function RowSpanning() { showCellVerticalBorder showColumnVerticalBorder disableRowSelectionOnClick - unstable_rowSpanning={enabled} + rowSpanning={enabled} hideFooter sx={{ '& .MuiDataGrid-row:hover': { diff --git a/docs/data/data-grid/row-spanning/RowSpanningCalendar.js b/docs/data/data-grid/row-spanning/RowSpanningCalendar.js index fa234baca5fe5..dc7bd1b0a3abf 100644 --- a/docs/data/data-grid/row-spanning/RowSpanningCalendar.js +++ b/docs/data/data-grid/row-spanning/RowSpanningCalendar.js @@ -137,7 +137,7 @@ export default function RowSpanningCalendar() { Span cells across several rows.

By default, each cell in a Data Grid takes up the height of one row. The row spanning feature makes it possible for a cell to fill multiple rows in a single column. -To enable, pass the `unstable_rowSpanning` prop to the Data Grid. +To enable, pass the `rowSpanning` prop to the Data Grid. The Data Grid will automatically merge consecutive cells with repeating values in the same column, as shown in the demo below—switch off the toggle button to see the actual rows: {{"demo": "RowSpanning.js", "bg": "inline", "defaultCodeOpen": false}} diff --git a/docs/data/data-grid/scrolling/ScrollPlayground.js b/docs/data/data-grid/scrolling/ScrollPlayground.js index 82ab01c58cb5b..b39feaf86e8a2 100644 --- a/docs/data/data-grid/scrolling/ScrollPlayground.js +++ b/docs/data/data-grid/scrolling/ScrollPlayground.js @@ -21,7 +21,7 @@ export default function ScrollPlayground() { colIndex: 0, }); - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, }); @@ -100,6 +100,7 @@ export default function ScrollPlayground() { apiRef={apiRef} onCellClick={handleCellClick} hideFooter + loading={loading} {...data} /> diff --git a/docs/data/data-grid/scrolling/ScrollPlayground.tsx b/docs/data/data-grid/scrolling/ScrollPlayground.tsx index 42d3e7912e6af..80fee8a95b18a 100644 --- a/docs/data/data-grid/scrolling/ScrollPlayground.tsx +++ b/docs/data/data-grid/scrolling/ScrollPlayground.tsx @@ -22,7 +22,7 @@ export default function ScrollPlayground() { colIndex: 0, }); - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, }); @@ -101,6 +101,7 @@ export default function ScrollPlayground() { apiRef={apiRef} onCellClick={handleCellClick} hideFooter + loading={loading} {...data} /> diff --git a/docs/data/data-grid/server-side-data/ServerSideDataGrid.js b/docs/data/data-grid/server-side-data/ServerSideDataGrid.js index 31bfbc5b61b7e..8095791c05b47 100644 --- a/docs/data/data-grid/server-side-data/ServerSideDataGrid.js +++ b/docs/data/data-grid/server-side-data/ServerSideDataGrid.js @@ -2,7 +2,7 @@ import * as React from 'react'; import { DataGridPro } from '@mui/x-data-grid-pro'; import { useMockServer } from '@mui/x-data-grid-generator'; -function ServerSideDataGrid() { +export default function ServerSideDataGrid() { const { columns, initialState, fetchRows } = useMockServer( {}, { useCursorPagination: false }, @@ -51,5 +51,3 @@ function ServerSideDataGrid() {
); } - -export default ServerSideDataGrid; diff --git a/docs/data/data-grid/server-side-data/ServerSideDataGrid.tsx b/docs/data/data-grid/server-side-data/ServerSideDataGrid.tsx index 498c1e0674299..019b75d767520 100644 --- a/docs/data/data-grid/server-side-data/ServerSideDataGrid.tsx +++ b/docs/data/data-grid/server-side-data/ServerSideDataGrid.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { DataGridPro, GridDataSource } from '@mui/x-data-grid-pro'; import { useMockServer } from '@mui/x-data-grid-generator'; -function ServerSideDataGrid() { +export default function ServerSideDataGrid() { const { columns, initialState, fetchRows } = useMockServer( {}, { useCursorPagination: false }, @@ -51,5 +51,3 @@ function ServerSideDataGrid() {
); } - -export default ServerSideDataGrid; diff --git a/docs/data/data-grid/server-side-data/ServerSideDataGrid.tsx.preview b/docs/data/data-grid/server-side-data/ServerSideDataGrid.tsx.preview new file mode 100644 index 0000000000000..85adc7fdbcfd6 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideDataGrid.tsx.preview @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/server-side-data/ServerSideDataGridNoCache.js b/docs/data/data-grid/server-side-data/ServerSideDataGridNoCache.js index 43c742a5b90a1..e598eb38982ed 100644 --- a/docs/data/data-grid/server-side-data/ServerSideDataGridNoCache.js +++ b/docs/data/data-grid/server-side-data/ServerSideDataGridNoCache.js @@ -38,6 +38,7 @@ export default function ServerSideDataGridNoCache() { ...initialState, pagination: { paginationModel: { pageSize: 10, page: 0 }, + rowCount: 0, }, }), [initialState], diff --git a/docs/data/data-grid/server-side-data/ServerSideDataGridNoCache.tsx b/docs/data/data-grid/server-side-data/ServerSideDataGridNoCache.tsx index b62606d8985f0..19a578b73a8c1 100644 --- a/docs/data/data-grid/server-side-data/ServerSideDataGridNoCache.tsx +++ b/docs/data/data-grid/server-side-data/ServerSideDataGridNoCache.tsx @@ -38,6 +38,7 @@ export default function ServerSideDataGridNoCache() { ...initialState, pagination: { paginationModel: { pageSize: 10, page: 0 }, + rowCount: 0, }, }), [initialState], diff --git a/docs/data/data-grid/server-side-data/ServerSideDataGridTTL.js b/docs/data/data-grid/server-side-data/ServerSideDataGridTTL.js index 33d5403393f86..71b71560b6053 100644 --- a/docs/data/data-grid/server-side-data/ServerSideDataGridTTL.js +++ b/docs/data/data-grid/server-side-data/ServerSideDataGridTTL.js @@ -4,7 +4,7 @@ import { useMockServer } from '@mui/x-data-grid-generator'; const lowTTLCache = new GridDataSourceCacheDefault({ ttl: 1000 * 10 }); // 10 seconds -function ServerSideDataGridTTL() { +export default function ServerSideDataGridTTL() { const { columns, initialState, fetchRows } = useMockServer( {}, { useCursorPagination: false }, @@ -54,5 +54,3 @@ function ServerSideDataGridTTL() {
); } - -export default ServerSideDataGridTTL; diff --git a/docs/data/data-grid/server-side-data/ServerSideDataGridTTL.tsx b/docs/data/data-grid/server-side-data/ServerSideDataGridTTL.tsx index f33906bf70b6f..ccf7346b98099 100644 --- a/docs/data/data-grid/server-side-data/ServerSideDataGridTTL.tsx +++ b/docs/data/data-grid/server-side-data/ServerSideDataGridTTL.tsx @@ -8,7 +8,7 @@ import { useMockServer } from '@mui/x-data-grid-generator'; const lowTTLCache = new GridDataSourceCacheDefault({ ttl: 1000 * 10 }); // 10 seconds -function ServerSideDataGridTTL() { +export default function ServerSideDataGridTTL() { const { columns, initialState, fetchRows } = useMockServer( {}, { useCursorPagination: false }, @@ -58,5 +58,3 @@ function ServerSideDataGridTTL() {
); } - -export default ServerSideDataGridTTL; diff --git a/docs/data/data-grid/server-side-data/ServerSideDataGridTTL.tsx.preview b/docs/data/data-grid/server-side-data/ServerSideDataGridTTL.tsx.preview new file mode 100644 index 0000000000000..dfa35d39ae48e --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideDataGridTTL.tsx.preview @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/server-side-data/ServerSideLazyLoadingErrorHandling.js b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingErrorHandling.js new file mode 100644 index 0000000000000..4f890e86fe5ee --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingErrorHandling.js @@ -0,0 +1,109 @@ +import * as React from 'react'; +import { + DataGridPro, + useGridApiRef, + GridToolbar, + GRID_ROOT_GROUP_ID, +} from '@mui/x-data-grid-pro'; +import Checkbox from '@mui/material/Checkbox'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import { useMockServer } from '@mui/x-data-grid-generator'; +import Alert from '@mui/material/Alert'; +import Button from '@mui/material/Button'; +import Snackbar from '@mui/material/Snackbar'; + +function ErrorSnackbar(props) { + const { onRetry, ...rest } = props; + return ( + + + Retry + + } + > + Failed to fetch row data + + + ); +} + +function ServerSideLazyLoadingErrorHandling() { + const apiRef = useGridApiRef(); + const [retryParams, setRetryParams] = React.useState(null); + const [shouldRequestsFail, setShouldRequestsFail] = React.useState(false); + + const { fetchRows, ...props } = useMockServer( + { rowLength: 100 }, + { useCursorPagination: false, minDelay: 300, maxDelay: 800 }, + shouldRequestsFail, + ); + + const dataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + filterModel: JSON.stringify(params.filterModel), + sortModel: JSON.stringify(params.sortModel), + start: `${params.start}`, + end: `${params.end}`, + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + + // Reset the retryParams when new rows are fetched + setRetryParams(null); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + }), + [fetchRows], + ); + + return ( +
+ setShouldRequestsFail(event.target.checked)} + /> + } + label="Make the requests fail" + /> +
+ {retryParams && ( + { + apiRef.current.unstable_dataSource.fetchRows( + GRID_ROOT_GROUP_ID, + retryParams, + ); + setRetryParams(null); + }} + /> + )} + setRetryParams(params)} + unstable_dataSourceCache={null} + unstable_lazyLoading + paginationModel={{ page: 0, pageSize: 10 }} + slots={{ toolbar: GridToolbar }} + /> +
+
+ ); +} + +export default ServerSideLazyLoadingErrorHandling; diff --git a/docs/data/data-grid/server-side-data/ServerSideLazyLoadingErrorHandling.tsx b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingErrorHandling.tsx new file mode 100644 index 0000000000000..53d4519d1fa2b --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingErrorHandling.tsx @@ -0,0 +1,113 @@ +import * as React from 'react'; +import { + DataGridPro, + useGridApiRef, + GridToolbar, + GridDataSource, + GridGetRowsParams, + GRID_ROOT_GROUP_ID, +} from '@mui/x-data-grid-pro'; +import Checkbox from '@mui/material/Checkbox'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import { useMockServer } from '@mui/x-data-grid-generator'; +import Alert from '@mui/material/Alert'; +import Button from '@mui/material/Button'; +import Snackbar, { SnackbarProps } from '@mui/material/Snackbar'; + +function ErrorSnackbar(props: SnackbarProps & { onRetry: () => void }) { + const { onRetry, ...rest } = props; + return ( + + + Retry + + } + > + Failed to fetch row data + + + ); +} + +function ServerSideLazyLoadingErrorHandling() { + const apiRef = useGridApiRef(); + const [retryParams, setRetryParams] = React.useState( + null, + ); + const [shouldRequestsFail, setShouldRequestsFail] = React.useState(false); + + const { fetchRows, ...props } = useMockServer( + { rowLength: 100 }, + { useCursorPagination: false, minDelay: 300, maxDelay: 800 }, + shouldRequestsFail, + ); + + const dataSource: GridDataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + filterModel: JSON.stringify(params.filterModel), + sortModel: JSON.stringify(params.sortModel), + start: `${params.start}`, + end: `${params.end}`, + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + + // Reset the retryParams when new rows are fetched + setRetryParams(null); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + }), + [fetchRows], + ); + + return ( +
+ setShouldRequestsFail(event.target.checked)} + /> + } + label="Make the requests fail" + /> +
+ {retryParams && ( + { + apiRef.current.unstable_dataSource.fetchRows( + GRID_ROOT_GROUP_ID, + retryParams, + ); + setRetryParams(null); + }} + /> + )} + setRetryParams(params)} + unstable_dataSourceCache={null} + unstable_lazyLoading + paginationModel={{ page: 0, pageSize: 10 }} + slots={{ toolbar: GridToolbar }} + /> +
+
+ ); +} + +export default ServerSideLazyLoadingErrorHandling; diff --git a/docs/data/data-grid/server-side-data/ServerSideLazyLoadingInfinite.js b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingInfinite.js new file mode 100644 index 0000000000000..59ff744f4e438 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingInfinite.js @@ -0,0 +1,44 @@ +import * as React from 'react'; +import { DataGridPro } from '@mui/x-data-grid-pro'; +import { useMockServer } from '@mui/x-data-grid-generator'; + +function ServerSideLazyLoadingInfinite() { + const { fetchRows, ...props } = useMockServer( + { rowLength: 100 }, + { useCursorPagination: false, minDelay: 200, maxDelay: 500 }, + ); + + const dataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + filterModel: JSON.stringify(params.filterModel), + sortModel: JSON.stringify(params.sortModel), + start: `${params.start}`, + end: `${params.end}`, + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + + return { + rows: getRowsResponse.rows, + }; + }, + }), + [fetchRows], + ); + + return ( +
+ +
+ ); +} + +export default ServerSideLazyLoadingInfinite; diff --git a/docs/data/data-grid/server-side-data/ServerSideLazyLoadingInfinite.tsx b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingInfinite.tsx new file mode 100644 index 0000000000000..b842453551b76 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingInfinite.tsx @@ -0,0 +1,48 @@ +import * as React from 'react'; +import { + DataGridPro, + GridDataSource, + GridGetRowsParams, +} from '@mui/x-data-grid-pro'; +import { useMockServer } from '@mui/x-data-grid-generator'; + +function ServerSideLazyLoadingInfinite() { + const { fetchRows, ...props } = useMockServer( + { rowLength: 100 }, + { useCursorPagination: false, minDelay: 200, maxDelay: 500 }, + ); + + const dataSource: GridDataSource = React.useMemo( + () => ({ + getRows: async (params: GridGetRowsParams) => { + const urlParams = new URLSearchParams({ + filterModel: JSON.stringify(params.filterModel), + sortModel: JSON.stringify(params.sortModel), + start: `${params.start}`, + end: `${params.end}`, + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + + return { + rows: getRowsResponse.rows, + }; + }, + }), + [fetchRows], + ); + + return ( +
+ +
+ ); +} + +export default ServerSideLazyLoadingInfinite; diff --git a/docs/data/data-grid/server-side-data/ServerSideLazyLoadingModeUpdate.js b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingModeUpdate.js new file mode 100644 index 0000000000000..ca6447d8e7e08 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingModeUpdate.js @@ -0,0 +1,82 @@ +import * as React from 'react'; +import { DataGridPro } from '@mui/x-data-grid-pro'; +import { useMockServer } from '@mui/x-data-grid-generator'; +import FormControl from '@mui/material/FormControl'; +import FormLabel from '@mui/material/FormLabel'; +import RadioGroup from '@mui/material/RadioGroup'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import Radio from '@mui/material/Radio'; + +function GridCustomToolbar({ count, setCount }) { + return ( + + Row count + setCount(Number(event.target.value))} + > + } label="Unknown" /> + } label="40" /> + } label="100" /> + + + ); +} + +function ServerSideLazyLoadingModeUpdate() { + const { fetchRows, ...props } = useMockServer( + { rowLength: 100 }, + { useCursorPagination: false, minDelay: 200, maxDelay: 500 }, + ); + + const [rowCount, setRowCount] = React.useState(-1); + + const dataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + filterModel: JSON.stringify(params.filterModel), + sortModel: JSON.stringify(params.sortModel), + start: `${params.start}`, + end: `${params.end}`, + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + + return { + rows: getRowsResponse.rows, + }; + }, + }), + [fetchRows], + ); + + return ( +
+ +
+ ); +} + +export default ServerSideLazyLoadingModeUpdate; diff --git a/docs/data/data-grid/server-side-data/ServerSideLazyLoadingModeUpdate.tsx b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingModeUpdate.tsx new file mode 100644 index 0000000000000..13ec706795e00 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingModeUpdate.tsx @@ -0,0 +1,94 @@ +import * as React from 'react'; +import { + DataGridPro, + GridDataSource, + GridGetRowsParams, + GridSlotProps, +} from '@mui/x-data-grid-pro'; +import { useMockServer } from '@mui/x-data-grid-generator'; +import FormControl from '@mui/material/FormControl'; +import FormLabel from '@mui/material/FormLabel'; +import RadioGroup from '@mui/material/RadioGroup'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import Radio from '@mui/material/Radio'; + +declare module '@mui/x-data-grid' { + interface ToolbarPropsOverrides { + count: number; + setCount: React.Dispatch>; + } +} + +function GridCustomToolbar({ count, setCount }: GridSlotProps['toolbar']) { + return ( + + Row count + setCount(Number(event.target.value))} + > + } label="Unknown" /> + } label="40" /> + } label="100" /> + + + ); +} + +function ServerSideLazyLoadingModeUpdate() { + const { fetchRows, ...props } = useMockServer( + { rowLength: 100 }, + { useCursorPagination: false, minDelay: 200, maxDelay: 500 }, + ); + + const [rowCount, setRowCount] = React.useState(-1); + + const dataSource: GridDataSource = React.useMemo( + () => ({ + getRows: async (params: GridGetRowsParams) => { + const urlParams = new URLSearchParams({ + filterModel: JSON.stringify(params.filterModel), + sortModel: JSON.stringify(params.sortModel), + start: `${params.start}`, + end: `${params.end}`, + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + + return { + rows: getRowsResponse.rows, + }; + }, + }), + [fetchRows], + ); + + return ( +
+ +
+ ); +} + +export default ServerSideLazyLoadingModeUpdate; diff --git a/docs/data/data-grid/server-side-data/ServerSideLazyLoadingRequestThrottle.js b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingRequestThrottle.js new file mode 100644 index 0000000000000..2a826d5dc52ab --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingRequestThrottle.js @@ -0,0 +1,114 @@ +import * as React from 'react'; +import { DataGridPro, GridRowCount } from '@mui/x-data-grid-pro'; +import { useMockServer } from '@mui/x-data-grid-generator'; +import Box from '@mui/material/Box'; +import FormControl from '@mui/material/FormControl'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import FormLabel from '@mui/material/FormLabel'; +import RadioGroup from '@mui/material/RadioGroup'; +import Radio from '@mui/material/Radio'; + +function GridCustomFooterRowCount({ requestCount, ...props }) { + return ( + + Request count: {requestCount} + + + ); +} + +function GridCustomToolbar({ throttleMs, setThrottleMs }) { + return ( + + + + Throttle + + setThrottleMs(Number(event.target.value))} + > + } label="0 ms" /> + } + label="500 ms (default)" + /> + } label="1500 ms" /> + + + + ); +} + +function ServerSideLazyLoadingRequestThrottle() { + const rowCount = 1000; + const { fetchRows, ...props } = useMockServer( + { rowLength: rowCount }, + { useCursorPagination: false, minDelay: 200, maxDelay: 500 }, + ); + + const [requestCount, setRequestCount] = React.useState(0); + const [throttleMs, setThrottleMs] = React.useState(500); + + const dataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + filterModel: JSON.stringify(params.filterModel), + sortModel: JSON.stringify(params.sortModel), + start: `${params.start}`, + end: `${params.end}`, + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + + setRequestCount((prev) => prev + 1); + return { + rows: getRowsResponse.rows, + }; + }, + }), + [fetchRows], + ); + + React.useEffect(() => { + setRequestCount(0); + }, [dataSource]); + + return ( +
+ +
+ ); +} + +export default ServerSideLazyLoadingRequestThrottle; diff --git a/docs/data/data-grid/server-side-data/ServerSideLazyLoadingRequestThrottle.tsx b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingRequestThrottle.tsx new file mode 100644 index 0000000000000..75056075affc9 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingRequestThrottle.tsx @@ -0,0 +1,133 @@ +import * as React from 'react'; +import { + DataGridPro, + GridDataSource, + GridGetRowsParams, + GridRowCount, + GridSlotProps, +} from '@mui/x-data-grid-pro'; +import { useMockServer } from '@mui/x-data-grid-generator'; +import Box from '@mui/material/Box'; +import FormControl from '@mui/material/FormControl'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import FormLabel from '@mui/material/FormLabel'; +import RadioGroup from '@mui/material/RadioGroup'; +import Radio from '@mui/material/Radio'; + +declare module '@mui/x-data-grid' { + interface ToolbarPropsOverrides { + throttleMs: number; + setThrottleMs: React.Dispatch>; + } + interface FooterRowCountOverrides { + requestCount?: number; + } +} + +function GridCustomFooterRowCount({ + requestCount, + ...props +}: GridSlotProps['footerRowCount']) { + return ( + + Request count: {requestCount} + + + ); +} + +function GridCustomToolbar({ throttleMs, setThrottleMs }: GridSlotProps['toolbar']) { + return ( + + + + Throttle + + setThrottleMs(Number(event.target.value))} + > + } label="0 ms" /> + } + label="500 ms (default)" + /> + } label="1500 ms" /> + + + + ); +} + +function ServerSideLazyLoadingRequestThrottle() { + const rowCount = 1000; + const { fetchRows, ...props } = useMockServer( + { rowLength: rowCount }, + { useCursorPagination: false, minDelay: 200, maxDelay: 500 }, + ); + + const [requestCount, setRequestCount] = React.useState(0); + const [throttleMs, setThrottleMs] = React.useState(500); + + const dataSource: GridDataSource = React.useMemo( + () => ({ + getRows: async (params: GridGetRowsParams) => { + const urlParams = new URLSearchParams({ + filterModel: JSON.stringify(params.filterModel), + sortModel: JSON.stringify(params.sortModel), + start: `${params.start}`, + end: `${params.end}`, + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + + setRequestCount((prev) => prev + 1); + return { + rows: getRowsResponse.rows, + }; + }, + }), + [fetchRows], + ); + + React.useEffect(() => { + setRequestCount(0); + }, [dataSource]); + + return ( +
+ +
+ ); +} + +export default ServerSideLazyLoadingRequestThrottle; diff --git a/docs/data/data-grid/server-side-data/ServerSideLazyLoadingViewport.js b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingViewport.js new file mode 100644 index 0000000000000..d6de6e60ca0d2 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingViewport.js @@ -0,0 +1,45 @@ +import * as React from 'react'; +import { DataGridPro } from '@mui/x-data-grid-pro'; +import { useMockServer } from '@mui/x-data-grid-generator'; + +function ServerSideLazyLoadingViewport() { + const { fetchRows, ...props } = useMockServer( + { rowLength: 100000 }, + { useCursorPagination: false, minDelay: 200, maxDelay: 500 }, + ); + + const dataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + filterModel: JSON.stringify(params.filterModel), + sortModel: JSON.stringify(params.sortModel), + start: `${params.start}`, + end: `${params.end}`, + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + }), + [fetchRows], + ); + + return ( +
+ +
+ ); +} + +export default ServerSideLazyLoadingViewport; diff --git a/docs/data/data-grid/server-side-data/ServerSideLazyLoadingViewport.tsx b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingViewport.tsx new file mode 100644 index 0000000000000..df60d3b0e3dc1 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideLazyLoadingViewport.tsx @@ -0,0 +1,49 @@ +import * as React from 'react'; +import { + DataGridPro, + GridDataSource, + GridGetRowsParams, +} from '@mui/x-data-grid-pro'; +import { useMockServer } from '@mui/x-data-grid-generator'; + +function ServerSideLazyLoadingViewport() { + const { fetchRows, ...props } = useMockServer( + { rowLength: 100000 }, + { useCursorPagination: false, minDelay: 200, maxDelay: 500 }, + ); + + const dataSource: GridDataSource = React.useMemo( + () => ({ + getRows: async (params: GridGetRowsParams) => { + const urlParams = new URLSearchParams({ + filterModel: JSON.stringify(params.filterModel), + sortModel: JSON.stringify(params.sortModel), + start: `${params.start}`, + end: `${params.end}`, + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + }), + [fetchRows], + ); + + return ( +
+ +
+ ); +} + +export default ServerSideLazyLoadingViewport; diff --git a/docs/data/data-grid/server-side-data/aggregation.md b/docs/data/data-grid/server-side-data/aggregation.md index 99b226b777709..e11485b7d80ce 100644 --- a/docs/data/data-grid/server-side-data/aggregation.md +++ b/docs/data/data-grid/server-side-data/aggregation.md @@ -1,5 +1,5 @@ --- -title: React Server-side row grouping +title: React Data Grid - Server-side aggregation --- # Data Grid - Server-side aggregation [](/x/introduction/licensing/#premium-plan 'Premium plan')🚧 diff --git a/docs/data/data-grid/server-side-data/index.md b/docs/data/data-grid/server-side-data/index.md index 3b89ae28e5b28..02906265e955a 100644 --- a/docs/data/data-grid/server-side-data/index.md +++ b/docs/data/data-grid/server-side-data/index.md @@ -2,10 +2,16 @@ title: React Data Grid - Server-side data --- -# Data Grid - Server-side data [](/x/introduction/licensing/#pro-plan 'Pro plan') +# Data Grid - Server-side data [](/x/introduction/licensing/#pro-plan 'Pro plan')🧪

The Data Grid server-side data.

+:::warning +This feature is under development and is marked as **unstable**. +While you can use this feature in production, the API could change in the future. +Feel free to subscribe or comment on the official GitHub [umbrella issue](https://github.com/mui/mui-x/issues/8179). +::: + ## Introduction Server-side data management in React can become complex with growing datasets. @@ -72,14 +78,6 @@ The idea for a centralized data source is to simplify server-side data fetching. It's an abstraction layer between the Data Grid and the server, providing a simple interface for interacting with the server. Think of it like an intermediary handling the communication between the Data Grid (client) and the actual data source (server). -:::warning - -This feature is under development and is marked as **unstable**. -The information shared on this page could change in the future. -Feel free to subscribe or comment on the official GitHub [umbrella issue](https://github.com/mui/mui-x/issues/8179). - -::: - It has an initial set of required methods that you need to implement. The Data Grid will use these methods internally to fetch a subset of data when needed. Let's take a look at the minimal `GridDataSource` interface configuration. @@ -88,8 +86,9 @@ Let's take a look at the minimal `GridDataSource` interface configuration. interface GridDataSource { /** * This method will be called when the grid needs to fetch some rows. - * @param {GridGetRowsParams} params The parameters required to fetch the rows - * @returns {Promise} A promise that resolves to the data of type [GridGetRowsResponse] + * @param {GridGetRowsParams} params The parameters required to fetch the rows. + * @returns {Promise} A promise that resolves to the data of + * type [GridGetRowsResponse]. */ getRows(params: GridGetRowsParams): Promise; } @@ -133,7 +132,7 @@ The code has been significantly reduced, the need for managing the controlled st The data source changes how the existing server-side features like `filtering`, `sorting`, and `pagination` work. -**Without data source** +### Without data source When there's no data source, the features `filtering`, `sorting`, `pagination` work on `client` by default. In order for them to work with server-side data, you need to set them to `server` explicitly and provide the [`onFilterModelChange`](/x/react-data-grid/filtering/server-side/), [`onSortModelChange`](/x/react-data-grid/sorting/#server-side-sorting), [`onPaginationModelChange`](/x/react-data-grid/pagination/#server-side-pagination) event handlers to fetch the data from the server based on the updated variables. @@ -158,7 +157,7 @@ In order for them to work with server-side data, you need to set them to `server /> ``` -**With data source** +### With data source With the data source, the features `filtering`, `sorting`, `pagination` are automatically set to `server`. @@ -167,7 +166,8 @@ When the corresponding models update, the Data Grid calls the `getRows` method w ```tsx ``` @@ -176,10 +176,10 @@ The following demo showcases this behavior. {{"demo": "ServerSideDataGrid.js", "bg": "inline"}} :::info -The data source demos use a utility function `useMockServer` to simulate the server-side data fetching. -In a real-world scenario, you should replace this with your own server-side data-fetching logic. +The data source demos use a `useMockServer` utility function to simulate server-side data fetching. +In a real-world scenario you would replace this with your own server-side data-fetching logic. -Open info section of the browser console to see the requests being made and the data being fetched in response. +Open the Info section of your browser console to see the requests being made and the data being fetched in response. ::: ## Data caching @@ -187,9 +187,44 @@ Open info section of the browser console to see the requests being made and the The data source caches fetched data by default. This means that if the user navigates to a page or expands a node that has already been fetched, the grid will not call the `getRows` function again to avoid unnecessary calls to the server. -The `GridDataSourceCacheDefault` is used by default which is a simple in-memory cache that stores the data in a plain object. It can be seen in action in the demo below. +The `GridDataSourceCacheDefault` is used by default which is a simple in-memory cache that stores the data in a plain object. It can be seen in action in the [demo above](#with-data-source). -{{"demo": "ServerSideDataGrid.js", "bg": "inline"}} +### Improving the cache hit rate + +To increase the cache hit rate, Data Grid splits `getRows()` results into chunks before storing them in cache. +For the requests that follow, chunks are combined as needed to recreate the response. +This means that a single request can make multiple calls to the `get()` or `set()` method of `GridDataSourceCache`. + +Chunk size is the lowest expected amount of records per request based on the `pageSize` value from the `paginationModel` and `pageSizeOptions` props. + +Because of this, values in the `pageSizeOptions` prop play a big role in the cache hit rate. +We recommend using values that are multiples of the lowest value; even better if each subsequent value is a multiple of the previous value. + +Here are some examples: + +1. Best scenario - `pageSizeOptions={[5, 10, 50, 100]}` + + In this case the chunk size is 5, which means that with `pageSize={100}` there are 20 cache records stored. + + Retrieving data for any other `pageSize` up to the first 100 records results in a cache hit, since the whole dataset can be made of the existing chunks. + +2. Parts of the data missing - `pageSizeOptions={[10, 20, 50]}` + + Loading the first page with `pageSize={50}` results in 5 cache records. + This works well with `pageSize={10}`, but not as well with `pageSize={20}`. + Loading the third page with `pageSize={20}` results in a new request being made, even though half of the data is already in the cache. + +3. Incompatible page sizes - `pageSizeOptions={[7, 15, 40]}` + + In this situation, the chunk size is 7. + Retrieving the first page with `pageSize={15}` creates chunks split into `[7, 7, 1]` records. + Loading the second page creates 3 new chunks (again `[7, 7, 1]`), but now the third chunk from the first request has an overlap of 1 record with the first chunk of the second request. + These chunks with 1 record can only be used as the last piece of a request for `pageSize={15}` and are useless in all other cases. + +:::info +In the examples above, `sortModel` and `filterModel` remained unchanged. +Changing those would require a new response to be retrieved and stored in the chunks. +::: ### Customize the cache lifetime diff --git a/docs/data/data-grid/server-side-data/infinite-loading.md b/docs/data/data-grid/server-side-data/infinite-loading.md deleted file mode 100644 index d2bcc0e58d038..0000000000000 --- a/docs/data/data-grid/server-side-data/infinite-loading.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: React Server-side infinite loading ---- - -# Data Grid - Server-side infinite loading [](/x/introduction/licensing/#pro-plan 'Pro plan')🚧 - -

Row infinite loading with server-side data source.

- -:::warning -This feature isn't implemented yet. It's coming. - -👍 Upvote [issue #10858](https://github.com/mui/mui-x/issues/10858) if you want to see it land faster. - -Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with the [current solution](https://mui.com/x/react-data-grid/row-updates/#infinite-loading). -::: diff --git a/docs/data/data-grid/server-side-data/lazy-loading.md b/docs/data/data-grid/server-side-data/lazy-loading.md index 6c66183ab0e65..176ddeff29133 100644 --- a/docs/data/data-grid/server-side-data/lazy-loading.md +++ b/docs/data/data-grid/server-side-data/lazy-loading.md @@ -1,15 +1,121 @@ --- -title: React Server-side lazy loading +title: React Data Grid - Server-side lazy loading --- -# Data Grid - Server-side lazy loading [](/x/introduction/licensing/#pro-plan 'Pro plan')🚧 +# Data Grid - Server-side lazy loading [](/x/introduction/licensing/#pro-plan 'Pro plan')🧪 -

Row lazy-loading with server-side data source.

+

Learn how to implement lazy-loading rows with a server-side data source.

+ +Lazy loading changes the way pagination works by removing page controls and loading data dynamically (in a single list) as the user scrolls through the grid. + +You can enable it with the `unstable_lazyLoading` prop paired with the `unstable_dataSource` prop. + +Initially, data for the first page is fetched and displayed in the grid. +The value of the total row count determines when the next page's data is loaded: + +- If the total row count is known, the Data Grid is filled with skeleton rows and fetches more data if one of the skeleton rows falls into the rendering context. + This loading strategy is often referred to as [**viewport loading**](#viewport-loading). + +- If the total row count is unknown, the Data Grid fetches more data when the user scrolls to the bottom. + This loading strategy is often referred to as [**infinite loading**](#infinite-loading). + +:::info +You can provide the row count through one of the following ways: + +- Pass it as the [`rowCount`](/x/api/data-grid/data-grid/#data-grid-prop-rowCount) prop +- Return `rowCount` in the `getRows()` method of the [data source](/x/react-data-grid/server-side-data/#data-source) +- Set the `rowCount` using the [`setRowCount()`](/x/api/data-grid/grid-api/#grid-api-prop-setRowCount) API method + +These options are presented in order of precedence, which means if the row count is set using the API, that value is overridden once a new value is returned by the `getRows()` method unless it's `undefined`. +::: + +## Viewport loading + +Viewport loading mode is enabled when the row count is known (and is greater than or equal to zero). +The Grid fetches the first page immediately and adds skeleton rows to match the total row count. +Other pages are fetched once the user starts scrolling and moves a skeleton row inside the rendering context (with the index range defined by [virtualization](/x/react-data-grid/virtualization/)). + +If the user scrolls too fast, the Grid loads multiple pages with one request (by adjusting `start` and `end` parameters) to reduce the server load. + +The demo below shows how viewport loading mode works: + +{{"demo": "ServerSideLazyLoadingViewport.js", "bg": "inline"}} + +:::info +The data source demos use a `useMockServer` utility function to simulate server-side data fetching. +In a real-world scenario you would replace this with your own server-side data-fetching logic. + +Open the Info section of your browser console to see the requests being made and the data being fetched in response. +::: + +### Request throttling + +As a user scrolls through the Grid, the rendering context changes and the Grid tries to fill in any missing rows by making a new server request. +It also throttles new data fetches to avoid making unnecessary requests. +The default throttle time is 500 milliseconds. +Use the `unstable_lazyLoadingRequestThrottleMs` prop to set a custom time, as shown below: + +{{"demo": "ServerSideLazyLoadingRequestThrottle.js", "bg": "inline"}} + +## Infinite loading + +Infinite loading mode is enabled when the row count is unknown (either `-1` or `undefined`). +A new page is loaded when the scroll reaches the bottom of the viewport area. + +You can use the `scrollEndThreshold` prop to change the area that triggers new requests. + +The demo below shows how infinite loading mode works. +Page size is set to `15` and the mock server is configured to return a total of 100 rows. +When the response contains no new rows, the Grid stops requesting new data. + +{{"demo": "ServerSideLazyLoadingInfinite.js", "bg": "inline"}} + +## Updating the loading mode + +The Grid changes the loading mode dynamically if the total row count gets updated by changing the `rowCount` prop, returning different `rowCount` in `GridGetRowsResponse` or via `setRowCount()` API. + +Based on the previous and the new value for the total row count, the following scenarios are possible: + +- **Unknown `rowCount` to known `rowCount`**: When the row count is set to a valid value from an unknown value, the Data Grid switches to viewport loading mode. It checks the number of already fetched rows and adds skeleton rows to match the provided row count. + +- **Known `rowCount` to unknown `rowCount`**: If the row count is updated and set to `-1`, the Data Grid resets, fetches the first page, then sets itself to infinite loading mode. + +- **Known `rowCount` greater than the actual row count**: This can happen either by reducing the value of the row count after more rows were already fetched, or if the row count was unknown and the Grid (while in the infinite loading mode) already fetched more rows. In this case, the Grid resets, fetches the first page, and then continues in one mode or the other depending on the new value of the `rowCount`. + +:::warning +`rowCount` is expected to be static. +Changing its value can cause the Grid to reset and the cache to be cleared which may lead to performance and UX degradation. +::: + +The demo below serves as a showcase of the behavior described above, and is not representative of something you would implement in a real-world scenario. + +{{"demo": "ServerSideLazyLoadingModeUpdate.js", "bg": "inline"}} + +## Nested lazy loading 🚧 :::warning This feature isn't implemented yet. It's coming. -👍 Upvote [issue #10857](https://github.com/mui/mui-x/issues/10857) if you want to see it land faster. +👍 Upvote [issue #14527](https://github.com/mui/mui-x/issues/14527) if you want to see it land faster. -Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with the [current solution](https://mui.com/x/react-data-grid/row-updates/#lazy-loading). +Don't hesitate to leave a comment on the issue to help influence what gets built—especially if you already have a use case for this feature, or if you're facing a specific pain point with your current solution. ::: + +When completed, it will be possible to use the `unstable_lazyLoading` flag in combination with [tree data](/x/react-data-grid/server-side-data/tree-data/) and [row grouping](/x/react-data-grid/server-side-data/row-grouping/). + +## Error handling + +To handle errors, use the `unstable_onDataSourceError()` prop as described in [Server-side data—Error handling](/x/react-data-grid/server-side-data/#error-handling). + +You can pass the second parameter of type `GridGetRowsParams` to the `getRows()` method of the [`unstable_dataSource`](/x/api/data-grid/grid-api/#grid-api-prop-unstable_dataSource) to retry the request. +If successful, the Data Grid uses `rows` and `rowCount` data to determine if the rows should be appended at the end of the grid or if the skeleton rows should be replaced. + +The following demo gives an example how to use `GridGetRowsParams` to retry a failed request. + +{{"demo": "ServerSideLazyLoadingErrorHandling.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/row-grouping.md b/docs/data/data-grid/server-side-data/row-grouping.md index 25b6044f3f43c..8ab13eb7e5c38 100644 --- a/docs/data/data-grid/server-side-data/row-grouping.md +++ b/docs/data/data-grid/server-side-data/row-grouping.md @@ -1,8 +1,8 @@ --- -title: React Server-side row grouping +title: React Data Grid - Server-side row grouping --- -# Data Grid - Server-side row grouping [](/x/introduction/licensing/#pro-plan 'Pro plan') +# Data Grid - Server-side row grouping [](/x/introduction/licensing/#premium-plan 'Premium plan')🧪

Lazy-loaded row grouping with server-side data source.

@@ -20,14 +20,14 @@ Similar to the [tree data](/x/react-data-grid/server-side-data/tree-data/), you ```tsx const customDataSource: GridDataSource = { getRows: async (params) => { - // Fetch the data from the server + // Fetch the data from the server. }, getGroupKey: (row) => { - // Return the group key for the row, e.g. `name` + // Return the group key for the row, e.g. `name`. return row.name; }, getChildrenCount: (row) => { - // Return the number of children for the row + // Return the number of children for the row. return row.childrenCount; }, }; @@ -45,7 +45,7 @@ const getRows: async (params) => { }); const getRowsResponse = await fetchRows( // Server should group the data based on `groupFields` and - // extract the rows for the nested level based on `groupKeys` + // extract the rows for the nested level based on `groupKeys`. `https://mui.com/x/api/data-grid?${urlParams.toString()}`, ); return { @@ -74,7 +74,7 @@ This example shows error handling with toast notifications and default error mes ## 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. +The following demo uses `defaultGroupingExpansionDepth={-1}` to expand all the groups. {{"demo": "ServerSideRowGroupingGroupExpansion.js", "bg": "inline"}} 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 d5c725ac456ed..b4af9c3548391 100644 --- a/docs/data/data-grid/server-side-data/tree-data.md +++ b/docs/data/data-grid/server-side-data/tree-data.md @@ -1,8 +1,8 @@ --- -title: React Server-side tree data +title: React Data Grid - Server-side tree data --- -# Data Grid - Server-side tree data [](/x/introduction/licensing/#pro-plan 'Pro plan') +# Data Grid - Server-side tree data [](/x/introduction/licensing/#pro-plan 'Pro plan')🧪

Tree data lazy-loading with server-side data source.

@@ -20,14 +20,14 @@ The data source also requires some additional props to handle tree data: ```tsx const customDataSource: GridDataSource = { getRows: async (params) => { - // Fetch the data from the server + // Fetch the data from the server. }, getGroupKey: (row) => { - // Return the group key for the row, e.g. `name` + // Return the group key for the row, e.g. `name`. return row.name; }, getChildrenCount: (row) => { - // Return the number of children for the row + // Return the number of children for the row. return row.childrenCount; }, }; @@ -39,11 +39,11 @@ 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']) + // 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` + // Server should extract the rows for the nested level based on `groupKeys`. `https://mui.com/x/api/data-grid?${urlParams.toString()}`, ); return { @@ -59,10 +59,10 @@ It also caches the data by default. {{"demo": "ServerSideTreeData.js", "bg": "inline"}} :::info -The data source demos use a utility function `useMockServer` to simulate the server-side data fetching. -In a real-world scenario, you would replace this with your own server-side data fetching logic. +The data source demos use a `useMockServer` utility function to simulate server-side data fetching. +In a real-world scenario you would replace this with your own server-side data-fetching logic. -Open the info section of the browser console to see the requests being made and the data being fetched in response. +Open the Info section of your browser console to see the requests being made and the data being fetched in response. ::: ## Error handling @@ -78,7 +78,7 @@ The demo below shows a toast apart from the default error message in the groupin The idea behind the group expansion is the same as explained in the [Row grouping](/x/react-data-grid/row-grouping/#group-expansion) section. The difference is that the data is not initially available and is fetched automatically after the Data Grid is mounted based on the props `defaultGroupingExpansionDepth` and `isGroupExpandedByDefault` in a waterfall manner. -The following demo uses `defaultGroupingExpansionDepth='-1'` to expand all levels of the tree by default. +The following demo uses `defaultGroupingExpansionDepth={-1}` to expand all levels of the tree by default. {{"demo": "ServerSideTreeDataGroupExpansion.js", "bg": "inline"}} diff --git a/docs/data/data-grid/sorting/BasicExampleDataGrid.js b/docs/data/data-grid/sorting/BasicExampleDataGrid.js index 5579e72de51fb..d1e100f78fc46 100644 --- a/docs/data/data-grid/sorting/BasicExampleDataGrid.js +++ b/docs/data/data-grid/sorting/BasicExampleDataGrid.js @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function BasicExampleDataGrid() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -13,7 +13,7 @@ export default function BasicExampleDataGrid() { return (
- +
); } diff --git a/docs/data/data-grid/sorting/BasicExampleDataGrid.tsx b/docs/data/data-grid/sorting/BasicExampleDataGrid.tsx index 5579e72de51fb..d1e100f78fc46 100644 --- a/docs/data/data-grid/sorting/BasicExampleDataGrid.tsx +++ b/docs/data/data-grid/sorting/BasicExampleDataGrid.tsx @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function BasicExampleDataGrid() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -13,7 +13,7 @@ export default function BasicExampleDataGrid() { return (
- +
); } diff --git a/docs/data/data-grid/sorting/BasicExampleDataGrid.tsx.preview b/docs/data/data-grid/sorting/BasicExampleDataGrid.tsx.preview index 4eba0f23a52f2..c0970b7369aa3 100644 --- a/docs/data/data-grid/sorting/BasicExampleDataGrid.tsx.preview +++ b/docs/data/data-grid/sorting/BasicExampleDataGrid.tsx.preview @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/data-grid/sorting/BasicExampleDataGridPro.js b/docs/data/data-grid/sorting/BasicExampleDataGridPro.js index c780f8c9dac00..3a89b1ba1405f 100644 --- a/docs/data/data-grid/sorting/BasicExampleDataGridPro.js +++ b/docs/data/data-grid/sorting/BasicExampleDataGridPro.js @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function BasicExampleDataGridPro() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -13,7 +13,7 @@ export default function BasicExampleDataGridPro() { return (
- +
); } diff --git a/docs/data/data-grid/sorting/BasicExampleDataGridPro.tsx b/docs/data/data-grid/sorting/BasicExampleDataGridPro.tsx index c780f8c9dac00..3a89b1ba1405f 100644 --- a/docs/data/data-grid/sorting/BasicExampleDataGridPro.tsx +++ b/docs/data/data-grid/sorting/BasicExampleDataGridPro.tsx @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function BasicExampleDataGridPro() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -13,7 +13,7 @@ export default function BasicExampleDataGridPro() { return (
- +
); } diff --git a/docs/data/data-grid/sorting/BasicExampleDataGridPro.tsx.preview b/docs/data/data-grid/sorting/BasicExampleDataGridPro.tsx.preview index 0f1aa8c3315ff..0693629eb1d3a 100644 --- a/docs/data/data-grid/sorting/BasicExampleDataGridPro.tsx.preview +++ b/docs/data/data-grid/sorting/BasicExampleDataGridPro.tsx.preview @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/data-grid/sorting/ControlledSort.js b/docs/data/data-grid/sorting/ControlledSort.js index 1fd156d178582..6ed47e89f8149 100644 --- a/docs/data/data-grid/sorting/ControlledSort.js +++ b/docs/data/data-grid/sorting/ControlledSort.js @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function ControlledSort() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -22,6 +22,7 @@ export default function ControlledSort() {
setSortModel(newSortModel)} /> diff --git a/docs/data/data-grid/sorting/ControlledSort.tsx b/docs/data/data-grid/sorting/ControlledSort.tsx index ff7b284f91215..f22f65b1e47ee 100644 --- a/docs/data/data-grid/sorting/ControlledSort.tsx +++ b/docs/data/data-grid/sorting/ControlledSort.tsx @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function ControlledSort() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -22,6 +22,7 @@ export default function ControlledSort() {
setSortModel(newSortModel)} /> diff --git a/docs/data/data-grid/sorting/ControlledSort.tsx.preview b/docs/data/data-grid/sorting/ControlledSort.tsx.preview index 303f849a8096f..bfd2999be0f61 100644 --- a/docs/data/data-grid/sorting/ControlledSort.tsx.preview +++ b/docs/data/data-grid/sorting/ControlledSort.tsx.preview @@ -1,5 +1,6 @@ setSortModel(newSortModel)} /> \ No newline at end of file diff --git a/docs/data/data-grid/sorting/DisableSortingGrid.js b/docs/data/data-grid/sorting/DisableSortingGrid.js index 93117ac410ada..ef721ab83d57c 100644 --- a/docs/data/data-grid/sorting/DisableSortingGrid.js +++ b/docs/data/data-grid/sorting/DisableSortingGrid.js @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function DisableSortingGrid() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -20,7 +20,7 @@ export default function DisableSortingGrid() { ); return (
- +
); } diff --git a/docs/data/data-grid/sorting/DisableSortingGrid.tsx b/docs/data/data-grid/sorting/DisableSortingGrid.tsx index 93117ac410ada..ef721ab83d57c 100644 --- a/docs/data/data-grid/sorting/DisableSortingGrid.tsx +++ b/docs/data/data-grid/sorting/DisableSortingGrid.tsx @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function DisableSortingGrid() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -20,7 +20,7 @@ export default function DisableSortingGrid() { ); return (
- +
); } diff --git a/docs/data/data-grid/sorting/DisableSortingGrid.tsx.preview b/docs/data/data-grid/sorting/DisableSortingGrid.tsx.preview index 50c4ffdb6a38b..6991c5aded8e7 100644 --- a/docs/data/data-grid/sorting/DisableSortingGrid.tsx.preview +++ b/docs/data/data-grid/sorting/DisableSortingGrid.tsx.preview @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/data-grid/sorting/DisableSortingGridAllColumns.js b/docs/data/data-grid/sorting/DisableSortingGridAllColumns.js index 7a6a775a2a01e..d46414f7429ed 100644 --- a/docs/data/data-grid/sorting/DisableSortingGridAllColumns.js +++ b/docs/data/data-grid/sorting/DisableSortingGridAllColumns.js @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function DisableSortingGridAllColumns() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -13,7 +13,7 @@ export default function DisableSortingGridAllColumns() { return (
- +
); } diff --git a/docs/data/data-grid/sorting/DisableSortingGridAllColumns.tsx b/docs/data/data-grid/sorting/DisableSortingGridAllColumns.tsx index 7a6a775a2a01e..d46414f7429ed 100644 --- a/docs/data/data-grid/sorting/DisableSortingGridAllColumns.tsx +++ b/docs/data/data-grid/sorting/DisableSortingGridAllColumns.tsx @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function DisableSortingGridAllColumns() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -13,7 +13,7 @@ export default function DisableSortingGridAllColumns() { return (
- +
); } diff --git a/docs/data/data-grid/sorting/DisableSortingGridAllColumns.tsx.preview b/docs/data/data-grid/sorting/DisableSortingGridAllColumns.tsx.preview index 1a8e6ff1d8d65..3a2f1aea572bc 100644 --- a/docs/data/data-grid/sorting/DisableSortingGridAllColumns.tsx.preview +++ b/docs/data/data-grid/sorting/DisableSortingGridAllColumns.tsx.preview @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/data-grid/sorting/ExtendedSortComparator.js b/docs/data/data-grid/sorting/ExtendedSortComparator.js index 705eb59585e86..70668d4ebedfe 100644 --- a/docs/data/data-grid/sorting/ExtendedSortComparator.js +++ b/docs/data/data-grid/sorting/ExtendedSortComparator.js @@ -26,7 +26,7 @@ const nameAdminSortComparator = (v1, v2, param1, param2) => { }; export default function ExtendedSortComparator() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -60,6 +60,7 @@ export default function ExtendedSortComparator() {
{ }; export default function ExtendedSortComparator() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -72,6 +72,7 @@ export default function ExtendedSortComparator() {
\ No newline at end of file diff --git a/docs/data/data-grid/sorting/FullyCustomSortComparator.js b/docs/data/data-grid/sorting/FullyCustomSortComparator.js index be364bee8b75c..697f35a61373b 100644 --- a/docs/data/data-grid/sorting/FullyCustomSortComparator.js +++ b/docs/data/data-grid/sorting/FullyCustomSortComparator.js @@ -7,7 +7,7 @@ const VISIBLE_FIELDS = ['name', 'rating', 'country', 'isAdmin']; const dayInMonthComparator = (v1, v2) => v1.getDate() - v2.getDate(); export default function FullyCustomSortComparator() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -32,6 +32,7 @@ export default function FullyCustomSortComparator() {
= (v1, v2) => v1.getDate() - v2.getDate(); export default function FullyCustomSortComparator() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -33,6 +33,7 @@ export default function FullyCustomSortComparator() {
\ No newline at end of file diff --git a/docs/data/data-grid/sorting/InitialSort.js b/docs/data/data-grid/sorting/InitialSort.js index 37f75136de2f6..adfd88da3c0ed 100644 --- a/docs/data/data-grid/sorting/InitialSort.js +++ b/docs/data/data-grid/sorting/InitialSort.js @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function InitialSort() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -15,6 +15,7 @@ export default function InitialSort() {
); diff --git a/docs/data/data-grid/sorting/OrderSortingGrid.tsx b/docs/data/data-grid/sorting/OrderSortingGrid.tsx index b54014f88c3a7..f7483837cbef7 100644 --- a/docs/data/data-grid/sorting/OrderSortingGrid.tsx +++ b/docs/data/data-grid/sorting/OrderSortingGrid.tsx @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function OrderSortingGrid() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -14,6 +14,8 @@ export default function OrderSortingGrid() { return (
); diff --git a/docs/data/data-grid/sorting/OrderSortingGrid.tsx.preview b/docs/data/data-grid/sorting/OrderSortingGrid.tsx.preview deleted file mode 100644 index ec463b91bb5ca..0000000000000 --- a/docs/data/data-grid/sorting/OrderSortingGrid.tsx.preview +++ /dev/null @@ -1,16 +0,0 @@ - \ No newline at end of file diff --git a/docs/data/data-grid/sorting/OrderSortingPerColumnGrid.js b/docs/data/data-grid/sorting/OrderSortingPerColumnGrid.js index ad56449a647d5..198c0f094b1b6 100644 --- a/docs/data/data-grid/sorting/OrderSortingPerColumnGrid.js +++ b/docs/data/data-grid/sorting/OrderSortingPerColumnGrid.js @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function OrderSortingPerColumnGrid() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -28,7 +28,12 @@ export default function OrderSortingPerColumnGrid() { return (
- +
); } diff --git a/docs/data/data-grid/sorting/OrderSortingPerColumnGrid.tsx b/docs/data/data-grid/sorting/OrderSortingPerColumnGrid.tsx index dcc833e19086a..d34fe33b9d4d0 100644 --- a/docs/data/data-grid/sorting/OrderSortingPerColumnGrid.tsx +++ b/docs/data/data-grid/sorting/OrderSortingPerColumnGrid.tsx @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function OrderSortingPerColumnGrid() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -28,7 +28,12 @@ export default function OrderSortingPerColumnGrid() { return (
- +
); } diff --git a/docs/data/data-grid/sorting/OrderSortingPerColumnGrid.tsx.preview b/docs/data/data-grid/sorting/OrderSortingPerColumnGrid.tsx.preview index 329d522ab336b..66e89edbcb36a 100644 --- a/docs/data/data-grid/sorting/OrderSortingPerColumnGrid.tsx.preview +++ b/docs/data/data-grid/sorting/OrderSortingPerColumnGrid.tsx.preview @@ -1 +1,6 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/data/data-grid/state/DirectSelector.js b/docs/data/data-grid/state/DirectSelector.js index 590aaa15a7bfe..08186da5a0f29 100644 --- a/docs/data/data-grid/state/DirectSelector.js +++ b/docs/data/data-grid/state/DirectSelector.js @@ -9,7 +9,7 @@ import { import { useDemoData } from '@mui/x-data-grid-generator'; export default function DirectSelector() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, maxColumns: 10, @@ -37,6 +37,7 @@ export default function DirectSelector() { void; -}) { +declare module '@mui/x-data-grid' { + interface ToolbarPropsOverrides { + syncState: (stateToSave: GridInitialState) => void; + } +} + +function GridCustomToolbar({ syncState }: GridSlotProps['toolbar']) { const rootProps = useGridRootProps(); const apiRef = useGridApiContext(); @@ -63,7 +65,7 @@ export default function RestoreStateInitialState() { diff --git a/docs/data/data-grid/state/RestoreStateInitialState.tsx.preview b/docs/data/data-grid/state/RestoreStateInitialState.tsx.preview index a02338eabb0bb..cb7e99c92deb1 100644 --- a/docs/data/data-grid/state/RestoreStateInitialState.tsx.preview +++ b/docs/data/data-grid/state/RestoreStateInitialState.tsx.preview @@ -2,7 +2,7 @@ diff --git a/docs/data/data-grid/style-recipes/CellFocusNoOutline.js b/docs/data/data-grid/style-recipes/CellFocusNoOutline.js index 1936ceec9db3b..0edb3f0421acf 100644 --- a/docs/data/data-grid/style-recipes/CellFocusNoOutline.js +++ b/docs/data/data-grid/style-recipes/CellFocusNoOutline.js @@ -5,7 +5,7 @@ import { useDemoData } from '@mui/x-data-grid-generator'; const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin']; export default function CellFocusNoOutline() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Employee', visibleFields: VISIBLE_FIELDS, rowLength: 100, @@ -14,6 +14,7 @@ export default function CellFocusNoOutline() { return (
({ })); export default function StylingRowsGrid() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, }); @@ -72,6 +72,7 @@ export default function StylingRowsGrid() { `super-app-theme--${params.row.status}`} /> diff --git a/docs/data/data-grid/style/StylingRowsGrid.tsx b/docs/data/data-grid/style/StylingRowsGrid.tsx index de1d8b44e7fdc..c4d50a57a4915 100644 --- a/docs/data/data-grid/style/StylingRowsGrid.tsx +++ b/docs/data/data-grid/style/StylingRowsGrid.tsx @@ -63,7 +63,7 @@ const StyledDataGrid = styled(DataGrid)(({ theme }) => ({ })); export default function StylingRowsGrid() { - const { data } = useDemoData({ + const { data, loading } = useDemoData({ dataSet: 'Commodity', rowLength: 100, }); @@ -72,6 +72,7 @@ export default function StylingRowsGrid() { `super-app-theme--${params.row.status}`} /> diff --git a/docs/data/data-grid/style/StylingRowsGrid.tsx.preview b/docs/data/data-grid/style/StylingRowsGrid.tsx.preview index fe48095d2b350..e25764355d336 100644 --- a/docs/data/data-grid/style/StylingRowsGrid.tsx.preview +++ b/docs/data/data-grid/style/StylingRowsGrid.tsx.preview @@ -1,4 +1,5 @@ `super-app-theme--${params.row.status}`} /> \ No newline at end of file diff --git a/docs/data/data-grid/virtualization/virtualization.md b/docs/data/data-grid/virtualization/virtualization.md index 46efb8f1de521..3dc949818c958 100644 --- a/docs/data/data-grid/virtualization/virtualization.md +++ b/docs/data/data-grid/virtualization/virtualization.md @@ -31,7 +31,12 @@ By default, columns coming under 150 pixels region are rendered outside of the v {{"demo": "ColumnVirtualizationGrid.js", "bg": "inline"}} -You can disable column virtualization by calling `apiRef.current.unstable_setColumnVirtualization(false)`, or by setting the column buffer to the number of total columns. +You can disable column virtualization by calling `apiRef.current.unstable_setColumnVirtualization(false)`, or by setting the [`columnBufferPx`](/x/api/data-grid/data-grid/#data-grid-prop-columnBufferPx) to a high value. + +:::info +Column virtualization is disabled when dynamic row height is enabled. +See [dynamic row height and column virtualization](/x/react-data-grid/row-height/#column-virtualization) to learn more. +::: ## Disable virtualization diff --git a/docs/data/date-pickers/adapters-locale/adapters-locale.md b/docs/data/date-pickers/adapters-locale/adapters-locale.md index 0168a00d75476..524ffb3df60c5 100644 --- a/docs/data/date-pickers/adapters-locale/adapters-locale.md +++ b/docs/data/date-pickers/adapters-locale/adapters-locale.md @@ -143,32 +143,32 @@ For example, they don't support day of the year or quarter. Here is the list of the currently supported formats: - The year - - ✅ 2-digits values (e.g: `23`) - - ✅ 4-digits values (e.g: `2023`) - - ❌ Values with ordinal (e.g: `2023th`) + - ✅ 2-digits values (for example, `23`) + - ✅ 4-digits values (for example, `2023`) + - ❌ Values with ordinal (for example, `2023th`) - The month - - ✅ 1-based digit (e.g: `08`) - - ✅ Multi-letter values (for example `Aug`, `August`) - - ❌ 1-letter values (e.g: `A`) because several months are represented with the same letter + - ✅ 1-based digit (for example, `08`) + - ✅ Multi-letter values (for example, `Aug`, `August`) + - ❌ 1-letter values (for example, `A`) because several months are represented with the same letter - The day of the month - - ✅ 1-based digit values (e.g: `24`) - - ✅ 1-based digit values with ordinal (e.g: `24th`) + - ✅ 1-based digit values (for example, `24`) + - ✅ 1-based digit values with ordinal (for example, `24th`) - The day of the week - - ✅ 0-based digit values (e.g: `03`) - - ✅ 1-based digit values (e.g: `04`) - - ✅ Multi-letter values (e.g: `Tue`, `Tuesday`) - - ❌ 1-letter values (e.g: `T`) because several days of the week are represented with the same letter + - ✅ 0-based digit values (for example, `03`) + - ✅ 1-based digit values (for example, `04`) + - ✅ Multi-letter values (for example, `Tue`, `Tuesday`) + - ❌ 1-letter values (for example, `T`) because several days of the week are represented with the same letter - The hours - - ✅ 0-based 12-hours values (e.g: `03`) - - ✅ 0-based 24-hours values (e.g: `15`) - - ❌ 1-based values (e.g: `24` instead of `00`) + - ✅ 0-based 12-hours values (for example, `03`) + - ✅ 0-based 24-hours values (for example, `15`) + - ❌ 1-based values (for example, `24` instead of `00`) - The minutes @@ -190,7 +190,7 @@ If you need to get the clean value from the input, you can remove this character ::: :::warning -Luxon is not able to respect the leading zeroes when using macro tokens (e.g: "DD"), so `shouldRespectLeadingZeros={true}` might lead to inconsistencies when using `AdapterLuxon`. +Luxon is not able to respect the leading zeroes when using macro tokens (for example "DD"), so `shouldRespectLeadingZeros={true}` might lead to inconsistencies when using `AdapterLuxon`. ::: {{"demo": "RespectLeadingZerosFieldFormat.js"}} diff --git a/docs/data/date-pickers/base-concepts/base-concepts.md b/docs/data/date-pickers/base-concepts/base-concepts.md index bdae427685bc9..ca61ae0cbe0f0 100644 --- a/docs/data/date-pickers/base-concepts/base-concepts.md +++ b/docs/data/date-pickers/base-concepts/base-concepts.md @@ -161,9 +161,14 @@ import type {} from '@mui/x-date-pickers-pro/themeAugmentation'; const theme = createTheme({ components: { MuiDatePicker: { + defaultProps: { + displayWeekNumber: true, + }, + }, + MuiDateRangeCalendar: { styleOverrides: { root: { - backgroundColor: 'red', + backgroundColor: '#f0f0f0', }, }, }, diff --git a/docs/data/date-pickers/calendar-systems/AdapterHijri.js b/docs/data/date-pickers/calendar-systems/AdapterHijri.js index fa738ee1e6e3e..377759e113758 100644 --- a/docs/data/date-pickers/calendar-systems/AdapterHijri.js +++ b/docs/data/date-pickers/calendar-systems/AdapterHijri.js @@ -46,14 +46,6 @@ function ButtonDateTimeField(props) { props: internalProps, }); - const handleTogglePicker = (event) => { - if (pickerContext.open) { - pickerContext.onClose(event); - } else { - pickerContext.onOpen(event); - } - }; - const valueStr = value == null ? parsedFormat : value.format(format); return ( @@ -62,7 +54,7 @@ function ButtonDateTimeField(props) { variant="outlined" color={hasValidationError ? 'error' : 'primary'} ref={InputProps?.ref} - onClick={handleTogglePicker} + onClick={() => pickerContext.setOpen((prev) => !prev)} > {label ? `${label}: ${valueStr}` : valueStr} diff --git a/docs/data/date-pickers/calendar-systems/AdapterHijri.tsx b/docs/data/date-pickers/calendar-systems/AdapterHijri.tsx index aa9b24d67f795..704dbee32ae79 100644 --- a/docs/data/date-pickers/calendar-systems/AdapterHijri.tsx +++ b/docs/data/date-pickers/calendar-systems/AdapterHijri.tsx @@ -50,14 +50,6 @@ function ButtonDateTimeField(props: DateTimePickerFieldProps) { props: internalProps, }); - const handleTogglePicker = (event: React.UIEvent) => { - if (pickerContext.open) { - pickerContext.onClose(event); - } else { - pickerContext.onOpen(event); - } - }; - const valueStr = value == null ? parsedFormat : value.format(format); return ( @@ -66,7 +58,7 @@ function ButtonDateTimeField(props: DateTimePickerFieldProps) { variant="outlined" color={hasValidationError ? 'error' : 'primary'} ref={InputProps?.ref} - onClick={handleTogglePicker} + onClick={() => pickerContext.setOpen((prev) => !prev)} > {label ? `${label}: ${valueStr}` : valueStr} diff --git a/docs/data/date-pickers/custom-components/custom-components.md b/docs/data/date-pickers/custom-components/custom-components.md index e05e9c6e808ab..ab573ddf7a56f 100644 --- a/docs/data/date-pickers/custom-components/custom-components.md +++ b/docs/data/date-pickers/custom-components/custom-components.md @@ -34,8 +34,8 @@ You can override the actions displayed by passing the `actions` prop to the `act actions: ['clear'], }, // The actions will be different between desktop and mobile - actionBar: ({ wrapperVariant }) => ({ - actions: wrapperVariant === 'desktop' ? [] : ['clear'], + actionBar: ({ variant }) => ({ + actions: variant === 'desktop' ? [] : ['clear'], }), }} /> diff --git a/docs/data/date-pickers/custom-field/BrowserV7Field.js b/docs/data/date-pickers/custom-field/BrowserV7Field.js index 3e6be2ea7b364..11f5b168ae3fc 100644 --- a/docs/data/date-pickers/custom-field/BrowserV7Field.js +++ b/docs/data/date-pickers/custom-field/BrowserV7Field.js @@ -5,8 +5,6 @@ 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'; - import { Unstable_PickersSectionList as PickersSectionList } from '@mui/x-date-pickers/PickersSectionList'; const BrowserFieldRoot = styled('div', { name: 'BrowserField', slot: 'Root' })({ @@ -27,7 +25,9 @@ const BrowserFieldContent = styled('div', { name: 'BrowserField', slot: 'Content }, ); -const BrowserTextField = React.forwardRef((props, ref) => { +const BrowserDateField = React.forwardRef((props, ref) => { + const fieldResponse = useDateField(props); + const { // Should be ignored enableAccessibleFieldDOMStructure, @@ -44,6 +44,9 @@ const BrowserTextField = React.forwardRef((props, ref) => { // Can be passed to a hidden element onChange, value, + // Can be passed to the button that clears the value + onClear, + clearable, // Can be used to render a custom label label, // Can be used to style the component @@ -55,7 +58,7 @@ const BrowserTextField = React.forwardRef((props, ref) => { InputProps: { ref: InputPropsRef, startAdornment, endAdornment } = {}, // The rest can be passed to the root element ...other - } = props; + } = fieldResponse; const handleRef = useForkRef(InputPropsRef, ref); @@ -80,21 +83,6 @@ const BrowserTextField = React.forwardRef((props, ref) => { ); }); -const BrowserDateField = React.forwardRef((props, ref) => { - const { slots, slotProps, ...textFieldProps } = props; - - const fieldResponse = useDateField(textFieldProps); - - /* 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 ( , - Omit< - React.HTMLAttributes, - keyof BaseSingleInputPickersTextFieldProps - > {} +const BrowserDateField = React.forwardRef( + (props: DatePickerFieldProps, ref: React.Ref) => { + const fieldResponse = useDateField(props); -const BrowserTextField = React.forwardRef( - (props: BrowserTextFieldProps, ref: React.Ref) => { const { // Should be ignored enableAccessibleFieldDOMStructure, @@ -64,6 +52,10 @@ const BrowserTextField = React.forwardRef( onChange, value, + // Can be passed to the button that clears the value + onClear, + clearable, + // Can be used to render a custom label label, @@ -78,7 +70,7 @@ const BrowserTextField = React.forwardRef( // The rest can be passed to the root element ...other - } = props; + } = fieldResponse; const handleRef = useForkRef(InputPropsRef, ref); @@ -104,33 +96,6 @@ const BrowserTextField = React.forwardRef( }, ); -interface BrowserDateFieldProps - extends UseDateFieldProps, - BaseSingleInputFieldProps< - // This usage of PickerValidDate will go away with TIsRange - PickerValidDate | null, - FieldSection, - true, - DateValidationError - > {} - -const BrowserDateField = React.forwardRef( - (props: BrowserDateFieldProps, ref: React.Ref) => { - const { slots, slotProps, ...textFieldProps } = props; - - const fieldResponse = useDateField(textFieldProps); - - /* 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 ( diff --git a/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.js b/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.js index 0023e32e477f4..5f7d2d494688d 100644 --- a/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.js +++ b/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.js @@ -5,7 +5,6 @@ import { styled } from '@mui/material/styles'; 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'; import { Unstable_PickersSectionList as PickersSectionList } from '@mui/x-date-pickers/PickersSectionList'; @@ -25,8 +24,6 @@ const BrowserFieldContent = styled('div', { name: 'BrowserField', slot: 'Content }, ); -// This demo uses `BasePickersTextFieldProps` instead of `BaseMultiInputPickersTextFieldProps`, -// That way you can reuse the same `BrowserTextField` for all your pickers, range or not. const BrowserTextField = React.forwardRef((props, ref) => { const { // Should be ignored @@ -84,12 +81,10 @@ const BrowserMultiInputDateRangeField = React.forwardRef((props, ref) => { const { slotProps, value, - defaultValue, format, onChange, readOnly, disabled, - onError, shouldDisableDate, minDate, maxDate, @@ -117,12 +112,10 @@ const BrowserMultiInputDateRangeField = React.forwardRef((props, ref) => { const fieldResponse = useMultiInputDateRangeField({ sharedProps: { value, - defaultValue, format, onChange, readOnly, disabled, - onError, shouldDisableDate, minDate, maxDate, diff --git a/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx b/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx index 725a629ce03f4..4c60152c21d0f 100644 --- a/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx +++ b/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx @@ -5,21 +5,17 @@ import { styled } from '@mui/material/styles'; import Stack from '@mui/material/Stack'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; -import { PickerValidDate } from '@mui/x-date-pickers/models'; import { DateRangePicker, + DateRangePickerFieldProps, DateRangePickerProps, } from '@mui/x-date-pickers-pro/DateRangePicker'; import { unstable_useMultiInputDateRangeField as useMultiInputDateRangeField } from '@mui/x-date-pickers-pro/MultiInputDateRangeField'; import { Unstable_PickersSectionList as PickersSectionList } from '@mui/x-date-pickers/PickersSectionList'; import { - RangeFieldSection, - BaseMultiInputFieldProps, - BasePickersTextFieldProps, MultiInputFieldSlotTextFieldProps, - DateRangeValidationError, - DateRange, - UseDateRangeFieldProps, + MultiInputFieldRefs, + BaseMultiInputPickersTextFieldProps, } from '@mui/x-date-pickers-pro/models'; const BrowserFieldRoot = styled('div', { name: 'BrowserField', slot: 'Root' })({ @@ -38,14 +34,12 @@ const BrowserFieldContent = styled('div', { name: 'BrowserField', slot: 'Content ); interface BrowserTextFieldProps - extends BasePickersTextFieldProps, + extends BaseMultiInputPickersTextFieldProps, Omit< React.HTMLAttributes, - keyof BasePickersTextFieldProps + keyof BaseMultiInputPickersTextFieldProps > {} -// This demo uses `BasePickersTextFieldProps` instead of `BaseMultiInputPickersTextFieldProps`, -// That way you can reuse the same `BrowserTextField` for all your pickers, range or not. const BrowserTextField = React.forwardRef( (props: BrowserTextFieldProps, ref: React.Ref) => { const { @@ -108,14 +102,11 @@ const BrowserTextField = React.forwardRef( ); interface BrowserMultiInputDateRangeFieldProps - extends UseDateRangeFieldProps, - BaseMultiInputFieldProps< - // This usage of PickerValidDate will go away with TIsRange - DateRange, - RangeFieldSection, - true, - DateRangeValidationError - > {} + extends Omit< + DateRangePickerFieldProps, + 'unstableFieldRef' | 'clearable' | 'onClear' + >, + MultiInputFieldRefs {} type BrowserMultiInputDateRangeFieldComponent = (( props: BrowserMultiInputDateRangeFieldProps & React.RefAttributes, @@ -126,12 +117,10 @@ const BrowserMultiInputDateRangeField = React.forwardRef( const { slotProps, value, - defaultValue, format, onChange, readOnly, disabled, - onError, shouldDisableDate, minDate, maxDate, @@ -162,12 +151,10 @@ const BrowserMultiInputDateRangeField = React.forwardRef( >({ sharedProps: { value, - defaultValue, format, onChange, readOnly, disabled, - onError, shouldDisableDate, minDate, maxDate, diff --git a/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.js b/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.js index a04931569d643..ae55770f60785 100644 --- a/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.js +++ b/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.js @@ -1,6 +1,5 @@ import * as React from 'react'; import useForkRef from '@mui/utils/useForkRef'; -import useSlotProps from '@mui/utils/useSlotProps'; import { styled } from '@mui/material/styles'; import IconButton from '@mui/material/IconButton'; import InputAdornment from '@mui/material/InputAdornment'; @@ -9,7 +8,7 @@ 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'; +import { usePickerContext } from '@mui/x-date-pickers/hooks'; import { Unstable_PickersSectionList as PickersSectionList } from '@mui/x-date-pickers/PickersSectionList'; const BrowserFieldRoot = styled('div', { name: 'BrowserField', slot: 'Root' })({ @@ -30,7 +29,9 @@ const BrowserFieldContent = styled('div', { name: 'BrowserField', slot: 'Content }, ); -const BrowserTextField = React.forwardRef((props, ref) => { +const BrowserSingleInputDateRangeField = React.forwardRef((props, ref) => { + const fieldResponse = useSingleInputDateRangeField(props); + const { // Should be ignored enableAccessibleFieldDOMStructure, @@ -47,6 +48,9 @@ const BrowserTextField = React.forwardRef((props, ref) => { // Can be passed to a hidden element onChange, value, + // Can be passed to the button that clears the value + onClear, + clearable, // Can be used to render a custom label label, // Can be used to style the component @@ -58,12 +62,19 @@ const BrowserTextField = React.forwardRef((props, ref) => { InputProps: { ref: InputPropsRef, startAdornment, endAdornment } = {}, // The rest can be passed to the root element ...other - } = props; + } = fieldResponse; + const pickerContext = usePickerContext(); const handleRef = useForkRef(InputPropsRef, 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: ( - + pickerContext.setOpen((prev) => !prev)}> - ), - }; - - const fieldResponse = useSingleInputDateRangeField(textFieldProps); - - /* 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 ( ); }); diff --git a/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.tsx b/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.tsx index adfe261465913..68f5f4c21737b 100644 --- a/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.tsx +++ b/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; import useForkRef from '@mui/utils/useForkRef'; -import useSlotProps from '@mui/utils/useSlotProps'; import { styled } from '@mui/material/styles'; import IconButton from '@mui/material/IconButton'; import InputAdornment from '@mui/material/InputAdornment'; @@ -9,25 +8,13 @@ import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import { DateRangePicker, + DateRangePickerFieldProps, DateRangePickerProps, } from '@mui/x-date-pickers-pro/DateRangePicker'; -import { - unstable_useSingleInputDateRangeField as useSingleInputDateRangeField, - UseSingleInputDateRangeFieldProps, -} from '@mui/x-date-pickers-pro/SingleInputDateRangeField'; -import { useClearableField } from '@mui/x-date-pickers/hooks'; +import { unstable_useSingleInputDateRangeField as useSingleInputDateRangeField } from '@mui/x-date-pickers-pro/SingleInputDateRangeField'; +import { usePickerContext } from '@mui/x-date-pickers/hooks'; import { Unstable_PickersSectionList as PickersSectionList } from '@mui/x-date-pickers/PickersSectionList'; -import { - BasePickersTextFieldProps, - DateRangeValidationError, - RangeFieldSection, - DateRange, - FieldType, -} from '@mui/x-date-pickers-pro/models'; -import { - BaseSingleInputFieldProps, - PickerValidDate, -} from '@mui/x-date-pickers/models'; +import { FieldType } from '@mui/x-date-pickers-pro/models'; const BrowserFieldRoot = styled('div', { name: 'BrowserField', slot: 'Root' })({ display: 'flex', @@ -47,15 +34,16 @@ const BrowserFieldContent = styled('div', { name: 'BrowserField', slot: 'Content }, ); -interface BrowserTextFieldProps - extends BasePickersTextFieldProps, - Omit< - React.HTMLAttributes, - keyof BasePickersTextFieldProps - > {} +interface BrowserSingleInputDateRangeFieldProps extends DateRangePickerFieldProps {} + +type BrowserSingleInputDateRangeFieldComponent = (( + props: BrowserSingleInputDateRangeFieldProps & React.RefAttributes, +) => React.JSX.Element) & { fieldType?: FieldType }; + +const BrowserSingleInputDateRangeField = React.forwardRef( + (props: BrowserSingleInputDateRangeFieldProps, ref: React.Ref) => { + const fieldResponse = useSingleInputDateRangeField(props); -const BrowserTextField = React.forwardRef( - (props: BrowserTextFieldProps, ref: React.Ref) => { const { // Should be ignored enableAccessibleFieldDOMStructure, @@ -75,6 +63,10 @@ const BrowserTextField = React.forwardRef( onChange, value, + // Can be passed to the button that clears the value + onClear, + clearable, + // Can be used to render a custom label label, @@ -89,12 +81,19 @@ const BrowserTextField = React.forwardRef( // The rest can be passed to the root element ...other - } = props; + } = fieldResponse; + const pickerContext = usePickerContext(); const handleRef = useForkRef(InputPropsRef, ref); return ( - + {startAdornment} {endAdornment} - - ); - }, -); - -interface BrowserSingleInputDateRangeFieldProps - extends UseSingleInputDateRangeFieldProps, - BaseSingleInputFieldProps< - // This usage of PickerValidDate will go away with TIsRange - DateRange, - RangeFieldSection, - true, - 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: typeof props = useSlotProps({ - elementType: 'input', - externalSlotProps: slotProps?.textField, - externalForwardedProps: other, - ownerState: props as any, - }); - - textFieldProps.InputProps = { - ...textFieldProps.InputProps, - endAdornment: ( - + pickerContext.setOpen((prev) => !prev)}> - ), - }; - - const fieldResponse = useSingleInputDateRangeField( - textFieldProps, - ); - - /* 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; @@ -180,29 +123,11 @@ 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 ( ); }, diff --git a/docs/data/date-pickers/custom-field/JoyV6Field.js b/docs/data/date-pickers/custom-field/JoyV6Field.js index 9d6802c1ecef0..156d8200c2f5f 100644 --- a/docs/data/date-pickers/custom-field/JoyV6Field.js +++ b/docs/data/date-pickers/custom-field/JoyV6Field.js @@ -17,53 +17,41 @@ 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 joyTheme = extendJoyTheme(); -const JoyField = React.forwardRef((props, ref) => { +const JoyDateField = React.forwardRef((props, ref) => { + const fieldResponse = useDateField({ + ...props, + enableAccessibleFieldDOMStructure: false, + }); + const { // Should be ignored enableAccessibleFieldDOMStructure, + // Can be passed to the button that clears the value + onClear, + clearable, disabled, id, label, InputProps: { ref: containerRef, startAdornment, endAdornment } = {}, - formControlSx, - endDecorator, - startDecorator, - slotProps, inputRef, + slots, + slotProps, ...other - } = props; + } = fieldResponse; return ( - + {label} - {startAdornment} - {startDecorator} - - } - endDecorator={ - - {endAdornment} - {endDecorator} - - } + startDecorator={startAdornment} + endDecorator={endAdornment} slotProps={{ - ...slotProps, - root: { ...slotProps?.root, ref: containerRef }, - input: { ...slotProps?.input, ref: inputRef }, + input: { ref: inputRef }, }} {...other} /> @@ -71,39 +59,12 @@ const JoyField = React.forwardRef((props, ref) => { ); }); -const JoyDateField = 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 JoyDatePicker = React.forwardRef((props, ref) => { return ( ); }); @@ -129,11 +90,7 @@ export default function JoyV6Field() { - + diff --git a/docs/data/date-pickers/custom-field/JoyV6Field.tsx b/docs/data/date-pickers/custom-field/JoyV6Field.tsx index a2dfdebe92559..9e30ca9e0b717 100644 --- a/docs/data/date-pickers/custom-field/JoyV6Field.tsx +++ b/docs/data/date-pickers/custom-field/JoyV6Field.tsx @@ -10,123 +10,61 @@ import { CssVarsProvider, THEME_ID, } from '@mui/joy/styles'; -import Input, { InputProps } from '@mui/joy/Input'; +import Input from '@mui/joy/Input'; import FormControl from '@mui/joy/FormControl'; import FormLabel from '@mui/joy/FormLabel'; 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, - PickerValidDate, -} from '@mui/x-date-pickers/models'; + DatePicker, + DatePickerFieldProps, + DatePickerProps, +} from '@mui/x-date-pickers/DatePicker'; +import { unstable_useDateField as useDateField } from '@mui/x-date-pickers/DateField'; const joyTheme = extendJoyTheme(); -interface JoyFieldProps extends InputProps { - label?: React.ReactNode; - inputRef?: React.Ref; - enableAccessibleFieldDOMStructure?: boolean; - InputProps?: { - ref?: React.Ref; - endAdornment?: React.ReactNode; - startAdornment?: React.ReactNode; - }; - formControlSx?: InputProps['sx']; -} - -type JoyFieldComponent = (( - props: JoyFieldProps & React.RefAttributes, -) => React.JSX.Element) & { propTypes?: any }; +const JoyDateField = React.forwardRef( + (props: DatePickerFieldProps, ref: React.Ref) => { + const fieldResponse = useDateField({ + ...props, + enableAccessibleFieldDOMStructure: false, + }); -const JoyField = React.forwardRef( - (props: JoyFieldProps, ref: React.Ref) => { const { // Should be ignored enableAccessibleFieldDOMStructure, + // Can be passed to the button that clears the value + onClear, + clearable, + disabled, id, label, InputProps: { ref: containerRef, startAdornment, endAdornment } = {}, - formControlSx, - endDecorator, - startDecorator, - slotProps, inputRef, + slots, + slotProps, ...other - } = props; + } = fieldResponse; return ( - + {label} - {startAdornment} - {startDecorator} - - } - endDecorator={ - - {endAdornment} - {endDecorator} - - } + startDecorator={startAdornment} + endDecorator={endAdornment} slotProps={{ - ...slotProps, - root: { ...slotProps?.root, ref: containerRef }, - input: { ...slotProps?.input, ref: inputRef }, + input: { ref: inputRef }, }} {...other} /> ); }, -) as JoyFieldComponent; - -interface JoyDateFieldProps - extends UseDateFieldProps, - BaseSingleInputFieldProps< - // This usage of PickerValidDate will go away with TIsRange - PickerValidDate | null, - FieldSection, - false, - DateValidationError - > {} - -const JoyDateField = React.forwardRef( - (props: JoyDateFieldProps, 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 JoyDatePicker = React.forwardRef( @@ -136,15 +74,6 @@ const JoyDatePicker = React.forwardRef( ref={ref} {...props} slots={{ ...props.slots, field: JoyDateField }} - slotProps={{ - ...props.slotProps, - field: { - ...props.slotProps?.field, - formControlSx: { - flexDirection: 'row', - }, - } as any, - }} /> ); }, @@ -171,11 +100,7 @@ export default function JoyV6Field() { - + diff --git a/docs/data/date-pickers/custom-field/JoyV6Field.tsx.preview b/docs/data/date-pickers/custom-field/JoyV6Field.tsx.preview index cff735f8a7af0..d1fc44acb736c 100644 --- a/docs/data/date-pickers/custom-field/JoyV6Field.tsx.preview +++ b/docs/data/date-pickers/custom-field/JoyV6Field.tsx.preview @@ -2,11 +2,7 @@ - + \ No newline at end of file diff --git a/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.js b/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.js index 74b17040c1529..61a8a5d231f7d 100644 --- a/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.js +++ b/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.js @@ -19,7 +19,6 @@ import FormLabel from '@mui/joy/FormLabel'; import Typography from '@mui/joy/Typography'; 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'; @@ -106,12 +105,10 @@ const JoyMultiInputDateRangeField = React.forwardRef((props, ref) => { const { slotProps, value, - defaultValue, format, onChange, readOnly, disabled, - onError, shouldDisableDate, minDate, maxDate, @@ -120,6 +117,8 @@ const JoyMultiInputDateRangeField = React.forwardRef((props, ref) => { selectedSections, onSelectedSectionsChange, className, + unstableStartFieldRef, + unstableEndFieldRef, } = props; const startTextFieldProps = useSlotProps({ @@ -137,12 +136,10 @@ const JoyMultiInputDateRangeField = React.forwardRef((props, ref) => { const fieldResponse = useMultiInputDateRangeField({ sharedProps: { value, - defaultValue, format, onChange, readOnly, disabled, - onError, shouldDisableDate, minDate, maxDate, @@ -154,6 +151,8 @@ const JoyMultiInputDateRangeField = React.forwardRef((props, ref) => { }, startTextFieldProps, endTextFieldProps, + unstableStartFieldRef, + unstableEndFieldRef, }); return ( diff --git a/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.tsx b/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.tsx index ce976dd69843a..f4c28e574437b 100644 --- a/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.tsx +++ b/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.tsx @@ -19,19 +19,15 @@ import FormLabel from '@mui/joy/FormLabel'; import Typography, { TypographyProps } from '@mui/joy/Typography'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; -import { PickerValidDate } from '@mui/x-date-pickers/models'; import { DateRangePicker, + DateRangePickerFieldProps, DateRangePickerProps, } from '@mui/x-date-pickers-pro/DateRangePicker'; import { unstable_useMultiInputDateRangeField as useMultiInputDateRangeField } from '@mui/x-date-pickers-pro/MultiInputDateRangeField'; import { - BaseMultiInputFieldProps, - DateRange, - DateRangeValidationError, + MultiInputFieldRefs, MultiInputFieldSlotTextFieldProps, - RangeFieldSection, - UseDateRangeFieldProps, } from '@mui/x-date-pickers-pro/models'; const joyTheme = extendJoyTheme(); @@ -132,14 +128,11 @@ const MultiInputJoyDateRangeFieldSeparator = styled( )({ marginTop: '25px' }); interface JoyMultiInputDateRangeFieldProps - extends UseDateRangeFieldProps, - BaseMultiInputFieldProps< - // This usage of PickerValidDate will go away with TIsRange - DateRange, - RangeFieldSection, - false, - DateRangeValidationError - > {} + extends Omit< + DateRangePickerFieldProps, + 'unstableFieldRef' | 'clearable' | 'onClear' + >, + MultiInputFieldRefs {} type JoyMultiInputDateRangeFieldComponent = (( props: JoyMultiInputDateRangeFieldProps & React.RefAttributes, @@ -150,12 +143,10 @@ const JoyMultiInputDateRangeField = React.forwardRef( const { slotProps, value, - defaultValue, format, onChange, readOnly, disabled, - onError, shouldDisableDate, minDate, maxDate, @@ -164,6 +155,8 @@ const JoyMultiInputDateRangeField = React.forwardRef( selectedSections, onSelectedSectionsChange, className, + unstableStartFieldRef, + unstableEndFieldRef, } = props; const startTextFieldProps = useSlotProps({ @@ -184,12 +177,10 @@ const JoyMultiInputDateRangeField = React.forwardRef( >({ sharedProps: { value, - defaultValue, format, onChange, readOnly, disabled, - onError, shouldDisableDate, minDate, maxDate, @@ -201,6 +192,8 @@ const JoyMultiInputDateRangeField = React.forwardRef( }, startTextFieldProps, endTextFieldProps, + unstableStartFieldRef, + unstableEndFieldRef, }); return ( diff --git a/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.js b/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.js index 0ede431a9e5bc..69123038f8508 100644 --- a/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.js +++ b/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.js @@ -4,63 +4,66 @@ import { useColorScheme as useMaterialColorScheme, Experimental_CssVarsProvider as MaterialCssVarsProvider, } from '@mui/material/styles'; -import useSlotProps from '@mui/utils/useSlotProps'; import { extendTheme as extendJoyTheme, useColorScheme, CssVarsProvider, THEME_ID, } from '@mui/joy/styles'; +import { createSvgIcon } from '@mui/joy/utils'; import Input from '@mui/joy/Input'; import FormControl from '@mui/joy/FormControl'; import FormLabel from '@mui/joy/FormLabel'; -import IconButton from '@mui/joy/IconButton'; -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'; + +export const DateRangeIcon = createSvgIcon( + , + 'DateRange', +); const joyTheme = extendJoyTheme(); -const JoyField = React.forwardRef((props, ref) => { +const JoySingleInputDateRangeField = React.forwardRef((props, ref) => { + const fieldResponse = useSingleInputDateRangeField({ + ...props, + enableAccessibleFieldDOMStructure: false, + }); + const { // Should be ignored enableAccessibleFieldDOMStructure, + // Can be passed to the button that clears the value + onClear, + clearable, disabled, id, label, - InputProps: { ref: containerRef, startAdornment, endAdornment } = {}, - endDecorator, - startDecorator, - slotProps, + InputProps: { ref: containerRef } = {}, inputRef, + slots, + slotProps, ...other - } = props; + } = fieldResponse; return ( - + {label} - {startAdornment} - {startDecorator} - - } - endDecorator={ - - {endAdornment} - {endDecorator} - - } + endDecorator={} slotProps={{ - ...slotProps, - root: { ...slotProps?.root, ref: containerRef }, - input: { ...slotProps?.input, ref: inputRef }, + input: { ref: inputRef }, }} {...other} /> @@ -68,76 +71,14 @@ const JoyField = React.forwardRef((props, ref) => { ); }); -const JoySingleInputDateRangeField = React.forwardRef((props, ref) => { - const { slots, slotProps, onAdornmentClick, ...other } = props; - - const textFieldProps = useSlotProps({ - elementType: FormControl, - externalSlotProps: slotProps?.textField, - externalForwardedProps: other, - ownerState: props, - }); - - 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 ( - - - - } - /> - ); -}); - JoySingleInputDateRangeField.fieldType = 'single-input'; const JoySingleInputDateRangePicker = React.forwardRef((props, ref) => { - const [isOpen, setIsOpen] = React.useState(false); - - const toggleOpen = (event) => { - // allows toggle behavior - event.stopPropagation(); - setIsOpen((currentOpen) => !currentOpen); - }; - - const handleOpen = () => setIsOpen(true); - - const handleClose = () => setIsOpen(false); - return ( ); }); @@ -163,11 +104,7 @@ export default function JoyV6SingleInputRangeField() { - + diff --git a/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.tsx b/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.tsx index e2815f70d823b..822610feac08b 100644 --- a/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.tsx +++ b/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.tsx @@ -4,193 +4,95 @@ import { useColorScheme as useMaterialColorScheme, Experimental_CssVarsProvider as MaterialCssVarsProvider, } from '@mui/material/styles'; -import useSlotProps from '@mui/utils/useSlotProps'; import { extendTheme as extendJoyTheme, useColorScheme, CssVarsProvider, THEME_ID, } from '@mui/joy/styles'; -import Input, { InputProps } from '@mui/joy/Input'; +import { createSvgIcon } from '@mui/joy/utils'; +import Input from '@mui/joy/Input'; import FormControl from '@mui/joy/FormControl'; import FormLabel from '@mui/joy/FormLabel'; -import IconButton from '@mui/joy/IconButton'; -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, + DateRangePickerFieldProps, DateRangePickerProps, } from '@mui/x-date-pickers-pro/DateRangePicker'; -import { - unstable_useSingleInputDateRangeField as useSingleInputDateRangeField, - UseSingleInputDateRangeFieldProps, -} from '@mui/x-date-pickers-pro/SingleInputDateRangeField'; -import { useClearableField } from '@mui/x-date-pickers/hooks'; -import { - BaseSingleInputFieldProps, - PickerValidDate, -} from '@mui/x-date-pickers/models'; -import { - RangeFieldSection, - DateRange, - DateRangeValidationError, - FieldType, -} from '@mui/x-date-pickers-pro/models'; +import { unstable_useSingleInputDateRangeField as useSingleInputDateRangeField } from '@mui/x-date-pickers-pro/SingleInputDateRangeField'; +import { FieldType } from '@mui/x-date-pickers-pro/models'; + +export const DateRangeIcon = createSvgIcon( + , + 'DateRange', +); const joyTheme = extendJoyTheme(); -interface JoyFieldProps extends InputProps { - label?: React.ReactNode; - inputRef?: React.Ref; - enableAccessibleFieldDOMStructure?: boolean; - InputProps?: { - ref?: React.Ref; - endAdornment?: React.ReactNode; - startAdornment?: React.ReactNode; - }; -} +type JoySingleInputDateRangeFieldComponent = (( + props: DateRangePickerFieldProps & React.RefAttributes, +) => React.JSX.Element) & { fieldType?: FieldType }; -type JoyFieldComponent = (( - props: JoyFieldProps & React.RefAttributes, -) => React.JSX.Element) & { propTypes?: any }; +const JoySingleInputDateRangeField = React.forwardRef( + (props: DateRangePickerFieldProps, ref: React.Ref) => { + const fieldResponse = useSingleInputDateRangeField({ + ...props, + enableAccessibleFieldDOMStructure: false, + }); -const JoyField = React.forwardRef( - (props: JoyFieldProps, ref: React.Ref) => { const { // Should be ignored enableAccessibleFieldDOMStructure, + // Can be passed to the button that clears the value + onClear, + clearable, + disabled, id, label, - InputProps: { ref: containerRef, startAdornment, endAdornment } = {}, - endDecorator, - startDecorator, - slotProps, + InputProps: { ref: containerRef } = {}, inputRef, + slots, + slotProps, ...other - } = props; + } = fieldResponse; return ( - + {label} - {startAdornment} - {startDecorator} - - } - endDecorator={ - - {endAdornment} - {endDecorator} - - } + endDecorator={} slotProps={{ - ...slotProps, - root: { ...slotProps?.root, ref: containerRef }, - input: { ...slotProps?.input, ref: inputRef }, + input: { ref: inputRef }, }} {...other} /> ); }, -) as JoyFieldComponent; - -interface JoySingleInputDateRangeFieldProps - extends UseSingleInputDateRangeFieldProps, - BaseSingleInputFieldProps< - // This usage of PickerValidDate will go away with TIsRange - DateRange, - RangeFieldSection, - false, - DateRangeValidationError - > { - onAdornmentClick?: () => void; -} - -type JoySingleInputDateRangeFieldComponent = (( - props: JoySingleInputDateRangeFieldProps & React.RefAttributes, -) => React.JSX.Element) & { fieldType?: FieldType }; - -const JoySingleInputDateRangeField = React.forwardRef( - (props: JoySingleInputDateRangeFieldProps, ref: React.Ref) => { - const { slots, slotProps, onAdornmentClick, ...other } = props; - - const textFieldProps: JoySingleInputDateRangeFieldProps = useSlotProps({ - elementType: FormControl, - externalSlotProps: slotProps?.textField, - externalForwardedProps: other, - ownerState: props as any, - }); - - const fieldResponse = useSingleInputDateRangeField< - false, - JoySingleInputDateRangeFieldProps - >({ ...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 JoySingleInputDateRangeFieldComponent; JoySingleInputDateRangeField.fieldType = 'single-input'; const JoySingleInputDateRangePicker = React.forwardRef( (props: DateRangePickerProps, ref: React.Ref) => { - const [isOpen, setIsOpen] = React.useState(false); - - const toggleOpen = (event: React.PointerEvent) => { - // allows toggle behavior - event.stopPropagation(); - setIsOpen((currentOpen) => !currentOpen); - }; - - const handleOpen = () => setIsOpen(true); - - const handleClose = () => setIsOpen(false); - return ( ); }, @@ -217,11 +119,7 @@ export default function JoyV6SingleInputRangeField() { - + diff --git a/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.tsx.preview b/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.tsx.preview index 90b0c5ff3c08f..b2b8613af3c6d 100644 --- a/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.tsx.preview +++ b/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.tsx.preview @@ -2,11 +2,7 @@ - + \ No newline at end of file diff --git a/docs/data/date-pickers/custom-field/behavior-autocomplete/MaterialDatePicker.js b/docs/data/date-pickers/custom-field/behavior-autocomplete/MaterialDatePicker.js index 0e849ab1228c0..2856b3af1a2d5 100644 --- a/docs/data/date-pickers/custom-field/behavior-autocomplete/MaterialDatePicker.js +++ b/docs/data/date-pickers/custom-field/behavior-autocomplete/MaterialDatePicker.js @@ -25,7 +25,7 @@ function AutocompleteField(props) { ...other } = forwardedProps; - const { hasValidationError } = useValidation({ + const { hasValidationError, getValidationErrorForNewValue } = useValidation({ validator: validateDate, value, timezone, @@ -85,7 +85,9 @@ function AutocompleteField(props) { }} value={value} onChange={(_, newValue) => { - onChange?.(newValue, { validationError: null }); + onChange(newValue, { + validationError: getValidationErrorForNewValue(newValue), + }); }} isOptionEqualToValue={(option, valueToCheck) => option.toISOString() === valueToCheck.toISOString() diff --git a/docs/data/date-pickers/custom-field/behavior-autocomplete/MaterialDatePicker.tsx b/docs/data/date-pickers/custom-field/behavior-autocomplete/MaterialDatePicker.tsx index 10228ff08be1b..7633f42d7199e 100644 --- a/docs/data/date-pickers/custom-field/behavior-autocomplete/MaterialDatePicker.tsx +++ b/docs/data/date-pickers/custom-field/behavior-autocomplete/MaterialDatePicker.tsx @@ -36,7 +36,7 @@ function AutocompleteField(props: AutocompleteFieldProps) { ...other } = forwardedProps; - const { hasValidationError } = useValidation({ + const { hasValidationError, getValidationErrorForNewValue } = useValidation({ validator: validateDate, value, timezone, @@ -96,7 +96,9 @@ function AutocompleteField(props: AutocompleteFieldProps) { }} value={value} onChange={(_, newValue) => { - onChange?.(newValue, { validationError: null }); + onChange(newValue, { + validationError: getValidationErrorForNewValue(newValue), + }); }} isOptionEqualToValue={(option, valueToCheck) => option.toISOString() === valueToCheck.toISOString() diff --git a/docs/data/date-pickers/custom-field/behavior-button/MaterialDatePicker.js b/docs/data/date-pickers/custom-field/behavior-button/MaterialDatePicker.js index f9306981aac0c..0e30e8d2605aa 100644 --- a/docs/data/date-pickers/custom-field/behavior-button/MaterialDatePicker.js +++ b/docs/data/date-pickers/custom-field/behavior-button/MaterialDatePicker.js @@ -34,14 +34,6 @@ function ButtonDateField(props) { props: internalProps, }); - const handleTogglePicker = (event) => { - if (pickerContext.open) { - pickerContext.onClose(event); - } else { - pickerContext.onOpen(event); - } - }; - const valueStr = value == null ? parsedFormat : value.format(format); return ( @@ -50,7 +42,7 @@ function ButtonDateField(props) { variant="outlined" color={hasValidationError ? 'error' : 'primary'} ref={InputProps?.ref} - onClick={handleTogglePicker} + onClick={() => pickerContext.setOpen((prev) => !prev)} > {label ? `${label}: ${valueStr}` : valueStr} diff --git a/docs/data/date-pickers/custom-field/behavior-button/MaterialDatePicker.tsx b/docs/data/date-pickers/custom-field/behavior-button/MaterialDatePicker.tsx index ac64ebd3a5f01..1da1b675decd7 100644 --- a/docs/data/date-pickers/custom-field/behavior-button/MaterialDatePicker.tsx +++ b/docs/data/date-pickers/custom-field/behavior-button/MaterialDatePicker.tsx @@ -38,14 +38,6 @@ function ButtonDateField(props: DatePickerFieldProps) { props: internalProps, }); - const handleTogglePicker = (event: React.UIEvent) => { - if (pickerContext.open) { - pickerContext.onClose(event); - } else { - pickerContext.onOpen(event); - } - }; - const valueStr = value == null ? parsedFormat : value.format(format); return ( @@ -54,7 +46,7 @@ function ButtonDateField(props: DatePickerFieldProps) { variant="outlined" color={hasValidationError ? 'error' : 'primary'} ref={InputProps?.ref} - onClick={handleTogglePicker} + onClick={() => pickerContext.setOpen((prev) => !prev)} > {label ? `${label}: ${valueStr}` : valueStr} diff --git a/docs/data/date-pickers/custom-field/behavior-button/MaterialDateRangePicker.js b/docs/data/date-pickers/custom-field/behavior-button/MaterialDateRangePicker.js index 7c56f7a2693a0..0884deadb8b48 100644 --- a/docs/data/date-pickers/custom-field/behavior-button/MaterialDateRangePicker.js +++ b/docs/data/date-pickers/custom-field/behavior-button/MaterialDateRangePicker.js @@ -36,14 +36,6 @@ function ButtonDateRangeField(props) { props: internalProps, }); - const handleTogglePicker = (event) => { - if (pickerContext.open) { - pickerContext.onClose(event); - } else { - pickerContext.onOpen(event); - } - }; - const formattedValue = (value ?? [null, null]) .map((date) => (date == null ? parsedFormat : date.format(format))) .join(' – '); @@ -54,7 +46,7 @@ function ButtonDateRangeField(props) { variant="outlined" color={hasValidationError ? 'error' : 'primary'} ref={InputProps?.ref} - onClick={handleTogglePicker} + onClick={() => pickerContext.setOpen((prev) => !prev)} > {label ? `${label}: ${formattedValue}` : formattedValue} diff --git a/docs/data/date-pickers/custom-field/behavior-button/MaterialDateRangePicker.tsx b/docs/data/date-pickers/custom-field/behavior-button/MaterialDateRangePicker.tsx index fbc0cd45c51ee..9361a51c256a1 100644 --- a/docs/data/date-pickers/custom-field/behavior-button/MaterialDateRangePicker.tsx +++ b/docs/data/date-pickers/custom-field/behavior-button/MaterialDateRangePicker.tsx @@ -40,14 +40,6 @@ function ButtonDateRangeField(props: DateRangePickerFieldProps) { props: internalProps, }); - const handleTogglePicker = (event: React.UIEvent) => { - if (pickerContext.open) { - pickerContext.onClose(event); - } else { - pickerContext.onOpen(event); - } - }; - const formattedValue = (value ?? [null, null]) .map((date: Dayjs) => (date == null ? parsedFormat : date.format(format))) .join(' – '); @@ -58,7 +50,7 @@ function ButtonDateRangeField(props: DateRangePickerFieldProps) { variant="outlined" color={hasValidationError ? 'error' : 'primary'} ref={InputProps?.ref} - onClick={handleTogglePicker} + onClick={() => pickerContext.setOpen((prev) => !prev)} > {label ? `${label}: ${formattedValue}` : formattedValue} diff --git a/docs/data/date-pickers/custom-field/behavior-masked-text-field/MaskedMaterialTextField.js b/docs/data/date-pickers/custom-field/behavior-masked-text-field/MaskedMaterialTextField.js index 0723d4565c514..107fb273f4964 100644 --- a/docs/data/date-pickers/custom-field/behavior-masked-text-field/MaskedMaterialTextField.js +++ b/docs/data/date-pickers/custom-field/behavior-masked-text-field/MaskedMaterialTextField.js @@ -2,7 +2,6 @@ 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'; @@ -15,7 +14,7 @@ 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) { +function getInputValueFromValue(value, format) { if (value == null) { return ''; } @@ -23,35 +22,21 @@ function getValueStrFromValue(value, format) { return value.isValid() ? value.format(format) : ''; } -function MaskedField(props) { +function MaskedDateField(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', - }); + const { format, value, onChange, timezone } = internalProps; // Control the input text const [inputValue, setInputValue] = React.useState(() => - getValueStrFromValue(value, format), + getInputValueFromValue(value, format), ); React.useEffect(() => { if (value && value.isValid()) { - const newDisplayDate = getValueStrFromValue(value, format); + const newDisplayDate = getInputValueFromValue(value, format); setInputValue(newDisplayDate); } }, [format, value]); @@ -61,22 +46,17 @@ function MaskedField(props) { const { hasValidationError, getValidationErrorForNewValue } = useValidation({ value, timezone, - onError, props: internalProps, validator: validateDate, }); - const handleValueStrChange = (newValueStr) => { - setInputValue(newValueStr); - - const newValue = dayjs(newValueStr, format); - setValue(newValue); + const handleInputValueChange = (newInputValue) => { + setInputValue(newInputValue); - if (onChange) { - onChange(newValue, { - validationError: getValidationErrorForNewValue(newValue), - }); - } + const newValue = dayjs(newInputValue, format); + onChange(newValue, { + validationError: getValidationErrorForNewValue(newValue), + }); }; const rifmFormat = React.useMemo(() => { @@ -137,7 +117,7 @@ function MaskedField(props) { const rifmProps = useRifm({ value: inputValue, - onChange: handleValueStrChange, + onChange: handleInputValueChange, format: rifmFormat, }); @@ -152,7 +132,9 @@ function MaskedField(props) { } function MaskedFieldDatePicker(props) { - return ; + return ( + + ); } export default function MaskedMaterialTextField() { diff --git a/docs/data/date-pickers/custom-field/behavior-masked-text-field/MaskedMaterialTextField.tsx b/docs/data/date-pickers/custom-field/behavior-masked-text-field/MaskedMaterialTextField.tsx index 13c0a71b54568..aa7b8023fcaf5 100644 --- a/docs/data/date-pickers/custom-field/behavior-masked-text-field/MaskedMaterialTextField.tsx +++ b/docs/data/date-pickers/custom-field/behavior-masked-text-field/MaskedMaterialTextField.tsx @@ -2,7 +2,6 @@ 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 { @@ -19,7 +18,7 @@ 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) { +function getInputValueFromValue(value: Dayjs | null, format: string) { if (value == null) { return ''; } @@ -27,35 +26,21 @@ function getValueStrFromValue(value: Dayjs | null, format: string) { return value.isValid() ? value.format(format) : ''; } -function MaskedField(props: DatePickerFieldProps) { +function MaskedDateField(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', - }); + const { format, value, onChange, timezone } = internalProps; // Control the input text const [inputValue, setInputValue] = React.useState(() => - getValueStrFromValue(value, format), + getInputValueFromValue(value, format), ); React.useEffect(() => { if (value && value.isValid()) { - const newDisplayDate = getValueStrFromValue(value, format); + const newDisplayDate = getInputValueFromValue(value, format); setInputValue(newDisplayDate); } }, [format, value]); @@ -65,22 +50,17 @@ function MaskedField(props: DatePickerFieldProps) { const { hasValidationError, getValidationErrorForNewValue } = useValidation({ value, timezone, - onError, props: internalProps, validator: validateDate, }); - const handleValueStrChange = (newValueStr: string) => { - setInputValue(newValueStr); - - const newValue = dayjs(newValueStr, format); - setValue(newValue); + const handleInputValueChange = (newInputValue: string) => { + setInputValue(newInputValue); - if (onChange) { - onChange(newValue, { - validationError: getValidationErrorForNewValue(newValue), - }); - } + const newValue = dayjs(newInputValue, format); + onChange(newValue, { + validationError: getValidationErrorForNewValue(newValue), + }); }; const rifmFormat = React.useMemo(() => { @@ -141,7 +121,7 @@ function MaskedField(props: DatePickerFieldProps) { const rifmProps = useRifm({ value: inputValue, - onChange: handleValueStrChange, + onChange: handleInputValueChange, format: rifmFormat, }); @@ -156,7 +136,9 @@ function MaskedField(props: DatePickerFieldProps) { } function MaskedFieldDatePicker(props: DatePickerProps) { - return ; + return ( + + ); } export default function MaskedMaterialTextField() { diff --git a/docs/data/date-pickers/custom-field/behavior-read-only-text-field/MaterialDatePicker.js b/docs/data/date-pickers/custom-field/behavior-read-only-text-field/MaterialDatePicker.js index 1e7d773f6fdf6..c5637b320e0ed 100644 --- a/docs/data/date-pickers/custom-field/behavior-read-only-text-field/MaterialDatePicker.js +++ b/docs/data/date-pickers/custom-field/behavior-read-only-text-field/MaterialDatePicker.js @@ -26,14 +26,6 @@ function ReadOnlyDateField(props) { props: internalProps, }); - const handleTogglePicker = (event) => { - if (pickerContext.open) { - pickerContext.onClose(event); - } else { - pickerContext.onOpen(event); - } - }; - return ( pickerContext.setOpen((prev) => !prev)} /> ); } diff --git a/docs/data/date-pickers/custom-field/behavior-read-only-text-field/MaterialDatePicker.tsx b/docs/data/date-pickers/custom-field/behavior-read-only-text-field/MaterialDatePicker.tsx index 1fd235a778199..a42da5e10407c 100644 --- a/docs/data/date-pickers/custom-field/behavior-read-only-text-field/MaterialDatePicker.tsx +++ b/docs/data/date-pickers/custom-field/behavior-read-only-text-field/MaterialDatePicker.tsx @@ -30,14 +30,6 @@ function ReadOnlyDateField(props: DatePickerFieldProps) { props: internalProps, }); - const handleTogglePicker = (event: React.UIEvent) => { - if (pickerContext.open) { - pickerContext.onClose(event); - } else { - pickerContext.onOpen(event); - } - }; - return ( pickerContext.setOpen((prev) => !prev)} /> ); } diff --git a/docs/data/date-pickers/custom-field/custom-field.md b/docs/data/date-pickers/custom-field/custom-field.md index 3b9459feb141f..e30850de8502d 100644 --- a/docs/data/date-pickers/custom-field/custom-field.md +++ b/docs/data/date-pickers/custom-field/custom-field.md @@ -154,51 +154,3 @@ and you don't want the UI to look like a Text Field, you can replace the field w The same logic can be applied to any Range Picker: {{"demo": "behavior-button/MaterialDateRangePicker.js", "defaultCodeOpen": false}} - -## How to build a custom field - -The main challenge when building a custom field, is to make sure that all the relevant props passed by the pickers are correctly handled. - -On the examples below, you can see that the typing of the props received by a custom field always have the same shape: - -```tsx -interface JoyDateFieldProps - extends UseDateFieldProps, // The headless field props - BaseSingleInputFieldProps< - Dayjs | null, - FieldSection, - true, // `false` for `enableAccessibleFieldDOMStructure={false}` - DateValidationError - > {} // The DOM field props - -interface JoyDateTimeFieldProps - extends UseDateTimeFieldProps, // The headless field props - BaseSingleInputFieldProps< - Dayjs | null, - FieldSection, - true, // `false` for `enableAccessibleFieldDOMStructure={false}` - DateTimeValidationError - > {} // The DOM field props -``` - -### The headless field props - -This interface depends on which type of field you are building (`UseDateField` for date field, `UseTimeField` for a time field, `UseDateRangeFieldProps` for a date range field, etc.). - -It contains: - -- the basic props common to all the fields (`value`, `onChange`, `format`, `readOnly`, etc.) -- the validation props for this type of field (`minDate`, `maxDate`, `shouldDisableDate`, etc.) - -:::info -If you are building a custom field that doesn't have any input editing (e.g: the _Button field_), you can ignore most of those props. -::: - -### The DOM field props - -This interface contains the props the pickers pass to its field in order to customize the rendering. - -These props are shaped to be received by the built-in fields which are using the `TextField` from `@mui/material`. -When used with another type of input (or no input at all), you will have to manually pass them to the relevant component. - -You can have a look at the `BaseSingleInputFieldProps` and `BaseMultiInputFieldProps` interfaces to know exactly what those interfaces contain. diff --git a/docs/data/date-pickers/custom-layout/AddComponent.js b/docs/data/date-pickers/custom-layout/AddComponent.js index d6e0d1db8b6fe..0e904ef3d2889 100644 --- a/docs/data/date-pickers/custom-layout/AddComponent.js +++ b/docs/data/date-pickers/custom-layout/AddComponent.js @@ -58,11 +58,11 @@ function RestaurantHeader() { } function CustomLayout(props) { - const { toolbar, tabs, content, actionBar } = usePickerLayout(props); + const { toolbar, tabs, content, actionBar, ownerState } = usePickerLayout(props); return ( {toolbar} {actionBar} - + {tabs} {content} diff --git a/docs/data/date-pickers/custom-layout/AddComponent.tsx b/docs/data/date-pickers/custom-layout/AddComponent.tsx index 2584a13756edf..9fc41c2b0666b 100644 --- a/docs/data/date-pickers/custom-layout/AddComponent.tsx +++ b/docs/data/date-pickers/custom-layout/AddComponent.tsx @@ -59,11 +59,11 @@ function RestaurantHeader() { } function CustomLayout(props: PickersLayoutProps) { - const { toolbar, tabs, content, actionBar } = usePickerLayout(props); + const { toolbar, tabs, content, actionBar, ownerState } = usePickerLayout(props); return ( ) { {toolbar} {actionBar} - + {tabs} {content} diff --git a/docs/data/date-pickers/custom-layout/custom-layout.md b/docs/data/date-pickers/custom-layout/custom-layout.md index ca327aaa57b69..0125630db5b10 100644 --- a/docs/data/date-pickers/custom-layout/custom-layout.md +++ b/docs/data/date-pickers/custom-layout/custom-layout.md @@ -86,14 +86,17 @@ import { } from '@mui/x-date-pickers/PickersLayout'; function MyCustomLayout(props) { - const { toolbar, tabs, content, actionBar } = usePickerLayout(props); + const { toolbar, tabs, content, actionBar, ownerState } = usePickerLayout(props); // Put the action bar before the content return ( - + {toolbar} {actionBar} - + {tabs} {content} diff --git a/docs/data/date-pickers/custom-opening-button/custom-opening-button.md b/docs/data/date-pickers/custom-opening-button/custom-opening-button.md index 21f4b44eeda54..c0ef70d69eb9f 100644 --- a/docs/data/date-pickers/custom-opening-button/custom-opening-button.md +++ b/docs/data/date-pickers/custom-opening-button/custom-opening-button.md @@ -46,7 +46,7 @@ In the example below, the warning icon will be visible anytime the current value {{"demo": "AddWarningIconWhenInvalid.js"}} -To add the same behavior to a picker that do not have an input adornment (e.g: Date Range Picker), +To add the same behavior to a picker that do not have an input adornment (for example Date Range Picker), you need to use the `textField` slot to add one: {{"demo": "AddWarningIconWhenInvalidRange.js"}} diff --git a/docs/data/date-pickers/date-picker/examplesConfig.styling.tsx b/docs/data/date-pickers/date-picker/examplesConfig.styling.tsx index cc0a7bbb078f1..07602069862ce 100644 --- a/docs/data/date-pickers/date-picker/examplesConfig.styling.tsx +++ b/docs/data/date-pickers/date-picker/examplesConfig.styling.tsx @@ -166,7 +166,7 @@ export const datePickerExamples: PickersSubcomponentType = { parentSlot: 'layout', parentComponent: 'PickersLayout', comments: - 'Because of the structure of the DesktopDatePicker and the way the popper renders, the `layout` slot will need to be replaced with a wtyled component', + 'Because of the structure of the DesktopDatePicker and the way the popper renders, the `layout` slot will need to be replaced with a styled component', }, }, slots: ['root'], @@ -187,7 +187,7 @@ export const datePickerExamples: PickersSubcomponentType = { parentSlot: 'layout', parentComponent: 'PickersLayout', comments: - 'Because of the structure of the DesktopDatePicker and the way the popper renders, the `layout` slot will need to be replaced with a wtyled component', + 'Because of the structure of the DesktopDatePicker and the way the popper renders, the `layout` slot will need to be replaced with a styled component', }, }, slots: ['root', 'label', 'labelContainer', 'switchViewButton', 'switchViewIcon'], @@ -208,7 +208,7 @@ export const datePickerExamples: PickersSubcomponentType = { parentSlot: 'layout', parentComponent: 'PickersLayout', comments: - 'Because of the structure of the DesktopDatePicker and the way the popper renders, the `layout` slot will need to be replaced with a wtyled component', + 'Because of the structure of the DesktopDatePicker and the way the popper renders, the `layout` slot will need to be replaced with a styled component', }, }, slots: [ @@ -235,7 +235,7 @@ export const datePickerExamples: PickersSubcomponentType = { parentSlot: 'layout', parentComponent: 'PickersLayout', comments: - 'Because of the structure of the DesktopDatePicker and the way the popper renders, the `layout` slot will need to be replaced with a wtyled component', + 'Because of the structure of the DesktopDatePicker and the way the popper renders, the `layout` slot will need to be replaced with a styled component', }, }, slots: ['root', 'today'], @@ -259,7 +259,7 @@ export const datePickerExamples: PickersSubcomponentType = { parentSlot: 'layout', parentComponent: 'PickersLayout', comments: - 'Because of the structure of the DesktopDatePicker and the way the popper renders, the `layout` slot will need to be replaced with a wtyled component', + 'Because of the structure of the DesktopDatePicker and the way the popper renders, the `layout` slot will need to be replaced with a styled component', componentProps: { views: ['month'] }, }, }, @@ -290,6 +290,30 @@ export const datePickerExamples: PickersSubcomponentType = { slots: ['root'], moreInformation: , }, + PickersPopper: { + examples: { + customTheme: { + type: 'success', + parentSlot: 'paper', + }, + sxProp: { + type: 'warning', + parentSlot: 'popper', + current: true, + comments: + 'Because of the structure of the DesktopDatePicker, the `sx` prop needs to be applied to the `popper` slot', + }, + styledComponents: { + type: 'warning', + parentSlot: 'desktopPaper', + parentComponent: 'Paper', + current: true, + comments: + 'Because of the structure of the DesktopDatePicker and the way the popper renders, the `desktopPaper` slot will need to be replaced with a styled component', + }, + }, + slots: ['paper', 'root'], + }, }; const pickerProps: DatePickerProps = { diff --git a/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.js b/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.js index ab660eb554b93..e102430740bdc 100644 --- a/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.js +++ b/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.js @@ -1,4 +1,5 @@ import * as React from 'react'; + import Typography from '@mui/material/Typography'; import Stack from '@mui/material/Stack'; import Button from '@mui/material/Button'; diff --git a/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.tsx b/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.tsx index 68995de41ed1d..6465a9a84a039 100644 --- a/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.tsx +++ b/docs/data/date-pickers/fields/ControlledSelectedSectionsSingleInputRangeField.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import { Dayjs } from 'dayjs'; import Typography from '@mui/material/Typography'; import Stack from '@mui/material/Stack'; import Button from '@mui/material/Button'; @@ -9,14 +10,14 @@ import { FieldSelectedSections, FieldRef, } from '@mui/x-date-pickers/models'; -import { RangeFieldSection, RangePosition } from '@mui/x-date-pickers-pro/models'; +import { DateRange, RangePosition } from '@mui/x-date-pickers-pro/models'; import { SingleInputDateRangeField } from '@mui/x-date-pickers-pro/SingleInputDateRangeField'; export default function ControlledSelectedSectionsSingleInputRangeField() { const [selectedSections, setSelectedSections] = React.useState(null); const inputRef = React.useRef(null); - const fieldRef = React.useRef>(null); + const fieldRef = React.useRef>>(null); const setSelectedSectionType = ( selectedSectionType: FieldSectionType, diff --git a/docs/data/date-pickers/getting-started/getting-started.md b/docs/data/date-pickers/getting-started/getting-started.md index e57e07a9de800..c3a703efd7b44 100644 --- a/docs/data/date-pickers/getting-started/getting-started.md +++ b/docs/data/date-pickers/getting-started/getting-started.md @@ -58,8 +58,8 @@ yarn add @mui/material @emotion/react @emotion/styled ```json "peerDependencies": { - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" }, ``` diff --git a/docs/data/date-pickers/lifecycle/lifecycle.md b/docs/data/date-pickers/lifecycle/lifecycle.md index b5ee50f1d8281..4d4bf1bc62ecf 100644 --- a/docs/data/date-pickers/lifecycle/lifecycle.md +++ b/docs/data/date-pickers/lifecycle/lifecycle.md @@ -174,10 +174,10 @@ Take a look at the [dedicated section](/x/react-date-pickers/lifecycle/#lifecycl If the component is controlled (i.e: if it has a `value` prop), clicking on a value will call `onChange` if the value to publish is different from the current value -(e.g: clicking on the already selected day in the `day` view will not call `onChange`). +(for example clicking on the already selected day in the `day` view will not call `onChange`). If the component is not controlled, the behavior is the same, except if no value has ever been published, in which case clicking on the current value will fire `onChange` -(e.g: clicking on the already selected day in the `day` view will call `onChange` if `onChange` has never been called before). +(for example clicking on the already selected day in the `day` view will call `onChange` if `onChange` has never been called before). Some views can decide not to call `onChange` for some value modifications. The most common example is the mobile time views (using the [`TimeClock`](/x/react-date-pickers/time-clock/) component). diff --git a/docs/data/date-pickers/localization/data.json b/docs/data/date-pickers/localization/data.json index 14a69bf378d62..6874c9a28d40a 100644 --- a/docs/data/date-pickers/localization/data.json +++ b/docs/data/date-pickers/localization/data.json @@ -227,7 +227,7 @@ "languageTag": "ro-RO", "importName": "roRO", "localeName": "Romanian", - "missingKeysCount": 14, + "missingKeysCount": 0, "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/locales/roRO.ts" }, diff --git a/docs/data/date-pickers/overview/overview.md b/docs/data/date-pickers/overview/overview.md index f3cd40be4bc75..97a9cd80382b2 100644 --- a/docs/data/date-pickers/overview/overview.md +++ b/docs/data/date-pickers/overview/overview.md @@ -17,6 +17,7 @@ waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/datepick {{"component": "modules/components/overview/FeatureHighlight.tsx"}} {{"component": "modules/components/overview/CommunityOrPro.tsx"}} +{{"component": "modules/components/overview/Customization.tsx"}} {{"component": "modules/components/overview/Keyboard.tsx"}} {{"component": "modules/components/overview/Internationalization.tsx"}} {{"component": "modules/components/overview/DateLibraries.tsx"}} diff --git a/docs/data/date-pickers/shortcuts/CustomizedRangeShortcuts.js b/docs/data/date-pickers/shortcuts/CustomizedRangeShortcuts.js index 31c77d7d74203..478f2dcb54553 100644 --- a/docs/data/date-pickers/shortcuts/CustomizedRangeShortcuts.js +++ b/docs/data/date-pickers/shortcuts/CustomizedRangeShortcuts.js @@ -1,10 +1,10 @@ import * as React from 'react'; +import dayjs from 'dayjs'; import List from '@mui/material/List'; import ListItem from '@mui/material/ListItem'; import Chip from '@mui/material/Chip'; import Divider from '@mui/material/Divider'; import Box from '@mui/material/Box'; -import dayjs from 'dayjs'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import { StaticDateRangePicker } from '@mui/x-date-pickers-pro/StaticDateRangePicker'; diff --git a/docs/data/date-pickers/shortcuts/CustomizedRangeShortcuts.tsx b/docs/data/date-pickers/shortcuts/CustomizedRangeShortcuts.tsx index 3e3d6fda53c99..87530990c3a87 100644 --- a/docs/data/date-pickers/shortcuts/CustomizedRangeShortcuts.tsx +++ b/docs/data/date-pickers/shortcuts/CustomizedRangeShortcuts.tsx @@ -1,10 +1,10 @@ import * as React from 'react'; +import dayjs, { Dayjs } from 'dayjs'; import List from '@mui/material/List'; import ListItem from '@mui/material/ListItem'; import Chip from '@mui/material/Chip'; import Divider from '@mui/material/Divider'; import Box from '@mui/material/Box'; -import dayjs, { Dayjs } from 'dayjs'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import { StaticDateRangePicker } from '@mui/x-date-pickers-pro/StaticDateRangePicker'; diff --git a/docs/data/introduction/licensing/licensing.md b/docs/data/introduction/licensing/licensing.md index dfbd380118781..58109d7740554 100644 --- a/docs/data/introduction/licensing/licensing.md +++ b/docs/data/introduction/licensing/licensing.md @@ -281,7 +281,7 @@ Most bundlers set this environment variable automatically when building for prod Note that `NODE_ENV=production` is not MUI X-specific and is a common practice in the JavaScript ecosystem. It allows bundlers and libraries to optimize the output for production and eliminate dead code, so it's worth checking if it's set correctly in your project. -See related documentation for [Webpack](https://webpack.js.org/guides/production/#specify-the-mode), [Node.js](https://nodejs.org/en/learn/getting-started/nodejs-the-difference-between-development-and-production) and [Next.js](https://nextjs.org/docs/messages/non-standard-node-env) for more information. +See related documentation for [webpack](https://webpack.js.org/guides/production/#specify-the-mode), [Node.js](https://nodejs.org/en/learn/getting-started/nodejs-the-difference-between-development-and-production) and [Next.js](https://nextjs.org/docs/messages/non-standard-node-env) for more information. ::: ### 4. License key plan mismatch diff --git a/docs/data/introduction/overview/overview.md b/docs/data/introduction/overview/overview.md index 2d7b7c2ed048b..6bfe817627503 100644 --- a/docs/data/introduction/overview/overview.md +++ b/docs/data/introduction/overview/overview.md @@ -47,4 +47,4 @@ These libraries are open source, MIT-licensed, and free forever. MUI X components are fully compatible with MUI Core. MUI X can extend the functionality of UIs built with Material UI or Base UI, but its components can also stand on their own, they can be used with third-parties React component libraries that implement different designs. -You can find [more details](https://mui-org.notion.site/MUI-X-3f8ad249aeca430d81aae5dee947451a#f8e48daaf2fa4902b1415e3708560c0f) about the difference in our handbook. +You can find [more details](https://mui-org.notion.site/MUI-s-products-a-brief-overview-9c5e8e11eb1247c3a124b446be7451cb) about the difference in our handbook. diff --git a/docs/data/introduction/support/support.md b/docs/data/introduction/support/support.md index ebba1a99214b5..37535f7e39b5d 100644 --- a/docs/data/introduction/support/support.md +++ b/docs/data/introduction/support/support.md @@ -96,7 +96,8 @@ This includes issues introduced by external sources, like browser upgrades or ch | MUI X version | Release | Supported | | ------------: | :--------- | :------------------------------------------------------------------ | -| ^7.0.0 | 2024-03-23 | ✅ Stable major (Continuous support) | +| ^8.0.0 | March 2025 | 🚧 Pre release (Continuous support) | +| ^7.0.0 | 2024-03-23 | ✅ Current stable major (Continuous support) | | ^6.0.0 | 2023-03-03 | ⚠️ Long-term support (Support for security issues and regressions). | | ^5.0.0 | 2021-11-23 | ❌ | | ^4.0.0 | 2021-09-28 | ❌ | diff --git a/docs/data/migration/migration-charts-v6/migration-charts-v6.md b/docs/data/migration/migration-charts-v6/migration-charts-v6.md index 34aff59d48708..469b03b57f7c9 100644 --- a/docs/data/migration/migration-charts-v6/migration-charts-v6.md +++ b/docs/data/migration/migration-charts-v6/migration-charts-v6.md @@ -41,13 +41,13 @@ The `legacy` bundle that used to support old browsers like IE 11 is no longer i If you need support for IE 11, you will need to keep using the latest version of the `v6` release. ::: -### Drop Webpack 4 support +### Drop webpack 4 support Dropping old browsers support also means that we no longer transpile some features that are natively supported by modern browsers – like [Nullish Coalescing](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing) and [Optional Chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining). -These features are not supported by Webpack 4, so if you are using Webpack 4, you will need to transpile these features yourself or upgrade to Webpack 5. +These features are not supported by webpack 4, so if you are using webpack 4, you will need to transpile these features yourself or upgrade to webpack 5. -Here is an example of how you can transpile these features on Webpack 4 using the `@babel/preset-env` preset: +Here is an example of how you can transpile these features on webpack 4 using the `@babel/preset-env` preset: ```diff // webpack.config.js @@ -75,7 +75,7 @@ Here is an example of how you can transpile these features on Webpack 4 using th #### Types -Some types got renamed for coherence: +Some types have been renamed for coherence: | v6 | v7 | | :-------------------------------- | :----------------------- | diff --git a/docs/data/migration/migration-charts-v7/migration-charts-v7.md b/docs/data/migration/migration-charts-v7/migration-charts-v7.md index c137ce3ab13c9..72a8ce9490119 100644 --- a/docs/data/migration/migration-charts-v7/migration-charts-v7.md +++ b/docs/data/migration/migration-charts-v7/migration-charts-v7.md @@ -19,6 +19,9 @@ In `package.json`, change the version of the charts package to `next`. ```diff -"@mui/x-charts": "^7.0.0", +"@mui/x-charts": "next", + +-"@mui/x-charts-pro": "^7.0.0", ++"@mui/x-charts-pro": "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`. @@ -38,10 +41,10 @@ You can either run it on a specific file, folder, or your entire codebase when c ```bash -// Charts specific +# Charts-specific npx @mui/x-codemod@latest v8.0.0/charts/preset-safe -// Target the other packages as well +# Target the other packages as well npx @mui/x-codemod@latest v8.0.0/preset-safe ``` @@ -61,7 +64,7 @@ Not all use cases are covered by codemods. In some scenarios, like props spreadi 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 - // The codemod will not modify the content of `pickerProps`. + // The codemod will not modify the content of `chartProps`. ``` After running the codemods, make sure to test your application and that you don't have any console errors. @@ -71,52 +74,74 @@ Feel free to [open an issue](https://github.com/mui/mui-x/issues/new/choose) for ## Series properties renaming -Some properties got deprecated in v7 in favor of a more consistent naming convention. -Those deprecated properties got removed in v8. +Some properties were deprecated in v7 in favor of a more consistent naming convention. +Those deprecated properties have been removed in v8. The impacted properties are: -- The `xAxisKey`, `yAxisKey`, and `zAxisKey` are renamed `xAxisId`, `yAxisId`, and `zAxisId`. -- The `highlighted` and `faded` properties of `series.highlightScope` are renamed `highlight` and `fade`. +- The `xAxisKey`, `yAxisKey`, and `zAxisKey` have been renamed `xAxisId`, `yAxisId`, and `zAxisId`. +- The `highlighted` and `faded` properties of `series.highlightScope` have been renamed `highlight` and `fade`. ## Legend props propagation ✅ -The `legend` props of charts single components got removed. +The `legend` prop of charts single components has been removed. To pass props to the legend, use the `slotProps.legend`. ```diff -- -+ +- ++ ``` ## Removing ResponsiveChartContainer ✅ -The `ResponsiveChartContainer` got removed. +The `ResponsiveChartContainer` has been removed. You can now use `ChartContainer` as a responsive container which works now exactly the same way. ```diff -- import { ResponsiveChartContainer } from '@mui/x-charts/ResponsiveChartContainer'; -- import { ResponsiveChartContainerPro } from '@mui/x-charts-pro/ResponsiveChartContainerPro'; -+ import { ChartContainer } from '@mui/x-charts/ResponsiveChartContainer'; -+ import { ChartContainerPro } from '@mui/x-charts-pro/ResponsiveChartContainerPro'; +-import { ResponsiveChartContainer } from '@mui/x-charts/ResponsiveChartContainer'; +-import { ResponsiveChartContainerPro } from '@mui/x-charts-pro/ResponsiveChartContainerPro'; ++import { ChartContainer } from '@mui/x-charts/ResponsiveChartContainer'; ++import { ChartContainerPro } from '@mui/x-charts-pro/ResponsiveChartContainerPro'; -- -+ +- ++ -- -+ +- ++ ``` ## New DOM structure for ChartContainer -The `` now wrap the `svg` component into a `div`. +The `` now wraps the `svg` component into a `div`. This change should not impact your codebase except for some CSS selector edge cases. ## Remove Pie Chart axes -The `` got by error the code to render axes. -This code is removed in v8, which implies removing the following props: `axisHighlight`, `topAxis`, `rightAxis`, `bottomAxis`, and `leftAxis`. +The `` by error had the code to render axes. +This code has been removed in v8, which implies removing the following props: `axisHighlight`, `topAxis`, `rightAxis`, `bottomAxis`, and `leftAxis`. This should not impact your code. If you used axes in a pie chart please open an issue, we would be curious to get more information about the use-case. + +## Remove `resolveSizeBeforeRender` prop + +The `resolveSizeBeforeRender` prop has been removed from all components. +If you were using this prop, you can safely remove it. + +## Rename `labelFontSize` and `tickFontSize` props ✅ + +The `labelFontSize` and `tickFontSize` props have been removed in favor of the style objects `labelStyle` and `tickStyle` respectively. + +```diff + +``` diff --git a/docs/data/migration/migration-data-grid-v5/migration-data-grid-v5.md b/docs/data/migration/migration-data-grid-v5/migration-data-grid-v5.md index 2ed5e027a87fd..4c96cc025e119 100644 --- a/docs/data/migration/migration-data-grid-v5/migration-data-grid-v5.md +++ b/docs/data/migration/migration-data-grid-v5/migration-data-grid-v5.md @@ -30,9 +30,10 @@ The `preset-safe` codemod will automatically adjust the bulk of your code to acc You can either run it on a specific file, folder, or your entire codebase when choosing the `` argument. ```bash -// Data Grid specific +# Data Grid specific npx @mui/x-codemod@latest v6.0.0/data-grid/preset-safe -// Target Date and Time Pickers as well + +# Target Date and Time Pickers as well npx @mui/x-codemod@latest v6.0.0/preset-safe ``` diff --git a/docs/data/migration/migration-data-grid-v6/migration-data-grid-v6.md b/docs/data/migration/migration-data-grid-v6/migration-data-grid-v6.md index 77be948cd923a..da8288a8a8c3b 100644 --- a/docs/data/migration/migration-data-grid-v6/migration-data-grid-v6.md +++ b/docs/data/migration/migration-data-grid-v6/migration-data-grid-v6.md @@ -62,10 +62,10 @@ You can either run it on a specific file, folder, or your entire codebase when c ```bash -// Data Grid specific +# Data Grid specific npx @mui/x-codemod@latest v7.0.0/data-grid/preset-safe -// Target other MUI X components as well +# Target other MUI X components as well npx @mui/x-codemod@latest v7.0.0/preset-safe ``` @@ -108,13 +108,13 @@ The `legacy` bundle that used to support old browsers like IE 11 is no longer i If you need support for IE 11, you will need to keep using the latest version of the `v6` release. ::: -### Drop Webpack 4 support +### Drop webpack 4 support Dropping old browsers support also means that we no longer transpile some features that are natively supported by modern browsers – like [Nullish Coalescing](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing) and [Optional Chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining). -These features are not supported by Webpack 4, so if you are using Webpack 4, you will need to transpile these features yourself or upgrade to Webpack 5. +These features are not supported by webpack 4, so if you are using webpack 4, you will need to transpile these features yourself or upgrade to webpack 5. -Here is an example of how you can transpile these features on Webpack 4 using the `@babel/preset-env` preset: +Here is an example of how you can transpile these features on webpack 4 using the `@babel/preset-env` preset: ```diff // webpack.config.js 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 index eea548d0fbc03..4f3753dd9989d 100644 --- 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 @@ -1,4 +1,5 @@ --- +title: React Data Grid - Migration from v7 to v8 productId: x-data-grid --- @@ -33,43 +34,69 @@ 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. -::: +### Selection - ```bash -// Date and Time Pickers specific +# Date and Time Pickers specific npx @mui/x-codemod@latest v7.0.0/pickers/preset-safe -// Target other MUI X components as well +# Target other MUI X components as well npx @mui/x-codemod@latest v7.0.0/preset-safe ``` @@ -101,13 +104,13 @@ The `legacy` bundle that used to support old browsers like IE 11 is no longer i If you need support for IE 11, you will need to keep using the latest version of the `v6` release. ::: -### Drop Webpack 4 support +### Drop webpack 4 support Dropping old browsers support also means that we no longer transpile some features that are natively supported by modern browsers – like [Nullish Coalescing](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing) and [Optional Chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining). -These features are not supported by Webpack 4, so if you are using Webpack 4, you will need to transpile these features yourself or upgrade to Webpack 5. +These features are not supported by webpack 4, so if you are using webpack 4, you will need to transpile these features yourself or upgrade to webpack 5. -Here is an example of how you can transpile these features on Webpack 4 using the `@babel/preset-env` preset: +Here is an example of how you can transpile these features on webpack 4 using the `@babel/preset-env` preset: ```diff // webpack.config.js @@ -177,7 +180,7 @@ The same applies to `slotProps` and `componentsProps`. ### ✅ Rename slots types -The slot interfaces got renamed to match with `@mui/base` naming convention. +The slot interfaces have been renamed to match with `@mui/base` naming convention. Suffix `SlotsComponent` is replaced by `Slots` and `SlotsComponentsProps` is replaced by `SlotProps`. If you are not relying on the codemod, consider checking all the renamed types in [this file](https://github.com/mui/mui-x/blob/HEAD/packages/x-codemod/src/v7.0.0/pickers/rename-slots-types/index.ts). Here is an example on the `DateCalendar` typing. @@ -407,7 +410,7 @@ If you are using a multi input range field hook, the same applies to the ref in The `useClearableField` hook API has been simplified to now take a `props` parameter instead of a `fieldProps`, `InputProps`, `clearable`, `onClear`, `slots` and `slotProps` parameters. -You should now be able to directly pass the returned value from your field hook (e.g: `useDateField`) to `useClearableField` +You should now be able to directly pass the returned value from your field hook (for example `useDateField`) to `useClearableField` ```diff const fieldResponse = useDateField(props); diff --git a/docs/data/migration/migration-pickers-v7/migration-pickers-v7.md b/docs/data/migration/migration-pickers-v7/migration-pickers-v7.md index c78ed186f4d5c..e442c69242932 100644 --- a/docs/data/migration/migration-pickers-v7/migration-pickers-v7.md +++ b/docs/data/migration/migration-pickers-v7/migration-pickers-v7.md @@ -17,6 +17,9 @@ 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", + +-"@mui/x-date-pickers-pro": "7.x.x", ++"@mui/x-date-pickers-pro": "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`. @@ -34,10 +37,10 @@ You can either run it on a specific file, folder, or your entire codebase when c ```bash -// Date and Time Pickers specific +# Date and Time Pickers specific npx @mui/x-codemod@latest v8.0.0/pickers/preset-safe -// Target the other packages as well +# Target the other packages as well npx @mui/x-codemod@latest v8.0.0/preset-safe ``` @@ -67,10 +70,13 @@ Feel free to [open an issue](https://github.com/mui/mui-x/issues/new/choose) for ## 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. +Before version `v7.x`, the fields' DOM structure consisted of an ``, which held the whole value for the component. +Unfortunately it presented accessibility limitations, which are impossible to resolve. + +Starting with version `v7.x`, we have introduced a new DOM structure that allows the field component to set aria attributes on individual sections, providing a far better experience on screen readers. +This approach is recommended in [W3C ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/examples/datepicker-spinbuttons/) example and is also used by native date HTML input element under the hood. -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. +Starting with version `v8.x`, the new DOM structure is the default for all fields. ### Fallback to the non-accessible DOM structure @@ -83,7 +89,7 @@ Starting with version `v8.x`, all the field and picker components come with a ne ### 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`. +the field consumes some props (for example `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. @@ -254,43 +260,196 @@ const theme = createTheme({ }); ``` -## Renamed variables +## Slots breaking changes + +### Slot: `layout` + +- The `` and `` components must now receive the `ownerState` returned by `usePickerLayout` instead of their props: + + ```diff + -const { toolbar, tabs, content, actionBar } = usePickerLayout(props); + +const { toolbar, tabs, content, actionBar, ownerState } = usePickerLayout(props); + + return ( + - + + + - + + + + + ); + ``` + +- The component passed to the `layout` slot no longer receives a `disabled` prop, instead you can use the `usePickerContext` hook: + + ```diff + -console.log(props.disabled); + +import { usePickerContext } from '@mui/x-date-pickers/hooks'; + +const { disabled } = usePickerContext(); + +console.log(disabled); + ``` + +- The component passed to the `layout` slot no longer receives a `readOnly` prop, instead you can use the `usePickerContext` hook: + + ```diff + -console.log(props.readOnly); + +import { usePickerContext } from '@mui/x-date-pickers/hooks'; + +const { readOnly } = usePickerContext(); + +console.log(readOnly); + ``` + +- The component passed to the `layout` slot no longer receives an `isRtl` prop. If you need to access this information, you can use the `useRtl` hook from `@mui/system`: + + ```diff + +import { useRtl } from '@mui/system/RtlProvider'; + function CustomLayout(props) { + - console.log(props.isRtl); + + const isRtl = useRtl(); + + console.log(isRtl); + } + ``` + +- The component passed to the `layout` slot no longer receives an `orientation` and the `isLandscape` props, instead you can use the `usePickerContext` hook: + + ```diff + -console.log(props.orientation); + +import { usePickerContext } from '@mui/x-date-pickers/hooks'; + +const { orientation } = usePickerContext(); + +console.log(orientation); + -console.log(props.isLandscape); + +import { usePickerContext } from '@mui/x-date-pickers/hooks'; + +const { orientation } = usePickerContext(); + +console.log(orientation === 'landscape'); + ``` + +- The component passed to the `layout` slot no longer receives a `wrapperVariant` prop, instead you can use the `usePickerContext` hook: + + ```diff + -console.log(props.wrapperVariant); + +import { usePickerContext } from '@mui/x-date-pickers/hooks'; + +const { variant } = usePickerContext(); + +console.log(variant); + ``` + +### Slot: `toolbar` + +- The component passed to the `toolbar` slot no longer receives a `disabled` prop, instead you can use the `usePickerContext` hook: + + ```diff + -console.log(props.disabled); + +import { usePickerContext } from '@mui/x-date-pickers/hooks'; + +const { disabled } = usePickerContext(); + +console.log(disabled); + ``` + +- The component passed to the `toolbar` slot no longer receives a `readOnly` prop, instead you can use the `usePickerContext` hook: + + ```diff + -console.log(props.readOnly); + +import { usePickerContext } from '@mui/x-date-pickers/hooks'; + +const { readOnly } = usePickerContext(); + +console.log(readOnly); + ``` + +## Renamed variables and types + +The following variables and types have been renamed to have a coherent `Picker` / `Pickers` prefix: + +- `usePickersTranslations` + + ```diff + -import { usePickersTranslations } from '@mui/x-date-pickers/hooks'; + -import { usePickersTranslations } from '@mui/x-date-pickers'; + -import { usePickersTranslations } from '@mui/x-date-pickers-pro'; + + +import { usePickerTranslations } from '@mui/x-date-pickers/hooks'; + +import { usePickerTranslations } from '@mui/x-date-pickers'; + +import { usePickerTranslations } from '@mui/x-date-pickers-pro'; + + -const translations = usePickersTranslations(); + +const translations = usePickerTranslations(); + ``` + +- `usePickersContext` + + ```diff + -import { usePickersContext } from '@mui/x-date-pickers/hooks'; + -import { usePickersContext } from '@mui/x-date-pickers'; + -import { usePickersContext } from '@mui/x-date-pickers-pro'; + + +import { usePickerContext } from '@mui/x-date-pickers/hooks'; + +import { usePickerContext } from '@mui/x-date-pickers'; + +import { usePickerContext } from '@mui/x-date-pickers-pro'; -The following variables were renamed to have a coherent `Picker` / `Pickers` prefix: + -const pickersContext = usePickersContext(); + +const pickerContext = usePickerContext(); + ``` -- `usePickersTranslation` +- `FieldValueType` ```diff - - import { usePickersTranslation } from '@mui/x-date-pickers/hooks'; - - import { usePickersTranslation } from '@mui/x-date-pickers'; - - import { usePickersTranslation } from '@mui/x-date-pickers-pro'; + -import { FieldValueType } from '@mui/x-date-pickers/models'; + -import { FieldValueType } from '@mui/x-date-pickers'; + -import { FieldValueType } from '@mui/x-date-pickers-pro'; + + +import { PickerValueType } from '@mui/x-date-pickers/models'; + +import { PickerValueType } from '@mui/x-date-pickers'; + +import { PickerValueType } from '@mui/x-date-pickers-pro'; + ``` + + - `RangeFieldSection` - + import { usePickerTranslation } from '@mui/x-date-pickers/hooks'; - + import { usePickerTranslation } from '@mui/x-date-pickers'; - + import { usePickerTranslation } from '@mui/x-date-pickers-pro'; + ```diff + -import { RangeFieldSection } from '@mui/x-date-pickers-pro/models'; + -import { RangeFieldSection } from '@mui/x-date-pickers-pro'; - - const translations = usePickersTranslation(); - + const translations = usePickerTranslation(); + +import { FieldRangeSection } from '@mui/x-date-pickers-pro/models'; + +import { FieldRangeSection } from '@mui/x-date-pickers-pro'; ``` - - `usePickersContext` +## Hooks breaking changes + +### `usePickerContext` + +- The `onOpen` and `onClose` methods have been replaced with a single `setOpen` method. + This method no longer takes an event, which was used to prevent the browser default behavior: ```diff - - import { usePickersContext } from '@mui/x-date-pickers/hooks'; - - import { usePickersContext } from '@mui/x-date-pickers'; - - import { usePickersContext } from '@mui/x-date-pickers-pro'; + const pickerContext = usePickerContext(); + + - + + + + - + + + + - + + + ``` - + import { usePickerContext } from '@mui/x-date-pickers/hooks'; - + import { usePickerContext } from '@mui/x-date-pickers'; - + import { usePickerContext } from '@mui/x-date-pickers-pro'; + If you want to prevent the default behavior, you now have to do it manually: - - const pickersContext = usePickersContext(); - + const pickerContext = usePickerContext(); + ```diff +
{ + if (event.key === 'Escape') { + - pickerContext.onClose(); + + event.preventDefault(); + + pickerContext.setOpen(false); + } + }} + /> ``` ## Typing breaking changes -### Remove `TDate` generic +### Do not pass the date object as a generic The `TDate` generic has been removed from all the types, interfaces, and variables of the `@mui/x-date-pickers` and `@mui/x-date-pickers-pro` packages. @@ -300,14 +459,24 @@ If you were passing your date object type as a generic to any element of one of - value={value} onChange={onChange} /> + --type Slot = DateCalendarSlots['calendarHeader']; -+type Slot = DateCalendarSlots['calendarHeader']; +-type FieldComponent = DatePickerSlots['field']; ++type FieldComponent = DatePickerSlots['field']; --type Props = DatePickerToolbarProps; -+type Props = DatePickerToolbarProps; +-function CustomDatePicker(props: DatePickerProps) {} ++function CustomDatePicker(props: DatePickerProps) {} ``` -A follow-up release will add the full list of the impacted elements to the migration guide. +### Do not pass the section type as a generic + +The `TSection` generic of the `FieldRef` type has been replaced with the `TValue` generic: + +```diff +-const fieldRef = React.useRef>(null); ++const fieldRef = React.useRef(null); + +-const fieldRef = React.useRef>(null); ++const fieldRef = React.useRef>(null); +``` ### Removed types @@ -365,9 +534,220 @@ If you were using them, you need to replace them with the following code: UseDateTimeFieldProps; ``` +- `BaseSingleInputFieldProps` + + - If you are building a custom field for a Date Picker: + + ```diff + -import { + - BaseSingleInputFieldProps, + - DateValidationError, + - FieldSection, + -} from '@mui/x-date-pickers/models'; + -import { UseDateFieldProps } from '@mui/x-date-pickers/DateField'; + +import { DatePickerFieldProps } from '@mui/x-date-pickers/DatePicker'; + + -interface CustomDateFieldProps + - extends UseDateFieldProps, + - BaseSingleInputFieldProps< + - Dayjs | null, + - Dayjs, + - FieldSection, + - true, + - DateValidationError + - > {} + +interface CustomDateFieldProps extends DatePickerFieldProps {} + ``` + + - If you are building a custom field for a Time Picker: + + ```diff + -import { + - BaseSingleInputFieldProps, + - TimeValidationError, + - FieldSection, + -} from '@mui/x-date-pickers/models'; + -import { UseTimeFieldProps } from '@mui/x-date-pickers/TimeField'; + +import { TimePickerFieldProps } from '@mui/x-date-pickers/TimePicker'; + + -interface CustomTimeFieldProps + - extends UseTimeFieldProps, + - BaseSingleInputFieldProps< + - Dayjs | null, + - Dayjs, + - FieldSection, + - true, + - TimeValidationError + - > {} + +interface CustomTimeFieldProps extends TimePickerFieldProps {} + ``` + + - If you are building a custom field for a Date Time Picker: + + ```diff + -import { + - BaseSingleInputFieldProps, + - DateTimeValidationError, + - FieldSection, + -} from '@mui/x-date-pickers/models'; + -import { UseDateTimeFieldProps } from '@mui/x-date-pickers/DateTimeField'; + +import { DateTimePickerFieldProps } from '@mui/x-date-pickers/DateTimePicker'; + + -interface CustomDateTimeFieldProps + - extends UseDateTimeFieldProps, + - BaseSingleInputFieldProps< + - Dayjs | null, + - Dayjs, + - FieldSection, + - true, + - DateTimeValidationError + - > {} + +interface CustomDateTimeFieldProps extends DateTimePickerFieldProps {} + ``` + + - If you are building a custom single input field for a Date Range Picker: + + ```diff + -import { + - DateRangeValidationError, + - RangeFieldSection, + - DateRange, + -} from '@mui/x-date-pickers-pro/models'; + -import { + - UseSingleInputDateRangeFieldProps + -} from '@mui/x-date-pickers-pro/SingleInputDateRangeField'; + +import { DateRangePickerFieldProps } from '@mui/x-date-pickers-pro/DateRangePicker'; + + -interface CustomDateRangeFieldProps + - extends UseSingleInputDateRangeFieldProps, + - BaseSingleInputFieldProps< + - DateRange, + - Dayjs, + - RangeFieldSection, + - true, + - DateRangeValidationError + - > + +interface CustomDateRangeFieldProps extends DateRangePickerFieldProps {} + ``` + + - If you are building a custom single input field for a Date Time Range Picker: + + ```diff + -import { + - DateTimeRangeValidationError, + - RangeFieldSection, + - DateRange, + -} from '@mui/x-date-pickers-pro/models'; + -import { + - UseSingleInputDateTimeRangeFieldProps + -} from '@mui/x-date-pickers-pro/SingleInputDateTimeRangeField'; + +import { + + DateTimeRangePickerFieldProps + +} from '@mui/x-date-pickers-pro/DateTimeRangePicker'; + + -interface CustomDateTimeRangeFieldProps + - extends UseSingleInputDateTimeRangeFieldProps, + - BaseSingleInputFieldProps< + - DateRange, + - Dayjs, + - RangeFieldSection, + - true, + - DateTimeRangeValidationError + - > + +interface CustomDateTimeRangeFieldProps extends DateTimeRangePickerFieldProps {} + ``` + +- `BaseMultiInputFieldProps` + + - If you are building a custom multi input field for a Date Range Picker: + + ```diff + -import { + - DateRangeValidationError, + - RangeFieldSection, + - DateRange, + -} from '@mui/x-date-pickers-pro/models'; + -import { + - UseMultiInputDateRangeFieldProps + -} from '@mui/x-date-pickers-pro/MultiInputDateRangeField'; + +import { DateRangePickerFieldProps } from '@mui/x-date-pickers-pro/DateRangePicker'; + + -interface CustomDateRangeFieldProps + - extends UseMultiInputDateRangeFieldProps, + - BaseMultiInputFieldProps< + - DateRange, + - Dayjs, + - RangeFieldSection, + - true, + - DateRangeValidationError + - > {} + +interface CustomDateRangeFieldProps + + extends Omit< + + DateRangePickerFieldProps, + + 'unstableFieldRef' | 'clearable' | 'onClear' + + >, + + MultiInputFieldRefs {} + ``` + + - If you are building a custom multi input field for a Date Time Range Picker: + + ```diff + -import { + - DateTimeRangeValidationError, + - RangeFieldSection, + - DateRange, + -} from '@mui/x-date-pickers-pro/models'; + -import { + - UseMultiInputDateTimeRangeFieldProps + -} from '@mui/x-date-pickers-pro/MultiInputDateTimeRangeField'; + +import { + + DateTimeRangePickerFieldProps + +} from '@mui/x-date-pickers-pro/DateTimeRangePicker'; + + -interface CustomDateTimeRangeFieldProps + - extends UseMultiInputDateTimeRangeFieldProps, + - BaseMultiInputFieldProps< + - DateRange, + - Dayjs, + - RangeFieldSection, + - false, + - DateTimeRangeValidationError + - > {} + +interface JoyMultiInputDateRangeFieldProps + + extends Omit< + + DateTimeRangePickerFieldProps, + + 'unstableFieldRef' | 'clearable' | 'onClear' + + >, + + MultiInputFieldRefs {} + ``` + +- `BasePickersTextFieldProps` + + - If your Text Field is used inside a non-range picker or in a range-picker with a single input field: + + ```diff + -import { BasePickersTextFieldProps } from '@mui/x-date-pickers-pro/models'; + +import { BaseSingleInputPickersTextFieldProps } from '@mui/x-date-pickers/models'; + + interface CustomTextFieldProps + - extends BasePickersTextFieldProps {} + + extends BaseSingleInputPickersTextFieldProps {} + ``` + + - If your Text Field is used inside a range-picker with a multi input field: + + ```diff + -import { BasePickersTextFieldProps } from '@mui/x-date-pickers-pro/models'; + +import { BaseMultiInputPickersTextFieldProps } from '@mui/x-date-pickers-pro/models'; + + interface CustomTextFieldProps + - extends BasePickersTextFieldProps {} + + extends BaseMultiInputPickersTextFieldProps {} + ``` + ## Stop using `LicenseInfo` from `@mui/x-date-pickers-pro` -The `LicenseInfo` object is not exported from the `@mui/x-date-pickers-pro` package anymore. +The `LicenseInfo` object is no longer exported from the `@mui/x-date-pickers-pro` package. You can import it from `@mui/x-license` instead: ```diff 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 2efbd13455fdd..3b848ccd33bb4 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 @@ -36,10 +36,10 @@ You can either run it on a specific file, folder, or your entire codebase when c ```bash -// Tree View specific +# Tree View specific npx @mui/x-codemod@latest v7.0.0/tree-view/preset-safe -// Target other MUI X components as well +# Target other MUI X components as well npx @mui/x-codemod@latest v7.0.0/preset-safe ``` @@ -81,13 +81,13 @@ The `legacy` bundle that used to support old browsers like IE 11 is no longer i If you need support for IE 11, you will need to keep using the latest version of the `v6` release. ::: -### Drop Webpack 4 support +### Drop webpack 4 support Dropping old browsers support also means that we no longer transpile some features that are natively supported by modern browsers – like [Nullish Coalescing](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing) and [Optional Chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining). -These features are not supported by Webpack 4, so if you are using Webpack 4, you will need to transpile these features yourself or upgrade to Webpack 5. +These features are not supported by webpack 4, so if you are using webpack 4, you will need to transpile these features yourself or upgrade to webpack 5. -Here is an example of how you can transpile these features on Webpack 4 using the `@babel/preset-env` preset: +Here is an example of how you can transpile these features on webpack 4 using the `@babel/preset-env` preset: ```diff // webpack.config.js 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 index e57862e0841c5..23a21fa1b2e18 100644 --- 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 @@ -17,6 +17,9 @@ 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", + +-"@mui/x-tree-view-pro": "7.x.x", ++"@mui/x-tree-view-pro": "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`. @@ -34,10 +37,10 @@ You can either run it on a specific file, folder, or your entire codebase when c ```bash -// Tree View specific +# Tree View specific npx @mui/x-codemod@latest v8.0.0/tree-view/preset-safe -// Target the other packages as well +# Target the other packages as well npx @mui/x-codemod@latest v8.0.0/preset-safe ``` @@ -57,7 +60,7 @@ Not all use cases are covered by codemods. In some scenarios, like props spreadi 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. @@ -128,7 +131,7 @@ This inconsistency has been solved, all the event manager now target the root of - + - -+ ++ ``` @@ -226,6 +229,46 @@ All the new Tree Item-related components and utils (introduced in the previous m + } from '@mui/x-tree-view/TreeItemLabelInput'; ``` +## Stop using `publicAPI` methods in the render + +The Tree Items are now memoized to improve the performances of the Tree View components. +If you call a `publicAPI` method in the render of an item, it might not re-render and you might not have the new value. + +```ts +function CustomTreeItem(props) { + const { publicAPI } = useTreeItemUtils(); + + // Invalid + console.log(publicAPI.getItem(props.itemId)); + + // Valid + React.useEffect(() => { + console.log(publicAPI.getItem(props.itemId)); + }); + + // Valid + function handleItemClick() { + console.log(publicAPI.getItem(props.itemId)); + } +} +``` + +If you need to access the tree item model inside the render, you can use the new `useTreeItemModel` hook: + +```diff ++import { useTreeItemModel } from '@mui/x-tree-view/hooks'; + + function CustomTreeItem(props) { +- const { publicAPI } = useTreeItemUtils(); +- const item = publicAPI.getItem(props.itemId); ++ const item = useTreeItemModel(props.itemId); + } +``` + +:::success +If you were using `publicAPI` methods to access other information than the tree item model inside the render, please open an issue so that we can provide a way to do it. +::: + ## Apply the indentation on the item content instead of it's parent's group The indentation of nested Tree Items is now applied on the content of the element. diff --git a/docs/data/pages.ts b/docs/data/pages.ts index c89a8c552c6c4..1e7a23dee23c7 100644 --- a/docs/data/pages.ts +++ b/docs/data/pages.ts @@ -90,7 +90,6 @@ const pages: MuiPage[] = [ { pathname: '/x/react-data-grid/filtering/header-filters', plan: 'pro', - newFeature: true, }, { pathname: '/x/react-data-grid/filtering-recipes', title: 'Recipes' }, ], @@ -100,7 +99,7 @@ const pages: MuiPage[] = [ pathname: '/x/react-data-grid/selection', children: [ { pathname: '/x/react-data-grid/row-selection' }, - { pathname: '/x/react-data-grid/cell-selection', plan: 'premium', newFeature: true }, + { pathname: '/x/react-data-grid/cell-selection', plan: 'premium' }, ], }, { pathname: '/x/react-data-grid/virtualization' }, @@ -128,9 +127,8 @@ const pages: MuiPage[] = [ { pathname: '/x/react-data-grid/aggregation', plan: 'premium' }, { pathname: '/x/react-data-grid/pivoting', plan: 'premium', planned: true }, { pathname: '/x/react-data-grid/export' }, - { pathname: '/x/react-data-grid/clipboard', title: 'Copy and paste', newFeature: true }, + { pathname: '/x/react-data-grid/clipboard', title: 'Copy and paste' }, { pathname: '/x/react-data-grid/scrolling' }, - { pathname: '/x/react-data-grid/list-view', title: 'List view', @@ -142,22 +140,26 @@ const pages: MuiPage[] = [ title: 'Server-side data', plan: 'pro', children: [ - { pathname: '/x/react-data-grid/server-side-data', title: 'Overview' }, - { pathname: '/x/react-data-grid/server-side-data/tree-data', plan: 'pro' }, { - pathname: '/x/react-data-grid/server-side-data/lazy-loading', + pathname: '/x/react-data-grid/server-side-data', + title: 'Overview', plan: 'pro', - planned: true, + unstable: true, }, { - pathname: '/x/react-data-grid/server-side-data/infinite-loading', + pathname: '/x/react-data-grid/server-side-data/tree-data', plan: 'pro', - planned: true, + unstable: true, + }, + { + pathname: '/x/react-data-grid/server-side-data/lazy-loading', + plan: 'pro', + unstable: true, }, { pathname: '/x/react-data-grid/server-side-data/row-grouping', plan: 'premium', - planned: true, + unstable: true, }, { pathname: '/x/react-data-grid/server-side-data/aggregation', @@ -211,6 +213,7 @@ const pages: MuiPage[] = [ }, { pathname: '/x/api/data-grid/grid-actions-col-def', title: 'GridActionsColDef' }, + { pathname: '/x/api/data-grid/grid-list-col-def', title: 'GridListColDef' }, { pathname: '/x/api/data-grid/grid-export-state-params', title: 'GridExportStateParams', @@ -340,7 +343,6 @@ const pages: MuiPage[] = [ { pathname: '/x/react-date-pickers/date-time-range-picker', title: 'Date Time Range Picker', - newFeature: true, }, { pathname: '/x/react-date-pickers/date-time-range-field', @@ -410,7 +412,6 @@ const pages: MuiPage[] = [ { pathname: '/x/react-charts-group', title: 'Charts', - newFeature: true, children: [ { pathname: '/x/react-charts', title: 'Overview' }, { pathname: '/x/react-charts/getting-started' }, @@ -460,7 +461,6 @@ const pages: MuiPage[] = [ pathname: '/x/react-charts/heatmap', title: 'Heatmap', plan: 'pro', - unstable: true, }, { pathname: '/x/react-charts/main-features', @@ -479,7 +479,6 @@ const pages: MuiPage[] = [ pathname: '/x/react-charts/zoom-and-pan', title: 'Zoom and pan', plan: 'pro', - unstable: true, }, ], }, @@ -525,7 +524,6 @@ const pages: MuiPage[] = [ { pathname: '/x/react-tree-view-group', title: 'Tree View', - newFeature: true, children: [ { pathname: '/x/react-tree-view', title: 'Overview' }, { pathname: '/x/react-tree-view/getting-started' }, @@ -549,8 +547,8 @@ const pages: MuiPage[] = [ { pathname: '/x/react-tree-view/rich-tree-view/expansion' }, { pathname: '/x/react-tree-view/rich-tree-view/customization' }, { pathname: '/x/react-tree-view/rich-tree-view/focus' }, - { pathname: '/x/react-tree-view/rich-tree-view/editing' }, - { pathname: '/x/react-tree-view/rich-tree-view/ordering', plan: 'pro' }, + { pathname: '/x/react-tree-view/rich-tree-view/editing', newFeature: true }, + { pathname: '/x/react-tree-view/rich-tree-view/ordering', plan: 'pro', newFeature: true }, ], }, { diff --git a/docs/data/tree-view/datasets/employees.js b/docs/data/tree-view/datasets/employees.js new file mode 100644 index 0000000000000..c11515cf4fbae --- /dev/null +++ b/docs/data/tree-view/datasets/employees.js @@ -0,0 +1,38 @@ +export const EMPLOYEES_DATASET = [ + { + 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 6acc9e5382c17..d45b06955911f 100644 --- a/docs/data/tree-view/getting-started/getting-started.md +++ b/docs/data/tree-view/getting-started/getting-started.md @@ -1,7 +1,7 @@ --- productId: x-tree-view title: Tree View - Getting started -components: SimpleTreeView, RichTreeView, TreeItem, TreeView +components: SimpleTreeView, RichTreeView, TreeItem packageName: '@mui/x-tree-view' githubLabel: 'component: tree view' waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/ @@ -44,8 +44,8 @@ Please note that [react](https://www.npmjs.com/package/react) and [react-dom](ht ```json "peerDependencies": { - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" }, ``` 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 304f82faaf74d..cfc8d7fe5ccde 100644 --- a/docs/data/tree-view/rich-tree-view/customization/FileExplorer.js +++ b/docs/data/tree-view/rich-tree-view/customization/FileExplorer.js @@ -26,6 +26,7 @@ import { 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 { useTreeItemModel } from '@mui/x-tree-view/hooks'; const ITEMS = [ { @@ -178,13 +179,6 @@ function CustomLabel({ icon: Icon, expandable, children, ...other }) { ); } -const isExpandable = (reactChildren) => { - if (Array.isArray(reactChildren)) { - return reactChildren.length > 0 && reactChildren.some(isExpandable); - } - return Boolean(reactChildren); -}; - const getIconFromFileType = (fileType) => { switch (fileType) { case 'image': @@ -210,6 +204,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) { const { id, itemId, label, disabled, children, ...other } = props; const { + getContextProviderProps, getRootProps, getContentProps, getIconContainerProps, @@ -218,20 +213,19 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) { getGroupTransitionProps, getDragAndDropOverlayProps, status, - publicAPI, } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref }); - const item = publicAPI.getItem(itemId); - const expandable = isExpandable(children); + const item = useTreeItemModel(itemId); + let icon; - if (expandable) { + if (status.expandable) { icon = FolderRounded; } else if (item.fileType) { icon = getIconFromFileType(item.fileType); } return ( - + 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 09291542de682..dd76a0417488b 100644 --- a/docs/data/tree-view/rich-tree-view/customization/FileExplorer.tsx +++ b/docs/data/tree-view/rich-tree-view/customization/FileExplorer.tsx @@ -26,6 +26,7 @@ import { 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 { useTreeItemModel } from '@mui/x-tree-view/hooks'; import { TreeViewBaseItem } from '@mui/x-tree-view/models'; type FileType = 'image' | 'pdf' | 'doc' | 'video' | 'folder' | 'pinned' | 'trash'; @@ -204,13 +205,6 @@ function CustomLabel({ ); } -const isExpandable = (reactChildren: React.ReactNode) => { - if (Array.isArray(reactChildren)) { - return reactChildren.length > 0 && reactChildren.some(isExpandable); - } - return Boolean(reactChildren); -}; - const getIconFromFileType = (fileType: FileType) => { switch (fileType) { case 'image': @@ -243,6 +237,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( const { id, itemId, label, disabled, children, ...other } = props; const { + getContextProviderProps, getRootProps, getContentProps, getIconContainerProps, @@ -251,20 +246,19 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( getGroupTransitionProps, getDragAndDropOverlayProps, status, - publicAPI, } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref }); - const item = publicAPI.getItem(itemId); - const expandable = isExpandable(children); + const item = useTreeItemModel(itemId)!; + let icon; - if (expandable) { + if (status.expandable) { icon = FolderRounded; } else if (item.fileType) { icon = getIconFromFileType(item.fileType); } return ( - + 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 172d7a1deaaf8..a946acc455c89 100644 --- a/docs/data/tree-view/rich-tree-view/customization/HeadlessAPI.js +++ b/docs/data/tree-view/rich-tree-view/customization/HeadlessAPI.js @@ -40,6 +40,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) { const { id, itemId, label, disabled, children, ...other } = props; const { + getContextProviderProps, getRootProps, getContentProps, getIconContainerProps, @@ -51,7 +52,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) { } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref }); return ( - + 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 bccd2390df601..3554fd4cc93e5 100644 --- a/docs/data/tree-view/rich-tree-view/customization/HeadlessAPI.tsx +++ b/docs/data/tree-view/rich-tree-view/customization/HeadlessAPI.tsx @@ -47,6 +47,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( const { id, itemId, label, disabled, children, ...other } = props; const { + getContextProviderProps, getRootProps, getContentProps, getIconContainerProps, @@ -58,7 +59,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref }); return ( - + 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 ae18c0407ee10..31172e0714200 100644 --- a/docs/data/tree-view/rich-tree-view/customization/customization.md +++ b/docs/data/tree-view/rich-tree-view/customization/customization.md @@ -1,6 +1,5 @@ --- productId: x-tree-view -title: Rich Tree View - Customization components: RichTreeView, TreeItem packageName: '@mui/x-tree-view' githubLabel: 'component: tree view' diff --git a/docs/data/tree-view/rich-tree-view/editing/CustomLabelInput.js b/docs/data/tree-view/rich-tree-view/editing/CustomLabelInput.js index 552f4de2ce1f3..dfbfeec308cbe 100644 --- a/docs/data/tree-view/rich-tree-view/editing/CustomLabelInput.js +++ b/docs/data/tree-view/rich-tree-view/editing/CustomLabelInput.js @@ -6,8 +6,8 @@ import IconButton from '@mui/material/IconButton'; import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; import CloseRoundedIcon from '@mui/icons-material/CloseRounded'; import { TreeItem, TreeItemLabel } from '@mui/x-tree-view/TreeItem'; -import { useTreeItem } from '@mui/x-tree-view/useTreeItem'; -import { useTreeItemUtils } from '@mui/x-tree-view/hooks'; + +import { useTreeItemUtils, useTreeItemModel } from '@mui/x-tree-view/hooks'; const StyledLabelInput = styled('input')(({ theme }) => ({ ...theme.typography.body1, @@ -69,9 +69,11 @@ function Label({ children, ...other }) { } const LabelInput = React.forwardRef(function LabelInput( - { item, handleCancelItemLabelEditing, handleSaveItemLabel, ...props }, + { itemId, handleCancelItemLabelEditing, handleSaveItemLabel, ...props }, ref, ) { + const item = useTreeItemModel(itemId); + const [initialNameValue, setInitialNameValue] = React.useState({ firstName: item.firstName, lastName: item.lastName, @@ -141,7 +143,6 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) { itemId: props.itemId, children: props.children, }); - const { publicAPI } = useTreeItem(props); const handleInputBlur = (event) => { event.defaultMuiPrevented = true; @@ -158,7 +159,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) { slots={{ label: Label, labelInput: LabelInput }} slotProps={{ labelInput: { - item: publicAPI.getItem(props.itemId), + itemId: props.itemId, onBlur: handleInputBlur, onKeyDown: handleInputKeyDown, handleCancelItemLabelEditing: interactions.handleCancelItemLabelEditing, diff --git a/docs/data/tree-view/rich-tree-view/editing/CustomLabelInput.tsx b/docs/data/tree-view/rich-tree-view/editing/CustomLabelInput.tsx index 8b4d1ad7c1434..248f80009c8cf 100644 --- a/docs/data/tree-view/rich-tree-view/editing/CustomLabelInput.tsx +++ b/docs/data/tree-view/rich-tree-view/editing/CustomLabelInput.tsx @@ -9,10 +9,9 @@ import { TreeItem, TreeItemLabel, TreeItemProps } from '@mui/x-tree-view/TreeIte import { UseTreeItemLabelInputSlotOwnProps, UseTreeItemLabelSlotOwnProps, - useTreeItem, } from '@mui/x-tree-view/useTreeItem'; -import { useTreeItemUtils } from '@mui/x-tree-view/hooks'; -import { TreeViewBaseItem } from '@mui/x-tree-view/models'; +import { useTreeItemUtils, useTreeItemModel } from '@mui/x-tree-view/hooks'; +import { TreeViewBaseItem, TreeViewItemId } from '@mui/x-tree-view/models'; const StyledLabelInput = styled('input')(({ theme }) => ({ ...theme.typography.body1, @@ -83,18 +82,20 @@ function Label({ children, ...other }: UseTreeItemLabelSlotOwnProps) { interface CustomLabelInputProps extends UseTreeItemLabelInputSlotOwnProps { handleCancelItemLabelEditing: (event: React.SyntheticEvent) => void; handleSaveItemLabel: (event: React.SyntheticEvent, label: string) => void; - item: TreeViewBaseItem; + itemId: TreeViewItemId; } const LabelInput = React.forwardRef(function LabelInput( { - item, + itemId, handleCancelItemLabelEditing, handleSaveItemLabel, ...props }: Omit, ref: React.Ref, ) { + const item = useTreeItemModel(itemId)!; + const [initialNameValue, setInitialNameValue] = React.useState({ firstName: item.firstName, lastName: item.lastName, @@ -167,7 +168,6 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( itemId: props.itemId, children: props.children, }); - const { publicAPI } = useTreeItem(props); const handleInputBlur: UseTreeItemLabelInputSlotOwnProps['onBlur'] = (event) => { event.defaultMuiPrevented = true; @@ -186,7 +186,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( slots={{ label: Label, labelInput: LabelInput }} slotProps={{ labelInput: { - item: publicAPI.getItem(props.itemId), + itemId: props.itemId, onBlur: handleInputBlur, onKeyDown: handleInputKeyDown, handleCancelItemLabelEditing: interactions.handleCancelItemLabelEditing, diff --git a/docs/data/tree-view/rich-tree-view/editing/editableProducts.js b/docs/data/tree-view/rich-tree-view/editing/editableProducts.js new file mode 100644 index 0000000000000..f34a7b652d408 --- /dev/null +++ b/docs/data/tree-view/rich-tree-view/editing/editableProducts.js @@ -0,0 +1,32 @@ +export const MUI_X_PRODUCTS = [ + { + id: 'grid', + label: 'Data Grid', + children: [ + { id: 'grid-community', label: '@mui/x-data-grid editable', editable: true }, + { id: 'grid-pro', label: '@mui/x-data-grid-pro editable', editable: true }, + { 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' }], + }, +]; diff --git a/docs/data/tree-view/rich-tree-view/editing/editing.md b/docs/data/tree-view/rich-tree-view/editing/editing.md index 743dcf808dea0..aaa70c2ae28e4 100644 --- a/docs/data/tree-view/rich-tree-view/editing/editing.md +++ b/docs/data/tree-view/rich-tree-view/editing/editing.md @@ -1,6 +1,5 @@ --- productId: x-tree-view -title: Rich Tree View - Editing components: RichTreeView, TreeItem githubLabel: 'component: tree view' packageName: '@mui/x-tree-view' diff --git a/docs/data/tree-view/rich-tree-view/editing/employees.js b/docs/data/tree-view/rich-tree-view/editing/employees.js new file mode 100644 index 0000000000000..df8b8474725e9 --- /dev/null +++ b/docs/data/tree-view/rich-tree-view/editing/employees.js @@ -0,0 +1,28 @@ +export const EMPLOYEES = [ + { + id: '1', + firstName: 'Jane', + lastName: 'Doe', + editable: true, + children: [ + { id: '1.1', firstName: 'Elena', lastName: 'Kim', editable: true }, + { id: '1.2', firstName: 'Noah', lastName: 'Rodriguez', editable: true }, + { id: '1.3', firstName: 'Maya', lastName: 'Patel', editable: true }, + ], + }, + { + id: '2', + firstName: 'Liam', + lastName: 'Clarke', + editable: true, + children: [ + { + id: '2.1', + firstName: 'Ethan', + lastName: 'Lee', + editable: true, + }, + { id: '2.2', firstName: 'Ava', lastName: 'Jones', editable: true }, + ], + }, +]; diff --git a/docs/data/tree-view/rich-tree-view/editing/products.js b/docs/data/tree-view/rich-tree-view/editing/products.js new file mode 100644 index 0000000000000..384f68c38b0b7 --- /dev/null +++ b/docs/data/tree-view/rich-tree-view/editing/products.js @@ -0,0 +1,32 @@ +export 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' }], + }, +]; diff --git a/docs/data/tree-view/rich-tree-view/expansion/expansion.md b/docs/data/tree-view/rich-tree-view/expansion/expansion.md index 84bcb34b503b5..2ca0d544853bd 100644 --- a/docs/data/tree-view/rich-tree-view/expansion/expansion.md +++ b/docs/data/tree-view/rich-tree-view/expansion/expansion.md @@ -1,6 +1,5 @@ --- productId: x-tree-view -title: Rich Tree View - Expansion components: RichTreeView, TreeItem packageName: '@mui/x-tree-view' githubLabel: 'component: tree view' diff --git a/docs/data/tree-view/rich-tree-view/focus/focus.md b/docs/data/tree-view/rich-tree-view/focus/focus.md index 9a23786173ea7..506ceb0423c5a 100644 --- a/docs/data/tree-view/rich-tree-view/focus/focus.md +++ b/docs/data/tree-view/rich-tree-view/focus/focus.md @@ -1,6 +1,5 @@ --- productId: x-tree-view -title: Rich Tree View - Focus components: RichTreeView, TreeItem packageName: '@mui/x-tree-view' githubLabel: 'component: tree view' diff --git a/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.js b/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.js index 1b76b33540846..3d6077c4fdac0 100644 --- a/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.js +++ b/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.js @@ -7,8 +7,11 @@ import { RichTreeViewRoot, RICH_TREE_VIEW_PLUGINS, } from '@mui/x-tree-view/RichTreeView'; -import { TreeItem } from '@mui/x-tree-view/TreeItem'; -import { useTreeView, TreeViewProvider } from '@mui/x-tree-view/internals'; +import { + useTreeView, + TreeViewProvider, + RichTreeViewItems, +} from '@mui/x-tree-view/internals'; const useTreeViewLogExpanded = ({ params, models }) => { const expandedStr = JSON.stringify(models.expandedItems.value); @@ -36,25 +39,15 @@ useTreeViewLogExpanded.params = { const TREE_VIEW_PLUGINS = [...RICH_TREE_VIEW_PLUGINS, useTreeViewLogExpanded]; function TreeView(props) { - const { getRootProps, contextValue, instance } = useTreeView({ + const { getRootProps, contextValue } = useTreeView({ plugins: TREE_VIEW_PLUGINS, props, }); - const itemsToRender = instance.getItemsToRender(); - - const renderItem = ({ children: itemChildren, ...itemProps }) => { - return ( - - {itemChildren?.map(renderItem)} - - ); - }; - return ( - {itemsToRender.map(renderItem)} + ); diff --git a/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx b/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx index 5c6942d61458b..bab71f7134789 100644 --- a/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx +++ b/docs/data/tree-view/rich-tree-view/headless/LogExpandedItems.tsx @@ -11,7 +11,6 @@ import { RichTreeViewPluginSlots, RichTreeViewPluginSlotProps, } from '@mui/x-tree-view/RichTreeView'; -import { TreeItem } from '@mui/x-tree-view/TreeItem'; import { UseTreeViewExpansionSignature, TreeViewPlugin, @@ -19,6 +18,7 @@ import { useTreeView, TreeViewProvider, ConvertPluginsIntoSignatures, + RichTreeViewItems, } from '@mui/x-tree-view/internals'; interface TreeViewLogExpandedParameters { @@ -86,7 +86,7 @@ type TreeViewPluginSignatures = ConvertPluginsIntoSignatures< function TreeView( props: TreeViewProps, ) { - const { getRootProps, contextValue, instance } = useTreeView< + const { getRootProps, contextValue } = useTreeView< TreeViewPluginSignatures, typeof props >({ @@ -94,23 +94,10 @@ function TreeView( props, }); - const itemsToRender = instance.getItemsToRender(); - - const renderItem = ({ - children: itemChildren, - ...itemProps - }: ReturnType[number]) => { - return ( - - {itemChildren?.map(renderItem)} - - ); - }; - return ( - {itemsToRender.map(renderItem)} + ); diff --git a/docs/data/tree-view/rich-tree-view/headless/headless.md b/docs/data/tree-view/rich-tree-view/headless/headless.md index ece539bc73d5d..0cc8c75d50b60 100644 --- a/docs/data/tree-view/rich-tree-view/headless/headless.md +++ b/docs/data/tree-view/rich-tree-view/headless/headless.md @@ -1,6 +1,5 @@ --- productId: x-tree-view -title: Rich Tree View - Headless packageName: '@mui/x-tree-view' githubLabel: 'component: tree view' waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/ @@ -123,7 +122,7 @@ const useCustomPlugin = ({ models }) => { models.expandedItems.setValue([]); // Check if an item is expanded - const isExpanded = instance.isNodeExpanded('some-item-id'); + const isExpanded = useSelector(selectorIsItemExpanded, 'some-item-id'); }; }; ``` 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 49db9da0a4e2b..63a9c2961e5b9 100644 --- a/docs/data/tree-view/rich-tree-view/items/items.md +++ b/docs/data/tree-view/rich-tree-view/items/items.md @@ -1,6 +1,5 @@ --- productId: x-tree-view -title: Rich Tree View - Items components: RichTreeView, TreeItem packageName: '@mui/x-tree-view' githubLabel: 'component: tree view' 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 0e7bf9686ca88..9951fed165c13 100644 --- a/docs/data/tree-view/rich-tree-view/ordering/FileExplorer.js +++ b/docs/data/tree-view/rich-tree-view/ordering/FileExplorer.js @@ -23,8 +23,7 @@ import { 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'; +import { useTreeItemModel, useTreeViewApiRef } from '@mui/x-tree-view/hooks'; const ITEMS = [ { @@ -164,13 +163,6 @@ function CustomLabel({ icon: Icon, expandable, children, ...other }) { ); } -const isExpandable = (reactChildren) => { - if (Array.isArray(reactChildren)) { - return reactChildren.length > 0 && reactChildren.some(isExpandable); - } - return Boolean(reactChildren); -}; - const getIconFromFileType = (fileType) => { switch (fileType) { case 'image': @@ -194,6 +186,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) { const { id, itemId, label, disabled, children, ...other } = props; const { + getContextProviderProps, getRootProps, getContentProps, getIconContainerProps, @@ -202,15 +195,19 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) { getGroupTransitionProps, getDragAndDropOverlayProps, status, - publicAPI, } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref }); - const item = publicAPI.getItem(itemId); - const expandable = isExpandable(children); - const icon = getIconFromFileType(item.fileType); + const item = useTreeItemModel(itemId); + + let icon; + if (status.expandable) { + icon = FolderRounded; + } else if (item.fileType) { + icon = getIconFromFileType(item.fileType); + } return ( - + 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 ff08427f4691f..49d4013853f53 100644 --- a/docs/data/tree-view/rich-tree-view/ordering/FileExplorer.tsx +++ b/docs/data/tree-view/rich-tree-view/ordering/FileExplorer.tsx @@ -23,8 +23,8 @@ import { 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 { useTreeItemModel, useTreeViewApiRef } from '@mui/x-tree-view/hooks'; import { TreeViewBaseItem } from '@mui/x-tree-view/models'; -import { useTreeViewApiRef } from '@mui/x-tree-view/hooks'; type FileType = 'image' | 'pdf' | 'doc' | 'video' | 'folder' | 'pinned' | 'trash'; @@ -189,13 +189,6 @@ function CustomLabel({ ); } -const isExpandable = (reactChildren: React.ReactNode) => { - if (Array.isArray(reactChildren)) { - return reactChildren.length > 0 && reactChildren.some(isExpandable); - } - return Boolean(reactChildren); -}; - const getIconFromFileType = (fileType: FileType) => { switch (fileType) { case 'image': @@ -226,6 +219,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( const { id, itemId, label, disabled, children, ...other } = props; const { + getContextProviderProps, getRootProps, getContentProps, getIconContainerProps, @@ -234,15 +228,19 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( getGroupTransitionProps, getDragAndDropOverlayProps, status, - publicAPI, } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref }); - const item = publicAPI.getItem(itemId); - const expandable = isExpandable(children); - const icon = getIconFromFileType(item.fileType); + const item = useTreeItemModel(itemId)!; + + let icon; + if (status.expandable) { + icon = FolderRounded; + } else if (item.fileType) { + icon = getIconFromFileType(item.fileType); + } return ( - + 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 6abae8742ed17..6d81228535526 100644 --- a/docs/data/tree-view/rich-tree-view/ordering/OnlyReorderFromDragHandle.js +++ b/docs/data/tree-view/rich-tree-view/ordering/OnlyReorderFromDragHandle.js @@ -50,6 +50,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) { const { id, itemId, label, disabled, children, ...other } = props; const { + getContextProviderProps, getRootProps, getContentProps, getIconContainerProps, @@ -73,7 +74,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) { }; return ( - + 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 bdf2378a6dbb0..f2d38f4972cc6 100644 --- a/docs/data/tree-view/rich-tree-view/ordering/OnlyReorderFromDragHandle.tsx +++ b/docs/data/tree-view/rich-tree-view/ordering/OnlyReorderFromDragHandle.tsx @@ -57,6 +57,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( const { id, itemId, label, disabled, children, ...other } = props; const { + getContextProviderProps, getRootProps, getContentProps, getIconContainerProps, @@ -84,7 +85,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( }; return ( - + diff --git a/docs/data/tree-view/rich-tree-view/selection/selection.md b/docs/data/tree-view/rich-tree-view/selection/selection.md index 02036050d5023..9dc9edd8b1163 100644 --- a/docs/data/tree-view/rich-tree-view/selection/selection.md +++ b/docs/data/tree-view/rich-tree-view/selection/selection.md @@ -1,6 +1,5 @@ --- productId: x-tree-view -title: Rich Tree View - Selection components: RichTreeView, TreeItem packageName: '@mui/x-tree-view' githubLabel: 'component: tree view' @@ -88,12 +87,12 @@ type TreeViewSelectionPropagation = { }; ``` -When `selectionPropagation.descendants` is set to `true`. +When `selectionPropagation.descendants` is set to `true`: - Selecting a parent selects all its descendants automatically. - Deselecting a parent deselects all its descendants automatically. -When `selectionPropagation.parents` is set to `true`. +When `selectionPropagation.parents` is set to `true`: - Selecting all the descendants of a parent selects the parent automatically. - Deselecting a descendant of a selected parent deselects the parent automatically. diff --git a/docs/data/tree-view/simple-tree-view/customization/GmailTreeView.js b/docs/data/tree-view/simple-tree-view/customization/GmailTreeView.js index da5c5eebb7f4a..c07504f8a92fc 100644 --- a/docs/data/tree-view/simple-tree-view/customization/GmailTreeView.js +++ b/docs/data/tree-view/simple-tree-view/customization/GmailTreeView.js @@ -69,6 +69,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) { } = props; const { + getContextProviderProps, getRootProps, getContentProps, getIconContainerProps, @@ -84,7 +85,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) { }; return ( - + + + diff --git a/docs/data/tree-view/simple-tree-view/customization/HeadlessAPI.tsx b/docs/data/tree-view/simple-tree-view/customization/HeadlessAPI.tsx index 10f47fe2aa3db..67c04b2c4b92f 100644 --- a/docs/data/tree-view/simple-tree-view/customization/HeadlessAPI.tsx +++ b/docs/data/tree-view/simple-tree-view/customization/HeadlessAPI.tsx @@ -25,6 +25,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( const { id, itemId, label, disabled, children, ...other } = props; const { + getContextProviderProps, getRootProps, getContentProps, getIconContainerProps, @@ -35,7 +36,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref }); return ( - + diff --git a/docs/data/tree-view/tree-item-customization/CustomTreeItemDemo.js b/docs/data/tree-view/tree-item-customization/CustomTreeItemDemo.js index 9a39125199f45..436d40ea821fc 100644 --- a/docs/data/tree-view/tree-item-customization/CustomTreeItemDemo.js +++ b/docs/data/tree-view/tree-item-customization/CustomTreeItemDemo.js @@ -103,12 +103,13 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) { getGroupTransitionProps, getDragAndDropOverlayProps, getLabelInputProps, + getContextProviderProps, status, } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref }); return ( - + - + + {status.expandable && ( + {status.expandable && ( , ) { - const { publicAPI } = useTreeItemUtils({ - itemId: props.itemId, - children: props.children, - }); - - const item = publicAPI.getItem(props.itemId); + const item = useTreeItemModel(props.itemId)!; return ( -Tree Item anatomy + Tree Item anatomy -Tree Item anatomy + Tree Item anatomy ### Content @@ -146,13 +146,20 @@ You can use the `useTreeItem` hook to access the `publicAPI` object from within See the **Imperative API** section on each feature page to learn more about the public API methods available on the Tree View. +:::warning +The `publicAPI` object should not be used in the render because the item won't necessarily re-render when the returned value is updated. + +If you want to access the item model, you can use the `useTreeItemModel` hook. +See [Tree Item Customization—useTreeItemModel](/x/react-tree-view/tree-item-customization/#usetreeitemmodel) for more details. +::: + ### `useTreeItemUtils` The `useTreeItemUtils` hook provides a set of interaction methods for implementing custom behaviors for the Tree View. It also returns the status of the Item. ```jsx -const { interactions, status } = useTreeItemUtils({ +const { interactions, status, publicAPI } = useTreeItemUtils({ itemId: props.itemId, children: props.children, }); @@ -207,3 +214,13 @@ const { ``` See [Editing—enable editing using only icons](/x/react-tree-view/rich-tree-view/editing/#enable-editing-using-only-icons) for more details on customizing this behavior. + +### `useTreeItemModel` + +The `useTreeItemModel` hook lets you access the item model (the object passed to `props.items`): + +```jsx +const item = useTreeItemModel(itemId); +``` + +{{"demo": "LabelSlot.js"}} diff --git a/docs/data/tree-view/tree-item-customization/useTreeItemHookProperties.js b/docs/data/tree-view/tree-item-customization/useTreeItemHookProperties.js index f9683d989e7bb..87f651ee8c6de 100644 --- a/docs/data/tree-view/tree-item-customization/useTreeItemHookProperties.js +++ b/docs/data/tree-view/tree-item-customization/useTreeItemHookProperties.js @@ -21,6 +21,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( ref, ) { const { + getContextProviderProps, getRootProps, getContentProps, getIconContainerProps, @@ -33,7 +34,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref }); return ( - + diff --git a/docs/data/tree-view/tree-item-customization/useTreeItemHookProperties.tsx b/docs/data/tree-view/tree-item-customization/useTreeItemHookProperties.tsx index 8e49e71df5474..0fc4072427ac6 100644 --- a/docs/data/tree-view/tree-item-customization/useTreeItemHookProperties.tsx +++ b/docs/data/tree-view/tree-item-customization/useTreeItemHookProperties.tsx @@ -22,6 +22,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( ref: React.Ref, ) { const { + getContextProviderProps, getRootProps, getContentProps, getIconContainerProps, @@ -34,7 +35,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref }); return ( - + diff --git a/docs/data/tree-view/tree-item-customization/useTreeItemHookPublicAPI.js b/docs/data/tree-view/tree-item-customization/useTreeItemHookPublicAPI.js index 72886928944de..0c71983ff031e 100644 --- a/docs/data/tree-view/tree-item-customization/useTreeItemHookPublicAPI.js +++ b/docs/data/tree-view/tree-item-customization/useTreeItemHookPublicAPI.js @@ -1,14 +1,14 @@ import * as React from 'react'; import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; -import Chip from '@mui/material/Chip'; +import Button from '@mui/material/Button'; import Stack from '@mui/material/Stack'; import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; import { TreeItem } from '@mui/x-tree-view/TreeItem'; import { useTreeItem } from '@mui/x-tree-view/useTreeItem'; import { MUI_X_PRODUCTS } from './products'; -function CustomLabel({ children, className, numberOfChildren }) { +function CustomLabel({ children, className, selectFirstChildren }) { return ( {children} - - + {!!selectFirstChildren && ( + + )} ); } const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) { - const { publicAPI } = useTreeItem(props); + const { publicAPI, status } = useTreeItem(props); - const childrenNumber = publicAPI.getItemOrderedChildrenIds(props.itemId).length; + const selectFirstChildren = status.expanded + ? (event) => { + event.stopPropagation(); + const children = publicAPI.getItemOrderedChildrenIds(props.itemId); + if (children.length > 0) { + publicAPI.selectItem({ + event, + itemId: children[0], + shouldBeSelected: true, + }); + } + } + : undefined; return ( ); diff --git a/docs/data/tree-view/tree-item-customization/useTreeItemHookPublicAPI.tsx b/docs/data/tree-view/tree-item-customization/useTreeItemHookPublicAPI.tsx index 48bf738b2fc80..3698ce968f026 100644 --- a/docs/data/tree-view/tree-item-customization/useTreeItemHookPublicAPI.tsx +++ b/docs/data/tree-view/tree-item-customization/useTreeItemHookPublicAPI.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; -import Chip from '@mui/material/Chip'; +import Button from '@mui/material/Button'; import Stack from '@mui/material/Stack'; import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; import { TreeItem, TreeItemProps } from '@mui/x-tree-view/TreeItem'; @@ -11,10 +11,14 @@ import { MUI_X_PRODUCTS } from './products'; interface CustomLabelProps { children: string; className: string; - numberOfChildren: number; + selectFirstChildren?: (event: React.MouseEvent) => void; } -function CustomLabel({ children, className, numberOfChildren }: CustomLabelProps) { +function CustomLabel({ + children, + className, + selectFirstChildren, +}: CustomLabelProps) { return ( {children} - - + {!!selectFirstChildren && ( + + )} ); } @@ -34,9 +46,21 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( props: TreeItemProps, ref: React.Ref, ) { - const { publicAPI } = useTreeItem(props); + const { publicAPI, status } = useTreeItem(props); - const childrenNumber = publicAPI.getItemOrderedChildrenIds(props.itemId).length; + const selectFirstChildren = status.expanded + ? (event: React.MouseEvent) => { + event.stopPropagation(); + const children = publicAPI.getItemOrderedChildrenIds(props.itemId); + if (children.length > 0) { + publicAPI.selectItem({ + event, + itemId: children[0], + shouldBeSelected: true, + }); + } + } + : undefined; return ( ); diff --git a/docs/data/tree-view/tree-item-customization/useTreeItemHookStatus.js b/docs/data/tree-view/tree-item-customization/useTreeItemHookStatus.js index 5c6e53c47b149..13395175085d7 100644 --- a/docs/data/tree-view/tree-item-customization/useTreeItemHookStatus.js +++ b/docs/data/tree-view/tree-item-customization/useTreeItemHookStatus.js @@ -88,6 +88,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( ref, ) { const { + getContextProviderProps, getRootProps, getContentProps, getLabelProps, @@ -98,7 +99,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( } = useTreeItem({ id, itemId, label, disabled, children, rootRef: ref }); return ( - + diff --git a/docs/data/tree-view/tree-item-customization/useTreeItemHookStatus.tsx b/docs/data/tree-view/tree-item-customization/useTreeItemHookStatus.tsx index d03d53ca63d01..783bf24064ca3 100644 --- a/docs/data/tree-view/tree-item-customization/useTreeItemHookStatus.tsx +++ b/docs/data/tree-view/tree-item-customization/useTreeItemHookStatus.tsx @@ -91,6 +91,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( ref: React.Ref, ) { const { + getContextProviderProps, getRootProps, getContentProps, getLabelProps, @@ -101,7 +102,7 @@ const CustomTreeItem = React.forwardRef(function CustomTreeItem( } = useTreeItem({ id, itemId, label, disabled, children, rootRef: ref }); return ( - + diff --git a/docs/data/tree-view/tree-item-customization/useTreeItemModelHook.js b/docs/data/tree-view/tree-item-customization/useTreeItemModelHook.js new file mode 100644 index 0000000000000..eba242636def9 --- /dev/null +++ b/docs/data/tree-view/tree-item-customization/useTreeItemModelHook.js @@ -0,0 +1,32 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; +import { TreeItem } from '@mui/x-tree-view/TreeItem'; +import { useTreeItemModel } from '@mui/x-tree-view/hooks'; +import { MUI_X_PRODUCTS } from './products'; + +const CustomTreeItem = React.forwardRef(function CustomTreeItem(props, ref) { + const item = useTreeItemModel(props.itemId); + + return ( + + ); +}); + +export default function useTreeItemModelHook() { + return ( + + + + ); +} diff --git a/docs/data/tree-view/tree-item-customization/useTreeItemModelHook.tsx b/docs/data/tree-view/tree-item-customization/useTreeItemModelHook.tsx new file mode 100644 index 0000000000000..fedf73068fa7d --- /dev/null +++ b/docs/data/tree-view/tree-item-customization/useTreeItemModelHook.tsx @@ -0,0 +1,41 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; +import { TreeItem, TreeItemProps } from '@mui/x-tree-view/TreeItem'; +import { useTreeItemModel } from '@mui/x-tree-view/hooks'; +import { MUI_X_PRODUCTS } from './products'; + +type TreeItemWithLabel = { + id: string; + label: string; + isHighlighted?: boolean; +}; + +const CustomTreeItem = React.forwardRef(function CustomTreeItem( + props: TreeItemProps, + ref: React.Ref, +) { + const item = useTreeItemModel(props.itemId)!; + + return ( + + ); +}); + +export default function useTreeItemModelHook() { + return ( + + + + ); +} diff --git a/docs/data/tree-view/tree-item-customization/useTreeItemModelHook.tsx.preview b/docs/data/tree-view/tree-item-customization/useTreeItemModelHook.tsx.preview new file mode 100644 index 0000000000000..1333b932705fa --- /dev/null +++ b/docs/data/tree-view/tree-item-customization/useTreeItemModelHook.tsx.preview @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/docs/data/treeViewApiPages.ts b/docs/data/treeViewApiPages.ts index c68f64fdefccb..d60b19a355292 100644 --- a/docs/data/treeViewApiPages.ts +++ b/docs/data/treeViewApiPages.ts @@ -26,5 +26,9 @@ const treeViewApiPages: MuiPage[] = [ pathname: '/x/api/tree-view/tree-item-icon', title: 'TreeItemIcon', }, + { + pathname: '/x/api/tree-view/tree-item-provider', + title: 'TreeItemProvider', + }, ]; export default treeViewApiPages; diff --git a/docs/package.json b/docs/package.json index 2ea905f3e7846..a809ea21fa5f3 100644 --- a/docs/package.json +++ b/docs/package.json @@ -22,20 +22,20 @@ "@babel/core": "^7.26.0", "@babel/runtime": "^7.26.0", "@babel/runtime-corejs2": "^7.26.0", - "@docsearch/react": "^3.7.0", - "@emotion/cache": "^11.13.1", - "@emotion/react": "^11.13.3", + "@docsearch/react": "^3.8.0", + "@emotion/cache": "^11.13.5", + "@emotion/react": "^11.13.5", "@emotion/server": "^11.11.0", - "@emotion/styled": "^11.13.0", - "@mui/docs": "6.1.6", - "@mui/icons-material": "^5.16.7", + "@emotion/styled": "^11.13.5", + "@mui/docs": "6.1.10", + "@mui/icons-material": "^5.16.9", "@mui/joy": "^5.0.0-beta.48", "@mui/lab": "^5.0.0-alpha.173", - "@mui/material": "^5.16.7", - "@mui/material-nextjs": "^5.16.6", - "@mui/styles": "^5.16.7", - "@mui/system": "^5.16.7", - "@mui/utils": "^5.16.6", + "@mui/material": "^5.16.9", + "@mui/material-nextjs": "^5.16.8", + "@mui/styles": "^5.16.9", + "@mui/system": "^5.16.8", + "@mui/utils": "^5.16.8", "@mui/x-charts": "workspace:*", "@mui/x-charts-vendor": "workspace:*", "@mui/x-data-grid": "workspace:*", @@ -46,7 +46,7 @@ "@mui/x-date-pickers-pro": "workspace:*", "@mui/x-tree-view": "workspace:*", "@react-spring/web": "^9.7.5", - "@tanstack/query-core": "^5.59.20", + "@tanstack/query-core": "^5.62.3", "ast-types": "^0.14.2", "autoprefixer": "^10.4.20", "babel-plugin-module-resolver": "^5.0.2", @@ -71,23 +71,23 @@ "lodash": "^4.17.21", "luxon": "^3.5.0", "lz-string": "^1.5.0", - "markdown-to-jsx": "^7.5.0", + "markdown-to-jsx": "^7.7.1", "moment": "^2.30.1", "moment-hijri": "^3.0.0", - "moment-jalaali": "^0.10.1", + "moment-jalaali": "^0.10.4", "moment-timezone": "^0.5.46", - "next": "^14.2.17", + "next": "^14.2.20", "nprogress": "^0.2.0", - "postcss": "^8.4.47", + "postcss": "^8.4.49", "prismjs": "^1.29.0", "prop-types": "^15.8.1", "react": "^18.3.1", "react-docgen": "^5.4.3", "react-dom": "^18.3.1", - "react-hook-form": "^7.53.1", + "react-hook-form": "^7.54.0", "react-is": "^18.3.1", - "react-router": "^6.27.0", - "react-router-dom": "^6.27.0", + "react-router": "^6.28.0", + "react-router-dom": "^6.28.0", "react-runner": "^1.0.5", "react-simple-code-editor": "^0.14.1", "recast": "^0.23.9", @@ -102,21 +102,21 @@ "devDependencies": { "@babel/plugin-transform-react-constant-elements": "^7.25.9", "@babel/preset-typescript": "^7.26.0", - "@mui/internal-docs-utils": "^1.0.15", - "@mui/internal-scripts": "^1.0.26", + "@mui/internal-docs-utils": "^1.0.16", + "@mui/internal-scripts": "^1.0.29", "@types/chance": "^1.1.6", "@types/d3-scale": "^4.0.8", - "@types/d3-scale-chromatic": "^3.0.3", + "@types/d3-scale-chromatic": "^3.1.0", "@types/doctrine": "^0.0.9", "@types/gtag.js": "^0.0.20", "@types/lodash": "^4.17.13", "@types/luxon": "^3.4.2", "@types/moment-hijri": "^2.1.4", "@types/moment-jalaali": "^0.7.9", - "@types/prop-types": "^15.7.13", - "@types/react-dom": "^18.3.0", + "@types/prop-types": "^15.7.14", + "@types/react-dom": "^18.3.2", "@types/react-router-dom": "^5.3.3", - "@types/stylis": "^4.2.6", + "@types/stylis": "^4.2.7", "@types/webpack-bundle-analyzer": "^4.7.0", "gm": "^1.25.0", "serve": "^14.2.4" diff --git a/docs/pages/_app.js b/docs/pages/_app.js index 8f1471a414c70..3bd2fdb0ca7bb 100644 --- a/docs/pages/_app.js +++ b/docs/pages/_app.js @@ -222,6 +222,13 @@ function AppWrapper(props) { href: `${languagePrefix}${productIdSubpathMap[id]}/`, }; } + if (version === 'v7') { + // #default-branch-switch + return { + text: version, + href: `https://mui.com${languagePrefix}${productIdSubpathMap[id]}/`, + }; + } return { text: version, href: `https://${version}.mui.com${languagePrefix}${productIdSubpathMap[id]}/`, @@ -232,7 +239,7 @@ function AppWrapper(props) { metadata: '', name: 'MUI X', versions: [ - ...getVersionOptions('introduction', ['next', process.env.LIB_VERSION, 'v6', 'v5']), + ...getVersionOptions('introduction', [process.env.LIB_VERSION, 'v7', 'v6', 'v5']), { text: 'v4', href: `https://v4.mui.com${languagePrefix}/components/data-grid/` }, ], }; @@ -242,7 +249,7 @@ function AppWrapper(props) { metadata: 'MUI X', name: 'Data Grid', versions: [ - ...getVersionOptions('x-data-grid', ['next', process.env.DATA_GRID_VERSION, 'v6', 'v5']), + ...getVersionOptions('x-data-grid', [process.env.DATA_GRID_VERSION, 'v7', 'v6', 'v5']), { text: 'v4', href: `https://v4.mui.com${languagePrefix}/components/data-grid/` }, ], }; @@ -251,7 +258,7 @@ function AppWrapper(props) { metadata: 'MUI X', name: 'Date Pickers', versions: [ - ...getVersionOptions('x-date-pickers', ['next', process.env.DATE_PICKERS_VERSION, 'v6']), + ...getVersionOptions('x-date-pickers', [process.env.DATE_PICKERS_VERSION, 'v7', 'v6']), { text: 'v5', href: `https://v5.mui.com${languagePrefix}/x/react-date-pickers/getting-started/`, @@ -262,14 +269,14 @@ function AppWrapper(props) { productIdentifier = { metadata: 'MUI X', name: 'Charts', - versions: getVersionOptions('x-charts', ['next', process.env.CHARTS_VERSION, 'v6']), + versions: getVersionOptions('x-charts', [process.env.CHARTS_VERSION, 'v7', 'v6']), }; } else if (productId === 'x-tree-view') { productIdentifier = { metadata: 'MUI X', name: 'Tree View', versions: [ - ...getVersionOptions('x-tree-view', ['next', process.env.TREE_VIEW_VERSION]), + ...getVersionOptions('x-tree-view', [process.env.TREE_VIEW_VERSION, 'v7']), { text: 'v6', href: `https://v6.mui.com${languagePrefix}/x/react-tree-view/getting-started`, diff --git a/docs/pages/x/api/charts/axis-config.json b/docs/pages/x/api/charts/axis-config.json index 930aac071102a..d5d5f7117ac4e 100644 --- a/docs/pages/x/api/charts/axis-config.json +++ b/docs/pages/x/api/charts/axis-config.json @@ -1,6 +1,9 @@ { "name": "AxisConfig", - "imports": ["import { AxisConfig } from '@mui/x-charts'"], + "imports": [ + "import { AxisConfig } from '@mui/x-charts-pro'", + "import { AxisConfig } from '@mui/x-charts'" + ], "properties": { "id": { "type": { "description": "AxisId" }, "required": true }, "scaleType": { "type": { "description": "'band'" }, "required": true }, @@ -32,6 +35,7 @@ }, "valueFormatter": { "type": { "description": "(value: V, context: AxisValueFormatterContext) => string" } - } + }, + "zoom": { "type": { "description": "boolean | ZoomOptions" }, "isProPlan": true } } } diff --git a/docs/pages/x/api/charts/bar-chart-pro.json b/docs/pages/x/api/charts/bar-chart-pro.json index dd938b1859a6c..3e659753eeeff 100644 --- a/docs/pages/x/api/charts/bar-chart-pro.json +++ b/docs/pages/x/api/charts/bar-chart-pro.json @@ -10,7 +10,7 @@ "description": "{ x?: 'band'
| 'line'
| 'none', y?: 'band'
| 'line'
| 'none' }" }, "seeMoreLink": { - "url": "https://mui.com/x/react-charts/highlighting", + "url": "https://mui.com/x/react-charts/highlighting/", "text": "highlighting docs" } }, @@ -81,7 +81,6 @@ "describedArgs": ["zoomData"] } }, - "resolveSizeBeforeRender": { "type": { "name": "bool" }, "default": "false" }, "rightAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -93,13 +92,6 @@ "default": "{}", "additionalInfo": { "slotsApi": true } }, - "tooltip": { - "type": { - "name": "shape", - "description": "{ axisContent?: elementType, classes?: object, itemContent?: elementType, slotProps?: object, slots?: object, trigger?: 'axis'
| 'item'
| 'none' }" - }, - "seeMoreLink": { "url": "https://mui.com/x/react-charts/tooltip/", "text": "tooltip docs" } - }, "topAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -108,13 +100,13 @@ "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } }, "zoom": { diff --git a/docs/pages/x/api/charts/bar-chart.json b/docs/pages/x/api/charts/bar-chart.json index d0c21625f430e..7cb920914914d 100644 --- a/docs/pages/x/api/charts/bar-chart.json +++ b/docs/pages/x/api/charts/bar-chart.json @@ -10,7 +10,7 @@ "description": "{ x?: 'band'
| 'line'
| 'none', y?: 'band'
| 'line'
| 'none' }" }, "seeMoreLink": { - "url": "https://mui.com/x/react-charts/highlighting", + "url": "https://mui.com/x/react-charts/highlighting/", "text": "highlighting docs" } }, @@ -74,7 +74,6 @@ "describedArgs": ["event", "barItemIdentifier"] } }, - "resolveSizeBeforeRender": { "type": { "name": "bool" }, "default": "false" }, "rightAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -86,13 +85,6 @@ "default": "{}", "additionalInfo": { "slotsApi": true } }, - "tooltip": { - "type": { - "name": "shape", - "description": "{ axisContent?: elementType, classes?: object, itemContent?: elementType, slotProps?: object, slots?: object, trigger?: 'axis'
| 'item'
| 'none' }" - }, - "seeMoreLink": { "url": "https://mui.com/x/react-charts/tooltip/", "text": "tooltip docs" } - }, "topAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -101,13 +93,13 @@ "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" } }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" } } }, @@ -118,12 +110,6 @@ "import { BarChart } from '@mui/x-charts-pro';" ], "slots": [ - { - "name": "axisContent", - "description": "Custom component for displaying tooltip content when triggered by axis event.", - "default": "DefaultChartsAxisTooltipContent", - "class": null - }, { "name": "axisLabel", "description": "Custom component for axis label.", @@ -160,12 +146,6 @@ "default": "BarLabel", "class": null }, - { - "name": "itemContent", - "description": "Custom component for displaying tooltip content when triggered by item event.", - "default": "DefaultChartsItemTooltipContent", - "class": null - }, { "name": "legend", "description": "Custom rendering of the legend.", @@ -185,7 +165,7 @@ "class": null }, { - "name": "popper", + "name": "tooltip", "description": "Custom component for the tooltip popper.", "default": "ChartsTooltipRoot", "class": null diff --git a/docs/pages/x/api/charts/bar-element.json b/docs/pages/x/api/charts/bar-element.json index df4e8a407471e..ea3557373d077 100644 --- a/docs/pages/x/api/charts/bar-element.json +++ b/docs/pages/x/api/charts/bar-element.json @@ -22,6 +22,18 @@ } ], "classes": [ + { + "key": "faded", + "className": "MuiBarElement-faded", + "description": "Styles applied to the root element if it is faded.", + "isGlobal": false + }, + { + "key": "highlighted", + "className": "MuiBarElement-highlighted", + "description": "Styles applied to the root element if it is highlighted.", + "isGlobal": false + }, { "key": "root", "className": "MuiBarElement-root", diff --git a/docs/pages/x/api/charts/bar-series-type.json b/docs/pages/x/api/charts/bar-series-type.json index 29c14e4317f73..de9972728689c 100644 --- a/docs/pages/x/api/charts/bar-series-type.json +++ b/docs/pages/x/api/charts/bar-series-type.json @@ -1,6 +1,9 @@ { "name": "BarSeriesType", - "imports": ["import { BarSeriesType } from '@mui/x-charts'"], + "imports": [ + "import { BarSeriesType } from '@mui/x-charts-pro'", + "import { BarSeriesType } from '@mui/x-charts'" + ], "properties": { "type": { "type": { "description": "'bar'" }, "required": true }, "color": { "type": { "description": "string" } }, diff --git a/docs/pages/x/api/charts/chart-container-pro.json b/docs/pages/x/api/charts/chart-container-pro.json index ddebdaf446dc0..b1a75bf88ef77 100644 --- a/docs/pages/x/api/charts/chart-container-pro.json +++ b/docs/pages/x/api/charts/chart-container-pro.json @@ -39,19 +39,18 @@ } }, "plugins": { "type": { "name": "arrayOf", "description": "Array<object>" } }, - "resolveSizeBeforeRender": { "type": { "name": "bool" }, "default": "false" }, "skipAnimation": { "type": { "name": "bool" } }, "width": { "type": { "name": "number" } }, "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } }, "zAxis": { diff --git a/docs/pages/x/api/charts/chart-container.json b/docs/pages/x/api/charts/chart-container.json index 48e77d7b691d1..190b36e011f41 100644 --- a/docs/pages/x/api/charts/chart-container.json +++ b/docs/pages/x/api/charts/chart-container.json @@ -32,19 +32,18 @@ } }, "plugins": { "type": { "name": "arrayOf", "description": "Array<object>" } }, - "resolveSizeBeforeRender": { "type": { "name": "bool" }, "default": "false" }, "skipAnimation": { "type": { "name": "bool" } }, "width": { "type": { "name": "number" } }, "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" } }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" } }, "zAxis": { diff --git a/docs/pages/x/api/charts/default-heatmap-tooltip.js b/docs/pages/x/api/charts/chart-data-provider.js similarity index 76% rename from docs/pages/x/api/charts/default-heatmap-tooltip.js rename to docs/pages/x/api/charts/chart-data-provider.js index 2f8ce6db2a16d..73a45a0bc9325 100644 --- a/docs/pages/x/api/charts/default-heatmap-tooltip.js +++ b/docs/pages/x/api/charts/chart-data-provider.js @@ -1,7 +1,7 @@ import * as React from 'react'; import ApiPage from 'docs/src/modules/components/ApiPage'; import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; -import jsonPageContent from './default-heatmap-tooltip.json'; +import jsonPageContent from './chart-data-provider.json'; export default function Page(props) { const { descriptions, pageContent } = props; @@ -10,9 +10,9 @@ export default function Page(props) { Page.getInitialProps = () => { const req = require.context( - 'docsx/translations/api-docs/charts/default-heatmap-tooltip', + 'docsx/translations/api-docs/charts/chart-data-provider', false, - /\.\/default-heatmap-tooltip.*.json$/, + /\.\/chart-data-provider.*.json$/, ); const descriptions = mapApiPageTranslations(req); diff --git a/docs/pages/x/api/charts/chart-data-provider.json b/docs/pages/x/api/charts/chart-data-provider.json new file mode 100644 index 0000000000000..a1464572974db --- /dev/null +++ b/docs/pages/x/api/charts/chart-data-provider.json @@ -0,0 +1,70 @@ +{ + "props": { + "series": { + "type": { "name": "arrayOf", "description": "Array<object>" }, + "required": true + }, + "colors": { + "type": { "name": "union", "description": "Array<string>
| func" }, + "default": "blueberryTwilightPalette" + }, + "dataset": { "type": { "name": "arrayOf", "description": "Array<object>" } }, + "height": { "type": { "name": "number" } }, + "highlightedItem": { + "type": { + "name": "shape", + "description": "{ dataIndex?: number, seriesId?: number
| string }" + } + }, + "margin": { + "type": { + "name": "shape", + "description": "{ bottom?: number, left?: number, right?: number, top?: number }" + }, + "default": "object Depends on the charts type." + }, + "onHighlightChange": { + "type": { "name": "func" }, + "signature": { + "type": "function(highlightedItem: HighlightItemData | null) => void", + "describedArgs": ["highlightedItem"] + } + }, + "plugins": { "type": { "name": "arrayOf", "description": "Array<object>" } }, + "skipAnimation": { "type": { "name": "bool" } }, + "width": { "type": { "name": "number" } }, + "xAxis": { + "type": { + "name": "arrayOf", + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" + } + }, + "yAxis": { + "type": { + "name": "arrayOf", + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" + } + }, + "zAxis": { + "type": { + "name": "arrayOf", + "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string, max?: number, min?: number }>" + } + } + }, + "name": "ChartDataProvider", + "imports": [ + "import { ChartDataProvider } from '@mui/x-charts/context';", + "import { ChartDataProvider } from '@mui/x-charts';", + "import { ChartDataProvider } from '@mui/x-charts-pro';" + ], + "classes": [], + "spread": false, + "themeDefaultProps": false, + "muiName": "MuiChartDataProvider", + "forwardsRefTo": "SVGSVGElement", + "filename": "/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/pages/x/api/charts/default-charts-axis-tooltip-content.js b/docs/pages/x/api/charts/charts-axis-tooltip-content.js similarity index 72% rename from docs/pages/x/api/charts/default-charts-axis-tooltip-content.js rename to docs/pages/x/api/charts/charts-axis-tooltip-content.js index 662486e7e061c..9dc6feb6568cf 100644 --- a/docs/pages/x/api/charts/default-charts-axis-tooltip-content.js +++ b/docs/pages/x/api/charts/charts-axis-tooltip-content.js @@ -1,7 +1,7 @@ import * as React from 'react'; import ApiPage from 'docs/src/modules/components/ApiPage'; import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; -import jsonPageContent from './default-charts-axis-tooltip-content.json'; +import jsonPageContent from './charts-axis-tooltip-content.json'; export default function Page(props) { const { descriptions, pageContent } = props; @@ -10,9 +10,9 @@ export default function Page(props) { Page.getInitialProps = () => { const req = require.context( - 'docsx/translations/api-docs/charts/default-charts-axis-tooltip-content', + 'docsx/translations/api-docs/charts/charts-axis-tooltip-content', false, - /\.\/default-charts-axis-tooltip-content.*.json$/, + /\.\/charts-axis-tooltip-content.*.json$/, ); const descriptions = mapApiPageTranslations(req); diff --git a/docs/pages/x/api/charts/charts-axis-tooltip-content.json b/docs/pages/x/api/charts/charts-axis-tooltip-content.json new file mode 100644 index 0000000000000..c1cc1bbfb3d1c --- /dev/null +++ b/docs/pages/x/api/charts/charts-axis-tooltip-content.json @@ -0,0 +1,76 @@ +{ + "props": { "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } } }, + "name": "ChartsAxisTooltipContent", + "imports": [ + "import { ChartsAxisTooltipContent } from '@mui/x-charts/ChartsTooltip';", + "import { ChartsAxisTooltipContent } from '@mui/x-charts';", + "import { ChartsAxisTooltipContent } from '@mui/x-charts-pro';" + ], + "classes": [ + { + "key": "axisValueCell", + "className": "MuiChartsAxisTooltipContent-axisValueCell", + "description": "Styles applied to the axisValueCell element. Only available for axis tooltip.", + "isGlobal": false + }, + { + "key": "cell", + "className": "MuiChartsAxisTooltipContent-cell", + "description": "Styles applied to the cell element.", + "isGlobal": false + }, + { + "key": "labelCell", + "className": "MuiChartsAxisTooltipContent-labelCell", + "description": "Styles applied to the labelCell element.", + "isGlobal": false + }, + { + "key": "mark", + "className": "MuiChartsAxisTooltipContent-mark", + "description": "Styles applied to the mark element.", + "isGlobal": false + }, + { + "key": "markCell", + "className": "MuiChartsAxisTooltipContent-markCell", + "description": "Styles applied to the markCell element.", + "isGlobal": false + }, + { + "key": "paper", + "className": "MuiChartsAxisTooltipContent-paper", + "description": "Styles applied to the paper element.", + "isGlobal": false + }, + { + "key": "root", + "className": "MuiChartsAxisTooltipContent-root", + "description": "Styles applied to the root element.", + "isGlobal": false + }, + { + "key": "row", + "className": "MuiChartsAxisTooltipContent-row", + "description": "Styles applied to the row element.", + "isGlobal": false + }, + { + "key": "table", + "className": "MuiChartsAxisTooltipContent-table", + "description": "Styles applied to the table element.", + "isGlobal": false + }, + { + "key": "valueCell", + "className": "MuiChartsAxisTooltipContent-valueCell", + "description": "Styles applied to the valueCell element.", + "isGlobal": false + } + ], + "muiName": "MuiChartsAxisTooltipContent", + "filename": "/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/pages/x/api/charts/default-charts-item-tooltip-content.js b/docs/pages/x/api/charts/charts-item-tooltip-content.js similarity index 72% rename from docs/pages/x/api/charts/default-charts-item-tooltip-content.js rename to docs/pages/x/api/charts/charts-item-tooltip-content.js index 64821059860d7..3eb3dbfb139a1 100644 --- a/docs/pages/x/api/charts/default-charts-item-tooltip-content.js +++ b/docs/pages/x/api/charts/charts-item-tooltip-content.js @@ -1,7 +1,7 @@ import * as React from 'react'; import ApiPage from 'docs/src/modules/components/ApiPage'; import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; -import jsonPageContent from './default-charts-item-tooltip-content.json'; +import jsonPageContent from './charts-item-tooltip-content.json'; export default function Page(props) { const { descriptions, pageContent } = props; @@ -10,9 +10,9 @@ export default function Page(props) { Page.getInitialProps = () => { const req = require.context( - 'docsx/translations/api-docs/charts/default-charts-item-tooltip-content', + 'docsx/translations/api-docs/charts/charts-item-tooltip-content', false, - /\.\/default-charts-item-tooltip-content.*.json$/, + /\.\/charts-item-tooltip-content.*.json$/, ); const descriptions = mapApiPageTranslations(req); diff --git a/docs/pages/x/api/charts/charts-item-tooltip-content.json b/docs/pages/x/api/charts/charts-item-tooltip-content.json new file mode 100644 index 0000000000000..0d615795096e7 --- /dev/null +++ b/docs/pages/x/api/charts/charts-item-tooltip-content.json @@ -0,0 +1,76 @@ +{ + "props": { "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } } }, + "name": "ChartsItemTooltipContent", + "imports": [ + "import { ChartsItemTooltipContent } from '@mui/x-charts/ChartsTooltip';", + "import { ChartsItemTooltipContent } from '@mui/x-charts';", + "import { ChartsItemTooltipContent } from '@mui/x-charts-pro';" + ], + "classes": [ + { + "key": "axisValueCell", + "className": "MuiChartsItemTooltipContent-axisValueCell", + "description": "Styles applied to the axisValueCell element. Only available for axis tooltip.", + "isGlobal": false + }, + { + "key": "cell", + "className": "MuiChartsItemTooltipContent-cell", + "description": "Styles applied to the cell element.", + "isGlobal": false + }, + { + "key": "labelCell", + "className": "MuiChartsItemTooltipContent-labelCell", + "description": "Styles applied to the labelCell element.", + "isGlobal": false + }, + { + "key": "mark", + "className": "MuiChartsItemTooltipContent-mark", + "description": "Styles applied to the mark element.", + "isGlobal": false + }, + { + "key": "markCell", + "className": "MuiChartsItemTooltipContent-markCell", + "description": "Styles applied to the markCell element.", + "isGlobal": false + }, + { + "key": "paper", + "className": "MuiChartsItemTooltipContent-paper", + "description": "Styles applied to the paper element.", + "isGlobal": false + }, + { + "key": "root", + "className": "MuiChartsItemTooltipContent-root", + "description": "Styles applied to the root element.", + "isGlobal": false + }, + { + "key": "row", + "className": "MuiChartsItemTooltipContent-row", + "description": "Styles applied to the row element.", + "isGlobal": false + }, + { + "key": "table", + "className": "MuiChartsItemTooltipContent-table", + "description": "Styles applied to the table element.", + "isGlobal": false + }, + { + "key": "valueCell", + "className": "MuiChartsItemTooltipContent-valueCell", + "description": "Styles applied to the valueCell element.", + "isGlobal": false + } + ], + "muiName": "MuiChartsItemTooltipContent", + "filename": "/packages/x-charts/src/ChartsTooltip/ChartsItemTooltipContent.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/pages/x/api/charts/charts-surface.json b/docs/pages/x/api/charts/charts-surface.json index 6e280f8a01193..e5abdd4769eed 100644 --- a/docs/pages/x/api/charts/charts-surface.json +++ b/docs/pages/x/api/charts/charts-surface.json @@ -1,9 +1,5 @@ { - "props": { - "height": { "type": { "name": "number" }, "required": true }, - "width": { "type": { "name": "number" }, "required": true }, - "disableAxisListener": { "type": { "name": "bool" }, "default": "false" } - }, + "props": { "disableAxisListener": { "type": { "name": "bool" }, "default": "false" } }, "name": "ChartsSurface", "imports": [ "import { ChartsSurface } from '@mui/x-charts/ChartsSurface';", @@ -11,9 +7,11 @@ "import { ChartsSurface } from '@mui/x-charts-pro';" ], "classes": [], + "spread": true, + "themeDefaultProps": null, "muiName": "MuiChartsSurface", "filename": "/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx", "inheritance": null, - "demos": "", + "demos": "", "cssComponent": false } diff --git a/docs/pages/x/api/charts/charts-tooltip-container.js b/docs/pages/x/api/charts/charts-tooltip-container.js new file mode 100644 index 0000000000000..12e07a81bb759 --- /dev/null +++ b/docs/pages/x/api/charts/charts-tooltip-container.js @@ -0,0 +1,23 @@ +import * as React from 'react'; +import ApiPage from 'docs/src/modules/components/ApiPage'; +import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; +import jsonPageContent from './charts-tooltip-container.json'; + +export default function Page(props) { + const { descriptions, pageContent } = props; + return ; +} + +Page.getInitialProps = () => { + const req = require.context( + 'docsx/translations/api-docs/charts/charts-tooltip-container', + false, + /\.\/charts-tooltip-container.*.json$/, + ); + const descriptions = mapApiPageTranslations(req); + + return { + descriptions, + pageContent: jsonPageContent, + }; +}; diff --git a/docs/pages/x/api/charts/charts-tooltip-container.json b/docs/pages/x/api/charts/charts-tooltip-container.json new file mode 100644 index 0000000000000..4e3a06ef05b44 --- /dev/null +++ b/docs/pages/x/api/charts/charts-tooltip-container.json @@ -0,0 +1,150 @@ +{ + "props": { + "anchorEl": { + "type": { + "name": "union", + "description": "HTML element
| object
| func" + } + }, + "children": { "type": { "name": "node" } }, + "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } }, + "component": { "type": { "name": "elementType" } }, + "components": { + "type": { "name": "shape", "description": "{ Root?: elementType }" }, + "default": "{}" + }, + "componentsProps": { + "type": { "name": "shape", "description": "{ root?: func
| object }" }, + "default": "{}" + }, + "container": { + "type": { + "name": "union", + "description": "(props, propName) => {\n if (props[propName] == null) {\n return new Error(`Prop '${propName}' is required but wasn't specified`);\n }\n if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) {\n return new Error(`Expected prop '${propName}' to be of type Element`);\n }\n return null;\n}
| func" + } + }, + "disablePortal": { "type": { "name": "bool" }, "default": "false" }, + "keepMounted": { "type": { "name": "bool" }, "default": "false" }, + "modifiers": { + "type": { + "name": "arrayOf", + "description": "Array<{ data?: object, effect?: func, enabled?: bool, fn?: func, name?: any, options?: object, phase?: 'afterMain'
| 'afterRead'
| 'afterWrite'
| 'beforeMain'
| 'beforeRead'
| 'beforeWrite'
| 'main'
| 'read'
| 'write', requires?: Array<string>, requiresIfExists?: Array<string> }>" + } + }, + "open": { "type": { "name": "bool" } }, + "placement": { + "type": { + "name": "enum", + "description": "'auto-end'
| 'auto-start'
| 'auto'
| 'bottom-end'
| 'bottom-start'
| 'bottom'
| 'left-end'
| 'left-start'
| 'left'
| 'right-end'
| 'right-start'
| 'right'
| 'top-end'
| 'top-start'
| 'top'" + }, + "default": "'bottom'" + }, + "popperOptions": { + "type": { + "name": "shape", + "description": "{ modifiers?: array, onFirstUpdate?: func, placement?: 'auto-end'
| 'auto-start'
| 'auto'
| 'bottom-end'
| 'bottom-start'
| 'bottom'
| 'left-end'
| 'left-start'
| 'left'
| 'right-end'
| 'right-start'
| 'right'
| 'top-end'
| 'top-start'
| 'top', strategy?: 'absolute'
| 'fixed' }" + }, + "default": "{}" + }, + "popperRef": { + "type": { + "name": "union", + "description": "func
| { current?: { destroy: func, forceUpdate: func, setOptions: func, state: { attributes: object, elements: object, modifiersData: object, options: object, orderedModifiers: Array<object>, placement: 'auto-end'
| 'auto-start'
| 'auto'
| 'bottom-end'
| 'bottom-start'
| 'bottom'
| 'left-end'
| 'left-start'
| 'left'
| 'right-end'
| 'right-start'
| 'right'
| 'top-end'
| 'top-start'
| 'top', rects: object, reset: bool, scrollParents: object, strategy: 'absolute'
| 'fixed', styles: object }, update: func } }" + } + }, + "slotProps": { "type": { "name": "object" }, "default": "{}" }, + "slots": { + "type": { "name": "object" }, + "default": "{}", + "additionalInfo": { "slotsApi": true } + }, + "sx": { + "type": { + "name": "union", + "description": "Array<func
| object
| bool>
| func
| object" + }, + "additionalInfo": { "sx": true } + }, + "transition": { "type": { "name": "bool" }, "default": "false" }, + "trigger": { + "type": { + "name": "enum", + "description": "'axis'
| 'item'
| 'none'" + }, + "default": "'axis'" + } + }, + "name": "ChartsTooltipContainer", + "imports": [ + "import { ChartsTooltipContainer } from '@mui/x-charts/ChartsTooltip';", + "import { ChartsTooltipContainer } from '@mui/x-charts';", + "import { ChartsTooltipContainer } from '@mui/x-charts-pro';" + ], + "classes": [ + { + "key": "axisValueCell", + "className": "MuiChartsTooltipContainer-axisValueCell", + "description": "Styles applied to the axisValueCell element. Only available for axis tooltip.", + "isGlobal": false + }, + { + "key": "cell", + "className": "MuiChartsTooltipContainer-cell", + "description": "Styles applied to the cell element.", + "isGlobal": false + }, + { + "key": "labelCell", + "className": "MuiChartsTooltipContainer-labelCell", + "description": "Styles applied to the labelCell element.", + "isGlobal": false + }, + { + "key": "mark", + "className": "MuiChartsTooltipContainer-mark", + "description": "Styles applied to the mark element.", + "isGlobal": false + }, + { + "key": "markCell", + "className": "MuiChartsTooltipContainer-markCell", + "description": "Styles applied to the markCell element.", + "isGlobal": false + }, + { + "key": "paper", + "className": "MuiChartsTooltipContainer-paper", + "description": "Styles applied to the paper element.", + "isGlobal": false + }, + { + "key": "root", + "className": "MuiChartsTooltipContainer-root", + "description": "Styles applied to the root element.", + "isGlobal": false + }, + { + "key": "row", + "className": "MuiChartsTooltipContainer-row", + "description": "Styles applied to the row element.", + "isGlobal": false + }, + { + "key": "table", + "className": "MuiChartsTooltipContainer-table", + "description": "Styles applied to the table element.", + "isGlobal": false + }, + { + "key": "valueCell", + "className": "MuiChartsTooltipContainer-valueCell", + "description": "Styles applied to the valueCell element.", + "isGlobal": false + } + ], + "muiName": "MuiChartsTooltipContainer", + "filename": "/packages/x-charts/src/ChartsTooltip/ChartsTooltipContainer.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/pages/x/api/charts/charts-tooltip.json b/docs/pages/x/api/charts/charts-tooltip.json index cc191b7a0bf88..f89a6742ab279 100644 --- a/docs/pages/x/api/charts/charts-tooltip.json +++ b/docs/pages/x/api/charts/charts-tooltip.json @@ -1,15 +1,55 @@ { "props": { - "axisContent": { - "type": { "name": "elementType" }, - "deprecated": true, - "deprecationInfo": "Use slots.axisContent instead" + "anchorEl": { + "type": { + "name": "union", + "description": "HTML element
| object
| func" + } }, "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } }, - "itemContent": { - "type": { "name": "elementType" }, - "deprecated": true, - "deprecationInfo": "Use slots.itemContent instead" + "component": { "type": { "name": "elementType" } }, + "components": { + "type": { "name": "shape", "description": "{ Root?: elementType }" }, + "default": "{}" + }, + "componentsProps": { + "type": { "name": "shape", "description": "{ root?: func
| object }" }, + "default": "{}" + }, + "container": { + "type": { + "name": "union", + "description": "(props, propName) => {\n if (props[propName] == null) {\n return new Error(`Prop '${propName}' is required but wasn't specified`);\n }\n if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) {\n return new Error(`Expected prop '${propName}' to be of type Element`);\n }\n return null;\n}
| func" + } + }, + "disablePortal": { "type": { "name": "bool" }, "default": "false" }, + "keepMounted": { "type": { "name": "bool" }, "default": "false" }, + "modifiers": { + "type": { + "name": "arrayOf", + "description": "Array<{ data?: object, effect?: func, enabled?: bool, fn?: func, name?: any, options?: object, phase?: 'afterMain'
| 'afterRead'
| 'afterWrite'
| 'beforeMain'
| 'beforeRead'
| 'beforeWrite'
| 'main'
| 'read'
| 'write', requires?: Array<string>, requiresIfExists?: Array<string> }>" + } + }, + "open": { "type": { "name": "bool" } }, + "placement": { + "type": { + "name": "enum", + "description": "'auto-end'
| 'auto-start'
| 'auto'
| 'bottom-end'
| 'bottom-start'
| 'bottom'
| 'left-end'
| 'left-start'
| 'left'
| 'right-end'
| 'right-start'
| 'right'
| 'top-end'
| 'top-start'
| 'top'" + }, + "default": "'bottom'" + }, + "popperOptions": { + "type": { + "name": "shape", + "description": "{ modifiers?: array, onFirstUpdate?: func, placement?: 'auto-end'
| 'auto-start'
| 'auto'
| 'bottom-end'
| 'bottom-start'
| 'bottom'
| 'left-end'
| 'left-start'
| 'left'
| 'right-end'
| 'right-start'
| 'right'
| 'top-end'
| 'top-start'
| 'top', strategy?: 'absolute'
| 'fixed' }" + }, + "default": "{}" + }, + "popperRef": { + "type": { + "name": "union", + "description": "func
| { current?: { destroy: func, forceUpdate: func, setOptions: func, state: { attributes: object, elements: object, modifiersData: object, options: object, orderedModifiers: Array<object>, placement: 'auto-end'
| 'auto-start'
| 'auto'
| 'bottom-end'
| 'bottom-start'
| 'bottom'
| 'left-end'
| 'left-start'
| 'left'
| 'right-end'
| 'right-start'
| 'right'
| 'top-end'
| 'top-start'
| 'top', rects: object, reset: bool, scrollParents: object, strategy: 'absolute'
| 'fixed', styles: object }, update: func } }" + } }, "slotProps": { "type": { "name": "object" }, "default": "{}" }, "slots": { @@ -17,6 +57,14 @@ "default": "{}", "additionalInfo": { "slotsApi": true } }, + "sx": { + "type": { + "name": "union", + "description": "Array<func
| object
| bool>
| func
| object" + }, + "additionalInfo": { "sx": true } + }, + "transition": { "type": { "name": "bool" }, "default": "false" }, "trigger": { "type": { "name": "enum", @@ -31,27 +79,13 @@ "import { ChartsTooltip } from '@mui/x-charts';", "import { ChartsTooltip } from '@mui/x-charts-pro';" ], - "slots": [ - { - "name": "axisContent", - "description": "Custom component for displaying tooltip content when triggered by axis event.", - "default": "DefaultChartsAxisTooltipContent", - "class": null - }, + "classes": [ { - "name": "itemContent", - "description": "Custom component for displaying tooltip content when triggered by item event.", - "default": "DefaultChartsItemTooltipContent", - "class": null + "key": "axisValueCell", + "className": "MuiChartsTooltip-axisValueCell", + "description": "Styles applied to the axisValueCell element. Only available for axis tooltip.", + "isGlobal": false }, - { - "name": "popper", - "description": "Custom component for the tooltip popper.", - "default": "ChartsTooltipRoot", - "class": null - } - ], - "classes": [ { "key": "cell", "className": "MuiChartsTooltip-cell", diff --git a/docs/pages/x/api/charts/charts-x-axis.json b/docs/pages/x/api/charts/charts-x-axis.json index ddfb6a1329f98..eb1c3e2ddf247 100644 --- a/docs/pages/x/api/charts/charts-x-axis.json +++ b/docs/pages/x/api/charts/charts-x-axis.json @@ -6,12 +6,6 @@ "disableTicks": { "type": { "name": "bool" }, "default": "false" }, "fill": { "type": { "name": "string" }, "default": "'currentColor'" }, "label": { "type": { "name": "string" } }, - "labelFontSize": { - "type": { "name": "number" }, - "default": "14", - "deprecated": true, - "deprecationInfo": "Consider using labelStyle.fontSize instead." - }, "labelStyle": { "type": { "name": "object" } }, "position": { "type": { "name": "enum", "description": "'bottom'
| 'top'" } }, "slotProps": { "type": { "name": "object" }, "default": "{}" }, @@ -21,12 +15,6 @@ "additionalInfo": { "slotsApi": true } }, "stroke": { "type": { "name": "string" }, "default": "'currentColor'" }, - "tickFontSize": { - "type": { "name": "number" }, - "default": "12", - "deprecated": true, - "deprecationInfo": "Consider using tickLabelStyle.fontSize instead." - }, "tickInterval": { "type": { "name": "union", "description": "'auto'
| array
| func" }, "default": "'auto'" diff --git a/docs/pages/x/api/charts/charts-y-axis.json b/docs/pages/x/api/charts/charts-y-axis.json index f7c09f9fe809f..7461e94adc33e 100644 --- a/docs/pages/x/api/charts/charts-y-axis.json +++ b/docs/pages/x/api/charts/charts-y-axis.json @@ -6,12 +6,6 @@ "disableTicks": { "type": { "name": "bool" }, "default": "false" }, "fill": { "type": { "name": "string" }, "default": "'currentColor'" }, "label": { "type": { "name": "string" } }, - "labelFontSize": { - "type": { "name": "number" }, - "default": "14", - "deprecated": true, - "deprecationInfo": "Consider using labelStyle.fontSize instead." - }, "labelStyle": { "type": { "name": "object" } }, "position": { "type": { "name": "enum", "description": "'left'
| 'right'" } }, "slotProps": { "type": { "name": "object" }, "default": "{}" }, @@ -21,12 +15,6 @@ "additionalInfo": { "slotsApi": true } }, "stroke": { "type": { "name": "string" }, "default": "'currentColor'" }, - "tickFontSize": { - "type": { "name": "number" }, - "default": "12", - "deprecated": true, - "deprecationInfo": "Consider using tickLabelStyle.fontSize instead." - }, "tickInterval": { "type": { "name": "union", "description": "'auto'
| array
| func" }, "default": "'auto'" diff --git a/docs/pages/x/api/charts/default-charts-axis-tooltip-content.json b/docs/pages/x/api/charts/default-charts-axis-tooltip-content.json deleted file mode 100644 index 2594869a42ab4..0000000000000 --- a/docs/pages/x/api/charts/default-charts-axis-tooltip-content.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "props": { - "axis": { "type": { "name": "object" }, "required": true }, - "axisData": { - "type": { - "name": "shape", - "description": "{ x?: { index?: number, value: Date
| number
| string }, y?: { index?: number, value: Date
| number
| string } }" - }, - "required": true - }, - "classes": { - "type": { "name": "object" }, - "required": true, - "additionalInfo": { "cssApi": true } - }, - "series": { - "type": { "name": "arrayOf", "description": "Array<object>" }, - "required": true - }, - "axisValue": { - "type": { "name": "union", "description": "Date
| number
| string" } - }, - "dataIndex": { "type": { "name": "number" } } - }, - "name": "DefaultChartsAxisTooltipContent", - "imports": [ - "import { DefaultChartsAxisTooltipContent } from '@mui/x-charts/ChartsTooltip';", - "import { DefaultChartsAxisTooltipContent } from '@mui/x-charts';", - "import { DefaultChartsAxisTooltipContent } from '@mui/x-charts-pro';" - ], - "classes": [ - { - "key": "cell", - "className": "MuiDefaultChartsAxisTooltipContent-cell", - "description": "Styles applied to the cell element.", - "isGlobal": false - }, - { - "key": "labelCell", - "className": "MuiDefaultChartsAxisTooltipContent-labelCell", - "description": "Styles applied to the labelCell element.", - "isGlobal": false - }, - { - "key": "mark", - "className": "MuiDefaultChartsAxisTooltipContent-mark", - "description": "Styles applied to the mark element.", - "isGlobal": false - }, - { - "key": "markCell", - "className": "MuiDefaultChartsAxisTooltipContent-markCell", - "description": "Styles applied to the markCell element.", - "isGlobal": false - }, - { - "key": "paper", - "className": "MuiDefaultChartsAxisTooltipContent-paper", - "description": "Styles applied to the paper element.", - "isGlobal": false - }, - { - "key": "root", - "className": "MuiDefaultChartsAxisTooltipContent-root", - "description": "Styles applied to the root element.", - "isGlobal": false - }, - { - "key": "row", - "className": "MuiDefaultChartsAxisTooltipContent-row", - "description": "Styles applied to the row element.", - "isGlobal": false - }, - { - "key": "table", - "className": "MuiDefaultChartsAxisTooltipContent-table", - "description": "Styles applied to the table element.", - "isGlobal": false - }, - { - "key": "valueCell", - "className": "MuiDefaultChartsAxisTooltipContent-valueCell", - "description": "Styles applied to the valueCell element.", - "isGlobal": false - } - ], - "muiName": "MuiDefaultChartsAxisTooltipContent", - "filename": "/packages/x-charts/src/ChartsTooltip/DefaultChartsAxisTooltipContent.tsx", - "inheritance": null, - "demos": "", - "cssComponent": false -} diff --git a/docs/pages/x/api/charts/default-charts-item-tooltip-content.json b/docs/pages/x/api/charts/default-charts-item-tooltip-content.json deleted file mode 100644 index 7d76f641a34f6..0000000000000 --- a/docs/pages/x/api/charts/default-charts-item-tooltip-content.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "props": { - "classes": { - "type": { "name": "object" }, - "required": true, - "additionalInfo": { "cssApi": true } - }, - "getColor": { - "type": { "name": "func" }, - "required": true, - "signature": { - "type": "function(dataIndex: number) => string", - "describedArgs": ["dataIndex"], - "returned": "string" - } - }, - "itemData": { - "type": { - "name": "shape", - "description": "{ dataIndex?: number, seriesId: number
| string, type: 'bar'
| 'line'
| 'pie'
| 'scatter' }" - }, - "required": true - }, - "series": { "type": { "name": "object" }, "required": true } - }, - "name": "DefaultChartsItemTooltipContent", - "imports": [ - "import { DefaultChartsItemTooltipContent } from '@mui/x-charts/ChartsTooltip';", - "import { DefaultChartsItemTooltipContent } from '@mui/x-charts';", - "import { DefaultChartsItemTooltipContent } from '@mui/x-charts-pro';" - ], - "classes": [ - { - "key": "cell", - "className": "MuiDefaultChartsItemTooltipContent-cell", - "description": "Styles applied to the cell element.", - "isGlobal": false - }, - { - "key": "labelCell", - "className": "MuiDefaultChartsItemTooltipContent-labelCell", - "description": "Styles applied to the labelCell element.", - "isGlobal": false - }, - { - "key": "mark", - "className": "MuiDefaultChartsItemTooltipContent-mark", - "description": "Styles applied to the mark element.", - "isGlobal": false - }, - { - "key": "markCell", - "className": "MuiDefaultChartsItemTooltipContent-markCell", - "description": "Styles applied to the markCell element.", - "isGlobal": false - }, - { - "key": "paper", - "className": "MuiDefaultChartsItemTooltipContent-paper", - "description": "Styles applied to the paper element.", - "isGlobal": false - }, - { - "key": "root", - "className": "MuiDefaultChartsItemTooltipContent-root", - "description": "Styles applied to the root element.", - "isGlobal": false - }, - { - "key": "row", - "className": "MuiDefaultChartsItemTooltipContent-row", - "description": "Styles applied to the row element.", - "isGlobal": false - }, - { - "key": "table", - "className": "MuiDefaultChartsItemTooltipContent-table", - "description": "Styles applied to the table element.", - "isGlobal": false - }, - { - "key": "valueCell", - "className": "MuiDefaultChartsItemTooltipContent-valueCell", - "description": "Styles applied to the valueCell element.", - "isGlobal": false - } - ], - "muiName": "MuiDefaultChartsItemTooltipContent", - "filename": "/packages/x-charts/src/ChartsTooltip/DefaultChartsItemTooltipContent.tsx", - "inheritance": null, - "demos": "", - "cssComponent": false -} diff --git a/docs/pages/x/api/charts/default-heatmap-tooltip.json b/docs/pages/x/api/charts/default-heatmap-tooltip.json deleted file mode 100644 index 66e8ffa29495c..0000000000000 --- a/docs/pages/x/api/charts/default-heatmap-tooltip.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "props": { - "classes": { - "type": { "name": "object" }, - "required": true, - "additionalInfo": { "cssApi": true } - }, - "getColor": { - "type": { "name": "func" }, - "required": true, - "signature": { - "type": "function(dataIndex: number) => string", - "describedArgs": ["dataIndex"], - "returned": "string" - } - }, - "itemData": { - "type": { - "name": "shape", - "description": "{ dataIndex: number, seriesId: number
| string, type: 'heatmap' }" - }, - "required": true - }, - "series": { "type": { "name": "object" }, "required": true } - }, - "name": "DefaultHeatmapTooltip", - "imports": [ - "import { DefaultHeatmapTooltip } from '@mui/x-charts-pro/Heatmap';", - "import { DefaultHeatmapTooltip } from '@mui/x-charts-pro';" - ], - "classes": [ - { - "key": "cell", - "className": "MuiDefaultHeatmapTooltip-cell", - "description": "Styles applied to the cell element.", - "isGlobal": false - }, - { - "key": "labelCell", - "className": "MuiDefaultHeatmapTooltip-labelCell", - "description": "Styles applied to the labelCell element.", - "isGlobal": false - }, - { - "key": "mark", - "className": "MuiDefaultHeatmapTooltip-mark", - "description": "Styles applied to the mark element.", - "isGlobal": false - }, - { - "key": "markCell", - "className": "MuiDefaultHeatmapTooltip-markCell", - "description": "Styles applied to the markCell element.", - "isGlobal": false - }, - { - "key": "paper", - "className": "MuiDefaultHeatmapTooltip-paper", - "description": "Styles applied to the paper element.", - "isGlobal": false - }, - { - "key": "root", - "className": "MuiDefaultHeatmapTooltip-root", - "description": "Styles applied to the root element.", - "isGlobal": false - }, - { - "key": "row", - "className": "MuiDefaultHeatmapTooltip-row", - "description": "Styles applied to the row element.", - "isGlobal": false - }, - { - "key": "table", - "className": "MuiDefaultHeatmapTooltip-table", - "description": "Styles applied to the table element.", - "isGlobal": false - }, - { - "key": "valueCell", - "className": "MuiDefaultHeatmapTooltip-valueCell", - "description": "Styles applied to the valueCell element.", - "isGlobal": false - } - ], - "muiName": "MuiDefaultHeatmapTooltip", - "filename": "/packages/x-charts-pro/src/Heatmap/DefaultHeatmapTooltip.tsx", - "inheritance": null, - "demos": "", - "cssComponent": false -} diff --git a/docs/pages/x/api/charts/heatmap-tooltip.js b/docs/pages/x/api/charts/heatmap-tooltip.js new file mode 100644 index 0000000000000..30853287ca8b9 --- /dev/null +++ b/docs/pages/x/api/charts/heatmap-tooltip.js @@ -0,0 +1,23 @@ +import * as React from 'react'; +import ApiPage from 'docs/src/modules/components/ApiPage'; +import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; +import jsonPageContent from './heatmap-tooltip.json'; + +export default function Page(props) { + const { descriptions, pageContent } = props; + return ; +} + +Page.getInitialProps = () => { + const req = require.context( + 'docsx/translations/api-docs/charts/heatmap-tooltip', + false, + /\.\/heatmap-tooltip.*.json$/, + ); + const descriptions = mapApiPageTranslations(req); + + return { + descriptions, + pageContent: jsonPageContent, + }; +}; diff --git a/docs/pages/x/api/charts/heatmap-tooltip.json b/docs/pages/x/api/charts/heatmap-tooltip.json new file mode 100644 index 0000000000000..ed4926bc10795 --- /dev/null +++ b/docs/pages/x/api/charts/heatmap-tooltip.json @@ -0,0 +1,141 @@ +{ + "props": { + "anchorEl": { + "type": { + "name": "union", + "description": "HTML element
| object
| func" + } + }, + "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } }, + "component": { "type": { "name": "elementType" } }, + "components": { + "type": { "name": "shape", "description": "{ Root?: elementType }" }, + "default": "{}" + }, + "componentsProps": { + "type": { "name": "shape", "description": "{ root?: func
| object }" }, + "default": "{}" + }, + "container": { + "type": { + "name": "union", + "description": "(props, propName) => {\n if (props[propName] == null) {\n return new Error(`Prop '${propName}' is required but wasn't specified`);\n }\n if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) {\n return new Error(`Expected prop '${propName}' to be of type Element`);\n }\n return null;\n}
| func" + } + }, + "disablePortal": { "type": { "name": "bool" }, "default": "false" }, + "keepMounted": { "type": { "name": "bool" }, "default": "false" }, + "modifiers": { + "type": { + "name": "arrayOf", + "description": "Array<{ data?: object, effect?: func, enabled?: bool, fn?: func, name?: any, options?: object, phase?: 'afterMain'
| 'afterRead'
| 'afterWrite'
| 'beforeMain'
| 'beforeRead'
| 'beforeWrite'
| 'main'
| 'read'
| 'write', requires?: Array<string>, requiresIfExists?: Array<string> }>" + } + }, + "open": { "type": { "name": "bool" } }, + "placement": { + "type": { + "name": "enum", + "description": "'auto-end'
| 'auto-start'
| 'auto'
| 'bottom-end'
| 'bottom-start'
| 'bottom'
| 'left-end'
| 'left-start'
| 'left'
| 'right-end'
| 'right-start'
| 'right'
| 'top-end'
| 'top-start'
| 'top'" + }, + "default": "'bottom'" + }, + "popperOptions": { + "type": { + "name": "shape", + "description": "{ modifiers?: array, onFirstUpdate?: func, placement?: 'auto-end'
| 'auto-start'
| 'auto'
| 'bottom-end'
| 'bottom-start'
| 'bottom'
| 'left-end'
| 'left-start'
| 'left'
| 'right-end'
| 'right-start'
| 'right'
| 'top-end'
| 'top-start'
| 'top', strategy?: 'absolute'
| 'fixed' }" + }, + "default": "{}" + }, + "popperRef": { + "type": { + "name": "union", + "description": "func
| { current?: { destroy: func, forceUpdate: func, setOptions: func, state: { attributes: object, elements: object, modifiersData: object, options: object, orderedModifiers: Array<object>, placement: 'auto-end'
| 'auto-start'
| 'auto'
| 'bottom-end'
| 'bottom-start'
| 'bottom'
| 'left-end'
| 'left-start'
| 'left'
| 'right-end'
| 'right-start'
| 'right'
| 'top-end'
| 'top-start'
| 'top', rects: object, reset: bool, scrollParents: object, strategy: 'absolute'
| 'fixed', styles: object }, update: func } }" + } + }, + "slotProps": { "type": { "name": "object" }, "default": "{}" }, + "slots": { + "type": { "name": "object" }, + "default": "{}", + "additionalInfo": { "slotsApi": true } + }, + "sx": { + "type": { + "name": "union", + "description": "Array<func
| object
| bool>
| func
| object" + }, + "additionalInfo": { "sx": true } + }, + "transition": { "type": { "name": "bool" }, "default": "false" } + }, + "name": "HeatmapTooltip", + "imports": [ + "import { HeatmapTooltip } from '@mui/x-charts-pro/Heatmap';", + "import { HeatmapTooltip } from '@mui/x-charts-pro';" + ], + "classes": [ + { + "key": "axisValueCell", + "className": "MuiHeatmapTooltip-axisValueCell", + "description": "Styles applied to the axisValueCell element. Only available for axis tooltip.", + "isGlobal": false + }, + { + "key": "cell", + "className": "MuiHeatmapTooltip-cell", + "description": "Styles applied to the cell element.", + "isGlobal": false + }, + { + "key": "labelCell", + "className": "MuiHeatmapTooltip-labelCell", + "description": "Styles applied to the labelCell element.", + "isGlobal": false + }, + { + "key": "mark", + "className": "MuiHeatmapTooltip-mark", + "description": "Styles applied to the mark element.", + "isGlobal": false + }, + { + "key": "markCell", + "className": "MuiHeatmapTooltip-markCell", + "description": "Styles applied to the markCell element.", + "isGlobal": false + }, + { + "key": "paper", + "className": "MuiHeatmapTooltip-paper", + "description": "Styles applied to the paper element.", + "isGlobal": false + }, + { + "key": "root", + "className": "MuiHeatmapTooltip-root", + "description": "Styles applied to the root element.", + "isGlobal": false + }, + { + "key": "row", + "className": "MuiHeatmapTooltip-row", + "description": "Styles applied to the row element.", + "isGlobal": false + }, + { + "key": "table", + "className": "MuiHeatmapTooltip-table", + "description": "Styles applied to the table element.", + "isGlobal": false + }, + { + "key": "valueCell", + "className": "MuiHeatmapTooltip-valueCell", + "description": "Styles applied to the valueCell element.", + "isGlobal": false + } + ], + "muiName": "MuiHeatmapTooltip", + "filename": "/packages/x-charts-pro/src/Heatmap/HeatmapTooltip.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/pages/x/api/charts/heatmap.json b/docs/pages/x/api/charts/heatmap.json index 73e966a09c058..f5f3665c76b52 100644 --- a/docs/pages/x/api/charts/heatmap.json +++ b/docs/pages/x/api/charts/heatmap.json @@ -7,14 +7,14 @@ "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ barGapRatio?: number, categoryGapRatio?: number, classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ barGapRatio?: number, categoryGapRatio?: number, classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" }, "required": true }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ barGapRatio?: number, categoryGapRatio?: number, classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ barGapRatio?: number, categoryGapRatio?: number, classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" }, "required": true }, @@ -61,7 +61,6 @@ "describedArgs": ["highlightedItem"] } }, - "resolveSizeBeforeRender": { "type": { "name": "bool" }, "default": "false" }, "rightAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -73,10 +72,7 @@ "additionalInfo": { "slotsApi": true } }, "tooltip": { - "type": { - "name": "shape", - "description": "{ axisContent?: elementType, classes?: object, itemContent?: elementType, slotProps?: object, slots?: object, trigger?: 'axis'
| 'item'
| 'none' }" - }, + "type": { "name": "object" }, "seeMoreLink": { "url": "https://mui.com/x/react-charts/tooltip/", "text": "tooltip docs" } }, "topAxis": { diff --git a/docs/pages/x/api/charts/line-chart-pro.json b/docs/pages/x/api/charts/line-chart-pro.json index 7b8d440d88aef..83f6174cd1b0c 100644 --- a/docs/pages/x/api/charts/line-chart-pro.json +++ b/docs/pages/x/api/charts/line-chart-pro.json @@ -11,7 +11,7 @@ }, "default": "{ x: 'line' }", "seeMoreLink": { - "url": "https://mui.com/x/react-charts/highlighting", + "url": "https://mui.com/x/react-charts/highlighting/", "text": "highlighting docs" } }, @@ -74,7 +74,6 @@ "describedArgs": ["zoomData"] } }, - "resolveSizeBeforeRender": { "type": { "name": "bool" }, "default": "false" }, "rightAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -86,14 +85,6 @@ "default": "{}", "additionalInfo": { "slotsApi": true } }, - "tooltip": { - "type": { - "name": "shape", - "description": "{ axisContent?: elementType, classes?: object, itemContent?: elementType, slotProps?: object, slots?: object, trigger?: 'axis'
| 'item'
| 'none' }" - }, - "default": "{ trigger: 'item' }", - "seeMoreLink": { "url": "https://mui.com/x/react-charts/tooltip/", "text": "tooltip docs" } - }, "topAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -102,13 +93,13 @@ "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } }, "zoom": { diff --git a/docs/pages/x/api/charts/line-chart.json b/docs/pages/x/api/charts/line-chart.json index fec2c41c13577..a03a00045fa09 100644 --- a/docs/pages/x/api/charts/line-chart.json +++ b/docs/pages/x/api/charts/line-chart.json @@ -11,7 +11,7 @@ }, "default": "{ x: 'line' }", "seeMoreLink": { - "url": "https://mui.com/x/react-charts/highlighting", + "url": "https://mui.com/x/react-charts/highlighting/", "text": "highlighting docs" } }, @@ -67,7 +67,6 @@ }, "onLineClick": { "type": { "name": "func" } }, "onMarkClick": { "type": { "name": "func" } }, - "resolveSizeBeforeRender": { "type": { "name": "bool" }, "default": "false" }, "rightAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -79,14 +78,6 @@ "default": "{}", "additionalInfo": { "slotsApi": true } }, - "tooltip": { - "type": { - "name": "shape", - "description": "{ axisContent?: elementType, classes?: object, itemContent?: elementType, slotProps?: object, slots?: object, trigger?: 'axis'
| 'item'
| 'none' }" - }, - "default": "{ trigger: 'item' }", - "seeMoreLink": { "url": "https://mui.com/x/react-charts/tooltip/", "text": "tooltip docs" } - }, "topAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -95,13 +86,13 @@ "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" } }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" } } }, @@ -118,12 +109,6 @@ "default": "AnimatedArea", "class": null }, - { - "name": "axisContent", - "description": "Custom component for displaying tooltip content when triggered by axis event.", - "default": "DefaultChartsAxisTooltipContent", - "class": null - }, { "name": "axisLabel", "description": "Custom component for axis label.", @@ -148,12 +133,6 @@ "default": "ChartsText", "class": null }, - { - "name": "itemContent", - "description": "Custom component for displaying tooltip content when triggered by item event.", - "default": "DefaultChartsItemTooltipContent", - "class": null - }, { "name": "legend", "description": "Custom rendering of the legend.", @@ -181,7 +160,7 @@ "class": null }, { - "name": "popper", + "name": "tooltip", "description": "Custom component for the tooltip popper.", "default": "ChartsTooltipRoot", "class": null diff --git a/docs/pages/x/api/charts/line-series-type.json b/docs/pages/x/api/charts/line-series-type.json index 7833c73708042..85a484a515400 100644 --- a/docs/pages/x/api/charts/line-series-type.json +++ b/docs/pages/x/api/charts/line-series-type.json @@ -1,6 +1,9 @@ { "name": "LineSeriesType", - "imports": ["import { LineSeriesType } from '@mui/x-charts'"], + "imports": [ + "import { LineSeriesType } from '@mui/x-charts-pro'", + "import { LineSeriesType } from '@mui/x-charts'" + ], "properties": { "type": { "type": { "description": "'line'" }, "required": true }, "area": { "type": { "description": "boolean" } }, diff --git a/docs/pages/x/api/charts/pie-chart.json b/docs/pages/x/api/charts/pie-chart.json index 935c0d74a230b..090da6099a855 100644 --- a/docs/pages/x/api/charts/pie-chart.json +++ b/docs/pages/x/api/charts/pie-chart.json @@ -34,7 +34,6 @@ } }, "onItemClick": { "type": { "name": "func" } }, - "resolveSizeBeforeRender": { "type": { "name": "bool" }, "default": "false" }, "skipAnimation": { "type": { "name": "bool" } }, "slotProps": { "type": { "name": "object" }, "default": "{}" }, "slots": { @@ -42,25 +41,17 @@ "default": "{}", "additionalInfo": { "slotsApi": true } }, - "tooltip": { - "type": { - "name": "shape", - "description": "{ axisContent?: elementType, classes?: object, itemContent?: elementType, slotProps?: object, slots?: object, trigger?: 'axis'
| 'item'
| 'none' }" - }, - "default": "{ trigger: 'item' }", - "seeMoreLink": { "url": "https://mui.com/x/react-charts/tooltip/", "text": "tooltip docs" } - }, "width": { "type": { "name": "number" } }, "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" } }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" } } }, @@ -71,18 +62,6 @@ "import { PieChart } from '@mui/x-charts-pro';" ], "slots": [ - { - "name": "axisContent", - "description": "Custom component for displaying tooltip content when triggered by axis event.", - "default": "DefaultChartsAxisTooltipContent", - "class": null - }, - { - "name": "itemContent", - "description": "Custom component for displaying tooltip content when triggered by item event.", - "default": "DefaultChartsItemTooltipContent", - "class": null - }, { "name": "legend", "description": "Custom rendering of the legend.", @@ -104,7 +83,7 @@ { "name": "pieArc", "description": "", "class": null }, { "name": "pieArcLabel", "description": "", "class": null }, { - "name": "popper", + "name": "tooltip", "description": "Custom component for the tooltip popper.", "default": "ChartsTooltipRoot", "class": null diff --git a/docs/pages/x/api/charts/pie-series-type.json b/docs/pages/x/api/charts/pie-series-type.json index 12ff413eeeab8..b644991437236 100644 --- a/docs/pages/x/api/charts/pie-series-type.json +++ b/docs/pages/x/api/charts/pie-series-type.json @@ -1,6 +1,9 @@ { "name": "PieSeriesType", - "imports": ["import { PieSeriesType } from '@mui/x-charts'"], + "imports": [ + "import { PieSeriesType } from '@mui/x-charts-pro'", + "import { PieSeriesType } from '@mui/x-charts'" + ], "properties": { "data": { "type": { "description": "TData[]" }, "required": true }, "type": { "type": { "description": "'pie'" }, "required": true }, diff --git a/docs/pages/x/api/charts/scatter-chart-pro.json b/docs/pages/x/api/charts/scatter-chart-pro.json index fec553960c535..b83ffebebd564 100644 --- a/docs/pages/x/api/charts/scatter-chart-pro.json +++ b/docs/pages/x/api/charts/scatter-chart-pro.json @@ -11,7 +11,7 @@ }, "default": "{ x: 'none', y: 'none' }", "seeMoreLink": { - "url": "https://mui.com/x/react-charts/highlighting", + "url": "https://mui.com/x/react-charts/highlighting/", "text": "highlighting docs" } }, @@ -70,7 +70,6 @@ "describedArgs": ["zoomData"] } }, - "resolveSizeBeforeRender": { "type": { "name": "bool" }, "default": "false" }, "rightAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -82,14 +81,6 @@ "default": "{}", "additionalInfo": { "slotsApi": true } }, - "tooltip": { - "type": { - "name": "shape", - "description": "{ axisContent?: elementType, classes?: object, itemContent?: elementType, slotProps?: object, slots?: object, trigger?: 'axis'
| 'item'
| 'none' }" - }, - "default": "{ trigger: 'item' }", - "seeMoreLink": { "url": "https://mui.com/x/react-charts/tooltip/", "text": "tooltip docs" } - }, "topAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -99,13 +90,13 @@ "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } }, "zAxis": { diff --git a/docs/pages/x/api/charts/scatter-chart.json b/docs/pages/x/api/charts/scatter-chart.json index a3ead27efdcfd..9826eff4a7fea 100644 --- a/docs/pages/x/api/charts/scatter-chart.json +++ b/docs/pages/x/api/charts/scatter-chart.json @@ -11,7 +11,7 @@ }, "default": "{ x: 'none', y: 'none' }", "seeMoreLink": { - "url": "https://mui.com/x/react-charts/highlighting", + "url": "https://mui.com/x/react-charts/highlighting/", "text": "highlighting docs" } }, @@ -63,7 +63,6 @@ "describedArgs": ["event", "scatterItemIdentifier"] } }, - "resolveSizeBeforeRender": { "type": { "name": "bool" }, "default": "false" }, "rightAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -75,14 +74,6 @@ "default": "{}", "additionalInfo": { "slotsApi": true } }, - "tooltip": { - "type": { - "name": "shape", - "description": "{ axisContent?: elementType, classes?: object, itemContent?: elementType, slotProps?: object, slots?: object, trigger?: 'axis'
| 'item'
| 'none' }" - }, - "default": "{ trigger: 'item' }", - "seeMoreLink": { "url": "https://mui.com/x/react-charts/tooltip/", "text": "tooltip docs" } - }, "topAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -92,13 +83,13 @@ "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" } }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" } }, "zAxis": { @@ -115,12 +106,6 @@ "import { ScatterChart } from '@mui/x-charts-pro';" ], "slots": [ - { - "name": "axisContent", - "description": "Custom component for displaying tooltip content when triggered by axis event.", - "default": "DefaultChartsAxisTooltipContent", - "class": null - }, { "name": "axisLabel", "description": "Custom component for axis label.", @@ -145,12 +130,6 @@ "default": "ChartsText", "class": null }, - { - "name": "itemContent", - "description": "Custom component for displaying tooltip content when triggered by item event.", - "default": "DefaultChartsItemTooltipContent", - "class": null - }, { "name": "legend", "description": "Custom rendering of the legend.", @@ -169,13 +148,13 @@ "default": "ChartsNoDataOverlay", "class": null }, + { "name": "scatter", "description": "", "class": null }, { - "name": "popper", + "name": "tooltip", "description": "Custom component for the tooltip popper.", "default": "ChartsTooltipRoot", "class": null - }, - { "name": "scatter", "description": "", "class": null } + } ], "classes": [], "spread": true, diff --git a/docs/pages/x/api/charts/scatter-series-type.json b/docs/pages/x/api/charts/scatter-series-type.json index 5f422acb68962..436b9311ec3f8 100644 --- a/docs/pages/x/api/charts/scatter-series-type.json +++ b/docs/pages/x/api/charts/scatter-series-type.json @@ -1,6 +1,9 @@ { "name": "ScatterSeriesType", - "imports": ["import { ScatterSeriesType } from '@mui/x-charts'"], + "imports": [ + "import { ScatterSeriesType } from '@mui/x-charts-pro'", + "import { ScatterSeriesType } from '@mui/x-charts'" + ], "properties": { "type": { "type": { "description": "'scatter'" }, "required": true }, "color": { "type": { "description": "string" } }, diff --git a/docs/pages/x/api/charts/spark-line-chart.json b/docs/pages/x/api/charts/spark-line-chart.json index ef163ec9fc380..479e3b2ef2300 100644 --- a/docs/pages/x/api/charts/spark-line-chart.json +++ b/docs/pages/x/api/charts/spark-line-chart.json @@ -36,7 +36,6 @@ "type": { "name": "enum", "description": "'bar'
| 'line'" }, "default": "'line'" }, - "resolveSizeBeforeRender": { "type": { "name": "bool" }, "default": "false" }, "showHighlight": { "type": { "name": "bool" }, "default": "false" }, "showTooltip": { "type": { "name": "bool" }, "default": "false" }, "skipAnimation": { "type": { "name": "bool" } }, @@ -59,13 +58,13 @@ "xAxis": { "type": { "name": "shape", - "description": "{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }" + "description": "{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }" } }, "yAxis": { "type": { "name": "shape", - "description": "{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }" + "description": "{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }" } } }, @@ -82,24 +81,12 @@ "default": "AnimatedArea", "class": null }, - { - "name": "axisContent", - "description": "Custom component for displaying tooltip content when triggered by axis event.", - "default": "DefaultChartsAxisTooltipContent", - "class": null - }, { "name": "bar", "description": "The component that renders the bar.", "default": "BarElementPath", "class": null }, - { - "name": "itemContent", - "description": "Custom component for displaying tooltip content when triggered by item event.", - "default": "DefaultChartsItemTooltipContent", - "class": null - }, { "name": "line", "description": "The component that renders the line.", @@ -109,7 +96,7 @@ { "name": "lineHighlight", "description": "", "class": null }, { "name": "mark", "description": "", "class": null }, { - "name": "popper", + "name": "tooltip", "description": "Custom component for the tooltip popper.", "default": "ChartsTooltipRoot", "class": null diff --git a/docs/pages/x/api/data-grid/data-grid-premium.json b/docs/pages/x/api/data-grid/data-grid-premium.json index ded5c1bd3c907..633838afd551e 100644 --- a/docs/pages/x/api/data-grid/data-grid-premium.json +++ b/docs/pages/x/api/data-grid/data-grid-premium.json @@ -81,10 +81,7 @@ }, "estimatedRowCount": { "type": { "name": "number" } }, "experimentalFeatures": { - "type": { - "name": "shape", - "description": "{ ariaV8?: bool, warnIfFocusStateIsNotSynced?: bool }" - } + "type": { "name": "shape", "description": "{ warnIfFocusStateIsNotSynced?: bool }" } }, "filterDebounceMs": { "type": { "name": "number" }, "default": "150" }, "filterMode": { @@ -187,10 +184,6 @@ }, "default": "false" }, - "indeterminateCheckboxAction": { - "type": { "name": "enum", "description": "'deselect'
| 'select'" }, - "default": "\"deselect\"" - }, "initialState": { "type": { "name": "object" } }, "isCellEditable": { "type": { "name": "func" }, @@ -588,11 +581,6 @@ "rowGroupingModel": { "type": { "name": "arrayOf", "description": "Array<string>" } }, "rowHeight": { "type": { "name": "number" }, "default": "52" }, "rowModesModel": { "type": { "name": "object" } }, - "rowPositionsDebounceMs": { - "type": { "name": "number" }, - "default": "166", - "deprecated": true - }, "rowReordering": { "type": { "name": "bool" }, "default": "false" }, "rows": { "type": { "name": "arrayOf", "description": "Array<object>" }, @@ -607,15 +595,17 @@ }, "rowSelectionPropagation": { "type": { "name": "shape", "description": "{ descendants?: bool, parents?: bool }" }, - "default": "{ parents: false, descendants: false }" + "default": "{ parents: true, descendants: true }" }, "rowsLoadingMode": { - "type": { "name": "enum", "description": "'client'
| 'server'" } + "type": { "name": "enum", "description": "'client'
| 'server'" }, + "default": "\"client\"" }, "rowSpacingType": { "type": { "name": "enum", "description": "'border'
| 'margin'" }, "default": "\"margin\"" }, + "rowSpanning": { "type": { "name": "bool" }, "default": "false" }, "scrollbarSize": { "type": { "name": "number" } }, "scrollEndThreshold": { "type": { "name": "number" }, "default": "80" }, "showCellVerticalBorder": { "type": { "name": "bool" }, "default": "false" }, @@ -649,6 +639,8 @@ }, "throttleRowsMs": { "type": { "name": "number" }, "default": "0" }, "treeData": { "type": { "name": "bool" }, "default": "false" }, + "unstable_lazyLoading": { "type": { "name": "bool" }, "default": "false" }, + "unstable_lazyLoadingRequestThrottleMs": { "type": { "name": "number" }, "default": "500" }, "unstable_listColumn": { "type": { "name": "shape", @@ -656,7 +648,7 @@ } }, "unstable_listView": { "type": { "name": "bool" } }, - "unstable_rowSpanning": { "type": { "name": "bool" }, "default": "false" } + "virtualizeColumnsWithAutoRowHeight": { "type": { "name": "bool" }, "default": "false" } }, "name": "DataGridPremium", "imports": [ @@ -1125,6 +1117,18 @@ "description": "Icon displayed in column menu for aggregation", "default": "GridFunctionsIcon", "class": null + }, + { + "name": "toolbarPromptSendIcon", + "description": "Icon used for the button that sends a prompt", + "default": "GridFunctionsIcon", + "class": null + }, + { + "name": "toolbarPromptRecordIcon", + "description": "Icon used for the button that starts/stops recording the prompt", + "default": "GridFunctionsIcon", + "class": null } ], "classes": [ @@ -1476,6 +1480,12 @@ "description": "Styles applied to the columns management row element.", "isGlobal": false }, + { + "key": "columnsManagementSearchInput", + "className": "MuiDataGridPremium-columnsManagementSearchInput", + "description": "Styles applied to the columns management search input element.", + "isGlobal": false + }, { "key": "container--bottom", "className": "MuiDataGridPremium-container--bottom", @@ -1890,6 +1900,36 @@ "description": "Styles applied to the toolbar filter list element.", "isGlobal": false }, + { + "key": "toolbarPromptControl", + "className": "MuiDataGridPremium-toolbarPromptControl", + "description": "Styles applied to the toolbar prompt control element.", + "isGlobal": false + }, + { + "key": "toolbarPromptControl--recording", + "className": "MuiDataGridPremium-toolbarPromptControl--recording", + "description": "Styles applied to the toolbar prompt control element when recording.", + "isGlobal": false + }, + { + "key": "toolbarPromptControlRecordButton", + "className": "MuiDataGridPremium-toolbarPromptControlRecordButton", + "description": "Styles applied to the toolbar prompt control record button element.", + "isGlobal": false + }, + { + "key": "toolbarPromptControlRecordingIndicator", + "className": "MuiDataGridPremium-toolbarPromptControlRecordingIndicator", + "description": "Styles applied to the toolbar prompt control recording indicator element.", + "isGlobal": false + }, + { + "key": "toolbarPromptControlSendButton", + "className": "MuiDataGridPremium-toolbarPromptControlSendButton", + "description": "Styles applied to the toolbar prompt control send button element.", + "isGlobal": false + }, { "key": "treeDataGroupingCell", "className": "MuiDataGridPremium-treeDataGroupingCell", diff --git a/docs/pages/x/api/data-grid/data-grid-pro.json b/docs/pages/x/api/data-grid/data-grid-pro.json index 42df3c1393111..1dd61eee2593d 100644 --- a/docs/pages/x/api/data-grid/data-grid-pro.json +++ b/docs/pages/x/api/data-grid/data-grid-pro.json @@ -161,10 +161,6 @@ }, "default": "false" }, - "indeterminateCheckboxAction": { - "type": { "name": "enum", "description": "'deselect'
| 'select'" }, - "default": "\"deselect\"" - }, "initialState": { "type": { "name": "object" } }, "isCellEditable": { "type": { "name": "func" }, @@ -523,11 +519,6 @@ "rowCount": { "type": { "name": "number" } }, "rowHeight": { "type": { "name": "number" }, "default": "52" }, "rowModesModel": { "type": { "name": "object" } }, - "rowPositionsDebounceMs": { - "type": { "name": "number" }, - "default": "166", - "deprecated": true - }, "rowReordering": { "type": { "name": "bool" }, "default": "false" }, "rows": { "type": { "name": "arrayOf", "description": "Array<object>" }, @@ -542,15 +533,17 @@ }, "rowSelectionPropagation": { "type": { "name": "shape", "description": "{ descendants?: bool, parents?: bool }" }, - "default": "{ parents: false, descendants: false }" + "default": "{ parents: true, descendants: true }" }, "rowsLoadingMode": { - "type": { "name": "enum", "description": "'client'
| 'server'" } + "type": { "name": "enum", "description": "'client'
| 'server'" }, + "default": "\"client\"" }, "rowSpacingType": { "type": { "name": "enum", "description": "'border'
| 'margin'" }, "default": "\"margin\"" }, + "rowSpanning": { "type": { "name": "bool" }, "default": "false" }, "scrollbarSize": { "type": { "name": "number" } }, "scrollEndThreshold": { "type": { "name": "number" }, "default": "80" }, "showCellVerticalBorder": { "type": { "name": "bool" }, "default": "false" }, @@ -580,6 +573,8 @@ }, "throttleRowsMs": { "type": { "name": "number" }, "default": "0" }, "treeData": { "type": { "name": "bool" }, "default": "false" }, + "unstable_lazyLoading": { "type": { "name": "bool" }, "default": "false" }, + "unstable_lazyLoadingRequestThrottleMs": { "type": { "name": "number" }, "default": "500" }, "unstable_listColumn": { "type": { "name": "shape", @@ -587,7 +582,7 @@ } }, "unstable_listView": { "type": { "name": "bool" } }, - "unstable_rowSpanning": { "type": { "name": "bool" }, "default": "false" } + "virtualizeColumnsWithAutoRowHeight": { "type": { "name": "bool" }, "default": "false" } }, "name": "DataGridPro", "imports": [ @@ -1390,6 +1385,12 @@ "description": "Styles applied to the columns management row element.", "isGlobal": false }, + { + "key": "columnsManagementSearchInput", + "className": "MuiDataGridPro-columnsManagementSearchInput", + "description": "Styles applied to the columns management search input element.", + "isGlobal": false + }, { "key": "container--bottom", "className": "MuiDataGridPro-container--bottom", @@ -1804,6 +1805,36 @@ "description": "Styles applied to the toolbar filter list element.", "isGlobal": false }, + { + "key": "toolbarPromptControl", + "className": "MuiDataGridPro-toolbarPromptControl", + "description": "Styles applied to the toolbar prompt control element.", + "isGlobal": false + }, + { + "key": "toolbarPromptControl--recording", + "className": "MuiDataGridPro-toolbarPromptControl--recording", + "description": "Styles applied to the toolbar prompt control element when recording.", + "isGlobal": false + }, + { + "key": "toolbarPromptControlRecordButton", + "className": "MuiDataGridPro-toolbarPromptControlRecordButton", + "description": "Styles applied to the toolbar prompt control record button element.", + "isGlobal": false + }, + { + "key": "toolbarPromptControlRecordingIndicator", + "className": "MuiDataGridPro-toolbarPromptControlRecordingIndicator", + "description": "Styles applied to the toolbar prompt control recording indicator element.", + "isGlobal": false + }, + { + "key": "toolbarPromptControlSendButton", + "className": "MuiDataGridPro-toolbarPromptControlSendButton", + "description": "Styles applied to the toolbar prompt control send button element.", + "isGlobal": false + }, { "key": "treeDataGroupingCell", "className": "MuiDataGridPro-treeDataGroupingCell", diff --git a/docs/pages/x/api/data-grid/data-grid.json b/docs/pages/x/api/data-grid/data-grid.json index 9994e0dc63178..d0cd9370ee9b8 100644 --- a/docs/pages/x/api/data-grid/data-grid.json +++ b/docs/pages/x/api/data-grid/data-grid.json @@ -129,10 +129,6 @@ }, "default": "false" }, - "indeterminateCheckboxAction": { - "type": { "name": "enum", "description": "'deselect'
| 'select'" }, - "default": "\"deselect\"" - }, "initialState": { "type": { "name": "object" } }, "isCellEditable": { "type": { "name": "func" }, @@ -439,11 +435,6 @@ "rowCount": { "type": { "name": "number" } }, "rowHeight": { "type": { "name": "number" }, "default": "52" }, "rowModesModel": { "type": { "name": "object" } }, - "rowPositionsDebounceMs": { - "type": { "name": "number" }, - "default": "166", - "deprecated": true - }, "rows": { "type": { "name": "arrayOf", "description": "Array<object>" }, "default": "[]" @@ -459,6 +450,7 @@ "type": { "name": "enum", "description": "'border'
| 'margin'" }, "default": "\"margin\"" }, + "rowSpanning": { "type": { "name": "bool" }, "default": "false" }, "scrollbarSize": { "type": { "name": "number" } }, "showCellVerticalBorder": { "type": { "name": "bool" }, "default": "false" }, "showColumnVerticalBorder": { "type": { "name": "bool" }, "default": "false" }, @@ -485,7 +477,7 @@ }, "additionalInfo": { "sx": true } }, - "unstable_rowSpanning": { "type": { "name": "bool" }, "default": "false" } + "virtualizeColumnsWithAutoRowHeight": { "type": { "name": "bool" }, "default": "false" } }, "name": "DataGrid", "imports": [ @@ -1265,6 +1257,12 @@ "description": "Styles applied to the columns management row element.", "isGlobal": false }, + { + "key": "columnsManagementSearchInput", + "className": "MuiDataGrid-columnsManagementSearchInput", + "description": "Styles applied to the columns management search input element.", + "isGlobal": false + }, { "key": "container--bottom", "className": "MuiDataGrid-container--bottom", @@ -1679,6 +1677,36 @@ "description": "Styles applied to the toolbar filter list element.", "isGlobal": false }, + { + "key": "toolbarPromptControl", + "className": "MuiDataGrid-toolbarPromptControl", + "description": "Styles applied to the toolbar prompt control element.", + "isGlobal": false + }, + { + "key": "toolbarPromptControl--recording", + "className": "MuiDataGrid-toolbarPromptControl--recording", + "description": "Styles applied to the toolbar prompt control element when recording.", + "isGlobal": false + }, + { + "key": "toolbarPromptControlRecordButton", + "className": "MuiDataGrid-toolbarPromptControlRecordButton", + "description": "Styles applied to the toolbar prompt control record button element.", + "isGlobal": false + }, + { + "key": "toolbarPromptControlRecordingIndicator", + "className": "MuiDataGrid-toolbarPromptControlRecordingIndicator", + "description": "Styles applied to the toolbar prompt control recording indicator element.", + "isGlobal": false + }, + { + "key": "toolbarPromptControlSendButton", + "className": "MuiDataGrid-toolbarPromptControlSendButton", + "description": "Styles applied to the toolbar prompt control send button element.", + "isGlobal": false + }, { "key": "treeDataGroupingCell", "className": "MuiDataGrid-treeDataGroupingCell", diff --git a/docs/pages/x/api/data-grid/grid-actions-col-def.json b/docs/pages/x/api/data-grid/grid-actions-col-def.json index eece855816ed8..7e938d8dd4386 100644 --- a/docs/pages/x/api/data-grid/grid-actions-col-def.json +++ b/docs/pages/x/api/data-grid/grid-actions-col-def.json @@ -93,6 +93,7 @@ "sortable": { "type": { "description": "boolean" }, "default": "true" }, "sortComparator": { "type": { "description": "GridComparatorFn<V>" } }, "sortingOrder": { "type": { "description": "readonly GridSortDirection[]" } }, + "unstable_examples": { "type": { "description": "V[]" } }, "valueFormatter": { "type": { "description": "GridValueFormatter<R, V, F>" } }, "valueGetter": { "type": { "description": "GridValueGetter<R, V, F>" } }, "valueParser": { "type": { "description": "GridValueParser<R, V, F>" } }, diff --git a/docs/pages/x/api/data-grid/grid-api.json b/docs/pages/x/api/data-grid/grid-api.json index 5f5202edf84f0..8e11d0b8cc804 100644 --- a/docs/pages/x/api/data-grid/grid-api.json +++ b/docs/pages/x/api/data-grid/grid-api.json @@ -246,7 +246,6 @@ "isPremiumPlan": true }, "resetRowHeights": { "type": { "description": "() => void" }, "required": true }, - "resize": { "type": { "description": "() => void" }, "required": true }, "restoreState": { "type": { "description": "(stateToRestore: InitialState) => void" }, "required": true diff --git a/docs/pages/x/api/data-grid/grid-col-def.json b/docs/pages/x/api/data-grid/grid-col-def.json index 0546471b90ea7..bc07f52910954 100644 --- a/docs/pages/x/api/data-grid/grid-col-def.json +++ b/docs/pages/x/api/data-grid/grid-col-def.json @@ -87,6 +87,7 @@ "sortComparator": { "type": { "description": "GridComparatorFn<V>" } }, "sortingOrder": { "type": { "description": "readonly GridSortDirection[]" } }, "type": { "type": { "description": "GridColType" }, "default": "'singleSelect'" }, + "unstable_examples": { "type": { "description": "V[]" } }, "valueFormatter": { "type": { "description": "GridValueFormatter<R, V, F>" } }, "valueGetter": { "type": { "description": "GridValueGetter<R, V, F>" } }, "valueParser": { "type": { "description": "GridValueParser<R, V, F>" } }, diff --git a/docs/pages/x/api/data-grid/grid-list-col-def.js b/docs/pages/x/api/data-grid/grid-list-col-def.js new file mode 100644 index 0000000000000..a8a1718c20c21 --- /dev/null +++ b/docs/pages/x/api/data-grid/grid-list-col-def.js @@ -0,0 +1,26 @@ +import * as React from 'react'; +import InterfaceApiPage from 'docsx/src/modules/components/InterfaceApiPage'; +import layoutConfig from 'docsx/src/modules/utils/dataGridLayoutConfig'; +import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; +import jsonPageContent from './grid-list-col-def.json'; + +export default function Page(props) { + const { descriptions, pageContent } = props; + return ( + + ); +} + +Page.getInitialProps = () => { + const req = require.context( + 'docsx/translations/api-docs/data-grid/', + false, + /\.\/grid-list-col-def.*.json$/, + ); + const descriptions = mapApiPageTranslations(req); + + return { + descriptions, + pageContent: jsonPageContent, + }; +}; diff --git a/docs/pages/x/api/data-grid/grid-list-col-def.json b/docs/pages/x/api/data-grid/grid-list-col-def.json new file mode 100644 index 0000000000000..bdb42bc4bb2f6 --- /dev/null +++ b/docs/pages/x/api/data-grid/grid-list-col-def.json @@ -0,0 +1,20 @@ +{ + "name": "GridListColDef", + "imports": [ + "import { GridListColDef } from '@mui/x-data-grid-premium'", + "import { GridListColDef } from '@mui/x-data-grid-pro'", + "import { GridListColDef } from '@mui/x-data-grid'" + ], + "demos": "", + "properties": { + "field": { "type": { "description": "string" }, "required": true }, + "align": { "type": { "description": "GridAlignment" } }, + "cellClassName": { "type": { "description": "GridCellClassNamePropType<R, V>" } }, + "display": { "type": { "description": "'text' | 'flex'" } }, + "renderCell": { + "type": { + "description": "(params: GridRenderCellParams<R, V, F>) => React.ReactNode" + } + } + } +} diff --git a/docs/pages/x/api/data-grid/grid-single-select-col-def.json b/docs/pages/x/api/data-grid/grid-single-select-col-def.json index e07981f5de85a..5ed842ac602ec 100644 --- a/docs/pages/x/api/data-grid/grid-single-select-col-def.json +++ b/docs/pages/x/api/data-grid/grid-single-select-col-def.json @@ -93,6 +93,7 @@ "sortable": { "type": { "description": "boolean" }, "default": "true" }, "sortComparator": { "type": { "description": "GridComparatorFn<V>" } }, "sortingOrder": { "type": { "description": "readonly GridSortDirection[]" } }, + "unstable_examples": { "type": { "description": "V[]" } }, "valueFormatter": { "type": { "description": "GridValueFormatter<R, V, F>" } }, "valueGetter": { "type": { "description": "GridValueGetter<R, V, F>" } }, "valueOptions": { diff --git a/docs/pages/x/api/data-grid/index.md b/docs/pages/x/api/data-grid/index.md index 69408d9cbd9e3..59c68e9a9b1fe 100644 --- a/docs/pages/x/api/data-grid/index.md +++ b/docs/pages/x/api/data-grid/index.md @@ -17,6 +17,7 @@ - [GridColDef](/x/api/data-grid/grid-col-def/) - [GridSingleSelectColDef](/x/api/data-grid/grid-single-select-col-def/) - [GridActionsColDef](/x/api/data-grid/grid-actions-col-def/) +- [GridListColDef](/x/api/data-grid/grid-list-col-def/) - [GridExportStateParams](/x/api/data-grid/grid-export-state-params/) - [GridFilterItem](/x/api/data-grid/grid-filter-item/) - [GridFilterModel](/x/api/data-grid/grid-filter-model/) diff --git a/docs/pages/x/api/data-grid/selectors.json b/docs/pages/x/api/data-grid/selectors.json index 06218ff0ab86d..689dce9585928 100644 --- a/docs/pages/x/api/data-grid/selectors.json +++ b/docs/pages/x/api/data-grid/selectors.json @@ -433,12 +433,6 @@ "description": "", "supportsApiRef": true }, - { - "name": "gridRowsDataRowIdToIdLookupSelector", - "returnType": "GridRowIdToIdLookup", - "description": "", - "supportsApiRef": true - }, { "name": "gridRowsLoadingSelector", "returnType": "boolean | undefined", diff --git a/docs/pages/x/api/date-pickers/date-picker.json b/docs/pages/x/api/date-pickers/date-picker.json index 33b4cd3a0f789..e27298dacae1d 100644 --- a/docs/pages/x/api/date-pickers/date-picker.json +++ b/docs/pages/x/api/date-pickers/date-picker.json @@ -97,6 +97,7 @@ "orientation": { "type": { "name": "enum", "description": "'landscape'
| 'portrait'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/date-range-picker.json b/docs/pages/x/api/date-pickers/date-range-picker.json index a357693be539b..9ee6734f43842 100644 --- a/docs/pages/x/api/date-pickers/date-range-picker.json +++ b/docs/pages/x/api/date-pickers/date-range-picker.json @@ -98,6 +98,7 @@ }, "open": { "type": { "name": "bool" }, "default": "false" }, "rangePosition": { "type": { "name": "enum", "description": "'end'
| 'start'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/date-time-picker.json b/docs/pages/x/api/date-pickers/date-time-picker.json index c0d304a92e666..b2443301cad98 100644 --- a/docs/pages/x/api/date-pickers/date-time-picker.json +++ b/docs/pages/x/api/date-pickers/date-time-picker.json @@ -105,6 +105,7 @@ "orientation": { "type": { "name": "enum", "description": "'landscape'
| 'portrait'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/date-time-range-picker.json b/docs/pages/x/api/date-pickers/date-time-range-picker.json index d3901e8bc3a05..add2fd7dede45 100644 --- a/docs/pages/x/api/date-pickers/date-time-range-picker.json +++ b/docs/pages/x/api/date-pickers/date-time-range-picker.json @@ -115,6 +115,7 @@ } }, "rangePosition": { "type": { "name": "enum", "description": "'end'
| 'start'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/desktop-date-picker.json b/docs/pages/x/api/date-pickers/desktop-date-picker.json index cc8dee6f79e6c..1418cf907e00a 100644 --- a/docs/pages/x/api/date-pickers/desktop-date-picker.json +++ b/docs/pages/x/api/date-pickers/desktop-date-picker.json @@ -93,6 +93,7 @@ "orientation": { "type": { "name": "enum", "description": "'landscape'
| 'portrait'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/desktop-date-range-picker.json b/docs/pages/x/api/date-pickers/desktop-date-range-picker.json index 32abb59adbbfe..23fd6ab658165 100644 --- a/docs/pages/x/api/date-pickers/desktop-date-range-picker.json +++ b/docs/pages/x/api/date-pickers/desktop-date-range-picker.json @@ -94,6 +94,7 @@ }, "open": { "type": { "name": "bool" }, "default": "false" }, "rangePosition": { "type": { "name": "enum", "description": "'end'
| 'start'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/desktop-date-time-picker.json b/docs/pages/x/api/date-pickers/desktop-date-time-picker.json index 62a9ffa7411c1..98a3cad44b438 100644 --- a/docs/pages/x/api/date-pickers/desktop-date-time-picker.json +++ b/docs/pages/x/api/date-pickers/desktop-date-time-picker.json @@ -101,6 +101,7 @@ "orientation": { "type": { "name": "enum", "description": "'landscape'
| 'portrait'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/desktop-date-time-range-picker.json b/docs/pages/x/api/date-pickers/desktop-date-time-range-picker.json index 7f2205b1922da..6706455ebb5b6 100644 --- a/docs/pages/x/api/date-pickers/desktop-date-time-range-picker.json +++ b/docs/pages/x/api/date-pickers/desktop-date-time-range-picker.json @@ -111,6 +111,7 @@ } }, "rangePosition": { "type": { "name": "enum", "description": "'end'
| 'start'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/desktop-time-picker.json b/docs/pages/x/api/date-pickers/desktop-time-picker.json index bc22f8994e8c5..d372b04bdfc0f 100644 --- a/docs/pages/x/api/date-pickers/desktop-time-picker.json +++ b/docs/pages/x/api/date-pickers/desktop-time-picker.json @@ -69,6 +69,7 @@ "orientation": { "type": { "name": "enum", "description": "'landscape'
| 'portrait'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/mobile-date-picker.json b/docs/pages/x/api/date-pickers/mobile-date-picker.json index 6dcd610f508ec..37e3b9e9be0b8 100644 --- a/docs/pages/x/api/date-pickers/mobile-date-picker.json +++ b/docs/pages/x/api/date-pickers/mobile-date-picker.json @@ -93,6 +93,7 @@ "orientation": { "type": { "name": "enum", "description": "'landscape'
| 'portrait'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/mobile-date-range-picker.json b/docs/pages/x/api/date-pickers/mobile-date-range-picker.json index 4f50f20ccf6b5..82670cc2d753e 100644 --- a/docs/pages/x/api/date-pickers/mobile-date-range-picker.json +++ b/docs/pages/x/api/date-pickers/mobile-date-range-picker.json @@ -90,6 +90,7 @@ }, "open": { "type": { "name": "bool" }, "default": "false" }, "rangePosition": { "type": { "name": "enum", "description": "'end'
| 'start'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/mobile-date-time-picker.json b/docs/pages/x/api/date-pickers/mobile-date-time-picker.json index 79eb455f23798..23adb960d841c 100644 --- a/docs/pages/x/api/date-pickers/mobile-date-time-picker.json +++ b/docs/pages/x/api/date-pickers/mobile-date-time-picker.json @@ -101,6 +101,7 @@ "orientation": { "type": { "name": "enum", "description": "'landscape'
| 'portrait'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/mobile-date-time-range-picker.json b/docs/pages/x/api/date-pickers/mobile-date-time-range-picker.json index 9228bf05b26d4..32e3b7676d7d8 100644 --- a/docs/pages/x/api/date-pickers/mobile-date-time-range-picker.json +++ b/docs/pages/x/api/date-pickers/mobile-date-time-range-picker.json @@ -107,6 +107,7 @@ } }, "rangePosition": { "type": { "name": "enum", "description": "'end'
| 'start'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/mobile-time-picker.json b/docs/pages/x/api/date-pickers/mobile-time-picker.json index 64336f642f90f..c3898c0d4a927 100644 --- a/docs/pages/x/api/date-pickers/mobile-time-picker.json +++ b/docs/pages/x/api/date-pickers/mobile-time-picker.json @@ -69,6 +69,7 @@ "orientation": { "type": { "name": "enum", "description": "'landscape'
| 'portrait'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/month-calendar.json b/docs/pages/x/api/date-pickers/month-calendar.json index 5794619b01fcf..1f23727e31371 100644 --- a/docs/pages/x/api/date-pickers/month-calendar.json +++ b/docs/pages/x/api/date-pickers/month-calendar.json @@ -2,7 +2,7 @@ "props": { "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } }, "defaultValue": { "type": { "name": "object" } }, - "disabled": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, "disableFuture": { "type": { "name": "bool" }, "default": "false" }, "disableHighlightToday": { "type": { "name": "bool" }, "default": "false" }, "disablePast": { "type": { "name": "bool" }, "default": "false" }, @@ -19,7 +19,7 @@ "describedArgs": ["value"] } }, - "readOnly": { "type": { "name": "bool" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "referenceDate": { "type": { "name": "object" }, "default": "The closest valid month using the validation props, except callbacks such as `shouldDisableMonth`." diff --git a/docs/pages/x/api/date-pickers/pickers-layout.json b/docs/pages/x/api/date-pickers/pickers-layout.json index e75869f624a4f..56c29a639e392 100644 --- a/docs/pages/x/api/date-pickers/pickers-layout.json +++ b/docs/pages/x/api/date-pickers/pickers-layout.json @@ -1,10 +1,6 @@ { "props": { - "isRtl": { "type": { "name": "bool" }, "required": true }, "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } }, - "orientation": { - "type": { "name": "enum", "description": "'landscape'
| 'portrait'" } - }, "slotProps": { "type": { "name": "object" }, "default": "{}" }, "slots": { "type": { "name": "object" }, diff --git a/docs/pages/x/api/date-pickers/static-date-picker.json b/docs/pages/x/api/date-pickers/static-date-picker.json index 812b43b131ea1..2c656b2b01cb2 100644 --- a/docs/pages/x/api/date-pickers/static-date-picker.json +++ b/docs/pages/x/api/date-pickers/static-date-picker.json @@ -79,6 +79,7 @@ "orientation": { "type": { "name": "enum", "description": "'landscape'
| 'portrait'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/static-date-range-picker.json b/docs/pages/x/api/date-pickers/static-date-range-picker.json index 6948a339c0f09..5dace702ff425 100644 --- a/docs/pages/x/api/date-pickers/static-date-range-picker.json +++ b/docs/pages/x/api/date-pickers/static-date-range-picker.json @@ -80,6 +80,7 @@ } }, "rangePosition": { "type": { "name": "enum", "description": "'end'
| 'start'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/static-date-time-picker.json b/docs/pages/x/api/date-pickers/static-date-time-picker.json index cf48a45f5b7fb..e265e0d208c11 100644 --- a/docs/pages/x/api/date-pickers/static-date-time-picker.json +++ b/docs/pages/x/api/date-pickers/static-date-time-picker.json @@ -87,6 +87,7 @@ "orientation": { "type": { "name": "enum", "description": "'landscape'
| 'portrait'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/static-time-picker.json b/docs/pages/x/api/date-pickers/static-time-picker.json index 8e2fefb00aee5..2e9251b190fca 100644 --- a/docs/pages/x/api/date-pickers/static-time-picker.json +++ b/docs/pages/x/api/date-pickers/static-time-picker.json @@ -55,6 +55,7 @@ "orientation": { "type": { "name": "enum", "description": "'landscape'
| 'portrait'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/time-picker.json b/docs/pages/x/api/date-pickers/time-picker.json index e4ce5e054eeba..66c11b29ef3e0 100644 --- a/docs/pages/x/api/date-pickers/time-picker.json +++ b/docs/pages/x/api/date-pickers/time-picker.json @@ -73,6 +73,7 @@ "orientation": { "type": { "name": "enum", "description": "'landscape'
| 'portrait'" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "reduceAnimations": { "type": { "name": "bool" }, "default": "`@media(prefers-reduced-motion: reduce)` || `navigator.userAgent` matches Android <10 or iOS <13" diff --git a/docs/pages/x/api/date-pickers/year-calendar.json b/docs/pages/x/api/date-pickers/year-calendar.json index 67c5c221d51eb..e40978126d0b7 100644 --- a/docs/pages/x/api/date-pickers/year-calendar.json +++ b/docs/pages/x/api/date-pickers/year-calendar.json @@ -2,7 +2,7 @@ "props": { "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } }, "defaultValue": { "type": { "name": "object" } }, - "disabled": { "type": { "name": "bool" } }, + "disabled": { "type": { "name": "bool" }, "default": "false" }, "disableFuture": { "type": { "name": "bool" }, "default": "false" }, "disableHighlightToday": { "type": { "name": "bool" }, "default": "false" }, "disablePast": { "type": { "name": "bool" }, "default": "false" }, @@ -15,7 +15,7 @@ "describedArgs": ["value"] } }, - "readOnly": { "type": { "name": "bool" } }, + "readOnly": { "type": { "name": "bool" }, "default": "false" }, "referenceDate": { "type": { "name": "object" }, "default": "The closest valid year using the validation props, except callbacks such as `shouldDisableYear`." diff --git a/docs/pages/x/api/tree-view/rich-tree-view-pro.json b/docs/pages/x/api/tree-view/rich-tree-view-pro.json index 2fcdf49e993d3..3456c4228964b 100644 --- a/docs/pages/x/api/tree-view/rich-tree-view-pro.json +++ b/docs/pages/x/api/tree-view/rich-tree-view-pro.json @@ -161,12 +161,6 @@ "default": "RichTreeViewProRoot", "class": "MuiRichTreeViewPro-root" }, - { - "name": "item", - "description": "Custom component for the item.", - "default": "TreeItem.", - "class": null - }, { "name": "collapseIcon", "description": "The default icon used to collapse the item.", @@ -181,6 +175,12 @@ "name": "endIcon", "description": "The default icon displayed next to an end item.\nThis is applied to all Tree Items and can be overridden by the TreeItem `icon` slot prop.", "class": null + }, + { + "name": "item", + "description": "Custom component to render a Tree Item.", + "default": "TreeItem.", + "class": null } ], "classes": [], diff --git a/docs/pages/x/api/tree-view/rich-tree-view.json b/docs/pages/x/api/tree-view/rich-tree-view.json index c5ca125dfd5d6..7b014b540d84f 100644 --- a/docs/pages/x/api/tree-view/rich-tree-view.json +++ b/docs/pages/x/api/tree-view/rich-tree-view.json @@ -136,12 +136,6 @@ "default": "RichTreeViewRoot", "class": "MuiRichTreeView-root" }, - { - "name": "item", - "description": "Custom component for the item.", - "default": "TreeItem.", - "class": null - }, { "name": "collapseIcon", "description": "The default icon used to collapse the item.", @@ -156,6 +150,12 @@ "name": "endIcon", "description": "The default icon displayed next to an end item.\nThis is applied to all Tree Items and can be overridden by the TreeItem `icon` slot prop.", "class": null + }, + { + "name": "item", + "description": "Custom component to render a Tree Item.", + "default": "TreeItem.", + "class": null } ], "classes": [], diff --git a/docs/pages/x/api/tree-view/tree-item-provider.js b/docs/pages/x/api/tree-view/tree-item-provider.js new file mode 100644 index 0000000000000..26c68824a62c2 --- /dev/null +++ b/docs/pages/x/api/tree-view/tree-item-provider.js @@ -0,0 +1,23 @@ +import * as React from 'react'; +import ApiPage from 'docs/src/modules/components/ApiPage'; +import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; +import jsonPageContent from './tree-item-provider.json'; + +export default function Page(props) { + const { descriptions, pageContent } = props; + return ; +} + +Page.getInitialProps = () => { + const req = require.context( + 'docsx/translations/api-docs/tree-view/tree-item-provider', + false, + /\.\/tree-item-provider.*.json$/, + ); + const descriptions = mapApiPageTranslations(req); + + return { + descriptions, + pageContent: jsonPageContent, + }; +}; diff --git a/docs/pages/x/api/tree-view/tree-item-provider.json b/docs/pages/x/api/tree-view/tree-item-provider.json new file mode 100644 index 0000000000000..0e35cb71f68c3 --- /dev/null +++ b/docs/pages/x/api/tree-view/tree-item-provider.json @@ -0,0 +1,15 @@ +{ + "props": {}, + "name": "TreeItemProvider", + "imports": [ + "import { TreeItemProvider } from '@mui/x-tree-view/TreeItemProvider';", + "import { TreeItemProvider } from '@mui/x-tree-view';", + "import { TreeItemProvider } from '@mui/x-tree-view-pro';" + ], + "classes": [], + "muiName": "MuiTreeItemProvider", + "filename": "/packages/x-tree-view/src/TreeItemProvider/TreeItemProvider.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/pages/x/api/tree-view/tree-item.json b/docs/pages/x/api/tree-view/tree-item.json index be0a273ec4c03..f1383007b5fe1 100644 --- a/docs/pages/x/api/tree-view/tree-item.json +++ b/docs/pages/x/api/tree-view/tree-item.json @@ -1,7 +1,7 @@ { "props": { "itemId": { "type": { "name": "string" }, "required": true }, - "children": { "type": { "name": "node" } }, + "children": { "type": { "name": "any" } }, "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } }, "disabled": { "type": { "name": "bool" }, "default": "false" }, "id": { "type": { "name": "string" } }, diff --git a/docs/pages/x/react-data-grid/prompt.js b/docs/pages/x/react-data-grid/prompt.js new file mode 100644 index 0000000000000..fc9cc8569c41b --- /dev/null +++ b/docs/pages/x/react-data-grid/prompt.js @@ -0,0 +1,7 @@ +import * as React from 'react'; +import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; +import * as pageProps from 'docsx/data/data-grid/prompt/prompt.md?muiMarkdown'; + +export default function Page() { + return ; +} diff --git a/docs/pages/x/react-data-grid/server-side-data/aggregation.js b/docs/pages/x/react-data-grid/server-side-data/aggregation.js index bfcbd582f587d..3ac36d099e2b7 100644 --- a/docs/pages/x/react-data-grid/server-side-data/aggregation.js +++ b/docs/pages/x/react-data-grid/server-side-data/aggregation.js @@ -3,5 +3,5 @@ import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; import * as pageProps from 'docsx/data/data-grid/server-side-data/aggregation.md?muiMarkdown'; export default function Page() { - return ; + return ; } diff --git a/docs/pages/x/react-data-grid/server-side-data/index.js b/docs/pages/x/react-data-grid/server-side-data/index.js index d9df4aa83ae58..df29698d72ab7 100644 --- a/docs/pages/x/react-data-grid/server-side-data/index.js +++ b/docs/pages/x/react-data-grid/server-side-data/index.js @@ -3,5 +3,5 @@ import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; import * as pageProps from 'docsx/data/data-grid/server-side-data/index.md?muiMarkdown'; export default function Page() { - return ; + return ; } diff --git a/docs/pages/x/react-data-grid/server-side-data/infinite-loading.js b/docs/pages/x/react-data-grid/server-side-data/infinite-loading.js deleted file mode 100644 index 17c80ea529aab..0000000000000 --- a/docs/pages/x/react-data-grid/server-side-data/infinite-loading.js +++ /dev/null @@ -1,7 +0,0 @@ -import * as React from 'react'; -import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; -import * as pageProps from 'docsx/data/data-grid/server-side-data/infinite-loading.md?muiMarkdown'; - -export default function Page() { - return ; -} diff --git a/docs/pages/x/react-data-grid/server-side-data/lazy-loading.js b/docs/pages/x/react-data-grid/server-side-data/lazy-loading.js index a5a2bfb0671a9..500157f7352e8 100644 --- a/docs/pages/x/react-data-grid/server-side-data/lazy-loading.js +++ b/docs/pages/x/react-data-grid/server-side-data/lazy-loading.js @@ -3,5 +3,5 @@ import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; import * as pageProps from 'docsx/data/data-grid/server-side-data/lazy-loading.md?muiMarkdown'; export default function Page() { - return ; + return ; } diff --git a/docs/pages/x/react-data-grid/server-side-data/row-grouping.js b/docs/pages/x/react-data-grid/server-side-data/row-grouping.js index 0ca6eb198e2f3..843d4e65ab4df 100644 --- a/docs/pages/x/react-data-grid/server-side-data/row-grouping.js +++ b/docs/pages/x/react-data-grid/server-side-data/row-grouping.js @@ -3,5 +3,5 @@ import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; import * as pageProps from 'docsx/data/data-grid/server-side-data/row-grouping.md?muiMarkdown'; export default function Page() { - return ; + return ; } diff --git a/docs/pages/x/react-data-grid/server-side-data/tree-data.js b/docs/pages/x/react-data-grid/server-side-data/tree-data.js index 0f161a986cc3e..545a750f55371 100644 --- a/docs/pages/x/react-data-grid/server-side-data/tree-data.js +++ b/docs/pages/x/react-data-grid/server-side-data/tree-data.js @@ -3,5 +3,5 @@ import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; import * as pageProps from 'docsx/data/data-grid/server-side-data/tree-data.md?muiMarkdown'; export default function Page() { - return ; + return ; } diff --git a/docs/scripts/createXTypeScriptProjects.ts b/docs/scripts/createXTypeScriptProjects.ts index 6acad90be81f7..c0f24cb61a2d5 100644 --- a/docs/scripts/createXTypeScriptProjects.ts +++ b/docs/scripts/createXTypeScriptProjects.ts @@ -140,6 +140,7 @@ export const interfacesToDocument: InterfacesToDocumentType[] = [ 'GridColDef', 'GridSingleSelectColDef', 'GridActionsColDef', + 'GridListColDef', 'GridCsvExportOptions', 'GridPrintExportOptions', 'GridExcelExportOptions', @@ -155,7 +156,7 @@ export const interfacesToDocument: InterfacesToDocumentType[] = [ }, { folder: 'charts', - packages: ['x-charts'], + packages: ['x-charts', 'x-charts-pro'], documentedInterfaces: [ 'BarSeriesType', 'LineSeriesType', diff --git a/docs/scripts/formattedTSDemos.js b/docs/scripts/formattedTSDemos.js index 51eb1f82ea799..ea698d165af6b 100644 --- a/docs/scripts/formattedTSDemos.js +++ b/docs/scripts/formattedTSDemos.js @@ -9,7 +9,7 @@ * List of demos to ignore when transpiling * Example: "app-bar/BottomAppBar.tsx" */ -const ignoreList = ['/pages.ts', 'styling.ts', 'styling.tsx']; +const ignoreList = ['/pages.ts', 'styling.ts', 'styling.tsx', 'types.ts']; const fs = require('fs'); const fse = require('fs-extra'); @@ -42,7 +42,7 @@ const babelConfig = { const workspaceRoot = path.join(__dirname, '../../'); -async function getFiles(root) { +async function getFiles(root, excludeRoot = false) { const files = []; try { @@ -55,8 +55,10 @@ async function getFiles(root) { files.push(...(await getFiles(filePath))); } else if ( stat.isFile() && - filePath.endsWith('.tsx') && - !ignoreList.some((ignorePath) => filePath.endsWith(path.normalize(ignorePath))) + /\.tsx?$/.test(filePath) && + !filePath.endsWith('.d.ts') && + !ignoreList.some((ignorePath) => filePath.endsWith(path.normalize(ignorePath))) && + !(excludeRoot && path.dirname(filePath) === root) ) { files.push(filePath); } @@ -79,7 +81,7 @@ const TranspileResult = { }; async function transpileFile(tsxPath, program, ignoreCache = false) { - const jsPath = tsxPath.replace('.tsx', '.js'); + const jsPath = tsxPath.replace(/\.tsx?$/, '.js'); try { if (!ignoreCache && (await fse.exists(jsPath))) { const [jsStat, tsxStat] = await Promise.all([fse.stat(jsPath), fse.stat(tsxPath)]); @@ -127,7 +129,7 @@ async function main(argv) { const tsxFiles = [ ...(await getFiles(path.join(workspaceRoot, 'docs/src/pages'))), // old structure - ...(await getFiles(path.join(workspaceRoot, 'docs/data'))), // new structure + ...(await getFiles(path.join(workspaceRoot, 'docs/data'), true)), // new structure ]; const program = ts.createProgram({ diff --git a/docs/scripts/generateProptypes.ts b/docs/scripts/generateProptypes.ts index b15053b7c1fd3..832fb60f80479 100644 --- a/docs/scripts/generateProptypes.ts +++ b/docs/scripts/generateProptypes.ts @@ -10,7 +10,7 @@ import { import { fixBabelGeneratorIssues, fixLineEndings } from '@mui/internal-docs-utils'; import { createXTypeScriptProjects, XTypeScriptProject } from './createXTypeScriptProjects'; -const COMPONENTS_WITHOUT_PROPTYPES = ['ChartsAxisTooltipContent', 'ChartsItemTooltipContent']; +const COMPONENTS_WITHOUT_PROPTYPES = ['AnimatedBarElement']; async function generateProptypes(project: XTypeScriptProject, sourceFile: string) { const isDateObject = (name: string) => { diff --git a/docs/src/modules/components/CustomizationPlayground.tsx b/docs/src/modules/components/CustomizationPlayground.tsx index 8f82c2c0dc306..2c2b6b72f0844 100644 --- a/docs/src/modules/components/CustomizationPlayground.tsx +++ b/docs/src/modules/components/CustomizationPlayground.tsx @@ -144,6 +144,7 @@ function StylingApproachTabs({ value, onChange, options }: TabsProps) { }} > @@ -240,6 +241,7 @@ function ColorSwitcher({ }) { return ( + {/* eslint-disable-next-line material-ui/no-hardcoded-labels */} Color {(Object.keys(DEFAULT_COLORS) as Array).map((color) => ( @@ -354,6 +357,7 @@ const CustomizationPlayground = function CustomizationPlayground({ + {/* eslint-disable-next-line material-ui/no-hardcoded-labels */} Components {availableSlots && ( + {/* eslint-disable-next-line material-ui/no-hardcoded-labels */} Slots {(availableSlots as string[]).map((slot: string) => ( @@ -388,6 +393,7 @@ const CustomizationPlayground = function CustomizationPlayground({ )} + {/* eslint-disable-next-line material-ui/no-hardcoded-labels */} Playground diff --git a/docs/src/modules/components/DemoPropsForm.tsx b/docs/src/modules/components/DemoPropsForm.tsx index 6af4554500ddb..c095e77e5b0b0 100644 --- a/docs/src/modules/components/DemoPropsForm.tsx +++ b/docs/src/modules/components/DemoPropsForm.tsx @@ -193,10 +193,12 @@ export default function ChartDemoPropsForm({ component="h3" fontWeight="bold" sx={{ scrollMarginTop: 160, fontFamily: 'General Sans' }} + // eslint-disable-next-line material-ui/no-hardcoded-labels > Playground onPropsChange(initialProps)} @@ -427,6 +429,7 @@ export default function ChartDemoPropsForm({ if (knob === 'placement') { return ( + {/* eslint-disable-next-line material-ui/no-hardcoded-labels */} Placement + {/* eslint-disable-next-line material-ui/no-hardcoded-labels */} Undefined + {/* eslint-disable-next-line material-ui/no-hardcoded-labels */} True + {/* eslint-disable-next-line material-ui/no-hardcoded-labels */} False } @@ -270,6 +273,7 @@ function ViewSwitcher({ return ( + {/* eslint-disable-next-line material-ui/no-hardcoded-labels */} Available views @@ -544,6 +548,7 @@ export default function PickersPlayground() { > + {/* eslint-disable-next-line material-ui/no-hardcoded-labels */} Selected components