diff --git a/.github/styles/Blog/BrandName.yml b/.github/styles/Blog/BrandName.yml index b95387c58510b..bfdb8da88c272 100644 --- a/.github/styles/Blog/BrandName.yml +++ b/.github/styles/Blog/BrandName.yml @@ -1,4 +1,7 @@ -# Without a non-breaking space, brand names can be split in the middle, with the start and end on two different lines. +# Without a non-breaking space, brand names can be split in the middle +# with the start and end on two different lines. +# For example, Apple does this meticulously with their brand name: https://www.apple.com/macbook-air/. +# Also read https://www.chrisdpeters.com/blog/using-non-breaking-spaces-to-help-with-branding/ for why. extends: substitution message: Use a non-breaking space for brand name ('%s' instead of '%s') level: error @@ -14,3 +17,8 @@ swap: MUI Core: MUI Core MUI Toolpad: MUI Toolpad MUI Connect: MUI Connect + Stack Overflow: Stack Overflow +# Don't forget to run the following command to generate the package writing-rules.zip file +# Vale uses that ZIP file and not the YAML files. +# +# pnpm docs:zipRules diff --git a/.github/workflows/closed-issue-message.yaml b/.github/workflows/closed-issue-message.yaml index a14afd879f116..9dddd9cfa32b4 100644 --- a/.github/workflows/closed-issue-message.yaml +++ b/.github/workflows/closed-issue-message.yaml @@ -1,23 +1,27 @@ name: Add comment + on: issues: types: - closed -env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GH_REPO: ${{ github.repository }} - NUMBER: ${{ github.event.issue.number }} - BODY: | - :warning: **This issue has been closed.** - If you have a similar problem, please open a [new issue](https://github.com/mui/mui-x/issues/new/choose) and provide details about your specific problem. - If you can provide additional information related to this topic that could help future readers, please feel free to leave a comment. - APPENDIX: | - **How did we do @${{ github.event.issue.user.login }}?** - Your experience with our support team matters to us. If you have a moment, please share your thoughts through our [brief survey](https://tally.so/r/w4r5Mk?issue=${{ github.event.issue.number }}). +permissions: {} jobs: add-comment: + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + NUMBER: ${{ github.event.issue.number }} + BODY: | + :warning: **This issue has been closed.** + If you have a similar problem, please open a [new issue](https://github.com/mui/mui-x/issues/new/choose) and provide details about your specific problem. + If you can provide additional information related to this topic that could help future readers, please feel free to leave a comment. + APPENDIX: | + + **How did we do @${{ github.event.issue.user.login }}?** + Your experience with our support team matters to us. If you have a moment, please share your thoughts through our [brief survey](https://tally.so/r/w4r5Mk?issue=${{ github.event.issue.number }}). + if: github.event.issue.state_reason != 'inactivity' runs-on: ubuntu-latest permissions: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 01d8fd9197102..b83d736e55bf8 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v3.23.2 + uses: github/codeql-action/init@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 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@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v3.23.2 + uses: github/codeql-action/analyze@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 diff --git a/.github/workflows/l10n.yml b/.github/workflows/l10n.yml index 64adb63bc4dee..a1efe0794c607 100644 --- a/.github/workflows/l10n.yml +++ b/.github/workflows/l10n.yml @@ -19,7 +19,7 @@ jobs: - run: echo "${{ github.actor }}" - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Use Node.js 20.x - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: 20 cache: 'yarn' # https://github.com/actions/setup-node/blob/main/docs/advanced-usage.md#caching-packages-dependencies diff --git a/.github/workflows/mark-duplicate.yml b/.github/workflows/mark-duplicate.yml index 15e82efe76c2b..bb3b4df5b23a6 100644 --- a/.github/workflows/mark-duplicate.yml +++ b/.github/workflows/mark-duplicate.yml @@ -14,7 +14,7 @@ jobs: issues: write steps: - name: mark-duplicate - uses: actions-cool/issues-helper@5457ae8d7c1dc20597a753501d30183ed8043c8b # v3.5.2 + uses: actions-cool/issues-helper@a610082f8ac0cf03e357eb8dd0d5e2ba075e017e # v3.6.0 with: actions: 'mark-duplicate' token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/no-response.yml b/.github/workflows/no-response.yml index a12c61a4a79ed..cab433e1444d4 100644 --- a/.github/workflows/no-response.yml +++ b/.github/workflows/no-response.yml @@ -20,7 +20,7 @@ jobs: contents: read issues: write steps: - - uses: MBilalShafi/no-response-add-label@629add01d7b6f8e120811f978c42703736098947 + - uses: MBilalShafi/no-response-add-label@8336c12292902f27b931154c34ba4670cb9899a2 with: token: ${{ secrets.GITHUB_TOKEN }} # Number of days of inactivity before an Issue is closed for lack of response diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 43dd2dc1075fb..21b47b161d200 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@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v3.23.2 + uses: github/codeql-action/upload-sarif@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 with: sarif_file: results.sarif diff --git a/.github/workflows/support-stackoverflow.yml b/.github/workflows/support-stackoverflow.yml index 9ccd75e549dc5..c9d8069a636ff 100644 --- a/.github/workflows/support-stackoverflow.yml +++ b/.github/workflows/support-stackoverflow.yml @@ -29,7 +29,7 @@ jobs: For support, please check out https://mui.com/x/introduction/support/. Thanks! - If you have a question on Stack Overflow, you are welcome to link to it here, it might help others. + If you have a question on Stack Overflow, you are welcome to link to it here, it might help others. If your issue is subsequently confirmed as a bug, and the report follows the issue template, it can be reopened. close-issue: true lock-issue: false diff --git a/.github/workflows/vale-action.yml b/.github/workflows/vale-action.yml index 61078d7162eef..dc6d9faaf213c 100644 --- a/.github/workflows/vale-action.yml +++ b/.github/workflows/vale-action.yml @@ -13,7 +13,7 @@ jobs: pull-requests: write steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - uses: errata-ai/vale-action@c4213d4de3d5f718b8497bd86161531c78992084 # v2.0.1 + - uses: errata-ai/vale-action@38bf078c328061f59879b347ca344a718a736018 # v2.1.0 with: reporter: github-pr-review files: docs/data diff --git a/CHANGELOG.md b/CHANGELOG.md index 41587985378a8..40064527c000f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,157 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. -## v7.0.0-beta.3 +## 7.0.0-beta.4 + +_Feb 23, 2024_ + +We'd like to offer a big thanks to the 10 contributors who made this release possible. Here are some highlights ✨: + +- 🎁 Introduce a new DOM structure for the field components that provides a better accessibility +- 🚀 Simplify Data Grid DOM structure for improved performance (#12013) @romgrk +- 🕥 The support for IE11 has been removed (#12151) @flaviendelangle +- 🐞 Bugfixes +- 📚 Documentation improvements + +### Breaking changes + +- The support for IE11 has been removed from all MUI X packages. The `legacy` bundle that used to support old browsers like IE11 is no longer included. + +### Data Grid + +#### Breaking changes + +- The cell inner wrapper `.MuiDataGrid-cellContent` has been removed, use `.MuiDataGrid-cell` to style the cells. + +#### `@mui/x-data-grid@7.0.0-beta.4` + +- [DataGrid] Simplify cell DOM structure (#12013) @romgrk +- [DataGrid] Fix values labels in `is any of` filter operator (#11939) @gitstart + +#### `@mui/x-data-grid-pro@7.0.0-beta.4` [![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.0.0-beta.4`. + +#### `@mui/x-data-grid-premium@7.0.0-beta.4` [![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.0.0-beta.4`. + +### Date Pickers + +#### Breaking changes + +- The `selectedSections` prop no longer accepts start and end indexes. + When selecting several — but not all — sections, the field components were not behaving correctly, you can now only select one or all sections: + + ```diff + + ``` + +- The headless field hooks (e.g.: `useDateField`) now returns a new prop called `enableAccessibleFieldDOMStructure`. + This property is utilized to determine whether the anticipated UI is constructed using an accessible DOM structure. Learn more about this new [accessible DOM structure](/x/react-date-pickers/fields/#accessible-dom-structure). + + When building a custom UI, you are most-likely only supporting one DOM structure, so you can remove `enableAccessibleFieldDOMStructure` before it is passed to the DOM: + + ```diff + function MyCustomTextField(props) { + const { + + // Should be ignored + + enableAccessibleFieldDOMStructure, + // ... rest of the props you are using + } = props; + + return ( /* Some UI to edit the date */ ) + } + + function MyCustomField(props) { + const fieldResponse = useDateField({ + ...props, + + // If you only support one DOM structure, we advise you to hardcode it here to avoid unwanted switches in your application + + enableAccessibleFieldDOMStructure: false, + }); + + return ; + } + + function App() { + return ; + } + ``` + +- The following internal types were exported by mistake and have been removed from the public API: + + - `UseDateFieldDefaultizedProps` + - `UseTimeFieldDefaultizedProps` + - `UseDateTimeFieldDefaultizedProps` + - `UseSingleInputDateRangeFieldComponentProps` + - `UseSingleInputTimeRangeFieldComponentProps` + - `UseSingleInputDateTimeRangeFieldComponentProps` + +#### `@mui/x-date-pickers@7.0.0-beta.4` + +- [fields] Add a11y support to multi-HTML field (#12173) @LukasTy +- [fields] Use the `PickersTextField` component in the fields (#10649) @flaviendelangle +- [pickers] Fix styling props propagation to `DateTimePickerTabs` (#12096) @LukasTy + +#### `@mui/x-date-pickers-pro@7.0.0-beta.4` [![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.0.0-beta.4`. + +### Charts / `@mui/x-charts@7.0.0-beta.4` + +#### Breaking changes + +These components are no longer exported from `@mui/x-charts`: + +- `CartesianContextProvider` +- `DrawingProvider` + +#### `@mui/x-charts@7.0.0-beta.4` + +- [charts] Don't display text if no value is provided (#12127) @alexfauquette +- [charts] Remove export of context providers (#12123) @oliviertassinari + +### Tree View / `@mui/x-tree-view@7.0.0-beta.4` + +- [TreeView] Stop using custom `findIndex` to support IE11 (#12129) @flaviendelangle + +### Docs + +- [docs] Add recipe for hiding separator on non-resizable columns (#12134) @michelengelen +- [docs] Add small improvements to the Gauge Chart page (#12076) @danilo-leal +- [docs] Add the 'point' scaleType to the axis documentation (#12179) @alexfauquette +- [docs] Clarify Pickers 'Component composition' section (#12097) @LukasTy +- [docs] Fix "Licensing" page link (#12156) @LukasTy +- [docs] Fix the Treemap illustration (#12185) @danilo-leal +- [docs] Fix error raised by Grammarly on the page @oliviertassinari +- [docs] Improve performance on Charts entry point @oliviertassinari +- [docs] Link to React Transition Group with https @oliviertassinari +- [docs] Move Heatmap to `pro` plan (#12047) @alexfauquette +- [docs] Reduce number of Vale errors @oliviertassinari +- [docs] Remove default value set to `undefined` (#12128) @alexfauquette + +### Core + +- [core] Fix docs link check (#12135) @LukasTy +- [core] Fix missing context display names (#12124) @oliviertassinari +- [core] Fix shortcuts when Caps Lock enabled (#12121) @oliviertassinari +- [core] Remove IE 11 compat logic (#12119) @oliviertassinari +- [core] Simplify key utils (#12120) @oliviertassinari +- [core] Use the @mui/internal-scripts package (#12142) @michaldudak +- [all components] Remove legacy IE 11 bundle (#12151) @flaviendelangle +- [code-infra] Bump monorepo (#11880) @Janpot +- [code-infra] Use `experimental.cpus` to control amount of export workers in Next.js (#12095) @Janpot +- [docs-infra] Remove randomized API page layout (#11876) @alexfauquette +- [test] Create local wrapper over `describeConformance` (#12130) @michaldudak + +## 7.0.0-beta.3 _Feb 16, 2024_ @@ -67,7 +217,7 @@ Same changes as in `@mui/x-data-grid-pro@7.0.0-beta.3`. - [core] Sort prop asc (#12033) @oliviertassinari - [core] Bump monorepo (#12055) @alexfauquette -## v7.0.0-beta.2 +## 7.0.0-beta.2 _Feb 9, 2024_ @@ -1353,7 +1503,7 @@ We'd like to offer a big thanks to the 15 contributors who made this release pos - The clipboard related exports `ignoreValueFormatterDuringExport` and `splitClipboardPastedText` are no longer prefixed with `unstable_`. -- The deprecated constants `SUBMIT_FILTER_STROKE_TIME` and `SUBMIT_FILTER_DATE_STROKE_TIME` have been removed from the `DataGrid` exports. Use the [`filterDebounceMs`](https://next.mui.com/x/api/data-grid/data-grid/#DataGrid-prop-filterDebounceMs) prop to customize filter debounce time. +- The deprecated constants `SUBMIT_FILTER_STROKE_TIME` and `SUBMIT_FILTER_DATE_STROKE_TIME` have been removed from the `DataGrid` exports. Use the [`filterDebounceMs`](https://next.mui.com/x/api/data-grid/data-grid/#data-grid-prop-filterDebounceMs) prop to customize filter debounce time. - The `slots.preferencesPanel` slot and the `slotProps.preferencesPanel` prop were removed. Use `slots.panel` and `slotProps.panel` instead. @@ -2202,7 +2352,68 @@ Here is an example of the renaming for the `` component. - [core] Update release instructions as per v7 configuration (#10962) @MBilalShafi - [license] Correctly throw errors (#10924) @oliviertassinari -## v6.19.4 +## 6.19.5 + +_Feb 23, 2024_ + +We'd like to offer a big thanks to the 6 contributors who made this release possible. Here are some highlights ✨: + +- 🐞 Bugfixes +- 📚 Documentation improvements + +### Data Grid + +#### `@mui/x-data-grid@6.19.5` + +- [DataGrid] Fix styling grid filter input single select (#12079) @FreakDroid + +#### `@mui/x-data-grid-pro@6.19.5` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan') + +Same changes as in `@mui/x-data-grid@6.19.5`. + +#### `@mui/x-data-grid-premium@6.19.5` [![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@6.19.5`. + +### Date Pickers + +#### `@mui/x-date-pickers@6.19.5` + +- [pickers] Fix `referenceDate` day calendar focus (#12136) @LukasTy +- [pickers] Fix styling props propagation to `DateTimePickerTabs` (#12131) @LukasTy + +#### `@mui/x-date-pickers-pro@6.19.5` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan') + +Same changes as in `@mui/x-date-pickers@6.19.5`. + +### Charts / `@mui/x-charts@6.19.5` + +- [charts] Allow to skip animation on sparkline bar (#12160) @alexfauquette + +### Docs + +- [docs] Clarify Pickers 'Component composition' section (#12147) @LukasTy +- [docs] Fix 301 redirection to StackBlitz @oliviertassinari +- [docs] Fix 301 to Material UI @oliviertassinari +- [docs] Fix 301 to Material UI @oliviertassinari +- [docs] Fix 404 links to translation source @oliviertassinari +- [docs] Fix dead link to translations @oliviertassinari +- [docs] Fix the Treemap illustration (#12189) @danilo-leal +- [docs] Fix typo for `AdapterDateFnsV3` (#12037) @flaviendelangle +- [docs] Improve performance on Charts entry point @oliviertassinari +- [docs] Move Heatmap to pro (#12170) @alexfauquette +- [docs] Remove Charts installation next tag call-out (#12133) @LukasTy +- [docs] Removed `focused` prop from demo (#12126) @michelengelen +- [docs] Add missing Heatmap pro icon @oliviertassinari +- [docs] Add more illustrations to the Overview page (#12041) @danilo-leal +- [docs] Avoid use of shorthand (#12009) @oliviertassinari + +### Core + +- [core] Fix CI @oliviertassinari +- [core] Fix docs link check (#12137) @LukasTy + +## 6.19.4 _Feb 9, 2024_ @@ -2214,7 +2425,7 @@ We'd like to offer a big thanks to the 10 contributors who made this release pos ### Data Grid -#### `@mui/x-data-grid@v6.19.4` +#### `@mui/x-data-grid@6.19.4` - [DataGrid] Add support for dialogs in menu actions (#11937) @cherniavskii - [DataGrid] Allow passing readonly arrays to `pageSizeOptions` prop (#11992) @pcorpet @@ -2222,28 +2433,28 @@ We'd like to offer a big thanks to the 10 contributors who made this release pos - [DataGrid] Replace `eval` with `new Function` (#11962) @cherniavskii - [l10n] Improve Danish (da-DK) locale (#11972) @ShahrazH -#### `@mui/x-data-grid-pro@v6.19.4` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan') +#### `@mui/x-data-grid-pro@6.19.4` [![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@v6.19.4`. +Same changes as in `@mui/x-data-grid@6.19.4`. -#### `@mui/x-data-grid-premium@v6.19.4` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan') +#### `@mui/x-data-grid-premium@6.19.4` [![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@v6.19.4`, plus: +Same changes as in `@mui/x-data-grid-pro@6.19.4`, plus: - [DataGridPremium] Fix autosize grouping cell (#11990) @romgrk - [DataGridPremium] Fix error after closing print export (#11889) @cherniavskii ### Date Pickers -#### `@mui/x-date-pickers@v6.19.4` +#### `@mui/x-date-pickers@6.19.4` - [pickers] Avoid relying on locale in Luxon `isWithinRange` method (#11940) @LukasTy -#### `@mui/x-date-pickers-pro@v6.19.4` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan') +#### `@mui/x-date-pickers-pro@6.19.4` [![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@v6.19.4`. +Same changes as in `@mui/x-date-pickers@6.19.4`. -### Charts / `@mui/x-charts@v6.19.4` +### Charts / `@mui/x-charts@6.19.4` - [charts] Add `reverse` property to axes (#11959) @alexfauquette - [charts] Allow series ids to be numbers (#11960) @alexfauquette @@ -4053,7 +4264,7 @@ We'd like to offer a big thanks to the 13 contributors who made this release pos #### `@mui/x-data-grid@6.9.1` -- [DataGrid] Add Joy UI `tooltip` and `loadingOverlay` slots (#9028) @cherniavskii +- [DataGrid] Add Joy UI `tooltip` and `loadingOverlay` slots (#9028) @cherniavskii - [DataGrid] Add section about enabling pagination on Pro and Premium (#8759) @joserodolfofreitas - [DataGrid] Don't forward `editCellState` prop to DOM element (#9501) @m4theushw - [DataGrid] Add experimental API for faster filtering performance (#9254) @romgrk @@ -4184,7 +4395,7 @@ Same changes as in `@mui/x-date-pickers@6.9.0`. - [docs] Fix random screenshot generation (#9364) @cherniavskii - [docs] Remove random generation from chart doc example (#9343) @flaviendelangle - [docs] Sync h1 with sidenav link (#9252) @oliviertassinari -- [docs] Use the mui-x Stack Overflow tag (#9352) @oliviertassinari +- [docs] Use the mui-x Stack Overflow tag (#9352) @oliviertassinari ### Core @@ -4511,8 +4722,8 @@ We'd like to offer a big thanks to the 12 contributors who made this release pos - [DataGrid] Fix DataGrid rendering in JSDOM (#8968) @cherniavskii - [DataGrid] Fix layout when rendered inside a parent with `display: grid` (#8577) @cherniavskii -- [DataGrid] Add Joy UI icon slots (#8940) @siriwatknp -- [DataGrid] Add Joy UI pagination slot (#8871) @cherniavskii +- [DataGrid] Add Joy UI icon slots (#8940) @siriwatknp +- [DataGrid] Add Joy UI pagination slot (#8871) @cherniavskii - [DataGrid] Extract `baseChip` slot (#8748) @cherniavskii - [DataGridPremium] Implement Clipboard import (#7389) @cherniavskii - [l10n] Improve French (fr-FR) locale (#8825) @allereaugabriel @@ -4562,7 +4773,7 @@ We'd like to offer a big thanks to the 7 contributors who made this release poss - [DataGrid] Fix falsy filter values not showing in filter button tooltip (#8550) @ithrforu - [DataGrid] Fix missing watermark in Pro and Premium packages (#8797) @cherniavskii - [DataGrid] Remove unwarranted warning log (#8847) @romgrk -- [DataGrid] Add Joy UI slots (`Select`, `SelectOption`, `InputLabel`, `FormControl`) (#8747) @cherniavskii +- [DataGrid] Add Joy UI slots (`Select`, `SelectOption`, `InputLabel`, `FormControl`) (#8747) @cherniavskii - [DataGridPremium] Fix expanded groups being collapsed after calling `updateRows` (#8823) @cherniavskii ### `@mui/x-date-pickers@6.3.1` / `@mui/x-date-pickers-pro@6.3.1` @@ -4613,7 +4824,7 @@ We'd like to offer a big thanks to the 15 contributors who made this release pos - [DataGrid] Add overlay classes to `gridClasses` (#8686) @lindapaiste - [DataGrid] Avoid passing `api` prop to div (#8679) @someden - [DataGrid] Fix 'ResizeObserver loop limit exceeded' error (#8744) @m4theushw -- [DataGrid] Add Joy UI slots (button and switch) (#8699) @siriwatknp +- [DataGrid] Add Joy UI slots (button and switch) (#8699) @siriwatknp - [DataGrid] Fix aggregation label alignment (#8694) @joserodolfofreitas - [DataGridPremium] Fix infinite loop when updating grouped rows (#8693) @cherniavskii - [DataGridPro] Fix error after updating `columns` and `columnGroupingModel` at once (#8730) @cherniavskii @@ -4675,7 +4886,7 @@ We'd like to offer a big thanks to the 9 contributors who made this release poss #### Changes - [DataGrid] Add `getTogglableColumns` to `Hide all` and `Show all` actions (#8496) @MBilalShafi -- [DataGrid] Add Grid + Joy UI experiment page (#8067) @cherniavskii +- [DataGrid] Add Grid + Joy UI experiment page (#8067) @cherniavskii - [DataGrid] Fix print style when rendering inside Shadow DOM (#8656) @Bwatermelon - [DataGrid] Replace `GridAutoSizer` with `ResizeObserver` (#8091) @m4theushw - [DataGrid] Use stable ID for the placeholder filter item (#8603) @m4theushw diff --git a/babel.config.js b/babel.config.js index 901553e569693..4b9c46dc91c7c 100644 --- a/babel.config.js +++ b/babel.config.js @@ -34,7 +34,7 @@ const productionPlugins = [ ]; module.exports = function getBabelConfig(api) { - const useESModules = api.env(['legacy', 'modern', 'stable', 'rollup']); + const useESModules = api.env(['modern', 'stable', 'rollup']); const presets = [ [ @@ -155,12 +155,6 @@ module.exports = function getBabelConfig(api) { ], ], }, - legacy: { - plugins: [ - // IE11 support - '@babel/plugin-transform-object-assign', - ], - }, test: { sourceMaps: 'both', plugins: [ diff --git a/changelogOld/CHANGELOG.v5.md b/changelogOld/CHANGELOG.v5.md index dc300290b139f..62a6d292bf609 100644 --- a/changelogOld/CHANGELOG.v5.md +++ b/changelogOld/CHANGELOG.v5.md @@ -2527,7 +2527,7 @@ A big thanks to the 5 contributors who made this release possible. Here are some - [core] Fix `yarn prettier` script (#3292) @oliviertassinari - [core] Improve tests for Tree Data (#3366) @flaviendelangle - [core] Never import directly from the `__modules__` folder in the `x-data-grid-generator` package (#3379) @flaviendelangle -- [core] Transition to a new Stack Overflow tag (#3308) @oliviertassinari +- [core] Transition to a new Stack Overflow tag (#3308) @oliviertassinari - [core] Update monorepo (#3370) @flaviendelangle - [core] Use pre-processors for sorting and filtering (#3318) @flaviendelangle - [test] Replace `useFakeTimers` (#3323) @m4theushw diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000000000..4425211595f51 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +next.config.local.js diff --git a/docs/.link-check-errors.txt b/docs/.link-check-errors.txt index 87eaaff0f8d8b..8096f1b7324bf 100644 --- a/docs/.link-check-errors.txt +++ b/docs/.link-check-errors.txt @@ -1,18 +1,2 @@ Broken links found by `yarn docs:link-check` that exist: -- https://mui.com/base-ui/react-autocomplete/hooks-api/#use-autocomplete -- https://mui.com/base-ui/react-portal/components-api/ -- https://mui.com/material-ui/api/button/#props -- https://mui.com/material-ui/api/input-base/#InputBase-prop-disableInjectingGlobalStyles -- https://mui.com/material-ui/api/menu-item/#css -- https://mui.com/material-ui/api/popper/#props -- https://mui.com/material-ui/guides/api/#native-properties -- https://mui.com/system/styles/api/#creategenerateclassname-options-class-name-generator -- https://mui.com/system/styles/api/#serverstylesheets -- https://mui.com/system/styles/api/#stylesprovider -- https://mui.com/system/styles/api/#themeprovider -- https://mui.com/x/api/charts/gauge/#classes -- https://mui.com/x/api/data-grid/data-grid/#DataGrid-prop-filterDebounceMs -- https://mui.com/x/api/data-grid/data-grid/#props -- https://mui.com/x/api/data-grid/data-grid/#slots -- https://mui.com/x/api/date-pickers/date-picker/#slots diff --git a/docs/babel.config.js b/docs/babel.config.js index 2ec7799d61593..d7a30a01f9136 100644 --- a/docs/babel.config.js +++ b/docs/babel.config.js @@ -35,8 +35,6 @@ module.exports = function getBabelConfig(api) { ], plugins: [ ...baseConfig.plugins, - // for IE 11 support - '@babel/plugin-transform-object-assign', 'babel-plugin-preval', [ 'babel-plugin-module-resolver', diff --git a/docs/data/charts/axis/axis.md b/docs/data/charts/axis/axis.md index b860975fb644f..0fa220dbc0fa3 100644 --- a/docs/data/charts/axis/axis.md +++ b/docs/data/charts/axis/axis.md @@ -41,6 +41,7 @@ Those demonstrations use the defaultized values. The axis type is specified by its property `scaleType` which expect one of the following values: - `'band'`: Split the axis in equal band. Mostly used for bar charts. +- `'point'`: Split the axis in equally spaced points. Mostly used for line charts on categories. - `'linear'`, `'log'`, `'sqrt'`: Map numerical values to the space available for the chart. `'linear'` is the default behavior. - `'time'`, `'utc'`: Map JavaScript `Date()` object to the space available for the chart. @@ -51,7 +52,7 @@ Which expects an array of value coherent with the `scaleType`: - For `'linear'`, `'log'`, or `'sqrt'` it should contain numerical values - For `'time'` or `'utc'` it should contain `Date()` objects -- For `'band'` it can contain `string`, or numerical values +- For `'band'` or `'point'` it can contain `string`, or numerical values Some series types also require specific axis attributes: diff --git a/docs/data/charts/components/components.md b/docs/data/charts/components/components.md index 6cb3134cd5549..1501c39b63b1b 100644 --- a/docs/data/charts/components/components.md +++ b/docs/data/charts/components/components.md @@ -1,7 +1,7 @@ --- title: Charts - Custom components productId: x-charts -components: ChartsClipPath, ChartsSurface, CartesianContextProvider, DrawingProvider, HighlightProvider, InteractionProvider, SeriesContextProvider +components: ChartsClipPath, ChartsSurface --- # Charts - Custom components diff --git a/docs/data/charts/heat-map/heat-map.md b/docs/data/charts/heat-map/heat-map.md index e44f62204401d..6d6413b064b8e 100644 --- a/docs/data/charts/heat-map/heat-map.md +++ b/docs/data/charts/heat-map/heat-map.md @@ -1,9 +1,9 @@ --- -title: React Heat map chart +title: React Heatmap chart productId: x-charts --- -# Charts - Heatmap 🚧 +# Charts - Heatmap [](/x/introduction/licensing/#pro-plan 'Pro plan')🚧

Heatmap charts allow to highlight correlation between categories.

diff --git a/docs/data/charts/overview/overview.md b/docs/data/charts/overview/overview.md index 26b8942a704e4..e3347418beb63 100644 --- a/docs/data/charts/overview/overview.md +++ b/docs/data/charts/overview/overview.md @@ -16,7 +16,7 @@ packageName: '@mui/x-charts' The `@mui/x-charts` is an MIT library for rendering charts relying on [D3.js](https://d3js.org/) for data manipulation and SVG for rendering. And, like other MUI X components, charts are production-ready components that integrate smoothly into your app. -With a high level of customization, MUI X Charts provides on three levels of customization layers: **single components** with great defaults, extensive **configuration props**, and **subcomponents** for flexible composition. +With a high level of customization, MUI X Charts provides three levels of customization layers: **single components** with great defaults, extensive **configuration props**, and **subcomponents** for flexible composition. Additionally, you can also use all the [MUI System](https://mui.com/system/getting-started/) tools, such as the theme override or the `sx` prop. {{"demo": "ChartsOverviewDemo.js", "defaultCodeOpen": true}} diff --git a/docs/data/charts/tree-map/tree-map.md b/docs/data/charts/tree-map/tree-map.md index b75b76738a00e..a9dbb2832c96c 100644 --- a/docs/data/charts/tree-map/tree-map.md +++ b/docs/data/charts/tree-map/tree-map.md @@ -1,14 +1,14 @@ --- -title: React Tree map chart +title: React Treemap chart productId: x-charts --- -# Charts - Tree map 🚧 +# Charts - Treemap 🚧 -

Tree map allows to display data with a hierarchical structure.

+

Treemap allows to display data with a hierarchical structure.

:::warning -The Tree map Chart component isn't available yet, but you can upvote [**this GitHub issue**](https://github.com/mui/mui-x/issues/7924) to see it arrive sooner. +The Treemap Chart component isn't available yet, but you can upvote [**this GitHub issue**](https://github.com/mui/mui-x/issues/7924) to see it arrive sooner. Don't hesitate to leave a comment there to influence what gets built. Especially if you already have a use case for this component, or if you're facing a pain point with your current solution. diff --git a/docs/data/data-grid/accessibility/accessibility.md b/docs/data/data-grid/accessibility/accessibility.md index 817bf14988e45..3a54c27b73b07 100644 --- a/docs/data/data-grid/accessibility/accessibility.md +++ b/docs/data/data-grid/accessibility/accessibility.md @@ -16,7 +16,7 @@ WCAG 2.1 has three levels of conformance: A, AA, and AAA. Level AA meets the most commonly encountered conformance guidelines. This is the most common target for organizations so what we aims to support very well. -The [WAI-ARIA authoring practices](https://www.w3.org/WAI/ARIA/apg/patterns/grid/) provide valuable information on how to optimize the accessibility of a data grid. +The [WAI-ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/patterns/grid/) provide valuable information on how to optimize the accessibility of a data grid. ## Density @@ -47,7 +47,7 @@ The Data Grid listens for keyboard interactions from the user and emits events i ### Tab sequence -According to [WAI-ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/grid/), only one of the focusable elements contained by a composite widget should be included in the page tab sequence. +According to [WAI-ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/patterns/grid/), only one of the focusable elements contained by a composite widget should be included in the page tab sequence. For an element to be included in the tab sequence, it needs to have a `tabIndex` value of zero or greater. When a user focuses on a Data Grid cell, the first inner element with `tabIndex={0}` receives the focus. diff --git a/docs/data/data-grid/aggregation/AggregationRenderCell.js b/docs/data/data-grid/aggregation/AggregationRenderCell.js index 4f034261d4239..1bf1c1bcc7b3a 100644 --- a/docs/data/data-grid/aggregation/AggregationRenderCell.js +++ b/docs/data/data-grid/aggregation/AggregationRenderCell.js @@ -11,6 +11,7 @@ const COLUMNS = [ type: 'number', width: 180, availableAggregationFunctions: ['min', 'max', 'avg', 'size'], + display: 'flex', // Imdb rating is on a scale from 0 to 10, the MUI rating component is on a scale from 0 to 5 renderCell: (params) => { if (params.aggregation && !params.aggregation.hasCellUnit) { diff --git a/docs/data/data-grid/aggregation/AggregationRenderCell.tsx b/docs/data/data-grid/aggregation/AggregationRenderCell.tsx index 11f653668ba1b..a0de64c3ee690 100644 --- a/docs/data/data-grid/aggregation/AggregationRenderCell.tsx +++ b/docs/data/data-grid/aggregation/AggregationRenderCell.tsx @@ -11,6 +11,7 @@ const COLUMNS: GridColDef[] = [ type: 'number', width: 180, availableAggregationFunctions: ['min', 'max', 'avg', 'size'], + display: 'flex', // Imdb rating is on a scale from 0 to 10, the MUI rating component is on a scale from 0 to 5 renderCell: (params) => { if (params.aggregation && !params.aggregation.hasCellUnit) { diff --git a/docs/data/data-grid/column-definition/RenderExpandCellGrid.js b/docs/data/data-grid/column-definition/RenderExpandCellGrid.js index 0f63178901493..598c8d14e4a83 100644 --- a/docs/data/data-grid/column-definition/RenderExpandCellGrid.js +++ b/docs/data/data-grid/column-definition/RenderExpandCellGrid.js @@ -38,8 +38,7 @@ const GridCellExpand = React.memo(function GridCellExpand(props) { } function handleKeyDown(nativeEvent) { - // IE11, Edge (prior to using Bink?) use 'Esc' - if (nativeEvent.key === 'Escape' || nativeEvent.key === 'Esc') { + if (nativeEvent.key === 'Escape') { setShowFullCell(false); } } diff --git a/docs/data/data-grid/column-definition/RenderExpandCellGrid.tsx b/docs/data/data-grid/column-definition/RenderExpandCellGrid.tsx index 945137a179c8f..43420b5fc9c66 100644 --- a/docs/data/data-grid/column-definition/RenderExpandCellGrid.tsx +++ b/docs/data/data-grid/column-definition/RenderExpandCellGrid.tsx @@ -45,8 +45,7 @@ const GridCellExpand = React.memo(function GridCellExpand( } function handleKeyDown(nativeEvent: KeyboardEvent) { - // IE11, Edge (prior to using Bink?) use 'Esc' - if (nativeEvent.key === 'Escape' || nativeEvent.key === 'Esc') { + if (nativeEvent.key === 'Escape') { setShowFullCell(false); } } diff --git a/docs/data/data-grid/column-dimensions/ColumnAutosizing.js b/docs/data/data-grid/column-dimensions/ColumnAutosizing.js index 030c4d0534d92..3d46d27bbd9b0 100644 --- a/docs/data/data-grid/column-dimensions/ColumnAutosizing.js +++ b/docs/data/data-grid/column-dimensions/ColumnAutosizing.js @@ -36,7 +36,12 @@ function useData(length) { { field: 'id', headerName: 'Brand ID' }, { field: 'brand', headerName: 'Brand name' }, { field: 'rep', headerName: 'Representative' }, - { field: 'rating', headerName: 'Rating', renderCell: renderRating }, + { + field: 'rating', + headerName: 'Rating', + renderCell: renderRating, + display: 'flex', + }, ]; return { rows, columns }; diff --git a/docs/data/data-grid/column-dimensions/ColumnAutosizing.tsx b/docs/data/data-grid/column-dimensions/ColumnAutosizing.tsx index 5f813676e7ee8..841b6642113d8 100644 --- a/docs/data/data-grid/column-dimensions/ColumnAutosizing.tsx +++ b/docs/data/data-grid/column-dimensions/ColumnAutosizing.tsx @@ -39,7 +39,12 @@ function useData(length: number) { { field: 'id', headerName: 'Brand ID' }, { field: 'brand', headerName: 'Brand name' }, { field: 'rep', headerName: 'Representative' }, - { field: 'rating', headerName: 'Rating', renderCell: renderRating }, + { + field: 'rating', + headerName: 'Rating', + renderCell: renderRating, + display: 'flex' as const, + }, ]; return { rows, columns }; diff --git a/docs/data/data-grid/column-dimensions/ColumnAutosizingAsync.js b/docs/data/data-grid/column-dimensions/ColumnAutosizingAsync.js index 01490fbfceb23..b030e5f9c060b 100644 --- a/docs/data/data-grid/column-dimensions/ColumnAutosizingAsync.js +++ b/docs/data/data-grid/column-dimensions/ColumnAutosizingAsync.js @@ -15,7 +15,12 @@ const columns = [ { field: 'id', headerName: 'Brand ID' }, { field: 'brand', headerName: 'Brand name' }, { field: 'rep', headerName: 'Representative' }, - { field: 'rating', headerName: 'Rating', renderCell: renderRating }, + { + field: 'rating', + headerName: 'Rating', + renderCell: renderRating, + display: 'flex', + }, ]; function renderRating(params) { diff --git a/docs/data/data-grid/column-dimensions/ColumnAutosizingAsync.tsx b/docs/data/data-grid/column-dimensions/ColumnAutosizingAsync.tsx index 2140a5e5ae3b0..d5a7cee379fb1 100644 --- a/docs/data/data-grid/column-dimensions/ColumnAutosizingAsync.tsx +++ b/docs/data/data-grid/column-dimensions/ColumnAutosizingAsync.tsx @@ -3,7 +3,7 @@ import Button from '@mui/material/Button'; import Rating from '@mui/material/Rating'; import Stack from '@mui/material/Stack'; import { useGridApiRef } from '@mui/x-data-grid'; -import { DataGridPro, GridApiPro } from '@mui/x-data-grid-pro'; +import { DataGridPro, GridApiPro, GridColDef } from '@mui/x-data-grid-pro'; import { randomInt, randomRating, @@ -12,11 +12,16 @@ import { import * as ReactDOM from 'react-dom'; import { GridData } from 'docsx/data/data-grid/virtualization/ColumnVirtualizationGrid'; -const columns = [ +const columns: GridColDef[] = [ { field: 'id', headerName: 'Brand ID' }, { field: 'brand', headerName: 'Brand name' }, { field: 'rep', headerName: 'Representative' }, - { field: 'rating', headerName: 'Rating', renderCell: renderRating }, + { + field: 'rating', + headerName: 'Rating', + renderCell: renderRating, + display: 'flex', + }, ]; function renderRating(params: any) { diff --git a/docs/data/data-grid/custom-columns/SparklineColumn.js b/docs/data/data-grid/custom-columns/SparklineColumn.js index 3b6eb6b9016b6..f2a38c1813cfa 100644 --- a/docs/data/data-grid/custom-columns/SparklineColumn.js +++ b/docs/data/data-grid/custom-columns/SparklineColumn.js @@ -24,6 +24,7 @@ const sparklineColumnType = { sortable: false, editable: false, groupable: false, + display: 'flex', renderCell: (params) => , }; diff --git a/docs/data/data-grid/custom-columns/SparklineColumn.tsx b/docs/data/data-grid/custom-columns/SparklineColumn.tsx index b643d30d037d6..cf646189b49f8 100644 --- a/docs/data/data-grid/custom-columns/SparklineColumn.tsx +++ b/docs/data/data-grid/custom-columns/SparklineColumn.tsx @@ -36,6 +36,7 @@ const sparklineColumnType: GridColTypeDef = { sortable: false, editable: false, groupable: false, + display: 'flex', renderCell: (params) => , }; diff --git a/docs/data/data-grid/demo/PopularFeaturesDemo.js b/docs/data/data-grid/demo/PopularFeaturesDemo.js index b30a71abeae74..3da89e7e926b2 100644 --- a/docs/data/data-grid/demo/PopularFeaturesDemo.js +++ b/docs/data/data-grid/demo/PopularFeaturesDemo.js @@ -368,6 +368,7 @@ const columns = [ flex: 0.2, minWidth: 100, groupable: false, + display: 'flex', renderCell: (params) => { if (params.aggregation) { return ; @@ -430,6 +431,7 @@ const columns = [ flex: 0.3, type: 'singleSelect', valueOptions: ['Premium', 'Pro', 'Community'], + display: 'flex', renderCell: (params) => { if (params.aggregation) { return ; diff --git a/docs/data/data-grid/demo/PopularFeaturesDemo.tsx b/docs/data/data-grid/demo/PopularFeaturesDemo.tsx index 982e81055f7e2..89912c4f12c4b 100644 --- a/docs/data/data-grid/demo/PopularFeaturesDemo.tsx +++ b/docs/data/data-grid/demo/PopularFeaturesDemo.tsx @@ -383,6 +383,7 @@ const columns: GridColDef[] = [ flex: 0.2, minWidth: 100, groupable: false, + display: 'flex', renderCell: (params) => { if (params.aggregation) { return ; @@ -445,6 +446,7 @@ const columns: GridColDef[] = [ flex: 0.3, type: 'singleSelect', valueOptions: ['Premium', 'Pro', 'Community'], + display: 'flex', renderCell: (params: GridRenderCellParams) => { if (params.aggregation) { return ; diff --git a/docs/data/data-grid/editing/CustomEditComponent.js b/docs/data/data-grid/editing/CustomEditComponent.js index d5d5cd3596fdf..bdacf3318440e 100644 --- a/docs/data/data-grid/editing/CustomEditComponent.js +++ b/docs/data/data-grid/editing/CustomEditComponent.js @@ -58,6 +58,7 @@ const columns = [ { field: 'rating', headerName: 'Rating', + display: 'flex', renderCell: renderRating, renderEditCell: renderRatingEditInputCell, editable: true, diff --git a/docs/data/data-grid/editing/CustomEditComponent.tsx b/docs/data/data-grid/editing/CustomEditComponent.tsx index 63d036378717a..d0fb1bde9c103 100644 --- a/docs/data/data-grid/editing/CustomEditComponent.tsx +++ b/docs/data/data-grid/editing/CustomEditComponent.tsx @@ -65,6 +65,7 @@ const columns: GridColDef[] = [ { field: 'rating', headerName: 'Rating', + display: 'flex', renderCell: renderRating, renderEditCell: renderRatingEditInputCell, editable: true, diff --git a/docs/data/data-grid/editing/ValidateServerNameGrid.tsx b/docs/data/data-grid/editing/ValidateServerNameGrid.tsx index 0fa47993d1712..5b460c759370f 100644 --- a/docs/data/data-grid/editing/ValidateServerNameGrid.tsx +++ b/docs/data/data-grid/editing/ValidateServerNameGrid.tsx @@ -25,7 +25,7 @@ const StyledBox = styled('div')(({ theme }) => ({ }, })); -let promiseTimeout: any; +let promiseTimeout: ReturnType; function validateName(username: string): Promise { const existingUsers = rows.map((row) => row.name.toLowerCase()); diff --git a/docs/data/data-grid/overview/overview.md b/docs/data/data-grid/overview/overview.md index 8f6051360e5f7..fbee25d014715 100644 --- a/docs/data/data-grid/overview/overview.md +++ b/docs/data/data-grid/overview/overview.md @@ -111,7 +111,7 @@ Here are some resources you might be interested in to learn more about the data - The [source on GitHub](https://github.com/mui/mui-x/tree/HEAD/packages/) - The [Material Design specification](https://m2.material.io/components/data-tables) specification -- The accessibility [WAI-ARIA authoring practices](https://www.w3.org/WAI/ARIA/apg/patterns/grid/) +- The accessibility [WAI-ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/patterns/grid/) - The Figma, Adobe XD, and Sketch [design kits](https://mui.com/design-kits/). ## API diff --git a/docs/data/data-grid/sorting/GetSortComparator.js b/docs/data/data-grid/sorting/GetSortComparator.js new file mode 100644 index 0000000000000..53ff478e32891 --- /dev/null +++ b/docs/data/data-grid/sorting/GetSortComparator.js @@ -0,0 +1,47 @@ +import * as React from 'react'; +import { DataGrid, gridStringOrNumberComparator } from '@mui/x-data-grid'; +import { + randomQuantity, + randomId, + randomCommodity, +} from '@mui/x-data-grid-generator'; + +const columns = [ + { field: 'commodity', headerName: 'Commodity', width: 200 }, + { + type: 'number', + field: 'quantity', + headerName: 'Quantity', + getSortComparator: (sortDirection) => { + const modifier = sortDirection === 'desc' ? -1 : 1; + return (value1, value2, cellParams1, cellParams2) => { + if (value1 === null) { + return 1; + } + if (value2 === null) { + return -1; + } + return ( + modifier * + gridStringOrNumberComparator(value1, value2, cellParams1, cellParams2) + ); + }; + }, + }, +]; + +const rows = [ + { id: randomId(), commodity: randomCommodity(), quantity: randomQuantity() }, + { id: randomId(), commodity: randomCommodity(), quantity: null }, + { id: randomId(), commodity: randomCommodity(), quantity: randomQuantity() }, + { id: randomId(), commodity: randomCommodity(), quantity: null }, + { id: randomId(), commodity: randomCommodity(), quantity: randomQuantity() }, +]; + +export default function GetSortComparator() { + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/sorting/GetSortComparator.tsx b/docs/data/data-grid/sorting/GetSortComparator.tsx new file mode 100644 index 0000000000000..7cdf29c2d073f --- /dev/null +++ b/docs/data/data-grid/sorting/GetSortComparator.tsx @@ -0,0 +1,51 @@ +import * as React from 'react'; +import { + DataGrid, + GridColDef, + gridStringOrNumberComparator, +} from '@mui/x-data-grid'; +import { + randomQuantity, + randomId, + randomCommodity, +} from '@mui/x-data-grid-generator'; + +const columns: GridColDef[] = [ + { field: 'commodity', headerName: 'Commodity', width: 200 }, + { + type: 'number', + field: 'quantity', + headerName: 'Quantity', + getSortComparator: (sortDirection) => { + const modifier = sortDirection === 'desc' ? -1 : 1; + return (value1, value2, cellParams1, cellParams2) => { + if (value1 === null) { + return 1; + } + if (value2 === null) { + return -1; + } + return ( + modifier * + gridStringOrNumberComparator(value1, value2, cellParams1, cellParams2) + ); + }; + }, + }, +]; + +const rows = [ + { id: randomId(), commodity: randomCommodity(), quantity: randomQuantity() }, + { id: randomId(), commodity: randomCommodity(), quantity: null }, + { id: randomId(), commodity: randomCommodity(), quantity: randomQuantity() }, + { id: randomId(), commodity: randomCommodity(), quantity: null }, + { id: randomId(), commodity: randomCommodity(), quantity: randomQuantity() }, +]; + +export default function GetSortComparator() { + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/sorting/GetSortComparator.tsx.preview b/docs/data/data-grid/sorting/GetSortComparator.tsx.preview new file mode 100644 index 0000000000000..6f326f7a9cd17 --- /dev/null +++ b/docs/data/data-grid/sorting/GetSortComparator.tsx.preview @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/sorting/sorting.md b/docs/data/data-grid/sorting/sorting.md index 3b486b634f8df..858cfec142d00 100644 --- a/docs/data/data-grid/sorting/sorting.md +++ b/docs/data/data-grid/sorting/sorting.md @@ -118,6 +118,16 @@ The sorting is based on `isAdmin` and then on `name`, if necessary. It re-uses t {{"demo": "ExtendedSortComparator.js", "bg": "inline", "defaultCodeOpen": false}} +### Asymmetric comparator + +The Data Grid considers the `sortComparator` function symmetric, automatically reversing the return value for descending sorting by multiplying it by `-1`. + +While this is sufficient for most use cases, it is possible to define an asymmetric comparator using the `getSortComparator` function – it receives the sorting direction as an argument and returns a comparator function. + +In the demo below, the `getSortComparator` function is used in the "Quantity" column to keep the `null` values at the bottom when sorting is applied (regardless of the sorting direction): + +{{"demo": "GetSortComparator.js", "bg": "inline", "defaultCodeOpen": false}} + ## Custom sort order By default, the sort order cycles between these three different modes: diff --git a/docs/data/data-grid/style-recipes/ColumnHeaderHideSeparator.js b/docs/data/data-grid/style-recipes/ColumnHeaderHideSeparator.js new file mode 100644 index 0000000000000..dee2d4bd41587 --- /dev/null +++ b/docs/data/data-grid/style-recipes/ColumnHeaderHideSeparator.js @@ -0,0 +1,44 @@ +import * as React from 'react'; +import { DataGridPro, gridClasses } from '@mui/x-data-grid-pro'; + +const rows = [ + { + id: 1, + username: '@MUI', + age: 20, + }, +]; + +const columns = [ + { + field: 'id', + }, + { + field: 'username', + width: 200, + resizable: false, + }, + { + field: 'age', + width: 100, + resizable: false, + }, +]; + +export default function ColumnHeaderHideSeparator() { + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/style-recipes/ColumnHeaderHideSeparator.tsx b/docs/data/data-grid/style-recipes/ColumnHeaderHideSeparator.tsx new file mode 100644 index 0000000000000..960c554ed66ce --- /dev/null +++ b/docs/data/data-grid/style-recipes/ColumnHeaderHideSeparator.tsx @@ -0,0 +1,44 @@ +import * as React from 'react'; +import { DataGridPro, GridColDef, gridClasses } from '@mui/x-data-grid-pro'; + +const rows = [ + { + id: 1, + username: '@MUI', + age: 20, + }, +]; + +const columns: GridColDef[] = [ + { + field: 'id', + }, + { + field: 'username', + width: 200, + resizable: false, + }, + { + field: 'age', + width: 100, + resizable: false, + }, +]; + +export default function ColumnHeaderHideSeparator() { + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/style-recipes/ColumnHeaderHideSeparator.tsx.preview b/docs/data/data-grid/style-recipes/ColumnHeaderHideSeparator.tsx.preview new file mode 100644 index 0000000000000..8411416b6d507 --- /dev/null +++ b/docs/data/data-grid/style-recipes/ColumnHeaderHideSeparator.tsx.preview @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/style-recipes/style-recipes.md b/docs/data/data-grid/style-recipes/style-recipes.md index 4aa1485c560ca..23cbd060e11f9 100644 --- a/docs/data/data-grid/style-recipes/style-recipes.md +++ b/docs/data/data-grid/style-recipes/style-recipes.md @@ -13,6 +13,17 @@ Removing the visible `focus` state hurts the accessibility of the grid. {{"demo": "CellFocusNoOutline.js", "bg": "inline", "defaultCodeOpen": false}} +## Remove drag handle for columns that are not resizeable + +In the MUI Data Grid, each column has a resize handle that allows users to adjust the width of the column. +However, there might be cases where you want to disable this feature for certain columns. + +To hide the drag handles on columns that are not resizable, you can use the resizable property in the GridColDef object. +When the column is not resizable, the drag handle will not have the `columnSeparator--resizable` class. +We can use that to hide the separator. + +{{"demo": "ColumnHeaderHideSeparator.js", "bg": "inline", "defaultCodeOpen": false}} + ## Styling Cells without impacting aggregation cells [](/x/introduction/licensing/#premium-plan 'Premium plan') Aggregation cells do not receive a special class, so styling cells without impacting them needs a small workaround in the `getClassName` function. diff --git a/docs/data/date-pickers/custom-field/PickerWithBrowserField.js b/docs/data/date-pickers/custom-field/BrowserV6Field.js similarity index 89% rename from docs/data/date-pickers/custom-field/PickerWithBrowserField.js rename to docs/data/date-pickers/custom-field/BrowserV6Field.js index b5a8aa1a476a6..f3a8f6cc98d17 100644 --- a/docs/data/date-pickers/custom-field/PickerWithBrowserField.js +++ b/docs/data/date-pickers/custom-field/BrowserV6Field.js @@ -10,6 +10,8 @@ import { useClearableField } from '@mui/x-date-pickers/hooks'; const BrowserField = React.forwardRef((props, ref) => { const { + // Should be ignored + enableAccessibleFieldDOMStructure, disabled, id, label, @@ -41,7 +43,10 @@ const BrowserField = React.forwardRef((props, ref) => { const BrowserDateField = React.forwardRef((props, ref) => { const { slots, slotProps, ...textFieldProps } = props; - const fieldResponse = useDateField(textFieldProps); + 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({ @@ -63,7 +68,7 @@ const BrowserDatePicker = React.forwardRef((props, ref) => { ); }); -export default function PickerWithBrowserField() { +export default function BrowserV6Field() { return ( , 'size'> { @@ -29,6 +29,7 @@ interface BrowserFieldProps focused?: boolean; ownerState?: any; sx?: any; + enableAccessibleFieldDOMStructure: boolean; } type BrowserFieldComponent = (( @@ -38,6 +39,9 @@ type BrowserFieldComponent = (( const BrowserField = React.forwardRef( (props: BrowserFieldProps, ref: React.Ref) => { const { + // Should be ignored + enableAccessibleFieldDOMStructure, + disabled, id, label, @@ -68,11 +72,12 @@ const BrowserField = React.forwardRef( ) as BrowserFieldComponent; interface BrowserDateFieldProps - extends UseDateFieldProps, + extends UseDateFieldProps, BaseSingleInputFieldProps< Dayjs | null, Dayjs, FieldSection, + false, DateValidationError > {} @@ -80,7 +85,10 @@ const BrowserDateField = React.forwardRef( (props: BrowserDateFieldProps, ref: React.Ref) => { const { slots, slotProps, ...textFieldProps } = props; - const fieldResponse = useDateField(textFieldProps); + 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({ @@ -94,9 +102,9 @@ const BrowserDateField = React.forwardRef( ); const BrowserDatePicker = React.forwardRef( - (props: DatePickerProps, ref: React.Ref) => { + (props: DatePickerProps, ref: React.Ref) => { return ( - ref={ref} {...props} slots={{ ...props.slots, field: BrowserDateField }} @@ -105,7 +113,7 @@ const BrowserDatePicker = React.forwardRef( }, ); -export default function PickerWithBrowserField() { +export default function BrowserV6Field() { return ( { const { + // Should be ignored + enableAccessibleFieldDOMStructure, disabled, id, label, @@ -57,6 +59,8 @@ const BrowserMultiInputDateRangeField = React.forwardRef((props, ref) => { selectedSections, onSelectedSectionsChange, className, + unstableStartFieldRef, + unstableEndFieldRef, } = props; const startTextFieldProps = useSlotProps({ @@ -87,9 +91,12 @@ const BrowserMultiInputDateRangeField = React.forwardRef((props, ref) => { disablePast, selectedSections, onSelectedSectionsChange, + enableAccessibleFieldDOMStructure: false, }, startTextFieldProps, endTextFieldProps, + unstableStartFieldRef, + unstableEndFieldRef, }); return ( @@ -117,7 +124,7 @@ const BrowserDateRangePicker = React.forwardRef((props, ref) => { ); }); -export default function RangePickerWithBrowserField() { +export default function BrowserV6MultiInputRangeField() { return ( diff --git a/docs/data/date-pickers/custom-field/RangePickerWithBrowserField.tsx b/docs/data/date-pickers/custom-field/BrowserV6MultiInputRangeField.tsx similarity index 88% rename from docs/data/date-pickers/custom-field/RangePickerWithBrowserField.tsx rename to docs/data/date-pickers/custom-field/BrowserV6MultiInputRangeField.tsx index 2bdd06ef5d0c5..78049576322c3 100644 --- a/docs/data/date-pickers/custom-field/RangePickerWithBrowserField.tsx +++ b/docs/data/date-pickers/custom-field/BrowserV6MultiInputRangeField.tsx @@ -15,10 +15,10 @@ import { BaseMultiInputFieldProps, DateRange, DateRangeValidationError, - UseDateRangeFieldProps, MultiInputFieldSlotTextFieldProps, RangeFieldSection, -} from '@mui/x-date-pickers-pro'; +} from '@mui/x-date-pickers-pro/models'; +import { UseDateRangeFieldProps } from '@mui/x-date-pickers-pro'; interface BrowserFieldProps extends Omit, 'size'> { @@ -33,6 +33,7 @@ interface BrowserFieldProps focused?: boolean; ownerState?: any; sx?: any; + enableAccessibleFieldDOMStructure: boolean; } type BrowserFieldComponent = (( @@ -42,6 +43,9 @@ type BrowserFieldComponent = (( const BrowserField = React.forwardRef( (props: BrowserFieldProps, ref: React.Ref) => { const { + // Should be ignored + enableAccessibleFieldDOMStructure, + disabled, id, label, @@ -72,11 +76,12 @@ const BrowserField = React.forwardRef( ) as BrowserFieldComponent; interface BrowserMultiInputDateRangeFieldProps - extends UseDateRangeFieldProps, + extends UseDateRangeFieldProps, BaseMultiInputFieldProps< DateRange, Dayjs, RangeFieldSection, + false, DateRangeValidationError > {} @@ -103,6 +108,8 @@ const BrowserMultiInputDateRangeField = React.forwardRef( selectedSections, onSelectedSectionsChange, className, + unstableStartFieldRef, + unstableEndFieldRef, } = props; const startTextFieldProps = useSlotProps({ @@ -119,6 +126,7 @@ const BrowserMultiInputDateRangeField = React.forwardRef( const fieldResponse = useMultiInputDateRangeField< Dayjs, + false, MultiInputFieldSlotTextFieldProps >({ sharedProps: { @@ -136,9 +144,12 @@ const BrowserMultiInputDateRangeField = React.forwardRef( disablePast, selectedSections, onSelectedSectionsChange, + enableAccessibleFieldDOMStructure: false, }, startTextFieldProps, endTextFieldProps, + unstableStartFieldRef, + unstableEndFieldRef, }); return ( @@ -158,7 +169,7 @@ const BrowserMultiInputDateRangeField = React.forwardRef( ) as BrowserMultiInputDateRangeFieldComponent; const BrowserDateRangePicker = React.forwardRef( - (props: DateRangePickerProps, ref: React.Ref) => { + (props: DateRangePickerProps, ref: React.Ref) => { return ( diff --git a/docs/data/date-pickers/custom-field/RangePickerWithBrowserField.tsx.preview b/docs/data/date-pickers/custom-field/BrowserV6MultiInputRangeField.tsx.preview similarity index 100% rename from docs/data/date-pickers/custom-field/RangePickerWithBrowserField.tsx.preview rename to docs/data/date-pickers/custom-field/BrowserV6MultiInputRangeField.tsx.preview diff --git a/docs/data/date-pickers/custom-field/RangePickerWithSingleInputBrowserField.js b/docs/data/date-pickers/custom-field/BrowserV6SingleInputRangeField.js similarity index 92% rename from docs/data/date-pickers/custom-field/RangePickerWithSingleInputBrowserField.js rename to docs/data/date-pickers/custom-field/BrowserV6SingleInputRangeField.js index a3f68577c8587..5761a6ea83bd0 100644 --- a/docs/data/date-pickers/custom-field/RangePickerWithSingleInputBrowserField.js +++ b/docs/data/date-pickers/custom-field/BrowserV6SingleInputRangeField.js @@ -14,6 +14,8 @@ import { useClearableField } from '@mui/x-date-pickers/hooks'; const BrowserField = React.forwardRef((props, ref) => { const { + // Should be ignored + enableAccessibleFieldDOMStructure, disabled, id, label, @@ -63,7 +65,10 @@ const BrowserSingleInputDateRangeField = React.forwardRef((props, ref) => { ), }; - const fieldResponse = useSingleInputDateRangeField(textFieldProps); + 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({ @@ -113,7 +118,7 @@ const BrowserSingleInputDateRangePicker = React.forwardRef((props, ref) => { ); }); -export default function RangePickerWithSingleInputBrowserField() { +export default function BrowserV6SingleInputRangeField() { return ( , 'size'> { @@ -31,6 +39,7 @@ interface BrowserFieldProps focused?: boolean; ownerState?: any; sx?: any; + enableAccessibleFieldDOMStructure: boolean; } type BrowserFieldComponent = (( @@ -40,6 +49,9 @@ type BrowserFieldComponent = (( const BrowserField = React.forwardRef( (props: BrowserFieldProps, ref: React.Ref) => { const { + // Should be ignored + enableAccessibleFieldDOMStructure, + disabled, id, label, @@ -70,27 +82,32 @@ const BrowserField = React.forwardRef( ) as BrowserFieldComponent; interface BrowserSingleInputDateRangeFieldProps - extends SingleInputDateRangeFieldProps< - Dayjs, - Omit, 'size'> - > { + extends UseSingleInputDateRangeFieldProps, + BaseSingleInputFieldProps< + DateRange, + Dayjs, + RangeFieldSection, + false, + DateRangeValidationError + > { onAdornmentClick?: () => void; } type BrowserSingleInputDateRangeFieldComponent = (( props: BrowserSingleInputDateRangeFieldProps & React.RefAttributes, -) => React.JSX.Element) & { fieldType?: string }; +) => React.JSX.Element) & { fieldType?: FieldType }; const BrowserSingleInputDateRangeField = React.forwardRef( (props: BrowserSingleInputDateRangeFieldProps, ref: React.Ref) => { const { slots, slotProps, onAdornmentClick, ...other } = props; - const textFieldProps: SingleInputDateRangeFieldProps = useSlotProps({ - elementType: 'input', - externalSlotProps: slotProps?.textField, - externalForwardedProps: other, - ownerState: props as any, - }); + const textFieldProps: SingleInputDateRangeFieldProps = + useSlotProps({ + elementType: 'input', + externalSlotProps: slotProps?.textField, + externalForwardedProps: other, + ownerState: props as any, + }); textFieldProps.InputProps = { ...textFieldProps.InputProps, @@ -103,9 +120,11 @@ const BrowserSingleInputDateRangeField = React.forwardRef( ), }; - const fieldResponse = useSingleInputDateRangeField( - textFieldProps, - ); + const fieldResponse = useSingleInputDateRangeField< + Dayjs, + false, + typeof textFieldProps + >({ ...textFieldProps, enableAccessibleFieldDOMStructure: false }); /* If you don't need a clear button, you can skip the use of this hook */ const processedFieldProps = useClearableField({ @@ -158,7 +177,7 @@ const BrowserSingleInputDateRangePicker = React.forwardRef( }, ); -export default function RangePickerWithSingleInputBrowserField() { +export default function BrowserV6SingleInputRangeField() { return ( { + const { + // Should be ignored + enableAccessibleFieldDOMStructure, + // Should be passed to the PickersSectionList component + elements, + sectionListRef, + contentEditable, + onFocus, + onBlur, + tabIndex, + onInput, + onPaste, + onKeyDown, + // Can be passed to a hidden element + onChange, + value, + // Can be used to render a custom label + label, + // Can be used to style the component + areAllSectionsEmpty, + disabled, + readOnly, + focused, + error, + InputProps: { ref: InputPropsRef, startAdornment, endAdornment } = {}, + // The rest can be passed to the root element + ...other + } = props; + + const handleRef = useForkRef(InputPropsRef, ref); + + return ( + + {startAdornment} + + + + {endAdornment} + + ); +}); + +const BrowserDateField = React.forwardRef((props, ref) => { + const { slots, slotProps, ...textFieldProps } = props; + + const fieldResponse = useDateField({ + ...textFieldProps, + enableAccessibleFieldDOMStructure: true, + }); + + /* If you don't need a clear button, you can skip the use of this hook */ + const processedFieldProps = useClearableField({ + ...fieldResponse, + slots, + slotProps, + }); + + return ; +}); + +const BrowserDatePicker = React.forwardRef((props, ref) => { + return ( + + ); +}); + +export default function BrowserV7Field() { + return ( + + + + ); +} diff --git a/docs/data/date-pickers/custom-field/BrowserV7Field.tsx b/docs/data/date-pickers/custom-field/BrowserV7Field.tsx new file mode 100644 index 0000000000000..a84e535d4340a --- /dev/null +++ b/docs/data/date-pickers/custom-field/BrowserV7Field.tsx @@ -0,0 +1,156 @@ +import * as React from 'react'; +import { Dayjs } from 'dayjs'; +import useForkRef from '@mui/utils/useForkRef'; +import { styled } from '@mui/material/styles'; +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 { + BaseSingleInputPickersTextFieldProps, + BaseSingleInputFieldProps, + DateValidationError, + FieldSection, +} from '@mui/x-date-pickers/models'; +import { Unstable_PickersSectionList as PickersSectionList } from '@mui/x-date-pickers/PickersSectionList'; + +const BrowserFieldRoot = styled('div', { name: 'BrowserField', slot: 'Root' })({ + display: 'flex', + alignItems: 'center', +}); + +const BrowserFieldContent = styled('div', { name: 'BrowserField', slot: 'Content' })( + { + border: '1px solid grey', + fontSize: 13.33333, + lineHeight: 'normal', + padding: '1px 2px', + whiteSpace: 'nowrap', + }, +); + +interface BrowserTextFieldProps + extends BaseSingleInputPickersTextFieldProps, + Omit< + React.HTMLAttributes, + keyof BaseSingleInputPickersTextFieldProps + > {} + +const BrowserTextField = React.forwardRef( + (props: BrowserTextFieldProps, ref: React.Ref) => { + const { + // Should be ignored + enableAccessibleFieldDOMStructure, + + // Should be passed to the PickersSectionList component + elements, + sectionListRef, + contentEditable, + onFocus, + onBlur, + tabIndex, + onInput, + onPaste, + onKeyDown, + + // Can be passed to a hidden element + onChange, + value, + + // Can be used to render a custom label + label, + + // Can be used to style the component + areAllSectionsEmpty, + disabled, + readOnly, + focused, + error, + + InputProps: { ref: InputPropsRef, startAdornment, endAdornment } = {}, + + // The rest can be passed to the root element + ...other + } = props; + + const handleRef = useForkRef(InputPropsRef, ref); + + return ( + + {startAdornment} + + + + {endAdornment} + + ); + }, +); + +interface BrowserDateFieldProps + extends UseDateFieldProps, + BaseSingleInputFieldProps< + Dayjs | null, + Dayjs, + FieldSection, + true, + DateValidationError + > {} + +const BrowserDateField = React.forwardRef( + (props: BrowserDateFieldProps, ref: React.Ref) => { + const { slots, slotProps, ...textFieldProps } = props; + + const fieldResponse = useDateField({ + ...textFieldProps, + enableAccessibleFieldDOMStructure: true, + }); + + /* 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 ( + + ); + }, +); + +export default function BrowserV7Field() { + return ( + + + + ); +} diff --git a/docs/data/date-pickers/custom-field/BrowserV7Field.tsx.preview b/docs/data/date-pickers/custom-field/BrowserV7Field.tsx.preview new file mode 100644 index 0000000000000..0bb9e399d3cb4 --- /dev/null +++ b/docs/data/date-pickers/custom-field/BrowserV7Field.tsx.preview @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.js b/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.js new file mode 100644 index 0000000000000..76d9cceb5c6aa --- /dev/null +++ b/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.js @@ -0,0 +1,172 @@ +import * as React from 'react'; + +import useForkRef from '@mui/utils/useForkRef'; +import { useSlotProps } from '@mui/base/utils'; +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'; + +const BrowserFieldRoot = styled('div', { name: 'BrowserField', slot: 'Root' })({ + display: 'flex', + alignItems: 'center', +}); + +const BrowserFieldContent = styled('div', { name: 'BrowserField', slot: 'Content' })( + { + border: '1px solid grey', + fontSize: 13.33333, + lineHeight: 'normal', + padding: '1px 2px', + whiteSpace: 'nowrap', + }, +); + +// 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 + enableAccessibleFieldDOMStructure, + // Should be passed to the PickersSectionList component + elements, + sectionListRef, + contentEditable, + onFocus, + onBlur, + tabIndex, + onInput, + onPaste, + onKeyDown, + // Can be passed to a hidden element + onChange, + value, + // Can be used to render a custom label + label, + // Can be used to style the component + areAllSectionsEmpty, + disabled, + readOnly, + focused, + error, + InputProps: { ref: InputPropsRef, startAdornment, endAdornment } = {}, + // The rest can be passed to the root element + ...other + } = props; + + const handleRef = useForkRef(InputPropsRef, ref); + + return ( + + {startAdornment} + + + + {endAdornment} + + ); +}); + +const BrowserMultiInputDateRangeField = React.forwardRef((props, ref) => { + const { + slotProps, + value, + defaultValue, + format, + onChange, + readOnly, + disabled, + onError, + shouldDisableDate, + minDate, + maxDate, + disableFuture, + disablePast, + selectedSections, + onSelectedSectionsChange, + className, + unstableStartFieldRef, + unstableEndFieldRef, + } = props; + + const startTextFieldProps = useSlotProps({ + elementType: 'input', + externalSlotProps: slotProps?.textField, + ownerState: { ...props, position: 'start' }, + }); + + const endTextFieldProps = useSlotProps({ + elementType: 'input', + externalSlotProps: slotProps?.textField, + ownerState: { ...props, position: 'end' }, + }); + + const fieldResponse = useMultiInputDateRangeField({ + sharedProps: { + value, + defaultValue, + format, + onChange, + readOnly, + disabled, + onError, + shouldDisableDate, + minDate, + maxDate, + disableFuture, + disablePast, + selectedSections, + onSelectedSectionsChange, + enableAccessibleFieldDOMStructure: true, + }, + startTextFieldProps, + endTextFieldProps, + unstableStartFieldRef, + unstableEndFieldRef, + }); + + return ( + + + + + + ); +}); + +const BrowserDateRangePicker = React.forwardRef((props, ref) => { + return ( + + ); +}); + +export default function BrowserV7MultiInputRangeField() { + return ( + + + + ); +} diff --git a/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx b/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx new file mode 100644 index 0000000000000..09e0c7eda30c6 --- /dev/null +++ b/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx @@ -0,0 +1,221 @@ +import * as React from 'react'; +import { Dayjs } from 'dayjs'; +import useForkRef from '@mui/utils/useForkRef'; +import { useSlotProps } from '@mui/base/utils'; +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, + 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, +} from '@mui/x-date-pickers-pro/models'; +import { UseDateRangeFieldProps } from '@mui/x-date-pickers-pro'; + +const BrowserFieldRoot = styled('div', { name: 'BrowserField', slot: 'Root' })({ + display: 'flex', + alignItems: 'center', +}); + +const BrowserFieldContent = styled('div', { name: 'BrowserField', slot: 'Content' })( + { + border: '1px solid grey', + fontSize: 13.33333, + lineHeight: 'normal', + padding: '1px 2px', + whiteSpace: 'nowrap', + }, +); + +interface BrowserTextFieldProps + extends BasePickersTextFieldProps, + Omit< + React.HTMLAttributes, + keyof BasePickersTextFieldProps + > {} + +// 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 { + // Should be ignored + enableAccessibleFieldDOMStructure, + + // Should be passed to the PickersSectionList component + elements, + sectionListRef, + contentEditable, + onFocus, + onBlur, + tabIndex, + onInput, + onPaste, + onKeyDown, + + // Can be passed to a hidden element + onChange, + value, + + // Can be used to render a custom label + label, + + // Can be used to style the component + areAllSectionsEmpty, + disabled, + readOnly, + focused, + error, + + InputProps: { ref: InputPropsRef, startAdornment, endAdornment } = {}, + + // The rest can be passed to the root element + ...other + } = props; + + const handleRef = useForkRef(InputPropsRef, ref); + + return ( + + {startAdornment} + + + + {endAdornment} + + ); + }, +); + +interface BrowserMultiInputDateRangeFieldProps + extends UseDateRangeFieldProps, + BaseMultiInputFieldProps< + DateRange, + Dayjs, + RangeFieldSection, + true, + DateRangeValidationError + > {} + +type BrowserMultiInputDateRangeFieldComponent = (( + props: BrowserMultiInputDateRangeFieldProps & React.RefAttributes, +) => React.JSX.Element) & { propTypes?: any }; + +const BrowserMultiInputDateRangeField = React.forwardRef( + (props: BrowserMultiInputDateRangeFieldProps, ref: React.Ref) => { + const { + slotProps, + value, + defaultValue, + format, + onChange, + readOnly, + disabled, + onError, + shouldDisableDate, + minDate, + maxDate, + disableFuture, + disablePast, + selectedSections, + onSelectedSectionsChange, + className, + unstableStartFieldRef, + unstableEndFieldRef, + } = props; + + const startTextFieldProps = useSlotProps({ + elementType: 'input', + externalSlotProps: slotProps?.textField, + ownerState: { ...props, position: 'start' }, + }) as MultiInputFieldSlotTextFieldProps; + + const endTextFieldProps = useSlotProps({ + elementType: 'input', + externalSlotProps: slotProps?.textField, + ownerState: { ...props, position: 'end' }, + }) as MultiInputFieldSlotTextFieldProps; + + const fieldResponse = useMultiInputDateRangeField< + Dayjs, + true, + MultiInputFieldSlotTextFieldProps + >({ + sharedProps: { + value, + defaultValue, + format, + onChange, + readOnly, + disabled, + onError, + shouldDisableDate, + minDate, + maxDate, + disableFuture, + disablePast, + selectedSections, + onSelectedSectionsChange, + enableAccessibleFieldDOMStructure: true, + }, + startTextFieldProps, + endTextFieldProps, + unstableStartFieldRef, + unstableEndFieldRef, + }); + + return ( + + + + + + ); + }, +) as BrowserMultiInputDateRangeFieldComponent; + +const BrowserDateRangePicker = React.forwardRef( + (props: DateRangePickerProps, ref: React.Ref) => { + return ( + + ); + }, +); + +export default function BrowserV7MultiInputRangeField() { + return ( + + + + ); +} diff --git a/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx.preview b/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx.preview new file mode 100644 index 0000000000000..d797406fa9997 --- /dev/null +++ b/docs/data/date-pickers/custom-field/BrowserV7MultiInputRangeField.tsx.preview @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.js b/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.js new file mode 100644 index 0000000000000..2eeede71d126d --- /dev/null +++ b/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.js @@ -0,0 +1,168 @@ +import * as React from 'react'; + +import useForkRef from '@mui/utils/useForkRef'; +import { useSlotProps } from '@mui/base/utils'; +import { styled } from '@mui/material/styles'; +import IconButton from '@mui/material/IconButton'; +import InputAdornment from '@mui/material/InputAdornment'; +import { DateRangeIcon } from '@mui/x-date-pickers/icons'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { DateRangePicker } from '@mui/x-date-pickers-pro/DateRangePicker'; +import { unstable_useSingleInputDateRangeField as useSingleInputDateRangeField } from '@mui/x-date-pickers-pro/SingleInputDateRangeField'; +import { useClearableField } from '@mui/x-date-pickers/hooks'; +import { Unstable_PickersSectionList as PickersSectionList } from '@mui/x-date-pickers/PickersSectionList'; + +const BrowserFieldRoot = styled('div', { name: 'BrowserField', slot: 'Root' })({ + display: 'flex', + alignItems: 'center', +}); + +const BrowserFieldContent = styled('div', { name: 'BrowserField', slot: 'Content' })( + { + border: '1px solid grey', + fontSize: 13.33333, + lineHeight: 'normal', + padding: '1px 2px', + whiteSpace: 'nowrap', + }, +); + +const BrowserTextField = React.forwardRef((props, ref) => { + const { + // Should be ignored + enableAccessibleFieldDOMStructure, + // Should be passed to the PickersSectionList component + elements, + sectionListRef, + contentEditable, + onFocus, + onBlur, + tabIndex, + onInput, + onPaste, + onKeyDown, + // Can be passed to a hidden element + onChange, + value, + // Can be used to render a custom label + label, + // Can be used to style the component + areAllSectionsEmpty, + disabled, + readOnly, + focused, + error, + InputProps: { ref: InputPropsRef, startAdornment, endAdornment } = {}, + // The rest can be passed to the root element + ...other + } = props; + + 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: ( + + + + + + ), + }; + + const fieldResponse = useSingleInputDateRangeField({ + ...textFieldProps, + enableAccessibleFieldDOMStructure: true, + }); + + /* If you don't need a clear button, you can skip the use of this hook */ + const processedFieldProps = useClearableField({ + ...fieldResponse, + slots, + slotProps, + }); + + return ( + + ); +}); + +BrowserSingleInputDateRangeField.fieldType = 'single-input'; + +const BrowserSingleInputDateRangePicker = React.forwardRef((props, ref) => { + const [isOpen, setIsOpen] = React.useState(false); + + const toggleOpen = () => setIsOpen((currentOpen) => !currentOpen); + + const handleOpen = () => setIsOpen(true); + + const handleClose = () => setIsOpen(false); + + return ( + + ); +}); + +export default function BrowserV7SingleInputRangeField() { + return ( + + + + ); +} diff --git a/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.tsx b/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.tsx new file mode 100644 index 0000000000000..eac9ebb26854a --- /dev/null +++ b/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.tsx @@ -0,0 +1,218 @@ +import * as React from 'react'; +import { Dayjs } from 'dayjs'; +import useForkRef from '@mui/utils/useForkRef'; +import { useSlotProps } from '@mui/base/utils'; +import { styled } from '@mui/material/styles'; +import IconButton from '@mui/material/IconButton'; +import InputAdornment from '@mui/material/InputAdornment'; +import { DateRangeIcon } from '@mui/x-date-pickers/icons'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { + DateRangePicker, + DateRangePickerProps, +} from '@mui/x-date-pickers-pro/DateRangePicker'; +import { + unstable_useSingleInputDateRangeField as useSingleInputDateRangeField, + UseSingleInputDateRangeFieldProps, +} from '@mui/x-date-pickers-pro/SingleInputDateRangeField'; +import { useClearableField } 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 } from '@mui/x-date-pickers'; + +const BrowserFieldRoot = styled('div', { name: 'BrowserField', slot: 'Root' })({ + display: 'flex', + alignItems: 'center', +}); + +const BrowserFieldContent = styled('div', { name: 'BrowserField', slot: 'Content' })( + { + border: '1px solid grey', + fontSize: 13.33333, + lineHeight: 'normal', + padding: '1px 2px', + whiteSpace: 'nowrap', + }, +); + +interface BrowserTextFieldProps + extends BasePickersTextFieldProps, + Omit< + React.HTMLAttributes, + keyof BasePickersTextFieldProps + > {} + +const BrowserTextField = React.forwardRef( + (props: BrowserTextFieldProps, ref: React.Ref) => { + const { + // Should be ignored + enableAccessibleFieldDOMStructure, + + // Should be passed to the PickersSectionList component + elements, + sectionListRef, + contentEditable, + onFocus, + onBlur, + tabIndex, + onInput, + onPaste, + onKeyDown, + + // Can be passed to a hidden element + onChange, + value, + + // Can be used to render a custom label + label, + + // Can be used to style the component + areAllSectionsEmpty, + disabled, + readOnly, + focused, + error, + + InputProps: { ref: InputPropsRef, startAdornment, endAdornment } = {}, + + // The rest can be passed to the root element + ...other + } = props; + + const handleRef = useForkRef(InputPropsRef, ref); + + return ( + + {startAdornment} + + + + {endAdornment} + + ); + }, +); + +interface BrowserSingleInputDateRangeFieldProps + extends UseSingleInputDateRangeFieldProps, + BaseSingleInputFieldProps< + DateRange, + Dayjs, + 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: ( + + + + + + ), + }; + + const fieldResponse = useSingleInputDateRangeField< + Dayjs, + true, + typeof textFieldProps + >({ ...textFieldProps, enableAccessibleFieldDOMStructure: true }); + + /* If you don't need a clear button, you can skip the use of this hook */ + const processedFieldProps = useClearableField({ + ...fieldResponse, + slots, + slotProps, + }); + + return ( + + ); + }, +) as BrowserSingleInputDateRangeFieldComponent; + +BrowserSingleInputDateRangeField.fieldType = 'single-input'; + +const BrowserSingleInputDateRangePicker = React.forwardRef( + (props: DateRangePickerProps, ref: React.Ref) => { + const [isOpen, setIsOpen] = React.useState(false); + + const toggleOpen = () => setIsOpen((currentOpen) => !currentOpen); + + const handleOpen = () => setIsOpen(true); + + const handleClose = () => setIsOpen(false); + + return ( + + ); + }, +); + +export default function BrowserV7SingleInputRangeField() { + return ( + + + + ); +} diff --git a/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.tsx.preview b/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.tsx.preview new file mode 100644 index 0000000000000..bcaf8043948fb --- /dev/null +++ b/docs/data/date-pickers/custom-field/BrowserV7SingleInputRangeField.tsx.preview @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/docs/data/date-pickers/custom-field/DateRangePickerWithButtonField.tsx b/docs/data/date-pickers/custom-field/DateRangePickerWithButtonField.tsx index 3268f758c80f8..1b894f55e6a15 100644 --- a/docs/data/date-pickers/custom-field/DateRangePickerWithButtonField.tsx +++ b/docs/data/date-pickers/custom-field/DateRangePickerWithButtonField.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { Dayjs } from 'dayjs'; import Button from '@mui/material/Button'; import useForkRef from '@mui/utils/useForkRef'; -import { DateRange } from '@mui/x-date-pickers-pro/models'; +import { DateRange, FieldType } from '@mui/x-date-pickers-pro/models'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { @@ -17,10 +17,10 @@ interface DateRangeButtonFieldProps extends SingleInputDateRangeFieldProps, -) => React.JSX.Element) & { fieldType?: string }; +) => React.JSX.Element) & { fieldType?: FieldType }; const DateRangeButtonField = React.forwardRef( - (props: DateRangeButtonFieldProps, ref: React.Ref) => { + (props: DateRangeButtonFieldProps, ref: React.Ref) => { const { setOpen, label, diff --git a/docs/data/date-pickers/custom-field/PickerWithJoyField.js b/docs/data/date-pickers/custom-field/JoyV6Field.js similarity index 92% rename from docs/data/date-pickers/custom-field/PickerWithJoyField.js rename to docs/data/date-pickers/custom-field/JoyV6Field.js index c685d14d25b9c..29f4e14ce2918 100644 --- a/docs/data/date-pickers/custom-field/PickerWithJoyField.js +++ b/docs/data/date-pickers/custom-field/JoyV6Field.js @@ -24,6 +24,8 @@ const joyTheme = extendJoyTheme(); const JoyField = React.forwardRef((props, ref) => { const { + // Should be ignored + enableAccessibleFieldDOMStructure, disabled, id, label, @@ -73,7 +75,10 @@ const JoyField = React.forwardRef((props, ref) => { const JoyDateField = React.forwardRef((props, ref) => { const { slots, slotProps, ...textFieldProps } = props; - const fieldResponse = useDateField(textFieldProps); + 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({ @@ -82,7 +87,7 @@ const JoyDateField = React.forwardRef((props, ref) => { slotProps, }); - return ; + return ; }); const JoyDatePicker = React.forwardRef((props, ref) => { @@ -118,7 +123,7 @@ function SyncThemeMode({ mode }) { return null; } -export default function PickerWithJoyField() { +export default function JoyV6Field() { const materialTheme = useMaterialTheme(); return ( diff --git a/docs/data/date-pickers/custom-field/PickerWithJoyField.tsx b/docs/data/date-pickers/custom-field/JoyV6Field.tsx similarity index 89% rename from docs/data/date-pickers/custom-field/PickerWithJoyField.tsx rename to docs/data/date-pickers/custom-field/JoyV6Field.tsx index 306a5adec5f66..05c311984ebf4 100644 --- a/docs/data/date-pickers/custom-field/PickerWithJoyField.tsx +++ b/docs/data/date-pickers/custom-field/JoyV6Field.tsx @@ -33,6 +33,7 @@ const joyTheme = extendJoyTheme(); interface JoyFieldProps extends InputProps { label?: React.ReactNode; inputRef?: React.Ref; + enableAccessibleFieldDOMStructure?: boolean; InputProps?: { ref?: React.Ref; endAdornment?: React.ReactNode; @@ -48,6 +49,9 @@ type JoyFieldComponent = (( const JoyField = React.forwardRef( (props: JoyFieldProps, ref: React.Ref) => { const { + // Should be ignored + enableAccessibleFieldDOMStructure, + disabled, id, label, @@ -96,11 +100,12 @@ const JoyField = React.forwardRef( ) as JoyFieldComponent; interface JoyDateFieldProps - extends UseDateFieldProps, + extends UseDateFieldProps, BaseSingleInputFieldProps< Dayjs | null, Dayjs, FieldSection, + false, DateValidationError > {} @@ -108,7 +113,10 @@ const JoyDateField = React.forwardRef( (props: JoyDateFieldProps, ref: React.Ref) => { const { slots, slotProps, ...textFieldProps } = props; - const fieldResponse = useDateField(textFieldProps); + 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({ @@ -117,12 +125,12 @@ const JoyDateField = React.forwardRef( slotProps, }); - return ; + return ; }, ); const JoyDatePicker = React.forwardRef( - (props: DatePickerProps, ref: React.Ref) => { + (props: DatePickerProps, ref: React.Ref) => { return ( diff --git a/docs/data/date-pickers/custom-field/JoyV6Field.tsx.preview b/docs/data/date-pickers/custom-field/JoyV6Field.tsx.preview new file mode 100644 index 0000000000000..cff735f8a7af0 --- /dev/null +++ b/docs/data/date-pickers/custom-field/JoyV6Field.tsx.preview @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/docs/data/date-pickers/custom-field/RangePickerWithJoyField.js b/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.js similarity index 96% rename from docs/data/date-pickers/custom-field/RangePickerWithJoyField.js rename to docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.js index 200b4229807eb..40b15af9295f9 100644 --- a/docs/data/date-pickers/custom-field/RangePickerWithJoyField.js +++ b/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.js @@ -27,6 +27,8 @@ const joyTheme = extendJoyTheme(); const JoyField = React.forwardRef((props, ref) => { const { + // Should be ignored + enableAccessibleFieldDOMStructure, disabled, id, label, @@ -148,6 +150,7 @@ const JoyMultiInputDateRangeField = React.forwardRef((props, ref) => { disablePast, selectedSections, onSelectedSectionsChange, + enableAccessibleFieldDOMStructure: false, }, startTextFieldProps, endTextFieldProps, @@ -186,7 +189,7 @@ function SyncThemeMode({ mode }) { return null; } -export default function RangePickerWithJoyField() { +export default function JoyV6MultiInputRangeField() { const materialTheme = useMaterialTheme(); return ( diff --git a/docs/data/date-pickers/custom-field/RangePickerWithJoyField.tsx b/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.tsx similarity index 94% rename from docs/data/date-pickers/custom-field/RangePickerWithJoyField.tsx rename to docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.tsx index bf1c1bdd5ca82..0790a3d607365 100644 --- a/docs/data/date-pickers/custom-field/RangePickerWithJoyField.tsx +++ b/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.tsx @@ -29,16 +29,17 @@ import { BaseMultiInputFieldProps, DateRange, DateRangeValidationError, - UseDateRangeFieldProps, MultiInputFieldSlotTextFieldProps, RangeFieldSection, -} from '@mui/x-date-pickers-pro'; +} from '@mui/x-date-pickers-pro/models'; +import { UseDateRangeFieldProps } from '@mui/x-date-pickers-pro'; const joyTheme = extendJoyTheme(); interface JoyFieldProps extends InputProps { label?: React.ReactNode; inputRef?: React.Ref; + enableAccessibleFieldDOMStructure?: boolean; InputProps?: { ref?: React.Ref; endAdornment?: React.ReactNode; @@ -53,6 +54,9 @@ type JoyFieldComponent = (( const JoyField = React.forwardRef( (props: JoyFieldProps, ref: React.Ref) => { const { + // Should be ignored + enableAccessibleFieldDOMStructure, + disabled, id, label, @@ -128,11 +132,12 @@ const MultiInputJoyDateRangeFieldSeparator = styled( )({ marginTop: '25px' }); interface JoyMultiInputDateRangeFieldProps - extends UseDateRangeFieldProps, + extends UseDateRangeFieldProps, BaseMultiInputFieldProps< DateRange, Dayjs, RangeFieldSection, + false, DateRangeValidationError > {} @@ -175,6 +180,7 @@ const JoyMultiInputDateRangeField = React.forwardRef( const fieldResponse = useMultiInputDateRangeField< Dayjs, + false, MultiInputFieldSlotTextFieldProps >({ sharedProps: { @@ -192,6 +198,7 @@ const JoyMultiInputDateRangeField = React.forwardRef( disablePast, selectedSections, onSelectedSectionsChange, + enableAccessibleFieldDOMStructure: false, }, startTextFieldProps, endTextFieldProps, @@ -233,7 +240,7 @@ function SyncThemeMode({ mode }: { mode: 'light' | 'dark' }) { return null; } -export default function RangePickerWithJoyField() { +export default function JoyV6MultiInputRangeField() { const materialTheme = useMaterialTheme(); return ( diff --git a/docs/data/date-pickers/custom-field/RangePickerWithJoyField.tsx.preview b/docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.tsx.preview similarity index 100% rename from docs/data/date-pickers/custom-field/RangePickerWithJoyField.tsx.preview rename to docs/data/date-pickers/custom-field/JoyV6MultiInputRangeField.tsx.preview diff --git a/docs/data/date-pickers/custom-field/RangePickerWithSingleInputJoyField.js b/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.js similarity index 94% rename from docs/data/date-pickers/custom-field/RangePickerWithSingleInputJoyField.js rename to docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.js index 1c8d0719826ed..7183f8d9c4a37 100644 --- a/docs/data/date-pickers/custom-field/RangePickerWithSingleInputJoyField.js +++ b/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.js @@ -27,6 +27,8 @@ const joyTheme = extendJoyTheme(); const JoyField = React.forwardRef((props, ref) => { const { + // Should be ignored + enableAccessibleFieldDOMStructure, disabled, id, label, @@ -77,7 +79,10 @@ const JoySingleInputDateRangeField = React.forwardRef((props, ref) => { ownerState: props, }); - const fieldResponse = useSingleInputDateRangeField(textFieldProps); + 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({ @@ -152,7 +157,7 @@ function SyncThemeMode({ mode }) { return null; } -export default function RangePickerWithSingleInputJoyField() { +export default function JoyV6SingleInputRangeField() { const materialTheme = useMaterialTheme(); return ( diff --git a/docs/data/date-pickers/custom-field/RangePickerWithSingleInputJoyField.tsx b/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.tsx similarity index 84% rename from docs/data/date-pickers/custom-field/RangePickerWithSingleInputJoyField.tsx rename to docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.tsx index 817129b9a4589..d7e26765a1a0b 100644 --- a/docs/data/date-pickers/custom-field/RangePickerWithSingleInputJoyField.tsx +++ b/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.tsx @@ -25,15 +25,23 @@ import { } from '@mui/x-date-pickers-pro/DateRangePicker'; import { unstable_useSingleInputDateRangeField as useSingleInputDateRangeField, - SingleInputDateRangeFieldProps, + UseSingleInputDateRangeFieldProps, } from '@mui/x-date-pickers-pro/SingleInputDateRangeField'; import { useClearableField } from '@mui/x-date-pickers/hooks'; +import { BaseSingleInputFieldProps } from '@mui/x-date-pickers/models'; +import { + RangeFieldSection, + DateRange, + DateRangeValidationError, + FieldType, +} from '@mui/x-date-pickers-pro/models'; const joyTheme = extendJoyTheme(); interface JoyFieldProps extends InputProps { label?: React.ReactNode; inputRef?: React.Ref; + enableAccessibleFieldDOMStructure?: boolean; InputProps?: { ref?: React.Ref; endAdornment?: React.ReactNode; @@ -48,6 +56,9 @@ type JoyFieldComponent = (( const JoyField = React.forwardRef( (props: JoyFieldProps, ref: React.Ref) => { const { + // Should be ignored + enableAccessibleFieldDOMStructure, + disabled, id, label, @@ -90,31 +101,37 @@ const JoyField = React.forwardRef( ) as JoyFieldComponent; interface JoySingleInputDateRangeFieldProps - extends SingleInputDateRangeFieldProps { + extends UseSingleInputDateRangeFieldProps, + BaseSingleInputFieldProps< + DateRange, + Dayjs, + RangeFieldSection, + false, + DateRangeValidationError + > { onAdornmentClick?: () => void; } type JoySingleInputDateRangeFieldComponent = (( props: JoySingleInputDateRangeFieldProps & React.RefAttributes, -) => React.JSX.Element) & { fieldType?: string }; +) => React.JSX.Element) & { fieldType?: FieldType }; const JoySingleInputDateRangeField = React.forwardRef( (props: JoySingleInputDateRangeFieldProps, ref: React.Ref) => { const { slots, slotProps, onAdornmentClick, ...other } = props; - const textFieldProps: SingleInputDateRangeFieldProps< - Dayjs, - JoyFieldProps & { inputRef: React.Ref } - > = useSlotProps({ + const textFieldProps: JoySingleInputDateRangeFieldProps = useSlotProps({ elementType: FormControl, externalSlotProps: slotProps?.textField, externalForwardedProps: other, ownerState: props as any, }); - const fieldResponse = useSingleInputDateRangeField( - textFieldProps, - ); + const fieldResponse = useSingleInputDateRangeField< + Dayjs, + false, + JoySingleInputDateRangeFieldProps + >({ ...textFieldProps, enableAccessibleFieldDOMStructure: false }); /* If you don't need a clear button, you can skip the use of this hook */ const processedFieldProps = useClearableField({ @@ -145,7 +162,7 @@ const JoySingleInputDateRangeField = React.forwardRef( JoySingleInputDateRangeField.fieldType = 'single-input'; const JoySingleInputDateRangePicker = React.forwardRef( - (props: DateRangePickerProps, ref: React.Ref) => { + (props: DateRangePickerProps, ref: React.Ref) => { const [isOpen, setIsOpen] = React.useState(false); const toggleOpen = (event: React.PointerEvent) => { @@ -192,7 +209,7 @@ function SyncThemeMode({ mode }: { mode: 'light' | 'dark' }) { return null; } -export default function RangePickerWithSingleInputJoyField() { +export default function JoyV6SingleInputRangeField() { const materialTheme = useMaterialTheme(); return ( diff --git a/docs/data/date-pickers/custom-field/RangePickerWithSingleInputJoyField.tsx.preview b/docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.tsx.preview similarity index 100% rename from docs/data/date-pickers/custom-field/RangePickerWithSingleInputJoyField.tsx.preview rename to docs/data/date-pickers/custom-field/JoyV6SingleInputRangeField.tsx.preview diff --git a/docs/data/date-pickers/custom-field/MaterialV6Field.js b/docs/data/date-pickers/custom-field/MaterialV6Field.js new file mode 100644 index 0000000000000..35d4e0ca73ead --- /dev/null +++ b/docs/data/date-pickers/custom-field/MaterialV6Field.js @@ -0,0 +1,17 @@ +import * as React from 'react'; +import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DateField } from '@mui/x-date-pickers/DateField'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +export default function MaterialV6Field() { + return ( + + + + + + + ); +} diff --git a/docs/data/date-pickers/custom-field/MaterialV6Field.tsx b/docs/data/date-pickers/custom-field/MaterialV6Field.tsx new file mode 100644 index 0000000000000..35d4e0ca73ead --- /dev/null +++ b/docs/data/date-pickers/custom-field/MaterialV6Field.tsx @@ -0,0 +1,17 @@ +import * as React from 'react'; +import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DateField } from '@mui/x-date-pickers/DateField'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +export default function MaterialV6Field() { + return ( + + + + + + + ); +} diff --git a/docs/data/date-pickers/custom-field/MaterialV6Field.tsx.preview b/docs/data/date-pickers/custom-field/MaterialV6Field.tsx.preview new file mode 100644 index 0000000000000..027cb7beacfac --- /dev/null +++ b/docs/data/date-pickers/custom-field/MaterialV6Field.tsx.preview @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/docs/data/date-pickers/custom-field/MaterialV6FieldWrapped.js b/docs/data/date-pickers/custom-field/MaterialV6FieldWrapped.js new file mode 100644 index 0000000000000..df1b5053a7451 --- /dev/null +++ b/docs/data/date-pickers/custom-field/MaterialV6FieldWrapped.js @@ -0,0 +1,22 @@ +import * as React from 'react'; +import MuiTextField from '@mui/material/TextField'; +import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DateField } from '@mui/x-date-pickers/DateField'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +const TextField = React.forwardRef((props, ref) => ( + +)); + +export default function MaterialV6FieldWrapped() { + return ( + + + + + + + ); +} diff --git a/docs/data/date-pickers/custom-field/MaterialV6FieldWrapped.tsx b/docs/data/date-pickers/custom-field/MaterialV6FieldWrapped.tsx new file mode 100644 index 0000000000000..0c90908a7d4b5 --- /dev/null +++ b/docs/data/date-pickers/custom-field/MaterialV6FieldWrapped.tsx @@ -0,0 +1,24 @@ +import * as React from 'react'; +import MuiTextField, { TextFieldProps } from '@mui/material/TextField'; +import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DateField } from '@mui/x-date-pickers/DateField'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +const TextField = React.forwardRef( + (props: TextFieldProps, ref: React.Ref) => ( + + ), +); + +export default function MaterialV6FieldWrapped() { + return ( + + + + + + + ); +} diff --git a/docs/data/date-pickers/custom-field/MaterialV6FieldWrapped.tsx.preview b/docs/data/date-pickers/custom-field/MaterialV6FieldWrapped.tsx.preview new file mode 100644 index 0000000000000..cd5ff731abbcd --- /dev/null +++ b/docs/data/date-pickers/custom-field/MaterialV6FieldWrapped.tsx.preview @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/docs/data/date-pickers/custom-field/MaterialV7Field.js b/docs/data/date-pickers/custom-field/MaterialV7Field.js new file mode 100644 index 0000000000000..f7c4f157b96a8 --- /dev/null +++ b/docs/data/date-pickers/custom-field/MaterialV7Field.js @@ -0,0 +1,17 @@ +import * as React from 'react'; +import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; +import { DateField } from '@mui/x-date-pickers/DateField'; + +export default function MaterialV7Field() { + return ( + + + + + + + ); +} diff --git a/docs/data/date-pickers/custom-field/MaterialV7Field.tsx b/docs/data/date-pickers/custom-field/MaterialV7Field.tsx new file mode 100644 index 0000000000000..f7c4f157b96a8 --- /dev/null +++ b/docs/data/date-pickers/custom-field/MaterialV7Field.tsx @@ -0,0 +1,17 @@ +import * as React from 'react'; +import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; +import { DateField } from '@mui/x-date-pickers/DateField'; + +export default function MaterialV7Field() { + return ( + + + + + + + ); +} diff --git a/docs/data/date-pickers/custom-field/MaterialV7Field.tsx.preview b/docs/data/date-pickers/custom-field/MaterialV7Field.tsx.preview new file mode 100644 index 0000000000000..9708ed359729e --- /dev/null +++ b/docs/data/date-pickers/custom-field/MaterialV7Field.tsx.preview @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.js b/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.js new file mode 100644 index 0000000000000..d125a8479b5c8 --- /dev/null +++ b/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.js @@ -0,0 +1,28 @@ +import * as React from 'react'; +import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; +import { DateField } from '@mui/x-date-pickers/DateField'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +const MyPickersTextField = React.forwardRef((props, ref) => ( + +)); + +export default function MaterialV7FieldWrapped() { + return ( + + + + + + + ); +} diff --git a/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.tsx b/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.tsx new file mode 100644 index 0000000000000..82e06da7316b3 --- /dev/null +++ b/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.tsx @@ -0,0 +1,33 @@ +import * as React from 'react'; +import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { + PickersTextField, + PickersTextFieldProps, +} from '@mui/x-date-pickers/PickersTextField'; +import { DateField } from '@mui/x-date-pickers/DateField'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +const MyPickersTextField = React.forwardRef( + (props: PickersTextFieldProps, ref: React.Ref) => ( + + ), +); + +export default function MaterialV7FieldWrapped() { + return ( + + + + + + + ); +} diff --git a/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.tsx.preview b/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.tsx.preview new file mode 100644 index 0000000000000..17535291f5f3b --- /dev/null +++ b/docs/data/date-pickers/custom-field/MaterialV7FieldWrapped.tsx.preview @@ -0,0 +1,8 @@ + + \ No newline at end of file diff --git a/docs/data/date-pickers/custom-field/PickerWithAutocompleteField.js b/docs/data/date-pickers/custom-field/PickerWithAutocompleteField.js index 12b3a98d85078..ea7512ace1590 100644 --- a/docs/data/date-pickers/custom-field/PickerWithAutocompleteField.js +++ b/docs/data/date-pickers/custom-field/PickerWithAutocompleteField.js @@ -97,8 +97,8 @@ function AutocompleteDatePicker(props) { return ( !optionsLookup[date.startOf('day').toISOString()]} {...other} /> diff --git a/docs/data/date-pickers/custom-field/PickerWithAutocompleteField.tsx b/docs/data/date-pickers/custom-field/PickerWithAutocompleteField.tsx index 6d5cfc980154a..1aac33d076c0d 100644 --- a/docs/data/date-pickers/custom-field/PickerWithAutocompleteField.tsx +++ b/docs/data/date-pickers/custom-field/PickerWithAutocompleteField.tsx @@ -14,11 +14,12 @@ import { } from '@mui/x-date-pickers/models'; interface AutoCompleteFieldProps - extends UseDateFieldProps, + extends UseDateFieldProps, BaseSingleInputFieldProps< Dayjs | null, Dayjs, FieldSection, + false, DateValidationError > { /** @@ -127,8 +128,8 @@ function AutocompleteDatePicker(props: AutocompleteDatePickerProps) { return ( - slots={{ field: AutocompleteField, ...props.slots }} - slotProps={{ field: { options } as any }} + slots={{ ...props.slots, field: AutocompleteField }} + slotProps={{ ...props.slotProps, field: { options } as any }} shouldDisableDate={(date) => !optionsLookup[date.startOf('day').toISOString()]} {...other} /> diff --git a/docs/data/date-pickers/custom-field/PickerWithButtonField.js b/docs/data/date-pickers/custom-field/PickerWithButtonField.js index 255784386528b..f13ca0315b2bb 100644 --- a/docs/data/date-pickers/custom-field/PickerWithButtonField.js +++ b/docs/data/date-pickers/custom-field/PickerWithButtonField.js @@ -34,8 +34,8 @@ function ButtonDatePicker(props) { return ( setOpen(false)} diff --git a/docs/data/date-pickers/custom-field/PickerWithButtonField.tsx b/docs/data/date-pickers/custom-field/PickerWithButtonField.tsx index c8cfc01a1964e..aa09717fb29ce 100644 --- a/docs/data/date-pickers/custom-field/PickerWithButtonField.tsx +++ b/docs/data/date-pickers/custom-field/PickerWithButtonField.tsx @@ -12,11 +12,12 @@ import { } from '@mui/x-date-pickers/models'; interface ButtonFieldProps - extends UseDateFieldProps, + extends UseDateFieldProps, BaseSingleInputFieldProps< Dayjs | null, Dayjs, FieldSection, + false, DateValidationError > { setOpen?: React.Dispatch>; @@ -53,8 +54,8 @@ function ButtonDatePicker( return ( setOpen(false)} diff --git a/docs/data/date-pickers/custom-field/WrappedSingleInputDateRangePicker.js b/docs/data/date-pickers/custom-field/SingleInputDateRangePickerWrapped.js similarity index 93% rename from docs/data/date-pickers/custom-field/WrappedSingleInputDateRangePicker.js rename to docs/data/date-pickers/custom-field/SingleInputDateRangePickerWrapped.js index 389bd55f5822c..aa20bda0c4275 100644 --- a/docs/data/date-pickers/custom-field/WrappedSingleInputDateRangePicker.js +++ b/docs/data/date-pickers/custom-field/SingleInputDateRangePickerWrapped.js @@ -12,7 +12,7 @@ const WrappedSingleInputDateRangeField = React.forwardRef((props, ref) => { WrappedSingleInputDateRangeField.fieldType = 'single-input'; -export default function WrappedSingleInputDateRangePicker() { +export default function SingleInputDateRangePickerWrapped() { return ( diff --git a/docs/data/date-pickers/custom-field/WrappedSingleInputDateRangePicker.tsx b/docs/data/date-pickers/custom-field/SingleInputDateRangePickerWrapped.tsx similarity index 88% rename from docs/data/date-pickers/custom-field/WrappedSingleInputDateRangePicker.tsx rename to docs/data/date-pickers/custom-field/SingleInputDateRangePickerWrapped.tsx index a7f000683fc7c..21ea29ee17dd7 100644 --- a/docs/data/date-pickers/custom-field/WrappedSingleInputDateRangePicker.tsx +++ b/docs/data/date-pickers/custom-field/SingleInputDateRangePickerWrapped.tsx @@ -9,11 +9,12 @@ import { } from '@mui/x-date-pickers-pro/SingleInputDateRangeField'; import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; import { PickerValidDate } from '@mui/x-date-pickers/models'; +import { FieldType } from '@mui/x-date-pickers-pro/models'; type FieldComponent = (( props: SingleInputDateRangeFieldProps & React.RefAttributes, -) => React.JSX.Element) & { fieldType?: string }; +) => React.JSX.Element) & { fieldType?: FieldType }; const WrappedSingleInputDateRangeField = React.forwardRef( ( @@ -26,7 +27,7 @@ const WrappedSingleInputDateRangeField = React.forwardRef( WrappedSingleInputDateRangeField.fieldType = 'single-input'; -export default function WrappedSingleInputDateRangePicker() { +export default function SingleInputDateRangePickerWrapped() { return ( diff --git a/docs/data/date-pickers/custom-field/WrappedSingleInputDateRangePicker.tsx.preview b/docs/data/date-pickers/custom-field/SingleInputDateRangePickerWrapped.tsx.preview similarity index 100% rename from docs/data/date-pickers/custom-field/WrappedSingleInputDateRangePicker.tsx.preview rename to docs/data/date-pickers/custom-field/SingleInputDateRangePickerWrapped.tsx.preview diff --git a/docs/data/date-pickers/custom-field/custom-field.md b/docs/data/date-pickers/custom-field/custom-field.md index 947d98059e12d..302cde45d08c8 100644 --- a/docs/data/date-pickers/custom-field/custom-field.md +++ b/docs/data/date-pickers/custom-field/custom-field.md @@ -39,7 +39,7 @@ You can pass the single input fields to the range picker to use it for keyboard If you want to create a wrapper around the field, make sure to set the `fieldType` static property to `'single-input'`. Otherwise, the picker won't know your field is a single input one and use the multi input event listeners: -{{"demo": "WrappedSingleInputDateRangePicker.js", "defaultCodeOpen": false}} +{{"demo": "SingleInputDateRangePickerWrapped.js", "defaultCodeOpen": false}} You can manually add an `endAdornment` if you want your range picker to look exactly like on a simple picker: @@ -56,11 +56,44 @@ Setting `formatDensity` to `"spacious"` will add a space before and after each ` {{"demo": "FieldFormatDensity.js"}} -## Commonly used custom field +## Usage with Material UI -### Using another input +### Using Material `TextField` -#### With the Joy UI input +You can import the `TextField` component to create custom wrappers: + +{{"demo": "MaterialV6FieldWrapped.js"}} + +:::success +This approach is only recommended if you need complex customizations on your `TextField`, +or if you already have a wrapper also used outside the Date and Time Pickers. + +If you just need to set some default props, you can use [the `slotProps` prop](/x/react-date-pickers/custom-field/#customize-the-textfield). +::: + +### Using Material `PickersTextField` + +Pass the `enableAccessibleFieldDOMStructure` to any Field or Picker component to enable the accessible DOM structure: + +{{"demo": "MaterialV7Field.js"}} + +:::success +Learn more about the [accessible DOM structure](/x/react-date-pickers/fields/#accessible-dom-structure). +::: + +You can import the `PickersTextField` component to create custom wrappers: + +{{"demo": "MaterialV7FieldWrapped.js"}} + +:::success +This approach is only recommended if you need complex customizations on your `PickersTextField`. + +If you just need to set some default props, you can use [the `slotProps` prop](/x/react-date-pickers/custom-field/#customize-the-textfield). +::: + +## Usage with Joy UI + +### Using Joy `Input` You can use the [Joy UI](https://mui.com/joy-ui/getting-started/) components instead of the Material UI ones: @@ -68,26 +101,46 @@ You can use the [Joy UI](https://mui.com/joy-ui/getting-started/) components in A higher-level solution for _Joy UI_ will be provided in the near future for even simpler usage. ::: -{{"demo": "PickerWithJoyField.js", "defaultCodeOpen": false}} +{{"demo": "JoyV6Field.js", "defaultCodeOpen": false}} -{{"demo": "RangePickerWithSingleInputJoyField.js", "defaultCodeOpen": false}} +{{"demo": "JoyV6SingleInputRangeField.js", "defaultCodeOpen": false}} -{{"demo": "RangePickerWithJoyField.js", "defaultCodeOpen": false}} +{{"demo": "JoyV6MultiInputRangeField.js", "defaultCodeOpen": false}} -#### With the browser input +### Using Joy `PickersTextField` -You can also use any other input: +:::warning +This component is not available yet. +::: -{{"demo": "PickerWithBrowserField.js", "defaultCodeOpen": false}} +## Usage with an unstyled input -{{"demo": "RangePickerWithSingleInputBrowserField.js", "defaultCodeOpen": false}} +### Using the browser input -{{"demo": "RangePickerWithBrowserField.js", "defaultCodeOpen": false}} +{{"demo": "BrowserV6Field.js", "defaultCodeOpen": false}} + +{{"demo": "BrowserV6SingleInputRangeField.js", "defaultCodeOpen": false}} + +{{"demo": "BrowserV6MultiInputRangeField.js", "defaultCodeOpen": false}} :::warning You will need to use a component that supports the `sx` prop as a wrapper for your input, in order to be able to benefit from the **hover** and **focus** behavior of the clear button. You will have access to the `clearable` and `onClear` props using native HTML elements, but the on **focus** and **hover** behavior depends on styles applied via the `sx` prop. ::: +### Using custom `PickersTextField` + +:::success +Learn more about the accessible DOM structure and its difference compared to the current one on the [dedicated doc section](/x/react-date-pickers/fields/#accessible-dom-structure). +::: + +{{"demo": "BrowserV7Field.js", "defaultCodeOpen": false}} + +{{"demo": "BrowserV7SingleInputRangeField.js", "defaultCodeOpen": false}} + +{{"demo": "BrowserV7MultiInputRangeField.js", "defaultCodeOpen": false}} + +## Usage with another UI + ### Using an `Autocomplete` If your user can only select a value in a small list of available dates, diff --git a/docs/data/date-pickers/date-picker/date-picker.md b/docs/data/date-pickers/date-picker/date-picker.md index e371e8afcf7a0..24099daa4407d 100644 --- a/docs/data/date-pickers/date-picker/date-picker.md +++ b/docs/data/date-pickers/date-picker/date-picker.md @@ -18,13 +18,15 @@ materialDesign: https://m2.material.io/components/date-pickers ## Component composition The component is built using the `DateField` for the keyboard editing and the `DateCalendar` for the view editing. -All the documented props of those two components can also be passed to the Date Picker component. Check-out their documentation page for more information: - [Date Field](/x/react-date-pickers/date-field/) - [Date Calendar](/x/react-date-pickers/date-calendar/) +You can check the available props of the combined component on the dedicated [API page](/x/api/date-pickers/date-picker/#props). +Some [DateField props](/x/api/date-pickers/date-field/#props) are not available on the Picker component, you can use `slotProps.field` to pass them to the field. + ## Uncontrolled vs. controlled value The value of the component can be uncontrolled or controlled. diff --git a/docs/data/date-pickers/date-range-picker/date-range-picker.md b/docs/data/date-pickers/date-range-picker/date-range-picker.md index b9662a672402c..43e680df8d33a 100644 --- a/docs/data/date-pickers/date-range-picker/date-range-picker.md +++ b/docs/data/date-pickers/date-range-picker/date-range-picker.md @@ -18,13 +18,15 @@ materialDesign: https://m2.material.io/components/date-pickers ## Component composition The component is built using the `MultiInputDateRangeField` for the keyboard editing and the `DateRangeCalendar` for the view editing. -All the documented props of those two components can also be passed to the Date Range Picker component. Check-out their documentation page for more information: - [Date Range Field](/x/react-date-pickers/date-range-field/) - [Date Range Calendar](/x/react-date-pickers/date-range-calendar/) +You can check the available props of the combined component on the dedicated [API page](/x/api/date-pickers/date-range-picker/#props). +Some [MultiInputDateRangeField props](/x/api/date-pickers/multi-input-date-range-field/#props) are not available on the Picker component, you can use `slotProps.field` to pass them to the field. + ## Uncontrolled vs. controlled value The value of the component can be uncontrolled or controlled. diff --git a/docs/data/date-pickers/date-time-picker/date-time-picker.md b/docs/data/date-pickers/date-time-picker/date-time-picker.md index c2ba925d76bc6..1ffbfa0388d26 100644 --- a/docs/data/date-pickers/date-time-picker/date-time-picker.md +++ b/docs/data/date-pickers/date-time-picker/date-time-picker.md @@ -18,7 +18,6 @@ materialDesign: https://m2.material.io/components/date-pickers ## Component composition The component is built using the `DateTimeField` for the keyboard editing, the `DateCalendar` for the date view editing, the `DigitalClock` for the desktop view editing, and the `TimeClock` for the mobile time view editing. -All the documented props of those four components can also be passed to the Date Time Picker component. Check-out their documentation page for more information: @@ -27,6 +26,9 @@ Check-out their documentation page for more information: - [Digital Clock](/x/react-date-pickers/digital-clock/) - [Time Clock](/x/react-date-pickers/time-clock/) +You can check the available props of the combined component on the dedicated [API page](/x/api/date-pickers/date-time-picker/#props). +Some [DateTimeField props](/x/api/date-pickers/date-time-field/#props) are not available on the Picker component, you can use `slotProps.field` to pass them to the field. + ## Uncontrolled vs. controlled value The value of the component can be uncontrolled or controlled. diff --git a/docs/data/date-pickers/date-time-range-picker/date-time-range-picker.md b/docs/data/date-pickers/date-time-range-picker/date-time-range-picker.md index 68121e182a38e..92137b72ba818 100644 --- a/docs/data/date-pickers/date-time-range-picker/date-time-range-picker.md +++ b/docs/data/date-pickers/date-time-range-picker/date-time-range-picker.md @@ -18,7 +18,6 @@ materialDesign: https://m2.material.io/components/date-pickers ## Component composition The component is built using the `MultiInputDateTimeRangeField` for the keyboard editing, the `DateRangeCalendar` for the date view editing and `DigitalClock` for the time view editing. -All the documented props of those two components can also be passed to the Date Time Range Picker component. Check-out their documentation page for more information: @@ -26,6 +25,9 @@ Check-out their documentation page for more information: - [Date Range Calendar](/x/react-date-pickers/date-range-calendar/) - [Digital Clock](/x/react-date-pickers/digital-clock/) +You can check the available props of the combined component on the dedicated [API page](/x/api/date-pickers/date-time-range-picker/#props). +Some [MultiInputDateTimeRangeField props](/x/api/date-pickers/multi-input-date-time-range-field/#props) are not available on the Picker component, you can use `slotProps.field` to pass them to the field. + ## Uncontrolled vs. controlled value The value of the component can be uncontrolled or controlled. diff --git a/docs/data/date-pickers/fields/BasicV6DOMStructure.js b/docs/data/date-pickers/fields/BasicV6DOMStructure.js new file mode 100644 index 0000000000000..20a6c9ae844be --- /dev/null +++ b/docs/data/date-pickers/fields/BasicV6DOMStructure.js @@ -0,0 +1,15 @@ +import * as React from 'react'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DateField } from '@mui/x-date-pickers/DateField'; +import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; + +export default function BasicV6DOMStructure() { + return ( + + + + + + ); +} diff --git a/docs/data/date-pickers/fields/BasicV6DOMStructure.tsx b/docs/data/date-pickers/fields/BasicV6DOMStructure.tsx new file mode 100644 index 0000000000000..20a6c9ae844be --- /dev/null +++ b/docs/data/date-pickers/fields/BasicV6DOMStructure.tsx @@ -0,0 +1,15 @@ +import * as React from 'react'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DateField } from '@mui/x-date-pickers/DateField'; +import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; + +export default function BasicV6DOMStructure() { + return ( + + + + + + ); +} diff --git a/docs/data/date-pickers/fields/BasicV6DOMStructure.tsx.preview b/docs/data/date-pickers/fields/BasicV6DOMStructure.tsx.preview new file mode 100644 index 0000000000000..2dc079345c091 --- /dev/null +++ b/docs/data/date-pickers/fields/BasicV6DOMStructure.tsx.preview @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/data/date-pickers/fields/BasicV7DOMStructure.js b/docs/data/date-pickers/fields/BasicV7DOMStructure.js new file mode 100644 index 0000000000000..1f32eca967da6 --- /dev/null +++ b/docs/data/date-pickers/fields/BasicV7DOMStructure.js @@ -0,0 +1,15 @@ +import * as React from 'react'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DateField } from '@mui/x-date-pickers/DateField'; +import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; + +export default function BasicV7DOMStructure() { + return ( + + + + + + ); +} diff --git a/docs/data/date-pickers/fields/BasicV7DOMStructure.tsx b/docs/data/date-pickers/fields/BasicV7DOMStructure.tsx new file mode 100644 index 0000000000000..1f32eca967da6 --- /dev/null +++ b/docs/data/date-pickers/fields/BasicV7DOMStructure.tsx @@ -0,0 +1,15 @@ +import * as React from 'react'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DateField } from '@mui/x-date-pickers/DateField'; +import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; + +export default function BasicV7DOMStructure() { + return ( + + + + + + ); +} diff --git a/docs/data/date-pickers/fields/BasicV7DOMStructure.tsx.preview b/docs/data/date-pickers/fields/BasicV7DOMStructure.tsx.preview new file mode 100644 index 0000000000000..f33bc6c8fdc7e --- /dev/null +++ b/docs/data/date-pickers/fields/BasicV7DOMStructure.tsx.preview @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/data/date-pickers/fields/fields.md b/docs/data/date-pickers/fields/fields.md index 9bd7260fff468..5f54b1411f66e 100644 --- a/docs/data/date-pickers/fields/fields.md +++ b/docs/data/date-pickers/fields/fields.md @@ -25,6 +25,201 @@ All fields to edit a range are available in a single input version and in a mult {{"demo": "DateRangeFieldExamples.js", "defaultCodeOpen": false}} +## Accessible DOM structure + +By default, the fields' DOM structure consists of an ``, which holds the whole value for the component, but unfortunately presents a few limitations in terms of accessibility when managing multiple section values. + +From v7 version, you can opt-in for a new and experimental DOM structure on any field or picker component using the `enableAccessibleFieldDOMStructure` prop. + +```tsx + + + +``` + +This new feature allows the field component to set aria attributes on individual sections, providing a far better experience with screen readers. + +{{"demo": "BasicV7DOMStructure.js", "defaultCodeOpen": false }} + +### Usage with `slotProps.field` + +When using `slotProps.field` to pass props to your field component, +the field consumes some props (e.g: `shouldRespectLeadingZeros`) and forwards the rest to the `TextField`. + +- For the props consumed by the field, the behavior should remain exactly the same with both DOM structures. + + Both components below will respect the leading zeroes on digit sections: + + ```js + + + ``` + +- For the props forwarded to the `TextField`, + you can have a look at the next section to see how the migration impact them. + + Both components below will render a small size UI: + + ```js + + + ``` + +### Usage with `slotProps.textField` + +If you are passing props to `slotProps.textField`, +these props will now be received by `PickersTextField` and should keep working the same way as before. + +Both components below will render a small size UI: + +```js + + +``` + +:::info +If you are passing `inputProps` to `slotProps.textField`, +these props will now be passed to the hidden `` element. +::: + +### Usage with `slots.field` + +If you are passing a custom field component to your pickers, you need to create a new one that is using the accessible DOM structure. +This new component will need to use the `PickersSectionList` component instead of an `` HTML element. + +You can have a look at the [custom PickersTextField](/x/react-date-pickers/custom-field/#using-custom-pickerstextfield) to have a concrete example. + +:::info +If your custom field was used to create a Joy UI design component, +you may want to wait a few weeks for the release of an out-of-the-box Joy `PickersTextField` component instead of implementing it yourself. +::: + +### Usage with `slots.textField` + +If you are passing a custom `TextField` component to your fields and pickers, +you need to create a new one that is using the accessible DOM structure. + +You can have a look at the second demo of the [Material PickersTextField section](/x/react-date-pickers/custom-field/#using-material-pickerstextfield) to have a concrete example. + +:::info +If your custom `TextField` was used to apply a totally different input that did not use `@mui/material/TextField`, +please consider having a look at the [custom PickersTextField](/x/react-date-pickers/custom-field/#using-custom-pickerstextfield) section which uses `slots.field`. +This approach can be more appropriate for deeper changes. +::: + +### Usage with theme + +If you are using the theme to customize `MuiTextField`, +you need to pass the same config to `MuiPickersTextField`: + +```js +const theme = createTheme({ + components: { + MuiTextField: { + defaultProps: { + variant: 'outlined', + }, + styleOverrides: { + root: { + '& .MuiInputLabel-outlined.Mui-focused': { + color: 'red', + }, + }, + }, + }, + MuiPickersTextField: { + defaultProps: { + variant: 'outlined', + }, + styleOverrides: { + root: { + '& .MuiInputLabel-outlined.Mui-focused': { + color: 'red', + }, + }, + }, + }, + }, +}); +``` + +If you are using the theme to customize `MuiInput`, `MuiOutlinedInput` or `MuiFilledInput`, +you need to pass the same config to `MuiPickersInput`, `MuiPickersOutlinedInput` or `MuiPickersFilledInput`: + +```js +const theme = createTheme({ + components: { + // Replace with `MuiOutlinedInput` or `MuiFilledInput` if needed + MuiInput: { + defaultProps: { + margin: 'dense', + }, + styleOverrides: { + root: { + color: 'red', + }, + }, + }, + // Replace with `MuiPickersOutlinedInput` or `MuiPickersFilledInput` if needed + MuiPickersInput: { + defaultProps: { + margin: 'dense', + }, + styleOverrides: { + root: { + color: 'red', + }, + }, + }, + }, +}); +``` + +If you are using the theme to customize `MuiInputBase`, +you need to pass the same config to `MuiPickersInputBase`: + +```js +const theme = createTheme({ + components: { + MuiInputBase: { + defaultProps: { + margin: 'dense', + }, + styleOverrides: { + root: { + color: 'red', + }, + }, + }, + MuiPickersInputBase: { + defaultProps: { + margin: 'dense', + }, + styleOverrides: { + root: { + color: 'red', + }, + }, + }, + }, +}); +``` + ## Advanced ### What is a section? diff --git a/docs/data/date-pickers/lifecycle/ServerInteraction.tsx b/docs/data/date-pickers/lifecycle/ServerInteraction.tsx index 0795fab5891ff..c265b005dd90d 100644 --- a/docs/data/date-pickers/lifecycle/ServerInteraction.tsx +++ b/docs/data/date-pickers/lifecycle/ServerInteraction.tsx @@ -40,7 +40,7 @@ function DisplayEvents(props: DisplayEventsProps) { // debounce function function debounce(func: (...arg: any) => void, wait = 500) { - let timeout: NodeJS.Timeout; + let timeout: ReturnType; function debounced(...args: any) { const later = () => { func(...args); diff --git a/docs/data/date-pickers/localization/data.json b/docs/data/date-pickers/localization/data.json index 78f5c7cd8618c..0a76129d0673b 100644 --- a/docs/data/date-pickers/localization/data.json +++ b/docs/data/date-pickers/localization/data.json @@ -3,264 +3,264 @@ "languageTag": "eu", "importName": "eu", "localeName": "Basque", - "missingKeysCount": 4, - "totalKeysCount": 41, + "missingKeysCount": 13, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/eu.ts" }, { "languageTag": "be-BY", "importName": "beBY", "localeName": "Belarusian", - "missingKeysCount": 6, - "totalKeysCount": 41, + "missingKeysCount": 15, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/beBY.ts" }, { "languageTag": "ca-ES", "importName": "caES", "localeName": "Catalan", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/caES.ts" }, { "languageTag": "zh-HK", "importName": "zhHK", "localeName": "Chinese (Hong Kong)", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/zhHK.ts" }, { "languageTag": "zh-CN", "importName": "zhCN", "localeName": "Chinese (Simplified)", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 0, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/zhCN.ts" }, { "languageTag": "cs-CZ", "importName": "csCZ", "localeName": "Czech", - "missingKeysCount": 6, - "totalKeysCount": 41, + "missingKeysCount": 15, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/csCZ.ts" }, { "languageTag": "da-DK", "importName": "daDK", "localeName": "Danish", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/daDK.ts" }, { "languageTag": "nl-NL", "importName": "nlNL", "localeName": "Dutch", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/nlNL.ts" }, { "languageTag": "fi-FI", "importName": "fiFI", "localeName": "Finnish", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/fiFI.ts" }, { "languageTag": "fr-FR", "importName": "frFR", "localeName": "French", - "missingKeysCount": 6, - "totalKeysCount": 41, + "missingKeysCount": 15, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/frFR.ts" }, { "languageTag": "de-DE", "importName": "deDE", "localeName": "German", - "missingKeysCount": 4, - "totalKeysCount": 41, + "missingKeysCount": 13, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/deDE.ts" }, { "languageTag": "el-GR", "importName": "elGR", "localeName": "Greek", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/elGR.ts" }, { "languageTag": "he-IL", "importName": "heIL", "localeName": "Hebrew", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/heIL.ts" }, { "languageTag": "hu-HU", "importName": "huHU", "localeName": "Hungarian", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/huHU.ts" }, { "languageTag": "is-IS", "importName": "isIS", "localeName": "Icelandic", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/isIS.ts" }, { "languageTag": "it-IT", "importName": "itIT", "localeName": "Italian", - "missingKeysCount": 6, - "totalKeysCount": 41, + "missingKeysCount": 15, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/itIT.ts" }, { "languageTag": "ja-JP", "importName": "jaJP", "localeName": "Japanese", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/jaJP.ts" }, { "languageTag": "kz-KZ", "importName": "kzKZ", "localeName": "Kazakh", - "missingKeysCount": 6, - "totalKeysCount": 41, + "missingKeysCount": 15, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/kzKZ.ts" }, { "languageTag": "ko-KR", "importName": "koKR", "localeName": "Korean", - "missingKeysCount": 6, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/koKR.ts" }, { "languageTag": "mk", "importName": "mk", "localeName": "Macedonian", - "missingKeysCount": 4, - "totalKeysCount": 41, + "missingKeysCount": 13, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/mk.ts" }, { "languageTag": "nb-NO", "importName": "nbNO", "localeName": "Norwegian (Bokmål)", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/nbNO.ts" }, { "languageTag": "fa-IR", "importName": "faIR", "localeName": "Persian", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/faIR.ts" }, { "languageTag": "pl-PL", "importName": "plPL", "localeName": "Polish", - "missingKeysCount": 13, - "totalKeysCount": 41, + "missingKeysCount": 22, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/plPL.ts" }, { "languageTag": "pt-BR", "importName": "ptBR", "localeName": "Portuguese (Brazil)", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/ptBR.ts" }, { "languageTag": "ro-RO", "importName": "roRO", "localeName": "Romanian", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/roRO.ts" }, { "languageTag": "ru-RU", "importName": "ruRU", "localeName": "Russian", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/ruRU.ts" }, { "languageTag": "sk-SK", "importName": "skSK", "localeName": "Slovak", - "missingKeysCount": 6, - "totalKeysCount": 41, + "missingKeysCount": 15, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/skSK.ts" }, { "languageTag": "es-ES", "importName": "esES", "localeName": "Spanish", - "missingKeysCount": 4, - "totalKeysCount": 41, + "missingKeysCount": 13, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/esES.ts" }, { "languageTag": "sv-SE", "importName": "svSE", "localeName": "Swedish", - "missingKeysCount": 13, - "totalKeysCount": 41, + "missingKeysCount": 22, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/svSE.ts" }, { "languageTag": "tr-TR", "importName": "trTR", "localeName": "Turkish", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/trTR.ts" }, { "languageTag": "uk-UA", "importName": "ukUA", "localeName": "Ukrainian", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/ukUA.ts" }, { "languageTag": "ur-PK", "importName": "urPK", "localeName": "Urdu (Pakistan)", - "missingKeysCount": 13, - "totalKeysCount": 41, + "missingKeysCount": 22, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/urPK.ts" }, { "languageTag": "vi-VN", "importName": "viVN", "localeName": "Vietnamese", - "missingKeysCount": 5, - "totalKeysCount": 41, + "missingKeysCount": 14, + "totalKeysCount": 50, "githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/viVN.ts" } ] diff --git a/docs/data/date-pickers/time-picker/time-picker.md b/docs/data/date-pickers/time-picker/time-picker.md index f936642668ff9..d6db6b9d53c99 100644 --- a/docs/data/date-pickers/time-picker/time-picker.md +++ b/docs/data/date-pickers/time-picker/time-picker.md @@ -18,7 +18,6 @@ materialDesign: https://m2.material.io/components/time-pickers ## Component composition The component is built using the `TimeField` for the keyboard editing, the `DigitalClock` for the desktop view editing, and the `TimeClock` for the mobile view editing. -All the documented props of those two components can also be passed to the Time Picker component. Check-out their documentation page for more information: @@ -26,6 +25,9 @@ Check-out their documentation page for more information: - [Digital Clock](/x/react-date-pickers/digital-clock/) - [Time Clock](/x/react-date-pickers/time-clock/) +You can check the available props of the combined component on the dedicated [API page](/x/api/date-pickers/time-picker/#props). +Some [TimeField props](/x/api/date-pickers/time-field/#props) are not available on the Picker component, you can use `slotProps.field` to pass them to the field. + ## Uncontrolled vs. controlled value The value of the component can be uncontrolled or controlled. diff --git a/docs/data/introduction/licensing/licensing.md b/docs/data/introduction/licensing/licensing.md index 97436b7302853..6764647c39533 100644 --- a/docs/data/introduction/licensing/licensing.md +++ b/docs/data/introduction/licensing/licensing.md @@ -296,7 +296,7 @@ This error indicates that your MUI X license key format isn't valid. It could be because the license key is missing a character or has a typo. To solve the issue, you need to double-check that `setLicenseKey()` is called with the right argument. -Please check the [license key installation](#license-key-installation). +Please check the [license key installation](/x/introduction/licensing/#license-key). ### 6. Invalid license key (TypeError: extracting license expiry timestamp) diff --git a/docs/data/introduction/support/support.md b/docs/data/introduction/support/support.md index e69ae612519fa..ce015dcceb0d8 100644 --- a/docs/data/introduction/support/support.md +++ b/docs/data/introduction/support/support.md @@ -27,29 +27,34 @@ We require bug reports to be accompanied by a **minimal reproduction**. It significantly increases the odds of fixing the problem. You have a few possible options to provide it: -- You can browse the documentation, find an example close to your use case, and then open it in a live editor: - - - Forking an example - - - Forking an example - - - - - [Data Grid](/x/react-data-grid/#mit-version-free-forever) - - [Date Pickers](/x/react-date-pickers/getting-started/#render-your-first-component) - - [Charts](/x/react-charts/getting-started/#single-charts) - - [Tree View](/x/react-tree-view/#simple-tree-view) - -- You can use a starter template to build a reproduction case with: - - - A minimal Data Grid [TypeScript template](https://stackblitz.com/github/mui/mui-x/tree/next/bug-reproductions/x-data-grid?file=src/index.tsx) - - A plain React [JavaScript](https://stackblitz.com/github/stackblitz/starters/tree/main/react) or [TypeScript](https://stackblitz.com/github/stackblitz/starters/tree/main/react-ts) template - -## Stack Overflow - -We use Stack Overflow for how-to questions. Answers are crowdsourced from expert developers in the MUI X community as well as MUI X maintainers. +#### Use the live editors + +You can browse the documentation, find an example close to your use case, and then open it in a live editor: + + + +Forking an example + + +Forking an example + + + +- [Data Grid](/x/react-data-grid/#mit-version-free-forever) +- [Date Pickers](/x/react-date-pickers/getting-started/#render-your-first-component) +- [Charts](/x/react-charts/getting-started/#single-charts) +- [Tree View](/x/react-tree-view/#simple-tree-view) + +#### Use starter templates + +You can use a starter template to build a reproduction case with: + +- A minimal Data Grid [TypeScript template](https://stackblitz.com/github/mui/mui-x/tree/next/bug-reproductions/x-data-grid?file=src/index.tsx) +- A plain React [JavaScript](https://stackblitz.com/github/stackblitz/starters/tree/main/react) or [TypeScript](https://stackblitz.com/github/stackblitz/starters/tree/main/react-ts) template + +## Stack Overflow + +We use Stack Overflow for how-to questions. Answers are crowdsourced from expert developers in the MUI X community as well as MUI X maintainers. You can search through existing questions and answers to see if someone has asked a similar question using one of [these tags](https://stackoverflow.com/questions/tagged/mui-x+or+mui-x-charts+or+mui-x-data-grid+or+mui-x-date-picker): @@ -110,7 +115,7 @@ Our tools are used by thousands of developers and teams all around the world, ma You can join Discord to engage in lively discussions, share your projects, and interact with developers just like you from all around the world. We'd love for you to join us! :::warning -How-to questions are not accepted on Discord, they should be asked on [Stack Overflow](#stack-overflow). +How-to questions are not accepted on Discord, they should be asked on [Stack Overflow](#stack-overflow). ::: ## Custom work 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 bf363d6181cbd..3ce5734605a16 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 @@ -104,6 +104,7 @@ As a result, the following changes have been made: - The main element now corresponds to the virtal scroller element. - Headers are now contained in the virtual scroller. - Pinned row and column sections are now contained in the virtual scroller. +- The cell inner wrapper `.MuiDataGrid-cellContent` has been removed.