diff --git a/.circleci/config.yml b/.circleci/config.yml index adb1bf6c916b..05cc3abd94bc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,8 +5,8 @@ parameters: description: Whether to force browserstack usage. We have limited resources on browserstack so the pipeline might decide to skip browserstack if this parameter isn't set to true. type: boolean default: false - react-dist-tag: - description: The dist-tag of react to be used + react-version: + description: The version of react to be used type: string default: stable workflow: @@ -20,10 +20,10 @@ parameters: default-job: &default-job parameters: - react-dist-tag: - description: The dist-tag of react to be used + react-version: + description: The version of react to be used type: string - default: << pipeline.parameters.react-dist-tag >> + default: << pipeline.parameters.react-version >> e2e-base-url: description: The base url for running end-to-end test type: string @@ -33,7 +33,7 @@ default-job: &default-job PLAYWRIGHT_BROWSERS_PATH: /tmp/pw-browsers # expose it globally otherwise we have to thread it from each job to the install command BROWSERSTACK_FORCE: << pipeline.parameters.browserstack-force >> - REACT_DIST_TAG: << parameters.react-dist-tag >> + REACT_VERSION: << parameters.react-version >> working_directory: /tmp/mui docker: - image: cimg/node:18.20 @@ -59,6 +59,13 @@ commands: description: 'Set to true if you intend to any browser (for example with playwright).' steps: + - run: + name: Resolve React version + command: | + node scripts/useReactVersion.mjs + # log a patch for maintainers who want to check out this change + git --no-pager diff HEAD + - when: condition: << parameters.browsers >> steps: @@ -90,7 +97,17 @@ commands: pnpm --version - run: name: Install js dependencies - command: pnpm install + command: | + echo "React version $REACT_VERSION" + if [ $REACT_VERSION == "stable" ]; + then + echo "pnpm install" + pnpm install + else + echo "pnpm install --no-frozen-lockfile" + pnpm install --no-frozen-lockfile + fi + - when: condition: << parameters.browsers >> steps: @@ -115,7 +132,7 @@ jobs: name: Should not have any git not staged command: git add -A && git diff --exit-code --staged - run: - name: Check for duplicated packages + name: '`pnpm dedupe` was run?' command: | if [[ $(git diff --name-status next | grep pnpm-lock) == "" ]]; then @@ -146,7 +163,7 @@ jobs: command: | curl -Os https://uploader.codecov.io/latest/linux/codecov chmod +x codecov - ./codecov -t ${CODECOV_TOKEN} -Z -F "$REACT_DIST_TAG-jsdom" + ./codecov -t ${CODECOV_TOKEN} -Z -F "$REACT_VERSION-jsdom" test_lint: <<: *default-job steps: @@ -330,3 +347,31 @@ workflows: - test_e2e_website: requires: - checkout + + react-next: + when: + equal: [react-next, << pipeline.parameters.workflow >>] + # triggers: + # - schedule: + # cron: '0 0 * * *' + # filters: + # branches: + # only: + # - master + jobs: + - test_unit: + <<: *default-context + react-version: next + name: test_unit-react@next + - test_browser: + <<: *default-context + react-version: next + name: test_browser-react@next + - test_regressions: + <<: *default-context + react-version: next + name: test_regressions-react@next + - test_e2e: + <<: *default-context + react-version: next + name: test_e2e-react@next diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json index 37d8d1c44544..2bcfb7926690 100644 --- a/.codesandbox/ci.json +++ b/.codesandbox/ci.json @@ -11,7 +11,8 @@ "packages/x-date-pickers", "packages/x-date-pickers-pro", "packages/x-charts", - "packages/x-tree-view" + "packages/x-tree-view", + "packages/x-internals" ], "publishDirectory": { "@mui/x-license": "packages/x-license/build", @@ -24,7 +25,8 @@ "@mui/x-charts": "packages/x-charts/build", "@mui/x-charts-pro": "packages/x-charts-pro/build", "@mui/x-tree-view": "packages/x-tree-view/build", - "@mui/x-tree-view-pro": "packages/x-tree-view-pro/build" + "@mui/x-tree-view-pro": "packages/x-tree-view-pro/build", + "@mui/x-internals": "packages/x-internals/build" }, "sandboxes": ["/bug-reproductions/x-data-grid"], "silent": true diff --git a/.eslintrc.js b/.eslintrc.js index 3afad759075e..f4762cac6c02 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,6 +1,19 @@ const baseline = require('@mui/monorepo/.eslintrc'); const path = require('path'); +const chartsPackages = ['x-charts', 'x-charts-pro']; + +const dataGridPackages = [ + 'x-data-grid', + 'x-data-grid-pro', + 'x-data-grid-premium', + 'x-data-grid-generator', +]; + +const datePickersPackages = ['x-date-pickers', 'x-date-pickers-pro']; + +const treeViewPackages = ['x-tree-view', 'x-tree-view-pro']; + // Enable React Compiler Plugin rules globally const ENABLE_REACT_COMPILER_PLUGIN = process.env.ENABLE_REACT_COMPILER_PLUGIN ?? false; @@ -139,6 +152,18 @@ module.exports = { ...(ENABLE_REACT_COMPILER_PLUGIN ? { 'react-compiler/react-compiler': 'error' } : {}), // TODO move to @mui/monorepo/.eslintrc, codebase is moving away from default exports 'import/prefer-default-export': 'off', + 'import/no-restricted-paths': [ + 'error', + { + zones: [...chartsPackages, ...datePickersPackages, ...treeViewPackages].map( + (packageName) => ({ + target: `./packages/${packageName}/src/**/!(*.test.*|*.spec.*)`, + from: `./packages/${packageName}/src/internals/index.ts`, + message: `Use a more specific import instead. E.g. import { MyInternal } from '../internals/MyInternal';`, + }), + ), + }, + ], // TODO move rule into the main repo once it has upgraded '@typescript-eslint/return-await': 'off', 'no-restricted-imports': 'off', @@ -167,7 +192,7 @@ module.exports = { // TODO move to @mui/monorepo/.eslintrc // TODO Fix props names to not conflict 'react/jsx-no-duplicate-props': [1, { ignoreCase: false }], - // TOOD move to @mui/monorepo/.eslintrc, these are false positive + // TODO move to @mui/monorepo/.eslintrc, these are false positive 'react/no-unstable-nested-components': ['error', { allowAsProps: true }], }, overrides: [ @@ -257,18 +282,9 @@ module.exports = { ...buildPackageRestrictedImports('@mui/x-tree-view-pro', 'x-tree-view-pro', false), ...buildPackageRestrictedImports('@mui/x-license', 'x-license'), - ...addReactCompilerRule(['x-charts', 'x-charts-pro'], ENABLE_REACT_COMPILER_PLUGIN_CHARTS), - ...addReactCompilerRule( - ['x-data-grid', 'x-data-grid-pro', 'x-data-grid-premium', 'x-data-grid-generator'], - ENABLE_REACT_COMPILER_PLUGIN_DATA_GRID, - ), - ...addReactCompilerRule( - ['x-date-pickers', 'x-date-pickers-pro'], - ENABLE_REACT_COMPILER_PLUGIN_DATE_PICKERS, - ), - ...addReactCompilerRule( - ['x-tree-view', 'x-tree-view-pro'], - ENABLE_REACT_COMPILER_PLUGIN_TREE_VIEW, - ), + ...addReactCompilerRule(chartsPackages, ENABLE_REACT_COMPILER_PLUGIN_CHARTS), + ...addReactCompilerRule(dataGridPackages, ENABLE_REACT_COMPILER_PLUGIN_DATA_GRID), + ...addReactCompilerRule(datePickersPackages, ENABLE_REACT_COMPILER_PLUGIN_DATE_PICKERS), + ...addReactCompilerRule(treeViewPackages, ENABLE_REACT_COMPILER_PLUGIN_TREE_VIEW), ], }; diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index ecf1ede8f2cb..d803a2ae9313 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10 + uses: github/codeql-action/init@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11 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@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10 + uses: github/codeql-action/analyze@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11 diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 2fb7dd32df08..2caad354b82e 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@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10 + uses: github/codeql-action/upload-sarif@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11 with: sarif_file: results.sarif diff --git a/CHANGELOG.md b/CHANGELOG.md index 62c83f81b4bf..55f098a29783 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,171 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 7.9.0 + +_Jul 5, 2024_ + +We'd like to offer a big thanks to the 7 contributors who made this release possible. Here are some highlights ✨: + +- πŸ”„ Add loading overlay variants, including a skeleton loader option to the Data Grid component. See [Loading overlay docs](https://mui.com/x/react-data-grid/overlays/#loading-overlay) for more details. +- 🌳 Add `selectItem` and `getItemDOMElement` methods to the TreeView component public API +- ⛏️ Make the `usePickersTranslations` hook public in the pickers component +- 🐞 Bugfixes + + + +### Data Grid + +#### `@mui/x-data-grid@7.9.0` + +- [DataGrid] Add skeleton loading overlay support (#13293) @KenanYusuf +- [DataGrid] Fix pagination when `pagination={undefined}` (#13349) @sai6855 + +#### `@mui/x-data-grid-pro@7.9.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan') + +Same changes as in `@mui/x-data-grid@7.9.0`. + +#### `@mui/x-data-grid-premium@7.9.0` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan') + +Same changes as in `@mui/x-data-grid-pro@7.9.0`. + +### Date and Time Pickers + +#### `@mui/x-date-pickers@7.9.0` + +- [pickers] Make the `usePickersTranslations` hook public (#13657) @flaviendelangle + +#### `@mui/x-date-pickers-pro@7.9.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan') + +Same changes as in `@mui/x-date-pickers@7.9.0`. + +### Charts + +#### `@mui/x-charts@7.9.0` + +- [charts] Add Heatmap (unreleased) (#13209) @alexfauquette +- [charts] Add initial `Zoom&Pan` to the Pro charts (unreleased) (#13405) @JCQuintas +- [charts] Fix Axis Highlight on horizontal bar charts regression (#13717) @JCQuintas +- [charts] Improve charts interaction for mobile users (#13692) @JCQuintas +- [charts] Add documentation on how to disable the tooltip on charts (#13724) @JCQuintas + +### Tree View + +#### `@mui/x-tree-view@7.9.0` + +- [TreeView] Add `selectItem` and `getItemDOMElement` methods to the public API (#13485) @flaviendelangle + +### Docs + +- [docs] Fix custom "no results overlay" demo in dark mode (#13715) @KenanYusuf + +### Core + +- [core] Add `react_next` workflow in CircleCI (#13360) @cherniavskii +- [core] Create a new package to share utils across X packages (#13528) @flaviendelangle +- [core] Fix dependency setup (#13684) @LukasTy +- [core] Remove `jscodeshift-add-imports` package (#13720) @LukasTy +- [code-infra] Cleanup monorepo and `@mui/docs` usage (#13713) @LukasTy + +## 7.8.0 + +_Jun 28, 2024_ + +We'd like to offer a big thanks to the 10 contributors who made this release possible. Here are some highlights ✨: + +- πŸ›° Introduce server-side data source for improved server integration in the Data Grid. + + Supports server-side pagination, sorting and filtering on plain and tree data, and automatic caching. + + To enable, provide a `getRows` function to the `unstable_dataSource` prop on the Data Grid component. + + ```tsx + const dataSource = { + getRows: async (params: GridServerGetRowsParams) => { + const data = await fetch( + `https://api.example.com/data?${new URLSearchParams({ + page: params.page, + pageSize: params.pageSize, + sortModel: JSON.stringify(params.sortModel), + filterModel: JSON.stringify(params.filterModel), + }).toString()}`, + ); + return { + rows: data.rows, + totalRows: data.totalRows, + }; + }, + } + + ``` + + See [server-side data documentation](https://mui.com/x/react-data-grid/server-side-data/) for more details. + +- πŸ“ˆ Support Date data on the BarChart component +- ↕️ Support custom column sort icons on the Data Grid +- πŸ–±οΈ Support modifying the expansion trigger on the Tree View components + + + +### Data Grid + +#### `@mui/x-data-grid@7.8.0` + +- [DataGrid] Add `columnHeaderSortIcon` slot (#13563) @arminmeh +- [DataGrid] Fix dimensions lag issue after autosize (#13587) @MBilalShafi +- [DataGrid] Fix print export failure when `hideFooter` option is set (#13034) @tarunrajput + +#### `@mui/x-data-grid-pro@7.8.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan') + +Same changes as in `@mui/x-data-grid@7.8.0`, plus: + +- [DataGridPro] Fix multi-sorting indicator being cut off (#13625) @KenanYusuf +- [DataGridPro] Server-side tree data support (#12317) @MBilalShafi + +#### `@mui/x-data-grid-premium@7.8.0` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan') + +Same changes as in `@mui/x-data-grid-pro@7.8.0`. + +### Date and Time Pickers + +#### `@mui/x-date-pickers@7.8.0` + +- [fields] Fix section clearing behavior on Android (#13652) @LukasTy + +#### `@mui/x-date-pickers-pro@7.8.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan') + +Same changes as in `@mui/x-date-pickers@7.8.0`. + +### Charts + +#### `@mui/x-charts@7.8.0` + +- [charts] Fix line chart props not passing correct event handlers (#13609) @JCQuintas +- [charts] Support BarChart with `Date` data (#13471) @alexfauquette +- [charts] Support RTL for y-axis (#13614) @alexfauquette +- [charts] Use default values instead of non-null assertion to prevent error being thrown (#13637) @JCQuintas + +### Tree View + +#### `@mui/x-tree-view@7.8.0` + +- [TreeView] Add `expansionTrigger` prop (#13533) @noraleonte +- [TreeView] Support experimental features from plugin's dependencies (#13632) @flaviendelangle + +### Docs + +- [docs] Add callout for `Luxon` `throwOnInvalid` support (#13621) @LukasTy +- [docs] Add "Overlays" section to the Data Grid documentation (#13624) @KenanYusuf + +### Core + +- [core] Add eslint rule to restrict import from `../internals` root (#13633) @JCQuintas +- [docs-infra] Sync `\_app` folder with monorepo (#13582) @Janpot +- [license] Allow usage of charts and tree view pro package for old premium licenses (#13619) @flaviendelangle + ## 7.7.1 _Jun 21, 2024_ @@ -44,7 +209,7 @@ Same changes as in `@mui/x-data-grid-pro@7.7.1`. - [pickers] Always use the same timezone in the field, the view and the layout components (#13481) @flaviendelangle - [pickers] Fix `AdapterDateFnsV3` generated method types (#13464) @alexey-kozlenkov - [pickers] Fix controlled `view` behavior (#13552) @LukasTy -- [TimePicker] Improves RTL verification for the time pickers default views (#13447) @arthurbalduini +- [TimePicker] Improves RTL verification for the time pickers default views (#13447) @arthurbalduini #### `@mui/x-date-pickers-pro@7.7.1` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan') diff --git a/babel.config.js b/babel.config.js index e10b6c313097..9e2bc852d0ed 100644 --- a/babel.config.js +++ b/babel.config.js @@ -18,6 +18,7 @@ const defaultAlias = { '@mui/x-charts-pro': resolveAliasPath('./packages/x-charts-pro/src'), '@mui/x-tree-view': resolveAliasPath('./packages/x-tree-view/src'), '@mui/x-tree-view-pro': resolveAliasPath('./packages/x-tree-view-pro/src'), + '@mui/x-internals': resolveAliasPath('./packages/x-internals/src'), '@mui/material-nextjs': '@mui/monorepo/packages/mui-material-nextjs/src', '@mui-internal/api-docs-builder': resolveAliasPath( './node_modules/@mui/monorepo/packages/api-docs-builder', diff --git a/changelogOld/CHANGELOG.v4.md b/changelogOld/CHANGELOG.v4.md index 662652efd208..2c3c89c28fc7 100644 --- a/changelogOld/CHANGELOG.v4.md +++ b/changelogOld/CHANGELOG.v4.md @@ -89,7 +89,7 @@ A big thanks to the 6 contributors who made this release possible. Here are some - [core] Simplify `useGridColumns` hook (#2343) @oliviertassinari - [core] Update `doesSupportTouchActionNone` implementation (#2378) @DanailH - [core] Upgrade dependency with the monorepo (#2377) @oliviertassinari -- [test] Use `.not.to.equal` in favour of `to.not.equal` (#2340) @oliviertassinari +- [test] Use `.not.to.equal` in favor of `.to.not.equal` (#2340) @oliviertassinari ## 4.0.0-alpha.37 diff --git a/docs/.link-check-errors.txt b/docs/.link-check-errors.txt index 10b54359e79c..6ecc503cc78a 100644 --- a/docs/.link-check-errors.txt +++ b/docs/.link-check-errors.txt @@ -1,3 +1,2 @@ Broken links found by `docs:link-check` that exist: -- https://mui.com/x/react-charts/heat-map/ diff --git a/docs/data/charts-component-api-pages.ts b/docs/data/charts-component-api-pages.ts index 3a0d808b2d06..c1ed7174bf0e 100644 --- a/docs/data/charts-component-api-pages.ts +++ b/docs/data/charts-component-api-pages.ts @@ -45,10 +45,6 @@ const apiPages: MuiPage[] = [ pathname: '/x/api/charts/charts-axis-highlight', title: 'ChartsAxisHighlight', }, - { - pathname: '/x/api/charts/charts-axis-tooltip-content', - title: 'ChartsAxisTooltipContent', - }, { pathname: '/x/api/charts/charts-clip-path', title: 'ChartsClipPath', @@ -57,10 +53,6 @@ const apiPages: MuiPage[] = [ pathname: '/x/api/charts/charts-grid', title: 'ChartsGrid', }, - { - pathname: '/x/api/charts/charts-item-tooltip-content', - title: 'ChartsItemTooltipContent', - }, { pathname: '/x/api/charts/charts-legend', title: 'ChartsLegend', diff --git a/docs/data/charts/gauge/gauge.md b/docs/data/charts/gauge/gauge.md index 6826a74780f9..30c5df560756 100644 --- a/docs/data/charts/gauge/gauge.md +++ b/docs/data/charts/gauge/gauge.md @@ -11,7 +11,7 @@ waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/meter/

Gauge charts let the user evaluate metrics.

-{{"component": "modules/components/ComponentLinkHeader.js", "design": false}} +{{"component": "@mui/docs/ComponentLinkHeader", "design": false}} ## Basics diff --git a/docs/data/charts/heatmap/BasicHeatmap.js b/docs/data/charts/heatmap/BasicHeatmap.js new file mode 100644 index 000000000000..1f3410543e9b --- /dev/null +++ b/docs/data/charts/heatmap/BasicHeatmap.js @@ -0,0 +1,19 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import '@mui/x-charts-pro/typeOverloads'; +import { UnstableHeatmap } from '@mui/x-charts-pro/Heatmap'; +import { data } from './dumbData'; + +export default function BasicHeatmap() { + return ( + + + + ); +} diff --git a/docs/data/charts/heatmap/BasicHeatmap.tsx b/docs/data/charts/heatmap/BasicHeatmap.tsx new file mode 100644 index 000000000000..1f3410543e9b --- /dev/null +++ b/docs/data/charts/heatmap/BasicHeatmap.tsx @@ -0,0 +1,19 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import '@mui/x-charts-pro/typeOverloads'; +import { UnstableHeatmap } from '@mui/x-charts-pro/Heatmap'; +import { data } from './dumbData'; + +export default function BasicHeatmap() { + return ( + + + + ); +} diff --git a/docs/data/charts/heatmap/BasicHeatmap.tsx.preview b/docs/data/charts/heatmap/BasicHeatmap.tsx.preview new file mode 100644 index 000000000000..bfe0e2212184 --- /dev/null +++ b/docs/data/charts/heatmap/BasicHeatmap.tsx.preview @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/docs/data/charts/heatmap/ColorConfig.js b/docs/data/charts/heatmap/ColorConfig.js new file mode 100644 index 000000000000..f99083ed8765 --- /dev/null +++ b/docs/data/charts/heatmap/ColorConfig.js @@ -0,0 +1,123 @@ +import * as React from 'react'; +import { interpolateBlues } from 'd3-scale-chromatic'; +import '@mui/x-charts-pro/typeOverloads'; +import { UnstableHeatmap } from '@mui/x-charts-pro/Heatmap'; + +const dataset = [ + { + london: 59, + paris: 57, + newYork: 86, + seoul: 21, + month: 'January', + }, + { + london: 50, + paris: 52, + newYork: 78, + seoul: 28, + month: 'February', + }, + { + london: 47, + paris: 53, + newYork: 106, + seoul: 41, + month: 'March', + }, + { + london: 54, + paris: 56, + newYork: 92, + seoul: 73, + month: 'April', + }, + { + london: 57, + paris: 69, + newYork: 92, + seoul: 99, + month: 'May', + }, + { + london: 60, + paris: 63, + newYork: 103, + seoul: 144, + month: 'June', + }, + { + london: 59, + paris: 60, + newYork: 105, + seoul: 319, + month: 'July', + }, + { + london: 65, + paris: 60, + newYork: 106, + seoul: 249, + month: 'August', + }, + { + london: 51, + paris: 51, + newYork: 95, + seoul: 131, + month: 'September', + }, + { + london: 60, + paris: 65, + newYork: 97, + seoul: 55, + month: 'October', + }, + { + london: 67, + paris: 64, + newYork: 76, + seoul: 48, + month: 'November', + }, + { + london: 61, + paris: 70, + newYork: 103, + seoul: 25, + month: 'December', + }, +]; + +const data = dataset.flatMap(({ london, paris, newYork, seoul }, monthIndex) => [ + [0, monthIndex, london], + [1, monthIndex, paris], + [2, monthIndex, newYork], + [3, monthIndex, seoul], +]); + +const xData = ['London', 'Paris', 'NewYork', 'Seoul']; +const yData = dataset.flatMap(({ month }) => month); + +export default function ColorConfig() { + return ( + + ); +} diff --git a/docs/data/charts/heatmap/ColorConfig.tsx b/docs/data/charts/heatmap/ColorConfig.tsx new file mode 100644 index 000000000000..88957b1db0ab --- /dev/null +++ b/docs/data/charts/heatmap/ColorConfig.tsx @@ -0,0 +1,126 @@ +import * as React from 'react'; +import { interpolateBlues } from 'd3-scale-chromatic'; +import '@mui/x-charts-pro/typeOverloads'; +import { UnstableHeatmap } from '@mui/x-charts-pro/Heatmap'; +import { HeatmapValueType } from '@mui/x-charts-pro/models'; + +const dataset = [ + { + london: 59, + paris: 57, + newYork: 86, + seoul: 21, + month: 'January', + }, + { + london: 50, + paris: 52, + newYork: 78, + seoul: 28, + month: 'February', + }, + { + london: 47, + paris: 53, + newYork: 106, + seoul: 41, + month: 'March', + }, + { + london: 54, + paris: 56, + newYork: 92, + seoul: 73, + month: 'April', + }, + { + london: 57, + paris: 69, + newYork: 92, + seoul: 99, + month: 'May', + }, + { + london: 60, + paris: 63, + newYork: 103, + seoul: 144, + month: 'June', + }, + { + london: 59, + paris: 60, + newYork: 105, + seoul: 319, + month: 'July', + }, + { + london: 65, + paris: 60, + newYork: 106, + seoul: 249, + month: 'August', + }, + { + london: 51, + paris: 51, + newYork: 95, + seoul: 131, + month: 'September', + }, + { + london: 60, + paris: 65, + newYork: 97, + seoul: 55, + month: 'October', + }, + { + london: 67, + paris: 64, + newYork: 76, + seoul: 48, + month: 'November', + }, + { + london: 61, + paris: 70, + newYork: 103, + seoul: 25, + month: 'December', + }, +]; + +const data = dataset.flatMap( + ({ london, paris, newYork, seoul }, monthIndex): HeatmapValueType[] => [ + [0, monthIndex, london], + [1, monthIndex, paris], + [2, monthIndex, newYork], + [3, monthIndex, seoul], + ], +); + +const xData = ['London', 'Paris', 'NewYork', 'Seoul']; +const yData = dataset.flatMap(({ month }) => month); + +export default function ColorConfig() { + return ( + + ); +} diff --git a/docs/data/charts/heatmap/CustomItem.js b/docs/data/charts/heatmap/CustomItem.js new file mode 100644 index 000000000000..af945337ef9e --- /dev/null +++ b/docs/data/charts/heatmap/CustomItem.js @@ -0,0 +1,46 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import '@mui/x-charts-pro/typeOverloads'; +import { UnstableHeatmap } from '@mui/x-charts-pro/Heatmap'; +import { data } from './dumbData'; + +function CustomCell(props) { + const { x, y, width, height, ownerState, ...other } = props; + + return ( + + + + {ownerState.value} + + + ); +} +export default function CustomItem() { + return ( + + + + ); +} diff --git a/docs/data/charts/heatmap/CustomItem.tsx b/docs/data/charts/heatmap/CustomItem.tsx new file mode 100644 index 000000000000..68d8357eba5f --- /dev/null +++ b/docs/data/charts/heatmap/CustomItem.tsx @@ -0,0 +1,46 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import '@mui/x-charts-pro/typeOverloads'; +import { UnstableHeatmap } from '@mui/x-charts-pro/Heatmap'; +import { data } from './dumbData'; + +function CustomCell(props: any) { + const { x, y, width, height, ownerState, ...other } = props; + + return ( + + + + {ownerState.value} + + + ); +} +export default function CustomItem() { + return ( + + + + ); +} diff --git a/docs/data/charts/heatmap/CustomItem.tsx.preview b/docs/data/charts/heatmap/CustomItem.tsx.preview new file mode 100644 index 000000000000..9c1801cf7cd4 --- /dev/null +++ b/docs/data/charts/heatmap/CustomItem.tsx.preview @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/docs/data/charts/heatmap/HighlightClasses.js b/docs/data/charts/heatmap/HighlightClasses.js new file mode 100644 index 000000000000..b27be9e2dd09 --- /dev/null +++ b/docs/data/charts/heatmap/HighlightClasses.js @@ -0,0 +1,38 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import '@mui/x-charts-pro/typeOverloads'; +import { UnstableHeatmap, heatmapClasses } from '@mui/x-charts-pro/Heatmap'; +import { data } from './dumbData'; + +export default function HighlightClasses() { + return ( + + + + ); +} diff --git a/docs/data/charts/heatmap/HighlightClasses.tsx b/docs/data/charts/heatmap/HighlightClasses.tsx new file mode 100644 index 000000000000..b27be9e2dd09 --- /dev/null +++ b/docs/data/charts/heatmap/HighlightClasses.tsx @@ -0,0 +1,38 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import '@mui/x-charts-pro/typeOverloads'; +import { UnstableHeatmap, heatmapClasses } from '@mui/x-charts-pro/Heatmap'; +import { data } from './dumbData'; + +export default function HighlightClasses() { + return ( + + + + ); +} diff --git a/docs/data/charts/heatmap/HighlightHeatmap.js b/docs/data/charts/heatmap/HighlightHeatmap.js new file mode 100644 index 000000000000..10996aaeaac8 --- /dev/null +++ b/docs/data/charts/heatmap/HighlightHeatmap.js @@ -0,0 +1,19 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import '@mui/x-charts-pro/typeOverloads'; +import { UnstableHeatmap } from '@mui/x-charts-pro/Heatmap'; +import { data } from './dumbData'; + +export default function HighlightHeatmap() { + return ( + + + + ); +} diff --git a/docs/data/charts/heatmap/HighlightHeatmap.tsx b/docs/data/charts/heatmap/HighlightHeatmap.tsx new file mode 100644 index 000000000000..10996aaeaac8 --- /dev/null +++ b/docs/data/charts/heatmap/HighlightHeatmap.tsx @@ -0,0 +1,19 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import '@mui/x-charts-pro/typeOverloads'; +import { UnstableHeatmap } from '@mui/x-charts-pro/Heatmap'; +import { data } from './dumbData'; + +export default function HighlightHeatmap() { + return ( + + + + ); +} diff --git a/docs/data/charts/heatmap/HighlightHeatmap.tsx.preview b/docs/data/charts/heatmap/HighlightHeatmap.tsx.preview new file mode 100644 index 000000000000..5d6588033cb7 --- /dev/null +++ b/docs/data/charts/heatmap/HighlightHeatmap.tsx.preview @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/docs/data/charts/heatmap/dumbData.ts b/docs/data/charts/heatmap/dumbData.ts new file mode 100644 index 000000000000..4aa53b77c337 --- /dev/null +++ b/docs/data/charts/heatmap/dumbData.ts @@ -0,0 +1,24 @@ +import { HeatmapValueType } from '@mui/x-charts-pro/models'; + +export const data: HeatmapValueType[] = [ + [0, 0, 10], + [0, 1, 20], + [0, 2, 40], + [0, 3, 90], + [0, 4, 70], + [1, 0, 30], + [1, 1, 50], + [1, 2, 10], + [1, 3, 70], + [1, 4, 40], + [2, 0, 50], + [2, 1, 20], + [2, 2, 90], + [2, 3, 20], + [2, 4, 70], + [3, 0, 40], + [3, 1, 50], + [3, 2, 20], + [3, 3, 70], + [3, 4, 90], +]; diff --git a/docs/data/charts/heatmap/heatmap.md b/docs/data/charts/heatmap/heatmap.md index 6d6413b064b8..3f662ec18a17 100644 --- a/docs/data/charts/heatmap/heatmap.md +++ b/docs/data/charts/heatmap/heatmap.md @@ -5,11 +5,57 @@ productId: x-charts # Charts - Heatmap [](/x/introduction/licensing/#pro-plan 'Pro plan')🚧 -

Heatmap charts allow to highlight correlation between categories.

+

Heatmap charts visually represents data with color variations to highlight patterns and trends across two dimensions.

:::warning -The Heatmap Chart component isn't available yet, but you can upvote [**this GitHub issue**](https://github.com/mui/mui-x/issues/7926) 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. +The Heatmap Chart component isn't stable. Don't hesitate to open issues to give feedback. ::: + +## Basics + +The Heatmap requires two axes with `data` properties. +Those data defined the x and y categories. + +The series `data` is an array of 3-tuples. +The 2 first numbers are respectively the x and y indexes of the cell. +And the third is its value. + +{{"demo": "BasicHeatmap.js"}} + +## Customization + +### Color mapping + +To customize the color mapping, use the `zAxis` configuration. +You can either use the piecewise or continuous [color mapping](https://mui.com/x/react-charts/styling/#values-color). + +{{"demo": "ColorConfig.js"}} + +### Highlight + +You can chose to highlight the hovered element by setting `highlightScope.highlight` to `'item'`. +To fade the other item, set `highlightScope.fade` to `'global'`. + +{{"demo": "HighlightHeatmap.js"}} + +By default highlighted/faded effect is obtained by applying the CSS property `filter: saturate(...)` to cells. +To modify this styling, use the `heatmapClasses.highlighted` and `heatmapClasses.faded` CSS classes to override the applied style. + +In the following demo, we replace the highlight saturation by a border radius and reduce the saturation of the faded cells. + +{{"demo": "HighlightClasses.js"}} + +### Axes + +The Heatmap axes can be customized like any other chart axis. +The available options are available in the [dedicated page](/x/react-charts/axis/#axis-customization). + +### Tooltip 🚧 + +## Legend 🚧 + +## Labels 🚧 + +## Custom item + +{{"demo": "CustomItem.js"}} diff --git a/docs/data/charts/overview/overview.md b/docs/data/charts/overview/overview.md index 809be9b9a09c..ef86f4a0793f 100644 --- a/docs/data/charts/overview/overview.md +++ b/docs/data/charts/overview/overview.md @@ -9,7 +9,7 @@ packageName: '@mui/x-charts'

A fast and extendable library of react chart components for data visualization.

-{{"component": "modules/components/ComponentLinkHeader.js", "design": false}} +{{"component": "@mui/docs/ComponentLinkHeader", "design": false}} ## Overview diff --git a/docs/data/charts/pie-demo/OnSeriesItemClick.js b/docs/data/charts/pie-demo/OnSeriesItemClick.js index 9d8700081026..fadc705a390c 100644 --- a/docs/data/charts/pie-demo/OnSeriesItemClick.js +++ b/docs/data/charts/pie-demo/OnSeriesItemClick.js @@ -50,7 +50,7 @@ ${formatObject(identifier)}`} data: items, }, ]} - onClick={handleClick} + onItemClick={handleClick} width={400} height={200} margin={{ right: 200 }} diff --git a/docs/data/charts/pie-demo/OnSeriesItemClick.tsx b/docs/data/charts/pie-demo/OnSeriesItemClick.tsx index 69a1aa4b7246..2a3bb8c59293 100644 --- a/docs/data/charts/pie-demo/OnSeriesItemClick.tsx +++ b/docs/data/charts/pie-demo/OnSeriesItemClick.tsx @@ -54,7 +54,7 @@ ${formatObject(identifier)}`} data: items, }, ]} - onClick={handleClick} + onItemClick={handleClick} width={400} height={200} margin={{ right: 200 }} diff --git a/docs/data/charts/tooltip/tooltip.md b/docs/data/charts/tooltip/tooltip.md index fb73719e2df5..ee43c997e6ce 100644 --- a/docs/data/charts/tooltip/tooltip.md +++ b/docs/data/charts/tooltip/tooltip.md @@ -17,6 +17,7 @@ The tooltip can be triggered by two kinds of events: - `'item'`β€”when the user's mouse hovers over an item on the chart, the tooltip will display data about this specific item. - `'axis'`β€”the user's mouse position is associated with a value of the x-axis. The tooltip will display data about all series at this specific x value. +- `'none'`β€”disable the tooltip. {{"demo": "Interaction.js"}} diff --git a/docs/data/charts/zoom-and-pan/ZoomBarChart.js b/docs/data/charts/zoom-and-pan/ZoomBarChart.js new file mode 100644 index 000000000000..afefa3368145 --- /dev/null +++ b/docs/data/charts/zoom-and-pan/ZoomBarChart.js @@ -0,0 +1,117 @@ +import * as React from 'react'; +import { BarChartPro } from '@mui/x-charts-pro/BarChartPro'; + +export default function ZoomBarChart() { + return ( + v.y1), + }, + { + label: 'Series B', + data: data.map((v) => v.y2), + }, + ]} + /> + ); +} + +const data = [ + { + y1: 443.28, + y2: 153.9, + }, + { + y1: 110.5, + y2: 217.8, + }, + { + y1: 175.23, + y2: 286.32, + }, + { + y1: 195.97, + y2: 325.12, + }, + { + y1: 351.77, + y2: 144.58, + }, + { + y1: 43.253, + y2: 146.51, + }, + { + y1: 376.34, + y2: 309.69, + }, + { + y1: 31.514, + y2: 236.38, + }, + { + y1: 231.31, + y2: 440.72, + }, + { + y1: 108.04, + y2: 20.29, + }, + { + y1: 321.77, + y2: 484.17, + }, + { + y1: 120.18, + y2: 54.962, + }, + { + y1: 366.2, + y2: 418.5, + }, + { + y1: 451.45, + y2: 181.32, + }, + { + y1: 294.8, + y2: 440.9, + }, + { + y1: 121.83, + y2: 273.52, + }, + { + y1: 287.7, + y2: 346.7, + }, + { + y1: 134.06, + y2: 74.528, + }, + { + y1: 104.5, + y2: 150.9, + }, + { + y1: 413.07, + y2: 26.483, + }, + { + y1: 74.68, + y2: 333.2, + }, + { + y1: 360.6, + y2: 422.0, + }, + { + y1: 330.72, + y2: 488.06, + }, +]; diff --git a/docs/data/charts/zoom-and-pan/ZoomBarChart.tsx b/docs/data/charts/zoom-and-pan/ZoomBarChart.tsx new file mode 100644 index 000000000000..afefa3368145 --- /dev/null +++ b/docs/data/charts/zoom-and-pan/ZoomBarChart.tsx @@ -0,0 +1,117 @@ +import * as React from 'react'; +import { BarChartPro } from '@mui/x-charts-pro/BarChartPro'; + +export default function ZoomBarChart() { + return ( + v.y1), + }, + { + label: 'Series B', + data: data.map((v) => v.y2), + }, + ]} + /> + ); +} + +const data = [ + { + y1: 443.28, + y2: 153.9, + }, + { + y1: 110.5, + y2: 217.8, + }, + { + y1: 175.23, + y2: 286.32, + }, + { + y1: 195.97, + y2: 325.12, + }, + { + y1: 351.77, + y2: 144.58, + }, + { + y1: 43.253, + y2: 146.51, + }, + { + y1: 376.34, + y2: 309.69, + }, + { + y1: 31.514, + y2: 236.38, + }, + { + y1: 231.31, + y2: 440.72, + }, + { + y1: 108.04, + y2: 20.29, + }, + { + y1: 321.77, + y2: 484.17, + }, + { + y1: 120.18, + y2: 54.962, + }, + { + y1: 366.2, + y2: 418.5, + }, + { + y1: 451.45, + y2: 181.32, + }, + { + y1: 294.8, + y2: 440.9, + }, + { + y1: 121.83, + y2: 273.52, + }, + { + y1: 287.7, + y2: 346.7, + }, + { + y1: 134.06, + y2: 74.528, + }, + { + y1: 104.5, + y2: 150.9, + }, + { + y1: 413.07, + y2: 26.483, + }, + { + y1: 74.68, + y2: 333.2, + }, + { + y1: 360.6, + y2: 422.0, + }, + { + y1: 330.72, + y2: 488.06, + }, +]; diff --git a/docs/data/charts/zoom-and-pan/ZoomBarChart.tsx.preview b/docs/data/charts/zoom-and-pan/ZoomBarChart.tsx.preview new file mode 100644 index 000000000000..b54614a7af00 --- /dev/null +++ b/docs/data/charts/zoom-and-pan/ZoomBarChart.tsx.preview @@ -0,0 +1,15 @@ + v.y1), + }, + { + label: 'Series B', + data: data.map((v) => v.y2), + }, + ]} +/> \ No newline at end of file diff --git a/docs/data/charts/zoom-and-pan/ZoomLineChart.js b/docs/data/charts/zoom-and-pan/ZoomLineChart.js new file mode 100644 index 000000000000..e792dfc45797 --- /dev/null +++ b/docs/data/charts/zoom-and-pan/ZoomLineChart.js @@ -0,0 +1,117 @@ +import * as React from 'react'; +import { LineChartPro } from '@mui/x-charts-pro/LineChartPro'; + +export default function ZoomLineChart() { + return ( + v.y1), + }, + { + label: 'Series B', + data: data.map((v) => v.y2), + }, + ]} + /> + ); +} + +const data = [ + { + y1: 443.28, + y2: 153.9, + }, + { + y1: 110.5, + y2: 217.8, + }, + { + y1: 175.23, + y2: 286.32, + }, + { + y1: 195.97, + y2: 325.12, + }, + { + y1: 351.77, + y2: 144.58, + }, + { + y1: 43.253, + y2: 146.51, + }, + { + y1: 376.34, + y2: 309.69, + }, + { + y1: 31.514, + y2: 236.38, + }, + { + y1: 231.31, + y2: 440.72, + }, + { + y1: 108.04, + y2: 20.29, + }, + { + y1: 321.77, + y2: 484.17, + }, + { + y1: 120.18, + y2: 54.962, + }, + { + y1: 366.2, + y2: 418.5, + }, + { + y1: 451.45, + y2: 181.32, + }, + { + y1: 294.8, + y2: 440.9, + }, + { + y1: 121.83, + y2: 273.52, + }, + { + y1: 287.7, + y2: 346.7, + }, + { + y1: 134.06, + y2: 74.528, + }, + { + y1: 104.5, + y2: 150.9, + }, + { + y1: 413.07, + y2: 26.483, + }, + { + y1: 74.68, + y2: 333.2, + }, + { + y1: 360.6, + y2: 422.0, + }, + { + y1: 330.72, + y2: 488.06, + }, +]; diff --git a/docs/data/charts/zoom-and-pan/ZoomLineChart.tsx b/docs/data/charts/zoom-and-pan/ZoomLineChart.tsx new file mode 100644 index 000000000000..e792dfc45797 --- /dev/null +++ b/docs/data/charts/zoom-and-pan/ZoomLineChart.tsx @@ -0,0 +1,117 @@ +import * as React from 'react'; +import { LineChartPro } from '@mui/x-charts-pro/LineChartPro'; + +export default function ZoomLineChart() { + return ( + v.y1), + }, + { + label: 'Series B', + data: data.map((v) => v.y2), + }, + ]} + /> + ); +} + +const data = [ + { + y1: 443.28, + y2: 153.9, + }, + { + y1: 110.5, + y2: 217.8, + }, + { + y1: 175.23, + y2: 286.32, + }, + { + y1: 195.97, + y2: 325.12, + }, + { + y1: 351.77, + y2: 144.58, + }, + { + y1: 43.253, + y2: 146.51, + }, + { + y1: 376.34, + y2: 309.69, + }, + { + y1: 31.514, + y2: 236.38, + }, + { + y1: 231.31, + y2: 440.72, + }, + { + y1: 108.04, + y2: 20.29, + }, + { + y1: 321.77, + y2: 484.17, + }, + { + y1: 120.18, + y2: 54.962, + }, + { + y1: 366.2, + y2: 418.5, + }, + { + y1: 451.45, + y2: 181.32, + }, + { + y1: 294.8, + y2: 440.9, + }, + { + y1: 121.83, + y2: 273.52, + }, + { + y1: 287.7, + y2: 346.7, + }, + { + y1: 134.06, + y2: 74.528, + }, + { + y1: 104.5, + y2: 150.9, + }, + { + y1: 413.07, + y2: 26.483, + }, + { + y1: 74.68, + y2: 333.2, + }, + { + y1: 360.6, + y2: 422.0, + }, + { + y1: 330.72, + y2: 488.06, + }, +]; diff --git a/docs/data/charts/zoom-and-pan/ZoomLineChart.tsx.preview b/docs/data/charts/zoom-and-pan/ZoomLineChart.tsx.preview new file mode 100644 index 000000000000..d26060a66574 --- /dev/null +++ b/docs/data/charts/zoom-and-pan/ZoomLineChart.tsx.preview @@ -0,0 +1,15 @@ + v.y1), + }, + { + label: 'Series B', + data: data.map((v) => v.y2), + }, + ]} +/> \ No newline at end of file diff --git a/docs/data/charts/zoom-and-pan/ZoomScatterChart.js b/docs/data/charts/zoom-and-pan/ZoomScatterChart.js new file mode 100644 index 000000000000..43faf6db2f4b --- /dev/null +++ b/docs/data/charts/zoom-and-pan/ZoomScatterChart.js @@ -0,0 +1,186 @@ +import * as React from 'react'; +import { ScatterChartPro } from '@mui/x-charts-pro/ScatterChartPro'; + +export default function ZoomScatterChart() { + return ( + ({ x: v.x1, y: v.y1, id: v.id })), + }, + { + label: 'Series B', + data: data.map((v) => ({ x: v.x1, y: v.y2, id: v.id })), + }, + ]} + /> + ); +} + +const data = [ + { + id: 'data-0', + x1: 329.39, + x2: 391.29, + y1: 443.28, + y2: 153.9, + }, + { + id: 'data-1', + x1: 96.94, + x2: 139.6, + y1: 110.5, + y2: 217.8, + }, + { + id: 'data-2', + x1: 336.35, + x2: 282.34, + y1: 175.23, + y2: 286.32, + }, + { + id: 'data-3', + x1: 159.44, + x2: 384.85, + y1: 195.97, + y2: 325.12, + }, + { + id: 'data-4', + x1: 188.86, + x2: 182.27, + y1: 351.77, + y2: 144.58, + }, + { + id: 'data-5', + x1: 143.86, + x2: 360.22, + y1: 43.253, + y2: 146.51, + }, + { + id: 'data-6', + x1: 202.02, + x2: 209.5, + y1: 376.34, + y2: 309.69, + }, + { + id: 'data-7', + x1: 384.41, + x2: 258.93, + y1: 31.514, + y2: 236.38, + }, + { + id: 'data-8', + x1: 256.76, + x2: 70.571, + y1: 231.31, + y2: 440.72, + }, + { + id: 'data-9', + x1: 143.79, + x2: 419.02, + y1: 108.04, + y2: 20.29, + }, + { + id: 'data-10', + x1: 103.48, + x2: 15.886, + y1: 321.77, + y2: 484.17, + }, + { + id: 'data-11', + x1: 272.39, + x2: 189.03, + y1: 120.18, + y2: 54.962, + }, + { + id: 'data-12', + x1: 23.57, + x2: 456.4, + y1: 366.2, + y2: 418.5, + }, + { + id: 'data-13', + x1: 219.73, + x2: 235.96, + y1: 451.45, + y2: 181.32, + }, + { + id: 'data-14', + x1: 54.99, + x2: 434.5, + y1: 294.8, + y2: 440.9, + }, + { + id: 'data-15', + x1: 134.13, + x2: 383.8, + y1: 121.83, + y2: 273.52, + }, + { + id: 'data-16', + x1: 12.7, + x2: 270.8, + y1: 287.7, + y2: 346.7, + }, + { + id: 'data-17', + x1: 176.51, + x2: 119.17, + y1: 134.06, + y2: 74.528, + }, + { + id: 'data-18', + x1: 65.05, + x2: 78.93, + y1: 104.5, + y2: 150.9, + }, + { + id: 'data-19', + x1: 162.25, + x2: 63.707, + y1: 413.07, + y2: 26.483, + }, + { + id: 'data-20', + x1: 68.88, + x2: 150.8, + y1: 74.68, + y2: 333.2, + }, + { + id: 'data-21', + x1: 95.29, + x2: 329.1, + y1: 360.6, + y2: 422.0, + }, + { + id: 'data-22', + x1: 390.62, + x2: 10.01, + y1: 330.72, + y2: 488.06, + }, +]; diff --git a/docs/data/charts/zoom-and-pan/ZoomScatterChart.tsx b/docs/data/charts/zoom-and-pan/ZoomScatterChart.tsx new file mode 100644 index 000000000000..43faf6db2f4b --- /dev/null +++ b/docs/data/charts/zoom-and-pan/ZoomScatterChart.tsx @@ -0,0 +1,186 @@ +import * as React from 'react'; +import { ScatterChartPro } from '@mui/x-charts-pro/ScatterChartPro'; + +export default function ZoomScatterChart() { + return ( + ({ x: v.x1, y: v.y1, id: v.id })), + }, + { + label: 'Series B', + data: data.map((v) => ({ x: v.x1, y: v.y2, id: v.id })), + }, + ]} + /> + ); +} + +const data = [ + { + id: 'data-0', + x1: 329.39, + x2: 391.29, + y1: 443.28, + y2: 153.9, + }, + { + id: 'data-1', + x1: 96.94, + x2: 139.6, + y1: 110.5, + y2: 217.8, + }, + { + id: 'data-2', + x1: 336.35, + x2: 282.34, + y1: 175.23, + y2: 286.32, + }, + { + id: 'data-3', + x1: 159.44, + x2: 384.85, + y1: 195.97, + y2: 325.12, + }, + { + id: 'data-4', + x1: 188.86, + x2: 182.27, + y1: 351.77, + y2: 144.58, + }, + { + id: 'data-5', + x1: 143.86, + x2: 360.22, + y1: 43.253, + y2: 146.51, + }, + { + id: 'data-6', + x1: 202.02, + x2: 209.5, + y1: 376.34, + y2: 309.69, + }, + { + id: 'data-7', + x1: 384.41, + x2: 258.93, + y1: 31.514, + y2: 236.38, + }, + { + id: 'data-8', + x1: 256.76, + x2: 70.571, + y1: 231.31, + y2: 440.72, + }, + { + id: 'data-9', + x1: 143.79, + x2: 419.02, + y1: 108.04, + y2: 20.29, + }, + { + id: 'data-10', + x1: 103.48, + x2: 15.886, + y1: 321.77, + y2: 484.17, + }, + { + id: 'data-11', + x1: 272.39, + x2: 189.03, + y1: 120.18, + y2: 54.962, + }, + { + id: 'data-12', + x1: 23.57, + x2: 456.4, + y1: 366.2, + y2: 418.5, + }, + { + id: 'data-13', + x1: 219.73, + x2: 235.96, + y1: 451.45, + y2: 181.32, + }, + { + id: 'data-14', + x1: 54.99, + x2: 434.5, + y1: 294.8, + y2: 440.9, + }, + { + id: 'data-15', + x1: 134.13, + x2: 383.8, + y1: 121.83, + y2: 273.52, + }, + { + id: 'data-16', + x1: 12.7, + x2: 270.8, + y1: 287.7, + y2: 346.7, + }, + { + id: 'data-17', + x1: 176.51, + x2: 119.17, + y1: 134.06, + y2: 74.528, + }, + { + id: 'data-18', + x1: 65.05, + x2: 78.93, + y1: 104.5, + y2: 150.9, + }, + { + id: 'data-19', + x1: 162.25, + x2: 63.707, + y1: 413.07, + y2: 26.483, + }, + { + id: 'data-20', + x1: 68.88, + x2: 150.8, + y1: 74.68, + y2: 333.2, + }, + { + id: 'data-21', + x1: 95.29, + x2: 329.1, + y1: 360.6, + y2: 422.0, + }, + { + id: 'data-22', + x1: 390.62, + x2: 10.01, + y1: 330.72, + y2: 488.06, + }, +]; diff --git a/docs/data/charts/zoom-and-pan/ZoomScatterChart.tsx.preview b/docs/data/charts/zoom-and-pan/ZoomScatterChart.tsx.preview new file mode 100644 index 000000000000..9f4bf4a61add --- /dev/null +++ b/docs/data/charts/zoom-and-pan/ZoomScatterChart.tsx.preview @@ -0,0 +1,15 @@ + ({ x: v.x1, y: v.y1, id: v.id })), + }, + { + label: 'Series B', + data: data.map((v) => ({ x: v.x1, y: v.y2, id: v.id })), + }, + ]} +/> \ No newline at end of file diff --git a/docs/data/charts/zoom-and-pan/zoom-and-pan.md b/docs/data/charts/zoom-and-pan/zoom-and-pan.md new file mode 100644 index 000000000000..f2b80cd8eab0 --- /dev/null +++ b/docs/data/charts/zoom-and-pan/zoom-and-pan.md @@ -0,0 +1,30 @@ +--- +title: Zoom & Pan +productId: x-charts +--- + +# Zoom & Pan [](/x/introduction/licensing/#pro-plan 'Pro plan') 🚧 + +

Enables zooming and panning on specific charts or axis.

+ +Zooming is possible on the **Pro**[](/x/introduction/licensing/#pro-plan 'Pro plan') versions of the charts: ``, ``, ``. + +:::warning +Zooming is currently only possible on the `X axis`. +::: + +## Basic usage + +To enable zooming and panning, set the `zoom` prop to `true` on the chart component. + +Enabling zoom will enable all the interactions, which are made to be as intuitive as possible. + +The following actions are supported: + +- **Scroll**: Zoom in/out by scrolling the mouse wheel. +- **Drag**: Pan the chart by dragging the mouse. +- **Pinch**: Zoom in/out by pinching the chart. + +{{"demo": "ZoomScatterChart.js"}} +{{"demo": "ZoomBarChart.js"}} +{{"demo": "ZoomLineChart.js"}} diff --git a/docs/data/data-grid/components/CustomEmptyOverlayGrid.js b/docs/data/data-grid/components/CustomEmptyOverlayGrid.js deleted file mode 100644 index 7bff6c5033d8..000000000000 --- a/docs/data/data-grid/components/CustomEmptyOverlayGrid.js +++ /dev/null @@ -1,96 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/material/Box'; -import { DataGrid } from '@mui/x-data-grid'; -import { useDemoData } from '@mui/x-data-grid-generator'; -import { styled } from '@mui/material/styles'; - -const StyledGridOverlay = styled('div')(({ theme }) => ({ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - height: '100%', - '& .ant-empty-img-1': { - fill: theme.palette.mode === 'light' ? '#aeb8c2' : '#262626', - }, - '& .ant-empty-img-2': { - fill: theme.palette.mode === 'light' ? '#f5f5f7' : '#595959', - }, - '& .ant-empty-img-3': { - fill: theme.palette.mode === 'light' ? '#dce0e6' : '#434343', - }, - '& .ant-empty-img-4': { - fill: theme.palette.mode === 'light' ? '#fff' : '#1c1c1c', - }, - '& .ant-empty-img-5': { - fillOpacity: theme.palette.mode === 'light' ? '0.8' : '0.08', - fill: theme.palette.mode === 'light' ? '#f5f5f5' : '#fff', - }, -})); - -function CustomNoRowsOverlay() { - return ( - - - - - - - - - - - - - - - - - No Rows - - ); -} - -export default function CustomEmptyOverlayGrid() { - const { data } = useDemoData({ - dataSet: 'Commodity', - rowLength: 100, - maxColumns: 6, - }); - - return ( -
- -
- ); -} diff --git a/docs/data/data-grid/components/CustomEmptyOverlayGrid.tsx b/docs/data/data-grid/components/CustomEmptyOverlayGrid.tsx deleted file mode 100644 index 7bff6c5033d8..000000000000 --- a/docs/data/data-grid/components/CustomEmptyOverlayGrid.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/material/Box'; -import { DataGrid } from '@mui/x-data-grid'; -import { useDemoData } from '@mui/x-data-grid-generator'; -import { styled } from '@mui/material/styles'; - -const StyledGridOverlay = styled('div')(({ theme }) => ({ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - height: '100%', - '& .ant-empty-img-1': { - fill: theme.palette.mode === 'light' ? '#aeb8c2' : '#262626', - }, - '& .ant-empty-img-2': { - fill: theme.palette.mode === 'light' ? '#f5f5f7' : '#595959', - }, - '& .ant-empty-img-3': { - fill: theme.palette.mode === 'light' ? '#dce0e6' : '#434343', - }, - '& .ant-empty-img-4': { - fill: theme.palette.mode === 'light' ? '#fff' : '#1c1c1c', - }, - '& .ant-empty-img-5': { - fillOpacity: theme.palette.mode === 'light' ? '0.8' : '0.08', - fill: theme.palette.mode === 'light' ? '#f5f5f5' : '#fff', - }, -})); - -function CustomNoRowsOverlay() { - return ( - - - - - - - - - - - - - - - - - No Rows - - ); -} - -export default function CustomEmptyOverlayGrid() { - const { data } = useDemoData({ - dataSet: 'Commodity', - rowLength: 100, - maxColumns: 6, - }); - - return ( -
- -
- ); -} diff --git a/docs/data/data-grid/components/CustomLoadingOverlayGrid.tsx b/docs/data/data-grid/components/CustomLoadingOverlayGrid.tsx deleted file mode 100644 index c278f02c68a4..000000000000 --- a/docs/data/data-grid/components/CustomLoadingOverlayGrid.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import * as React from 'react'; -import { DataGrid, GridSlots } from '@mui/x-data-grid'; -import LinearProgress from '@mui/material/LinearProgress'; -import { useDemoData } from '@mui/x-data-grid-generator'; - -export default function CustomLoadingOverlayGrid() { - const { data } = useDemoData({ - dataSet: 'Commodity', - rowLength: 100, - maxColumns: 6, - }); - - return ( -
- -
- ); -} diff --git a/docs/data/data-grid/components/CustomLoadingOverlayGrid.tsx.preview b/docs/data/data-grid/components/CustomLoadingOverlayGrid.tsx.preview deleted file mode 100644 index 84c2df95e838..000000000000 --- a/docs/data/data-grid/components/CustomLoadingOverlayGrid.tsx.preview +++ /dev/null @@ -1,7 +0,0 @@ - \ No newline at end of file diff --git a/docs/data/data-grid/components/components.md b/docs/data/data-grid/components/components.md index b94195c7f74a..6d78d7487beb 100644 --- a/docs/data/data-grid/components/components.md +++ b/docs/data/data-grid/components/components.md @@ -128,23 +128,6 @@ The next demo reuses `GridPagination` but replaces the previous and next page bu {{"demo": "CustomPaginationGrid.js", "bg": "inline"}} -### Loading overlay - -By default, the loading overlay displays a circular progress. -This demo replaces it with a linear progress. - -{{"demo": "CustomLoadingOverlayGrid.js", "bg": "inline"}} - -### No rows overlay - -In the following demo, an illustration is added on top of the default "No Rows" message. - -{{"demo": "CustomEmptyOverlayGrid.js", "bg": "inline"}} - -:::info -As with the no-rows overlay, the Data Grid also lets you override the no-results overlay using the `NoResultsOverlay` slot. -::: - ### Row The `slotProps.row` prop can be used to pass additional props to the row component. @@ -166,6 +149,10 @@ As any component slot, every icon can be customized. However, it is not yet poss {{"demo": "CustomSortIcons.js", "bg": "inline"}} +### Overlays + +See the [Overlays](/x/react-data-grid/overlays/) documentation on how to customize the `loadingOverlay`, `noRowsOverlay`, and `noResultsOverlay`. + ## Slot props To override default props or pass custom props to slot components, use the `slotProps` prop. diff --git a/docs/data/data-grid/layout/AutoHeightOverlayNoSnap.js b/docs/data/data-grid/layout/AutoHeightOverlayNoSnap.js index 0f9b9382f16e..b52f36d8eb20 100644 --- a/docs/data/data-grid/layout/AutoHeightOverlayNoSnap.js +++ b/docs/data/data-grid/layout/AutoHeightOverlayNoSnap.js @@ -9,21 +9,11 @@ const StyledGridOverlay = styled('div')(({ theme }) => ({ alignItems: 'center', justifyContent: 'center', height: '100%', - '& .ant-empty-img-1': { - fill: theme.palette.mode === 'light' ? '#aeb8c2' : '#262626', + '& .no-rows-primary': { + fill: theme.palette.mode === 'light' ? '#AEB8C2' : '#3D4751', }, - '& .ant-empty-img-2': { - fill: theme.palette.mode === 'light' ? '#f5f5f7' : '#595959', - }, - '& .ant-empty-img-3': { - fill: theme.palette.mode === 'light' ? '#dce0e6' : '#434343', - }, - '& .ant-empty-img-4': { - fill: theme.palette.mode === 'light' ? '#fff' : '#1c1c1c', - }, - '& .ant-empty-img-5': { - fillOpacity: theme.palette.mode === 'light' ? '0.8' : '0.08', - fill: theme.palette.mode === 'light' ? '#f5f5f5' : '#fff', + '& .no-rows-secondary': { + fill: theme.palette.mode === 'light' ? '#E8EAED' : '#1D2126', }, })); @@ -31,46 +21,31 @@ function CustomNoRowsOverlay() { return ( - - - - - - - - - - - - - + + + + - No Rows + No rows ); } diff --git a/docs/data/data-grid/layout/AutoHeightOverlayNoSnap.tsx b/docs/data/data-grid/layout/AutoHeightOverlayNoSnap.tsx index 0f9b9382f16e..b52f36d8eb20 100644 --- a/docs/data/data-grid/layout/AutoHeightOverlayNoSnap.tsx +++ b/docs/data/data-grid/layout/AutoHeightOverlayNoSnap.tsx @@ -9,21 +9,11 @@ const StyledGridOverlay = styled('div')(({ theme }) => ({ alignItems: 'center', justifyContent: 'center', height: '100%', - '& .ant-empty-img-1': { - fill: theme.palette.mode === 'light' ? '#aeb8c2' : '#262626', + '& .no-rows-primary': { + fill: theme.palette.mode === 'light' ? '#AEB8C2' : '#3D4751', }, - '& .ant-empty-img-2': { - fill: theme.palette.mode === 'light' ? '#f5f5f7' : '#595959', - }, - '& .ant-empty-img-3': { - fill: theme.palette.mode === 'light' ? '#dce0e6' : '#434343', - }, - '& .ant-empty-img-4': { - fill: theme.palette.mode === 'light' ? '#fff' : '#1c1c1c', - }, - '& .ant-empty-img-5': { - fillOpacity: theme.palette.mode === 'light' ? '0.8' : '0.08', - fill: theme.palette.mode === 'light' ? '#f5f5f5' : '#fff', + '& .no-rows-secondary': { + fill: theme.palette.mode === 'light' ? '#E8EAED' : '#1D2126', }, })); @@ -31,46 +21,31 @@ function CustomNoRowsOverlay() { return ( - - - - - - - - - - - - - + + + + - No Rows + No rows ); } diff --git a/docs/data/data-grid/layout/layout.md b/docs/data/data-grid/layout/layout.md index 67ff5ce52e17..1c960eb659dd 100644 --- a/docs/data/data-grid/layout/layout.md +++ b/docs/data/data-grid/layout/layout.md @@ -33,9 +33,9 @@ This is not recommended for large datasets as row virtualization will not be abl ### Overlay height -When `autoHeight` is enabled but there are no rows, grid overlays (such as -["Loading"](/x/react-data-grid/components/#loading-overlay) or -["No rows"](/x/react-data-grid/components/#no-rows-overlay)) +When `autoHeight` is enabled, grid overlays (such as +["Loading"](/x/react-data-grid/overlays/#loading-overlay) or +["No rows"](/x/react-data-grid/overlays/#no-rows-overlay)) take the height of two rows by default. To customize the overlay height, use the `--DataGrid-overlayHeight` CSS variable. diff --git a/docs/data/data-grid/overlays/LoadingOverlay.js b/docs/data/data-grid/overlays/LoadingOverlay.js new file mode 100644 index 000000000000..333a904448f6 --- /dev/null +++ b/docs/data/data-grid/overlays/LoadingOverlay.js @@ -0,0 +1,18 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { DataGrid } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; + +export default function LoadingOverlay() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 6, + maxColumns: 6, + }); + + return ( + + + + ); +} diff --git a/docs/data/data-grid/overlays/LoadingOverlay.tsx b/docs/data/data-grid/overlays/LoadingOverlay.tsx new file mode 100644 index 000000000000..333a904448f6 --- /dev/null +++ b/docs/data/data-grid/overlays/LoadingOverlay.tsx @@ -0,0 +1,18 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { DataGrid } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; + +export default function LoadingOverlay() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 6, + maxColumns: 6, + }); + + return ( + + + + ); +} diff --git a/docs/data/data-grid/overlays/LoadingOverlay.tsx.preview b/docs/data/data-grid/overlays/LoadingOverlay.tsx.preview new file mode 100644 index 000000000000..0948ca9faeec --- /dev/null +++ b/docs/data/data-grid/overlays/LoadingOverlay.tsx.preview @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/overlays/LoadingOverlayCustom.js b/docs/data/data-grid/overlays/LoadingOverlayCustom.js new file mode 100644 index 000000000000..a936b4296f19 --- /dev/null +++ b/docs/data/data-grid/overlays/LoadingOverlayCustom.js @@ -0,0 +1,80 @@ +import * as React from 'react'; +import { DataGrid } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; +import { styled } from '@mui/material/styles'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import CircularProgress from '@mui/material/CircularProgress'; + +const StyledGridOverlay = styled('div')(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + height: '100%', + backgroundColor: + theme.palette.mode === 'light' + ? 'rgba(255, 255, 255, 0.9)' + : 'rgba(18, 18, 18, 0.9)', +})); + +function CircularProgressWithLabel(props) { + return ( + + + + + {`${Math.round(props.value)}%`} + + + + ); +} + +function CustomLoadingOverlay() { + const [progress, setProgress] = React.useState(10); + + React.useEffect(() => { + const timer = setInterval(() => { + setProgress((prevProgress) => (prevProgress >= 100 ? 0 : prevProgress + 10)); + }, 800); + return () => { + clearInterval(timer); + }; + }, []); + + return ( + + + Loading rows… + + ); +} + +export default function LoadingOverlayCustom() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 100, + maxColumns: 6, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/overlays/LoadingOverlayCustom.tsx b/docs/data/data-grid/overlays/LoadingOverlayCustom.tsx new file mode 100644 index 000000000000..59209a50e686 --- /dev/null +++ b/docs/data/data-grid/overlays/LoadingOverlayCustom.tsx @@ -0,0 +1,86 @@ +import * as React from 'react'; +import { DataGrid } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; +import { styled } from '@mui/material/styles'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import CircularProgress, { + CircularProgressProps, +} from '@mui/material/CircularProgress'; + +const StyledGridOverlay = styled('div')(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + height: '100%', + backgroundColor: + theme.palette.mode === 'light' + ? 'rgba(255, 255, 255, 0.9)' + : 'rgba(18, 18, 18, 0.9)', +})); + +function CircularProgressWithLabel( + props: CircularProgressProps & { value: number }, +) { + return ( + + + + {`${Math.round(props.value)}%`} + + + ); +} + +function CustomLoadingOverlay() { + const [progress, setProgress] = React.useState(10); + + React.useEffect(() => { + const timer = setInterval(() => { + setProgress((prevProgress) => (prevProgress >= 100 ? 0 : prevProgress + 10)); + }, 800); + return () => { + clearInterval(timer); + }; + }, []); + + return ( + + + Loading rows… + + ); +} + +export default function LoadingOverlayCustom() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 100, + maxColumns: 6, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/overlays/LoadingOverlayCustom.tsx.preview b/docs/data/data-grid/overlays/LoadingOverlayCustom.tsx.preview new file mode 100644 index 000000000000..55daad1518bb --- /dev/null +++ b/docs/data/data-grid/overlays/LoadingOverlayCustom.tsx.preview @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/components/CustomLoadingOverlayGrid.js b/docs/data/data-grid/overlays/LoadingOverlayLinearProgress.js similarity index 52% rename from docs/data/data-grid/components/CustomLoadingOverlayGrid.js rename to docs/data/data-grid/overlays/LoadingOverlayLinearProgress.js index fef9a8145a76..5ad0b8a4b3e5 100644 --- a/docs/data/data-grid/components/CustomLoadingOverlayGrid.js +++ b/docs/data/data-grid/overlays/LoadingOverlayLinearProgress.js @@ -1,9 +1,9 @@ import * as React from 'react'; -import { DataGrid } from '@mui/x-data-grid'; -import LinearProgress from '@mui/material/LinearProgress'; +import Box from '@mui/material/Box'; import { useDemoData } from '@mui/x-data-grid-generator'; +import { DataGrid } from '@mui/x-data-grid'; -export default function CustomLoadingOverlayGrid() { +export default function LoadingOverlayLinearProgress() { const { data } = useDemoData({ dataSet: 'Commodity', rowLength: 100, @@ -11,14 +11,17 @@ export default function CustomLoadingOverlayGrid() { }); return ( -
+ -
+ ); } diff --git a/docs/data/data-grid/overlays/LoadingOverlayLinearProgress.tsx b/docs/data/data-grid/overlays/LoadingOverlayLinearProgress.tsx new file mode 100644 index 000000000000..5ad0b8a4b3e5 --- /dev/null +++ b/docs/data/data-grid/overlays/LoadingOverlayLinearProgress.tsx @@ -0,0 +1,27 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { useDemoData } from '@mui/x-data-grid-generator'; +import { DataGrid } from '@mui/x-data-grid'; + +export default function LoadingOverlayLinearProgress() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 100, + maxColumns: 6, + }); + + return ( + + + + ); +} diff --git a/docs/data/data-grid/overlays/LoadingOverlayLinearProgress.tsx.preview b/docs/data/data-grid/overlays/LoadingOverlayLinearProgress.tsx.preview new file mode 100644 index 000000000000..f4e0a9ef7417 --- /dev/null +++ b/docs/data/data-grid/overlays/LoadingOverlayLinearProgress.tsx.preview @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/overlays/LoadingOverlaySkeleton.js b/docs/data/data-grid/overlays/LoadingOverlaySkeleton.js new file mode 100644 index 000000000000..0e86a253dfcd --- /dev/null +++ b/docs/data/data-grid/overlays/LoadingOverlaySkeleton.js @@ -0,0 +1,32 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { useDemoData } from '@mui/x-data-grid-generator'; +import { DataGridPro } from '@mui/x-data-grid-pro'; + +export default function LoadingOverlaySkeleton() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 100, + maxColumns: 9, + }); + + return ( + + + + ); +} diff --git a/docs/data/data-grid/overlays/LoadingOverlaySkeleton.tsx b/docs/data/data-grid/overlays/LoadingOverlaySkeleton.tsx new file mode 100644 index 000000000000..0e86a253dfcd --- /dev/null +++ b/docs/data/data-grid/overlays/LoadingOverlaySkeleton.tsx @@ -0,0 +1,32 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { useDemoData } from '@mui/x-data-grid-generator'; +import { DataGridPro } from '@mui/x-data-grid-pro'; + +export default function LoadingOverlaySkeleton() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 100, + maxColumns: 9, + }); + + return ( + + + + ); +} diff --git a/docs/data/data-grid/overlays/LoadingOverlaySkeleton.tsx.preview b/docs/data/data-grid/overlays/LoadingOverlaySkeleton.tsx.preview new file mode 100644 index 000000000000..9173142c9f99 --- /dev/null +++ b/docs/data/data-grid/overlays/LoadingOverlaySkeleton.tsx.preview @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/overlays/NoResultsOverlay.js b/docs/data/data-grid/overlays/NoResultsOverlay.js new file mode 100644 index 000000000000..e112ec11cd38 --- /dev/null +++ b/docs/data/data-grid/overlays/NoResultsOverlay.js @@ -0,0 +1,35 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { DataGrid, GridToolbar } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; + +export default function NoResultsOverlay() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 6, + maxColumns: 6, + }); + + return ( + + + + ); +} diff --git a/docs/data/data-grid/overlays/NoResultsOverlay.tsx b/docs/data/data-grid/overlays/NoResultsOverlay.tsx new file mode 100644 index 000000000000..e112ec11cd38 --- /dev/null +++ b/docs/data/data-grid/overlays/NoResultsOverlay.tsx @@ -0,0 +1,35 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { DataGrid, GridToolbar } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; + +export default function NoResultsOverlay() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 6, + maxColumns: 6, + }); + + return ( + + + + ); +} diff --git a/docs/data/data-grid/overlays/NoResultsOverlayCustom.js b/docs/data/data-grid/overlays/NoResultsOverlayCustom.js new file mode 100644 index 000000000000..15320b97081c --- /dev/null +++ b/docs/data/data-grid/overlays/NoResultsOverlayCustom.js @@ -0,0 +1,85 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { DataGrid, GridToolbar } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; +import { styled } from '@mui/material/styles'; + +const StyledGridOverlay = styled('div')(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + height: '100%', + '& .no-results-primary': { + fill: theme.palette.mode === 'light' ? '#AEB8C2' : '#3D4751', + }, + '& .no-results-secondary': { + fill: theme.palette.mode === 'light' ? '#E8EAED' : '#1D2126', + }, +})); + +function CustomNoResultsOverlay() { + return ( + + + + + + + + No results found. + + ); +} + +export default function NoResultsOverlayCustom() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 6, + maxColumns: 6, + }); + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/overlays/NoResultsOverlayCustom.tsx b/docs/data/data-grid/overlays/NoResultsOverlayCustom.tsx new file mode 100644 index 000000000000..15320b97081c --- /dev/null +++ b/docs/data/data-grid/overlays/NoResultsOverlayCustom.tsx @@ -0,0 +1,85 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { DataGrid, GridToolbar } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; +import { styled } from '@mui/material/styles'; + +const StyledGridOverlay = styled('div')(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + height: '100%', + '& .no-results-primary': { + fill: theme.palette.mode === 'light' ? '#AEB8C2' : '#3D4751', + }, + '& .no-results-secondary': { + fill: theme.palette.mode === 'light' ? '#E8EAED' : '#1D2126', + }, +})); + +function CustomNoResultsOverlay() { + return ( + + + + + + + + No results found. + + ); +} + +export default function NoResultsOverlayCustom() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 6, + maxColumns: 6, + }); + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/overlays/NoRowsOverlay.js b/docs/data/data-grid/overlays/NoRowsOverlay.js new file mode 100644 index 000000000000..d748985be91a --- /dev/null +++ b/docs/data/data-grid/overlays/NoRowsOverlay.js @@ -0,0 +1,18 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { DataGrid } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; + +export default function NoRowsOverlay() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 0, + maxColumns: 6, + }); + + return ( + + + + ); +} diff --git a/docs/data/data-grid/overlays/NoRowsOverlay.tsx b/docs/data/data-grid/overlays/NoRowsOverlay.tsx new file mode 100644 index 000000000000..d748985be91a --- /dev/null +++ b/docs/data/data-grid/overlays/NoRowsOverlay.tsx @@ -0,0 +1,18 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { DataGrid } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; + +export default function NoRowsOverlay() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 0, + maxColumns: 6, + }); + + return ( + + + + ); +} diff --git a/docs/data/data-grid/overlays/NoRowsOverlay.tsx.preview b/docs/data/data-grid/overlays/NoRowsOverlay.tsx.preview new file mode 100644 index 000000000000..364fac54f80c --- /dev/null +++ b/docs/data/data-grid/overlays/NoRowsOverlay.tsx.preview @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/overlays/NoRowsOverlayCustom.js b/docs/data/data-grid/overlays/NoRowsOverlayCustom.js new file mode 100644 index 000000000000..bfe5090c0466 --- /dev/null +++ b/docs/data/data-grid/overlays/NoRowsOverlayCustom.js @@ -0,0 +1,72 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { DataGrid } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; +import { styled } from '@mui/material/styles'; + +const StyledGridOverlay = styled('div')(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + height: '100%', + '& .no-rows-primary': { + fill: theme.palette.mode === 'light' ? '#AEB8C2' : '#3D4751', + }, + '& .no-rows-secondary': { + fill: theme.palette.mode === 'light' ? '#E8EAED' : '#1D2126', + }, +})); + +function CustomNoRowsOverlay() { + return ( + + + + + + + + No rows + + ); +} + +export default function NoRowsOverlayCustom() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 100, + maxColumns: 6, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/overlays/NoRowsOverlayCustom.tsx b/docs/data/data-grid/overlays/NoRowsOverlayCustom.tsx new file mode 100644 index 000000000000..bfe5090c0466 --- /dev/null +++ b/docs/data/data-grid/overlays/NoRowsOverlayCustom.tsx @@ -0,0 +1,72 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { DataGrid } from '@mui/x-data-grid'; +import { useDemoData } from '@mui/x-data-grid-generator'; +import { styled } from '@mui/material/styles'; + +const StyledGridOverlay = styled('div')(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + height: '100%', + '& .no-rows-primary': { + fill: theme.palette.mode === 'light' ? '#AEB8C2' : '#3D4751', + }, + '& .no-rows-secondary': { + fill: theme.palette.mode === 'light' ? '#E8EAED' : '#1D2126', + }, +})); + +function CustomNoRowsOverlay() { + return ( + + + + + + + + No rows + + ); +} + +export default function NoRowsOverlayCustom() { + const { data } = useDemoData({ + dataSet: 'Commodity', + rowLength: 100, + maxColumns: 6, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/components/CustomEmptyOverlayGrid.tsx.preview b/docs/data/data-grid/overlays/NoRowsOverlayCustom.tsx.preview similarity index 100% rename from docs/data/data-grid/components/CustomEmptyOverlayGrid.tsx.preview rename to docs/data/data-grid/overlays/NoRowsOverlayCustom.tsx.preview diff --git a/docs/data/data-grid/overlays/overlays.md b/docs/data/data-grid/overlays/overlays.md new file mode 100644 index 000000000000..426e8b615b3e --- /dev/null +++ b/docs/data/data-grid/overlays/overlays.md @@ -0,0 +1,91 @@ +# Data Grid - Overlays + +

The various data grid overlays.

+ +## Loading overlay + +To display a loading overlay and signify that the data grid is in a loading state, set the `loading` prop to `true`. + +The data grid supports 3 loading overlay variants out of the box: + +- `circular-progress` (default): a circular loading spinner. +- `linear-progress`: an indeterminate linear progress bar. +- `skeleton`: an animated placeholder of the data grid. + +The type of loading overlay to display can be set via `slotProps.loadingOverlay` for the following two props: + +- `variant`: when `loading` and there are rows in the table. +- `noRowsVariant`: when `loading` and there are not any rows in the table. + +```tsx + +``` + +### Circular progress + +A circular loading spinner, the default loading overlay. + +{{"demo": "LoadingOverlay.js", "bg": "inline"}} + +### Linear progress + +An indeterminate linear progress bar. + +{{"demo": "LoadingOverlayLinearProgress.js", "bg": "inline"}} + +### Skeleton + +An animated placeholder of the data grid. + +{{"demo": "LoadingOverlaySkeleton.js", "bg": "inline"}} + +### Custom component + +If you want to customize the no rows overlay, a component can be passed to the `loadingOverlay` slot. + +In the following demo, a labelled determinate [CircularProgress](/material-ui/react-progress/#circular-determinate) component is rendered in place of the default loading overlay, with some additional _Loading rows…_ text. + +{{"demo": "LoadingOverlayCustom.js", "bg": "inline"}} + +## No rows overlay + +The no rows overlay is displayed when the data grid has no rows. + +{{"demo": "NoRowsOverlay.js", "bg": "inline"}} + +### Custom component + +If you want to customize the no rows overlay, a component can be passed to the `noRowsOverlay` slot and rendered in place. + +In the following demo, an illustration is added on top of the default "No rows" message. + +{{"demo": "NoRowsOverlayCustom.js", "bg": "inline"}} + +## No results overlay + +The no results overlay is displayed when the data grid has no results after filtering. + +{{"demo": "NoResultsOverlay.js", "bg": "inline"}} + +### Custom component + +If you want to customize the no results overlay, a component can be passed to the `noResults` slot and rendered in place. + +In the following demo, an illustration is added on top of the default "No results found" message. + +{{"demo": "NoResultsOverlayCustom.js", "bg": "inline"}} + +## API + +- [DataGrid](/x/api/data-grid/data-grid/) +- [DataGridPro](/x/api/data-grid/data-grid-pro/) +- [DataGridPremium](/x/api/data-grid/data-grid-premium/) diff --git a/docs/data/data-grid/overview/overview.md b/docs/data/data-grid/overview/overview.md index d39a88beb8eb..cb859d0d35c9 100644 --- a/docs/data/data-grid/overview/overview.md +++ b/docs/data/data-grid/overview/overview.md @@ -12,7 +12,7 @@ waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/grid/ The Data Grid component is built with React and TypeScript to provide a smooth UX for manipulating an unlimited set of data. It features an intuitive API for real-time updates as well as theming and custom templatesβ€”all with blazing-fast performance. -{{"component": "modules/components/ComponentLinkHeader.js"}} +{{"component": "@mui/docs/ComponentLinkHeader"}} ## Overview diff --git a/docs/data/data-grid/recipes-row-grouping/RowGroupingChildRowCount.js b/docs/data/data-grid/recipes-row-grouping/RowGroupingChildRowCount.js new file mode 100644 index 000000000000..837ea2546b6b --- /dev/null +++ b/docs/data/data-grid/recipes-row-grouping/RowGroupingChildRowCount.js @@ -0,0 +1,55 @@ +import * as React from 'react'; +import { + DataGridPremium, + useGridApiRef, + useGridSelector, + useKeepGroupedColumnsHidden, + useGridApiContext, + gridFilteredDescendantRowCountSelector, +} from '@mui/x-data-grid-premium'; +import { useMovieData } from '@mui/x-data-grid-generator'; +import { Box } from '@mui/material'; + +function CustomFooterRowCount(props) { + const { visibleRowCount: topLevelRowCount } = props; + const apiRef = useGridApiContext(); + const descendantRowCount = useGridSelector( + apiRef, + gridFilteredDescendantRowCountSelector, + ); + + return ( + + {descendantRowCount} row{descendantRowCount > 1 ? 's' : ''} in{' '} + {topLevelRowCount} group + {topLevelRowCount > 1 ? 's' : ''} + + ); +} + +export default function RowGroupingChildRowCount() { + const data = useMovieData(); + const apiRef = useGridApiRef(); + + const initialState = useKeepGroupedColumnsHidden({ + apiRef, + initialState: { + rowGrouping: { + model: ['company'], + }, + }, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/recipes-row-grouping/RowGroupingChildRowCount.tsx b/docs/data/data-grid/recipes-row-grouping/RowGroupingChildRowCount.tsx new file mode 100644 index 000000000000..514aa8358b3c --- /dev/null +++ b/docs/data/data-grid/recipes-row-grouping/RowGroupingChildRowCount.tsx @@ -0,0 +1,56 @@ +import * as React from 'react'; +import { + DataGridPremium, + GridRowCountProps, + useGridApiRef, + useGridSelector, + useKeepGroupedColumnsHidden, + useGridApiContext, + gridFilteredDescendantRowCountSelector, +} from '@mui/x-data-grid-premium'; +import { useMovieData } from '@mui/x-data-grid-generator'; +import { Box } from '@mui/material'; + +function CustomFooterRowCount(props: GridRowCountProps) { + const { visibleRowCount: topLevelRowCount } = props; + const apiRef = useGridApiContext(); + const descendantRowCount = useGridSelector( + apiRef, + gridFilteredDescendantRowCountSelector, + ); + + return ( + + {descendantRowCount} row{descendantRowCount > 1 ? 's' : ''} in{' '} + {topLevelRowCount} group + {topLevelRowCount > 1 ? 's' : ''} + + ); +} + +export default function RowGroupingChildRowCount() { + const data = useMovieData(); + const apiRef = useGridApiRef(); + + const initialState = useKeepGroupedColumnsHidden({ + apiRef, + initialState: { + rowGrouping: { + model: ['company'], + }, + }, + }); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/recipes-row-grouping/RowGroupingChildRowCount.tsx.preview b/docs/data/data-grid/recipes-row-grouping/RowGroupingChildRowCount.tsx.preview new file mode 100644 index 000000000000..f9d69b63cb0a --- /dev/null +++ b/docs/data/data-grid/recipes-row-grouping/RowGroupingChildRowCount.tsx.preview @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/recipes-row-grouping/recipes-row-grouping.md b/docs/data/data-grid/recipes-row-grouping/recipes-row-grouping.md index 014bbd94411a..90067a6eb271 100644 --- a/docs/data/data-grid/recipes-row-grouping/recipes-row-grouping.md +++ b/docs/data/data-grid/recipes-row-grouping/recipes-row-grouping.md @@ -25,3 +25,11 @@ By default, the row grouping column uses `sortComparator` of the grouping column To sort the row groups by the number of child rows, you can override it using `groupingColDef.sortComparator`: {{"demo": "RowGroupingSortByChildRows.js", "bg": "inline", "defaultCodeOpen": false}} + +## Dispaying child row count in footer + +By default, the row count in the footer is the number of top level rows that are visible after filtering. + +In the demo below, a `CustomFooterRowCount` component is added to the `footerRowCount` slot. This component uses the `gridFilteredDescendantRowCountSelector` to get the number of child rows and display it alongside the number of groups. + +{{"demo": "RowGroupingChildRowCount.js", "bg": "inline", "defaultCodeOpen": false}} diff --git a/docs/data/data-grid/server-side-data/ServerSideDataGrid.js b/docs/data/data-grid/server-side-data/ServerSideDataGrid.js new file mode 100644 index 000000000000..3c0dbeb76f86 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideDataGrid.js @@ -0,0 +1,57 @@ +import * as React from 'react'; +import { DataGridPro } from '@mui/x-data-grid-pro'; +import { useMockServer } from '@mui/x-data-grid-generator'; + +function ServerSideDataGrid() { + const { columns, initialState, fetchRows } = useMockServer( + {}, + { useCursorPagination: false }, + ); + + const dataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + paginationModel: encodeURIComponent( + JSON.stringify(params.paginationModel), + ), + filterModel: encodeURIComponent(JSON.stringify(params.filterModel)), + sortModel: encodeURIComponent(JSON.stringify(params.sortModel)), + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + }), + [fetchRows], + ); + + const initialStateWithPagination = React.useMemo( + () => ({ + ...initialState, + pagination: { + paginationModel: { pageSize: 10, page: 0 }, + rowCount: 0, + }, + }), + [initialState], + ); + + return ( +
+ +
+ ); +} + +export default ServerSideDataGrid; diff --git a/docs/data/data-grid/server-side-data/ServerSideDataGrid.tsx b/docs/data/data-grid/server-side-data/ServerSideDataGrid.tsx new file mode 100644 index 000000000000..514b77b23bf9 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideDataGrid.tsx @@ -0,0 +1,57 @@ +import * as React from 'react'; +import { DataGridPro, GridDataSource } from '@mui/x-data-grid-pro'; +import { useMockServer } from '@mui/x-data-grid-generator'; + +function ServerSideDataGrid() { + const { columns, initialState, fetchRows } = useMockServer( + {}, + { useCursorPagination: false }, + ); + + const dataSource: GridDataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + paginationModel: encodeURIComponent( + JSON.stringify(params.paginationModel), + ), + filterModel: encodeURIComponent(JSON.stringify(params.filterModel)), + sortModel: encodeURIComponent(JSON.stringify(params.sortModel)), + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + }), + [fetchRows], + ); + + const initialStateWithPagination = React.useMemo( + () => ({ + ...initialState, + pagination: { + paginationModel: { pageSize: 10, page: 0 }, + rowCount: 0, + }, + }), + [initialState], + ); + + return ( +
+ +
+ ); +} + +export default ServerSideDataGrid; diff --git a/docs/data/data-grid/server-side-data/ServerSideDataGridNoCache.js b/docs/data/data-grid/server-side-data/ServerSideDataGridNoCache.js new file mode 100644 index 000000000000..e059e7b98b00 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideDataGridNoCache.js @@ -0,0 +1,60 @@ +import * as React from 'react'; +import { DataGridPro } from '@mui/x-data-grid-pro'; +import { useMockServer } from '@mui/x-data-grid-generator'; + +const pageSizeOptions = [5, 10, 50]; + +const serverOptions = { useCursorPagination: false }; +const dataSetOptions = {}; + +export default function ServerSideDataGridNoCache() { + const { fetchRows, columns, initialState } = useMockServer( + dataSetOptions, + serverOptions, + ); + + const dataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + paginationModel: encodeURIComponent( + JSON.stringify(params.paginationModel), + ), + filterModel: encodeURIComponent(JSON.stringify(params.filterModel)), + sortModel: encodeURIComponent(JSON.stringify(params.sortModel)), + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + }), + [fetchRows], + ); + + const initialStateWithPagination = React.useMemo( + () => ({ + ...initialState, + pagination: { + paginationModel: { pageSize: 10, page: 0 }, + }, + }), + [initialState], + ); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/server-side-data/ServerSideDataGridNoCache.tsx b/docs/data/data-grid/server-side-data/ServerSideDataGridNoCache.tsx new file mode 100644 index 000000000000..ca8a9fe14814 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideDataGridNoCache.tsx @@ -0,0 +1,60 @@ +import * as React from 'react'; +import { DataGridPro, GridDataSource } from '@mui/x-data-grid-pro'; +import { useMockServer } from '@mui/x-data-grid-generator'; + +const pageSizeOptions = [5, 10, 50]; + +const serverOptions = { useCursorPagination: false }; +const dataSetOptions = {}; + +export default function ServerSideDataGridNoCache() { + const { fetchRows, columns, initialState } = useMockServer( + dataSetOptions, + serverOptions, + ); + + const dataSource: GridDataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + paginationModel: encodeURIComponent( + JSON.stringify(params.paginationModel), + ), + filterModel: encodeURIComponent(JSON.stringify(params.filterModel)), + sortModel: encodeURIComponent(JSON.stringify(params.sortModel)), + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + }), + [fetchRows], + ); + + const initialStateWithPagination = React.useMemo( + () => ({ + ...initialState, + pagination: { + paginationModel: { pageSize: 10, page: 0 }, + }, + }), + [initialState], + ); + + return ( +
+ +
+ ); +} diff --git a/docs/data/data-grid/server-side-data/ServerSideDataGridNoCache.tsx.preview b/docs/data/data-grid/server-side-data/ServerSideDataGridNoCache.tsx.preview new file mode 100644 index 000000000000..ed2e75557b91 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideDataGridNoCache.tsx.preview @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/docs/data/data-grid/server-side-data/ServerSideDataGridTTL.js b/docs/data/data-grid/server-side-data/ServerSideDataGridTTL.js new file mode 100644 index 000000000000..615cf4072a62 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideDataGridTTL.js @@ -0,0 +1,60 @@ +import * as React from 'react'; +import { DataGridPro, GridDataSourceCacheDefault } from '@mui/x-data-grid-pro'; +import { useMockServer } from '@mui/x-data-grid-generator'; + +const lowTTLCache = new GridDataSourceCacheDefault({ ttl: 1000 * 10 }); // 10 seconds + +function ServerSideDataGridTTL() { + const { columns, initialState, fetchRows } = useMockServer( + {}, + { useCursorPagination: false }, + ); + + const dataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + paginationModel: encodeURIComponent( + JSON.stringify(params.paginationModel), + ), + filterModel: encodeURIComponent(JSON.stringify(params.filterModel)), + sortModel: encodeURIComponent(JSON.stringify(params.sortModel)), + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + }), + [fetchRows], + ); + + const initialStateWithPagination = React.useMemo( + () => ({ + ...initialState, + pagination: { + paginationModel: { pageSize: 10, page: 0 }, + rowCount: 0, + }, + }), + [initialState], + ); + + return ( +
+ +
+ ); +} + +export default ServerSideDataGridTTL; diff --git a/docs/data/data-grid/server-side-data/ServerSideDataGridTTL.tsx b/docs/data/data-grid/server-side-data/ServerSideDataGridTTL.tsx new file mode 100644 index 000000000000..3f8f3525e78c --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideDataGridTTL.tsx @@ -0,0 +1,64 @@ +import * as React from 'react'; +import { + DataGridPro, + GridDataSource, + GridDataSourceCacheDefault, +} from '@mui/x-data-grid-pro'; +import { useMockServer } from '@mui/x-data-grid-generator'; + +const lowTTLCache = new GridDataSourceCacheDefault({ ttl: 1000 * 10 }); // 10 seconds + +function ServerSideDataGridTTL() { + const { columns, initialState, fetchRows } = useMockServer( + {}, + { useCursorPagination: false }, + ); + + const dataSource: GridDataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + paginationModel: encodeURIComponent( + JSON.stringify(params.paginationModel), + ), + filterModel: encodeURIComponent(JSON.stringify(params.filterModel)), + sortModel: encodeURIComponent(JSON.stringify(params.sortModel)), + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + }), + [fetchRows], + ); + + const initialStateWithPagination = React.useMemo( + () => ({ + ...initialState, + pagination: { + paginationModel: { pageSize: 10, page: 0 }, + rowCount: 0, + }, + }), + [initialState], + ); + + return ( +
+ +
+ ); +} + +export default ServerSideDataGridTTL; diff --git a/docs/data/data-grid/server-side-data/ServerSideErrorHandling.js b/docs/data/data-grid/server-side-data/ServerSideErrorHandling.js new file mode 100644 index 000000000000..1bf394ea930f --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideErrorHandling.js @@ -0,0 +1,125 @@ +import * as React from 'react'; +import { DataGridPro, useGridApiRef, GridToolbar } from '@mui/x-data-grid-pro'; +import Button from '@mui/material/Button'; +import Checkbox from '@mui/material/Checkbox'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import { alpha, styled, darken, lighten } from '@mui/material/styles'; +import { useMockServer } from '@mui/x-data-grid-generator'; + +const pageSizeOptions = [5, 10, 50]; +const serverOptions = { useCursorPagination: false }; +const datasetOptions = {}; + +function getBorderColor(theme) { + if (theme.palette.mode === 'light') { + return lighten(alpha(theme.palette.divider, 1), 0.88); + } + return darken(alpha(theme.palette.divider, 1), 0.68); +} + +const StyledDiv = styled('div')(({ theme: t }) => ({ + position: 'absolute', + zIndex: 10, + fontSize: '0.875em', + top: 0, + height: '100%', + width: '100%', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + borderRadius: '4px', + border: `1px solid ${getBorderColor(t)}`, + backgroundColor: t.palette.background.default, +})); + +function ErrorOverlay({ error }) { + if (!error) { + return null; + } + return {error}; +} + +export default function ServerSideErrorHandling() { + const apiRef = useGridApiRef(); + const [error, setError] = React.useState(); + const [shouldRequestsFail, setShouldRequestsFail] = React.useState(false); + + const { fetchRows, ...props } = useMockServer( + datasetOptions, + serverOptions, + shouldRequestsFail, + ); + + const dataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + paginationModel: encodeURIComponent( + JSON.stringify(params.paginationModel), + ), + filterModel: encodeURIComponent(JSON.stringify(params.filterModel)), + sortModel: encodeURIComponent(JSON.stringify(params.sortModel)), + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + }), + [fetchRows], + ); + + const initialState = React.useMemo( + () => ({ + ...props.initialState, + pagination: { + paginationModel: { + pageSize: 5, + }, + rowCount: 0, + }, + }), + [props.initialState], + ); + + return ( +
+
+ + setShouldRequestsFail(e.target.checked)} + /> + } + label="Make the requests fail" + /> +
+
+ setError(e.message)} + unstable_dataSourceCache={null} + apiRef={apiRef} + pagination + pageSizeOptions={pageSizeOptions} + initialState={initialState} + slots={{ toolbar: GridToolbar }} + /> + {error && } +
+
+ ); +} diff --git a/docs/data/data-grid/server-side-data/ServerSideErrorHandling.tsx b/docs/data/data-grid/server-side-data/ServerSideErrorHandling.tsx new file mode 100644 index 000000000000..a030a8bf6e50 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideErrorHandling.tsx @@ -0,0 +1,131 @@ +import * as React from 'react'; +import { + DataGridPro, + useGridApiRef, + GridInitialState, + GridToolbar, + GridDataSource, +} from '@mui/x-data-grid-pro'; +import Button from '@mui/material/Button'; +import Checkbox from '@mui/material/Checkbox'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import { alpha, styled, darken, lighten, Theme } from '@mui/material/styles'; +import { useMockServer } from '@mui/x-data-grid-generator'; + +const pageSizeOptions = [5, 10, 50]; +const serverOptions = { useCursorPagination: false }; +const datasetOptions = {}; + +function getBorderColor(theme: Theme) { + if (theme.palette.mode === 'light') { + return lighten(alpha(theme.palette.divider, 1), 0.88); + } + return darken(alpha(theme.palette.divider, 1), 0.68); +} + +const StyledDiv = styled('div')(({ theme: t }) => ({ + position: 'absolute', + zIndex: 10, + fontSize: '0.875em', + top: 0, + height: '100%', + width: '100%', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + borderRadius: '4px', + border: `1px solid ${getBorderColor(t)}`, + backgroundColor: t.palette.background.default, +})); + +function ErrorOverlay({ error }: { error: string }) { + if (!error) { + return null; + } + return {error}; +} + +export default function ServerSideErrorHandling() { + const apiRef = useGridApiRef(); + const [error, setError] = React.useState(); + const [shouldRequestsFail, setShouldRequestsFail] = React.useState(false); + + const { fetchRows, ...props } = useMockServer( + datasetOptions, + serverOptions, + shouldRequestsFail, + ); + + const dataSource: GridDataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + paginationModel: encodeURIComponent( + JSON.stringify(params.paginationModel), + ), + filterModel: encodeURIComponent(JSON.stringify(params.filterModel)), + sortModel: encodeURIComponent(JSON.stringify(params.sortModel)), + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + }), + [fetchRows], + ); + + const initialState: GridInitialState = React.useMemo( + () => ({ + ...props.initialState, + pagination: { + paginationModel: { + pageSize: 5, + }, + rowCount: 0, + }, + }), + [props.initialState], + ); + + return ( +
+
+ + setShouldRequestsFail(e.target.checked)} + /> + } + label="Make the requests fail" + /> +
+
+ setError(e.message)} + unstable_dataSourceCache={null} + apiRef={apiRef} + pagination + pageSizeOptions={pageSizeOptions} + initialState={initialState} + slots={{ toolbar: GridToolbar }} + /> + {error && } +
+
+ ); +} diff --git a/docs/data/data-grid/server-side-data/ServerSideTreeData.js b/docs/data/data-grid/server-side-data/ServerSideTreeData.js new file mode 100644 index 000000000000..ed0d0bc8e093 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideTreeData.js @@ -0,0 +1,76 @@ +import * as React from 'react'; +import { DataGridPro, useGridApiRef, GridToolbar } from '@mui/x-data-grid-pro'; +import Button from '@mui/material/Button'; +import { useMockServer } from '@mui/x-data-grid-generator'; + +const pageSizeOptions = [5, 10, 50]; +const dataSetOptions = { + dataSet: 'Employee', + rowLength: 1000, + treeData: { maxDepth: 3, groupingField: 'name', averageChildren: 5 }, +}; + +export default function ServerSideTreeData() { + const apiRef = useGridApiRef(); + + const { fetchRows, columns, initialState } = useMockServer(dataSetOptions); + + const initialStateWithPagination = React.useMemo( + () => ({ + ...initialState, + pagination: { + paginationModel: { + pageSize: 5, + }, + rowCount: 0, + }, + }), + [initialState], + ); + + const dataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + paginationModel: encodeURIComponent( + JSON.stringify(params.paginationModel), + ), + filterModel: encodeURIComponent(JSON.stringify(params.filterModel)), + sortModel: encodeURIComponent(JSON.stringify(params.sortModel)), + groupKeys: encodeURIComponent(JSON.stringify(params.groupKeys)), + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + getGroupKey: (row) => row[dataSetOptions.treeData.groupingField], + getChildrenCount: (row) => row.descendantCount, + }), + [fetchRows], + ); + + return ( +
+ +
+ +
+
+ ); +} diff --git a/docs/data/data-grid/server-side-data/ServerSideTreeData.tsx b/docs/data/data-grid/server-side-data/ServerSideTreeData.tsx new file mode 100644 index 000000000000..86a2e47fd1ef --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideTreeData.tsx @@ -0,0 +1,82 @@ +import * as React from 'react'; +import { + DataGridPro, + useGridApiRef, + GridInitialState, + GridToolbar, + GridDataSource, +} from '@mui/x-data-grid-pro'; +import Button from '@mui/material/Button'; +import { useMockServer } from '@mui/x-data-grid-generator'; + +const pageSizeOptions = [5, 10, 50]; +const dataSetOptions = { + dataSet: 'Employee' as const, + rowLength: 1000, + treeData: { maxDepth: 3, groupingField: 'name', averageChildren: 5 }, +}; + +export default function ServerSideTreeData() { + const apiRef = useGridApiRef(); + + const { fetchRows, columns, initialState } = useMockServer(dataSetOptions); + + const initialStateWithPagination: GridInitialState = React.useMemo( + () => ({ + ...initialState, + pagination: { + paginationModel: { + pageSize: 5, + }, + rowCount: 0, + }, + }), + [initialState], + ); + + const dataSource: GridDataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + paginationModel: encodeURIComponent( + JSON.stringify(params.paginationModel), + ), + filterModel: encodeURIComponent(JSON.stringify(params.filterModel)), + sortModel: encodeURIComponent(JSON.stringify(params.sortModel)), + groupKeys: encodeURIComponent(JSON.stringify(params.groupKeys)), + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + getGroupKey: (row) => row[dataSetOptions.treeData.groupingField], + getChildrenCount: (row) => row.descendantCount, + }), + [fetchRows], + ); + + return ( +
+ +
+ +
+
+ ); +} diff --git a/docs/data/data-grid/server-side-data/ServerSideTreeData.tsx.preview b/docs/data/data-grid/server-side-data/ServerSideTreeData.tsx.preview new file mode 100644 index 000000000000..4a508197000b --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideTreeData.tsx.preview @@ -0,0 +1,16 @@ + +
+ +
\ No newline at end of file diff --git a/docs/data/data-grid/server-side-data/ServerSideTreeDataCustomCache.js b/docs/data/data-grid/server-side-data/ServerSideTreeDataCustomCache.js new file mode 100644 index 000000000000..920a1b2d5609 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideTreeDataCustomCache.js @@ -0,0 +1,107 @@ +import * as React from 'react'; +import { DataGridPro, useGridApiRef, GridToolbar } from '@mui/x-data-grid-pro'; +import Button from '@mui/material/Button'; +import { useMockServer } from '@mui/x-data-grid-generator'; +import { QueryClient } from '@tanstack/query-core'; + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + staleTime: 1000 * 60 * 60, + }, + }, +}); + +function getKey(params) { + return [ + params.paginationModel, + params.sortModel, + params.filterModel, + params.groupKeys, + ]; +} + +const cache = { + set: (key, value) => { + const queryKey = getKey(key); + queryClient.setQueryData(queryKey, value); + }, + get: (key) => { + const queryKey = getKey(key); + return queryClient.getQueryData(queryKey); + }, + clear: () => { + queryClient.clear(); + }, +}; + +const pageSizeOptions = [5, 10, 50]; +const dataSetOptions = { + dataSet: 'Employee', + rowLength: 1000, + treeData: { maxDepth: 3, groupingField: 'name', averageChildren: 5 }, +}; + +export default function ServerSideTreeDataCustomCache() { + const apiRef = useGridApiRef(); + + const { fetchRows, ...props } = useMockServer(dataSetOptions); + + const dataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + paginationModel: encodeURIComponent( + JSON.stringify(params.paginationModel), + ), + filterModel: encodeURIComponent(JSON.stringify(params.filterModel)), + sortModel: encodeURIComponent(JSON.stringify(params.sortModel)), + groupKeys: encodeURIComponent(JSON.stringify(params.groupKeys)), + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + getGroupKey: (row) => row[dataSetOptions.treeData.groupingField], + getChildrenCount: (row) => row.descendantCount, + }), + [fetchRows], + ); + + const initialState = React.useMemo( + () => ({ + ...props.initialState, + pagination: { + paginationModel: { + pageSize: 5, + }, + rowCount: 0, + }, + }), + [props.initialState], + ); + + return ( +
+ +
+ +
+
+ ); +} diff --git a/docs/data/data-grid/server-side-data/ServerSideTreeDataCustomCache.tsx b/docs/data/data-grid/server-side-data/ServerSideTreeDataCustomCache.tsx new file mode 100644 index 000000000000..a3f2961d549f --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideTreeDataCustomCache.tsx @@ -0,0 +1,115 @@ +import * as React from 'react'; +import { + DataGridPro, + useGridApiRef, + GridInitialState, + GridToolbar, + GridDataSourceCache, + GridDataSource, + GridGetRowsParams, +} from '@mui/x-data-grid-pro'; +import Button from '@mui/material/Button'; +import { useMockServer } from '@mui/x-data-grid-generator'; +import { QueryClient } from '@tanstack/query-core'; + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + staleTime: 1000 * 60 * 60, + }, + }, +}); + +function getKey(params: GridGetRowsParams) { + return [ + params.paginationModel, + params.sortModel, + params.filterModel, + params.groupKeys, + ]; +} + +const cache: GridDataSourceCache = { + set: (key: GridGetRowsParams, value) => { + const queryKey = getKey(key); + queryClient.setQueryData(queryKey, value); + }, + get: (key: GridGetRowsParams) => { + const queryKey = getKey(key); + return queryClient.getQueryData(queryKey); + }, + clear: () => { + queryClient.clear(); + }, +}; + +const pageSizeOptions = [5, 10, 50]; +const dataSetOptions = { + dataSet: 'Employee' as 'Employee', + rowLength: 1000, + treeData: { maxDepth: 3, groupingField: 'name', averageChildren: 5 }, +}; + +export default function ServerSideTreeDataCustomCache() { + const apiRef = useGridApiRef(); + + const { fetchRows, ...props } = useMockServer(dataSetOptions); + + const dataSource: GridDataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + paginationModel: encodeURIComponent( + JSON.stringify(params.paginationModel), + ), + filterModel: encodeURIComponent(JSON.stringify(params.filterModel)), + sortModel: encodeURIComponent(JSON.stringify(params.sortModel)), + groupKeys: encodeURIComponent(JSON.stringify(params.groupKeys)), + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + getGroupKey: (row) => row[dataSetOptions.treeData.groupingField], + getChildrenCount: (row) => row.descendantCount, + }), + [fetchRows], + ); + + const initialState: GridInitialState = React.useMemo( + () => ({ + ...props.initialState, + pagination: { + paginationModel: { + pageSize: 5, + }, + rowCount: 0, + }, + }), + [props.initialState], + ); + + return ( +
+ +
+ +
+
+ ); +} diff --git a/docs/data/data-grid/server-side-data/ServerSideTreeDataCustomCache.tsx.preview b/docs/data/data-grid/server-side-data/ServerSideTreeDataCustomCache.tsx.preview new file mode 100644 index 000000000000..1c8c80d0e4b6 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideTreeDataCustomCache.tsx.preview @@ -0,0 +1,15 @@ + +
+ +
\ No newline at end of file diff --git a/docs/data/data-grid/server-side-data/ServerSideTreeDataErrorHandling.js b/docs/data/data-grid/server-side-data/ServerSideTreeDataErrorHandling.js new file mode 100644 index 000000000000..44da5bf0cab3 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideTreeDataErrorHandling.js @@ -0,0 +1,148 @@ +import * as React from 'react'; +import { DataGridPro, useGridApiRef } from '@mui/x-data-grid-pro'; +import Snackbar from '@mui/material/Snackbar'; +import Button from '@mui/material/Button'; +import Checkbox from '@mui/material/Checkbox'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import { alpha, styled, darken, lighten } from '@mui/material/styles'; +import { useMockServer } from '@mui/x-data-grid-generator'; + +const pageSizeOptions = [5, 10, 50]; +const serverOptions = { useCursorPagination: false }; +const dataSetOptions = { + dataSet: 'Employee', + rowLength: 1000, + treeData: { maxDepth: 3, groupingField: 'name', averageChildren: 5 }, +}; + +export default function ServerSideTreeDataErrorHandling() { + const apiRef = useGridApiRef(); + const [rootError, setRootError] = React.useState(); + const [childrenError, setChildrenError] = React.useState(); + const [shouldRequestsFail, setShouldRequestsFail] = React.useState(false); + + const { fetchRows, ...props } = useMockServer( + dataSetOptions, + serverOptions, + shouldRequestsFail, + ); + + const dataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + paginationModel: encodeURIComponent( + JSON.stringify(params.paginationModel), + ), + filterModel: encodeURIComponent(JSON.stringify(params.filterModel)), + sortModel: encodeURIComponent(JSON.stringify(params.sortModel)), + groupKeys: encodeURIComponent(JSON.stringify(params.groupKeys)), + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + getGroupKey: (row) => row[dataSetOptions.treeData.groupingField], + getChildrenCount: (row) => row.descendantCount, + }), + [fetchRows], + ); + + const initialState = React.useMemo( + () => ({ + ...props.initialState, + pagination: { + paginationModel: { + pageSize: 5, + }, + rowCount: 0, + }, + }), + [props.initialState], + ); + + return ( +
+
+ + setShouldRequestsFail(e.target.checked)} + /> + } + label="Make the requests fail" + /> +
+
+ { + if (!params.groupKeys || params.groupKeys.length === 0) { + setRootError(e.message); + } else { + setChildrenError( + `${e.message} (Requested level: ${params.groupKeys.join(' > ')})`, + ); + } + }} + unstable_dataSourceCache={null} + apiRef={apiRef} + pagination + pageSizeOptions={pageSizeOptions} + initialState={initialState} + /> + {rootError && } + setChildrenError('')} + message={childrenError} + /> +
+
+ ); +} + +function getBorderColor(theme) { + if (theme.palette.mode === 'light') { + return lighten(alpha(theme.palette.divider, 1), 0.88); + } + return darken(alpha(theme.palette.divider, 1), 0.68); +} + +const StyledDiv = styled('div')(({ theme: t }) => ({ + position: 'absolute', + zIndex: 10, + fontSize: '0.875em', + top: 0, + height: '100%', + width: '100%', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + borderRadius: '4px', + border: `1px solid ${getBorderColor(t)}`, + backgroundColor: t.palette.background.default, +})); + +function ErrorOverlay({ error }) { + if (!error) { + return null; + } + return {error}; +} diff --git a/docs/data/data-grid/server-side-data/ServerSideTreeDataErrorHandling.tsx b/docs/data/data-grid/server-side-data/ServerSideTreeDataErrorHandling.tsx new file mode 100644 index 000000000000..fdd4deeb1771 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideTreeDataErrorHandling.tsx @@ -0,0 +1,153 @@ +import * as React from 'react'; +import { + DataGridPro, + useGridApiRef, + GridInitialState, + GridDataSource, +} from '@mui/x-data-grid-pro'; +import Snackbar from '@mui/material/Snackbar'; +import Button from '@mui/material/Button'; +import Checkbox from '@mui/material/Checkbox'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import { alpha, styled, darken, lighten, Theme } from '@mui/material/styles'; +import { useMockServer } from '@mui/x-data-grid-generator'; + +const pageSizeOptions = [5, 10, 50]; +const serverOptions = { useCursorPagination: false }; +const dataSetOptions = { + dataSet: 'Employee' as 'Employee', + rowLength: 1000, + treeData: { maxDepth: 3, groupingField: 'name', averageChildren: 5 }, +}; + +export default function ServerSideTreeDataErrorHandling() { + const apiRef = useGridApiRef(); + const [rootError, setRootError] = React.useState(); + const [childrenError, setChildrenError] = React.useState(); + const [shouldRequestsFail, setShouldRequestsFail] = React.useState(false); + + const { fetchRows, ...props } = useMockServer( + dataSetOptions, + serverOptions, + shouldRequestsFail, + ); + + const dataSource: GridDataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + paginationModel: encodeURIComponent( + JSON.stringify(params.paginationModel), + ), + filterModel: encodeURIComponent(JSON.stringify(params.filterModel)), + sortModel: encodeURIComponent(JSON.stringify(params.sortModel)), + groupKeys: encodeURIComponent(JSON.stringify(params.groupKeys)), + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + getGroupKey: (row) => row[dataSetOptions.treeData.groupingField], + getChildrenCount: (row) => row.descendantCount, + }), + [fetchRows], + ); + + const initialState: GridInitialState = React.useMemo( + () => ({ + ...props.initialState, + pagination: { + paginationModel: { + pageSize: 5, + }, + rowCount: 0, + }, + }), + [props.initialState], + ); + + return ( +
+
+ + setShouldRequestsFail(e.target.checked)} + /> + } + label="Make the requests fail" + /> +
+
+ { + if (!params.groupKeys || params.groupKeys.length === 0) { + setRootError(e.message); + } else { + setChildrenError( + `${e.message} (Requested level: ${params.groupKeys.join(' > ')})`, + ); + } + }} + unstable_dataSourceCache={null} + apiRef={apiRef} + pagination + pageSizeOptions={pageSizeOptions} + initialState={initialState} + /> + {rootError && } + setChildrenError('')} + message={childrenError} + /> +
+
+ ); +} + +function getBorderColor(theme: Theme) { + if (theme.palette.mode === 'light') { + return lighten(alpha(theme.palette.divider, 1), 0.88); + } + return darken(alpha(theme.palette.divider, 1), 0.68); +} + +const StyledDiv = styled('div')(({ theme: t }) => ({ + position: 'absolute', + zIndex: 10, + fontSize: '0.875em', + top: 0, + height: '100%', + width: '100%', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + borderRadius: '4px', + border: `1px solid ${getBorderColor(t)}`, + backgroundColor: t.palette.background.default, +})); + +function ErrorOverlay({ error }: { error: string }) { + if (!error) { + return null; + } + return {error}; +} diff --git a/docs/data/data-grid/server-side-data/ServerSideTreeDataGroupExpansion.js b/docs/data/data-grid/server-side-data/ServerSideTreeDataGroupExpansion.js new file mode 100644 index 000000000000..9b61ceacdcf8 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideTreeDataGroupExpansion.js @@ -0,0 +1,77 @@ +import * as React from 'react'; +import { DataGridPro, useGridApiRef, GridToolbar } from '@mui/x-data-grid-pro'; +import Button from '@mui/material/Button'; +import { useMockServer } from '@mui/x-data-grid-generator'; + +const pageSizeOptions = [5, 10, 50]; +const dataSetOptions = { + dataSet: 'Employee', + rowLength: 1000, + treeData: { maxDepth: 3, groupingField: 'name', averageChildren: 5 }, +}; + +export default function ServerSideTreeDataGroupExpansion() { + const apiRef = useGridApiRef(); + + const { fetchRows, columns, initialState } = useMockServer(dataSetOptions); + + const dataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + paginationModel: encodeURIComponent( + JSON.stringify(params.paginationModel), + ), + filterModel: encodeURIComponent(JSON.stringify(params.filterModel)), + sortModel: encodeURIComponent(JSON.stringify(params.sortModel)), + groupKeys: encodeURIComponent(JSON.stringify(params.groupKeys)), + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + getGroupKey: (row) => row[dataSetOptions.treeData.groupingField], + getChildrenCount: (row) => row.descendantCount, + }), + [fetchRows], + ); + + const initialStateWithPagination = React.useMemo( + () => ({ + ...initialState, + pagination: { + paginationModel: { + pageSize: 5, + }, + rowCount: 0, + }, + }), + [initialState], + ); + + return ( +
+ +
+ +
+
+ ); +} diff --git a/docs/data/data-grid/server-side-data/ServerSideTreeDataGroupExpansion.tsx b/docs/data/data-grid/server-side-data/ServerSideTreeDataGroupExpansion.tsx new file mode 100644 index 000000000000..9eb7fdd75ba4 --- /dev/null +++ b/docs/data/data-grid/server-side-data/ServerSideTreeDataGroupExpansion.tsx @@ -0,0 +1,85 @@ +import * as React from 'react'; +import { + DataGridPro, + useGridApiRef, + GridInitialState, + GridToolbar, + GridDataSource, +} from '@mui/x-data-grid-pro'; +import Button from '@mui/material/Button'; +import { useMockServer } from '@mui/x-data-grid-generator'; + +type DataSet = 'Commodity' | 'Employee'; + +const pageSizeOptions = [5, 10, 50]; +const dataSetOptions = { + dataSet: 'Employee' as DataSet, + rowLength: 1000, + treeData: { maxDepth: 3, groupingField: 'name', averageChildren: 5 }, +}; + +export default function ServerSideTreeDataGroupExpansion() { + const apiRef = useGridApiRef(); + + const { fetchRows, columns, initialState } = useMockServer(dataSetOptions); + + const dataSource: GridDataSource = React.useMemo( + () => ({ + getRows: async (params) => { + const urlParams = new URLSearchParams({ + paginationModel: encodeURIComponent( + JSON.stringify(params.paginationModel), + ), + filterModel: encodeURIComponent(JSON.stringify(params.filterModel)), + sortModel: encodeURIComponent(JSON.stringify(params.sortModel)), + groupKeys: encodeURIComponent(JSON.stringify(params.groupKeys)), + }); + const getRowsResponse = await fetchRows( + `https://mui.com/x/api/data-grid?${urlParams.toString()}`, + ); + return { + rows: getRowsResponse.rows, + rowCount: getRowsResponse.rowCount, + }; + }, + getGroupKey: (row) => row[dataSetOptions.treeData.groupingField], + getChildrenCount: (row) => row.descendantCount, + }), + [fetchRows], + ); + + const initialStateWithPagination: GridInitialState = React.useMemo( + () => ({ + ...initialState, + pagination: { + paginationModel: { + pageSize: 5, + }, + rowCount: 0, + }, + }), + [initialState], + ); + + return ( +
+ +
+ +
+
+ ); +} diff --git a/docs/data/data-grid/server-side-data/index.md b/docs/data/data-grid/server-side-data/index.md index a626f60d7c3c..38a003c98581 100644 --- a/docs/data/data-grid/server-side-data/index.md +++ b/docs/data/data-grid/server-side-data/index.md @@ -2,23 +2,19 @@ title: React Data Grid - Server-side data --- -# Data Grid - Server-side data 🚧 +# Data Grid - Server-side data [](/x/introduction/licensing/#pro-plan 'Pro plan')

The data grid server-side data.

-## Overview +## Introduction -Managing server-side data efficiently in a React application can become complex as the dataset grows. +Server-side data management in React can become complex with growing datasets. +Challenges include manual data fetching, pagination, sorting, filtering, and performance optimization. +A dedicated module can help abstract these complexities, improving user experience. -Without a dedicated module that abstracts its complexities, developers often face challenges related to manual data fetching, pagination, sorting, and filtering, and it often gets trickier to tackle performance issues, which can lead to a poor user experience. - -Have a look at an example: - -### Example scenario - -Imagine having a data grid that displays a list of users. The data grid has pagination enabled and the user can sort the data by clicking on the column headers and also apply filters. - -The data grid is configured to fetch data from the server whenever the user changes the page or updates filtering or sorting. +Consider a Data Grid displaying a list of users. +It supports pagination, sorting by column headers, and filtering. +The Data Grid fetches data from the server when the user changes the page or updates filtering or sorting. ```tsx const [rows, setRows] = React.useState([]); @@ -72,51 +68,51 @@ Trying to solve these problems one after the other can make the code complex and ## Data source -A very common pattern to solve these problems is to use a centralized data source. A data source is an abstraction layer that sits between the data grid and the server. It provides a simple interface to the data grid to fetch data and update it. It handles a lot of the complexities related to server-side data fetching. Let's delve a bit deeper into how it will look like. +The idea for a centralized data source is to simplify server-side data fetching. +It's an abstraction layer between the Data Grid and the server, providing a simple interface for interacting with the server. +Think of it like a middleman handling the communication between the Data Grid (client) and the actual data source (server). :::warning -This feature is still under development and the information shared on this page is subject to change. Feel free to subscribe or comment on the official GitHub [issue](https://github.com/mui/mui-x/issues/8179). +This feature is under development and is marked as **unstable**. +The information shared on this page could change in future. +Feel free to subscribe or comment on the official GitHub [umbrella issue](https://github.com/mui/mui-x/issues/8179). ::: -### Overview - -The Data Grid already supports manual server-side data fetching for features like sorting, filtering, etc. In order to make it more powerful and simple to use, the grid will support a data source interface that you can implement with your existing data fetching logic. - -The datasource will work with all the major data grid features which require server-side data fetching such as sorting, filtering, pagination, grouping, etc. +It has an initial set of required methods that you need to implement. The data grid will use these methods internally to fetch a sub-set of data when needed. -### Usage - -The data grid server-side data source has an initial set of required methods that you need to implement. The data grid will call these methods internally when the data is required for a specific page. +Let's take a look at the minimal `GridDataSource` interface configuration. ```tsx -interface DataSource { +interface GridDataSource { /** - Fetcher Functions: - - `getRows` is required - - `updateRow` is optional - - `getRows` will be used by the grid to fetch data for the current page or children for the current parent group - It may return a `rowCount` to update the total count of rows in the grid - */ - getRows(params: GetRowsParams): Promise; - updateRow?(updatedRow: GridRowModel): Promise; + * This method will be called when the grid needs to fetch some rows + * @param {GridGetRowsParams} params The parameters required to fetch the rows + * @returns {Promise} A promise that resolves to the data of type [GridGetRowsResponse] + */ + getRows(params: GridGetRowsParams): Promise; } ``` -Here's how the code will look like for the above example when implemented with data source: +:::info + +The above interface is a minimal configuration required for a data source to work. +More specific properties like `getChildrenCount` and `getGroupKey` will be discussed in the corresponding sections. + +::: + +Here's how the above mentioned example would look like when implemented with the data source: ```tsx -const customDataSource: DataSource = { - getRows: async (params: GetRowsParams): GetRowsResponse => { - // fetch data from server +const customDataSource: GridDataSource = { + getRows: async (params: GridGetRowsParams): GetRowsResponse => { const response = await fetch('https://my-api.com/data', { method: 'GET', body: JSON.stringify(params), }); const data = await response.json(); - // return the data and the total number of rows + return { rows: data.rows, rowCount: data.totalCount, @@ -126,161 +122,145 @@ const customDataSource: DataSource = { ``` -Not only the code has been reduced significantly, it has removed the hassle of managing controlled states and data fetching logic too. +The code has been significantly reduced, the need for managing the controlled states is removed, and data fetching logic is centralized. -On top of that, the data source will also handle a lot of other aspects like caching and deduping of requests. +## Server-side filtering, sorting, and pagination -#### Loading data +The data source changes how the existing server-side features like `filtering`, `sorting`, and `pagination` work. -The method `dataSource.getRows` will be called with the `GetRowsParams` object whenever some data from the server is needed. This object contains all the information that you need to fetch the data from the server. +**Without data source** -Since previously, the data grid did not support internal data fetching, the `rows` prop was the way to pass the data to the grid. However, with server-side data, the `rows` prop is no longer needed. Instead, the data grid will call the `getRows` method whenever it needs to fetch data. - -Here's the `GetRowsParams` object for reference: +When there's no data source, the features `filtering`, `sorting`, `pagination` work on `client` by default. +In order for them to work with server-side data, you need to set them to `server` explicitly and provide the [`onFilterModelChange`](https://mui.com/x/react-data-grid/filtering/server-side/), [`onSortModelChange`](https://mui.com/x/react-data-grid/sorting/#server-side-sorting), [`onPaginationModelChange`](https://mui.com/x/react-data-grid/pagination/#server-side-pagination) event handlers to fetch the data from the server based on the updated variables. ```tsx -interface GetRowsParams { - sortModel: GridSortModel; - filterModel: GridFilterModel; - /** - * Alternate to `start` and `end`, maps to `GridPaginationModel` interface - */ - paginationModel: GridPaginationModel; - /** - * First row index to fetch (number) or cursor information (number | string) - */ - start: number | string; // first row index to fetch or cursor information - /** - * Last row index to fetch - */ - end: number; // last row index to fetch - /** - * Array of keys returned by `getGroupKey` of all the parent rows until the row for which the data is requested - * `getGroupKey` prop must be implemented to use this - * Useful for `treeData` and `rowGrouping` only - */ - groupKeys: string[]; - /** - * List of grouped columns (only applicable with `rowGrouping`) - */ - groupFields: GridColDef['field'][]; // list of grouped columns (`rowGrouping`) -} + { + // fetch data from server + }} + onSortModelChange={(newSortModel) => { + // fetch data from server + }} + onFilterModelChange={(newFilterModel) => { + // fetch data from server + }} +/> ``` -And here's the `GetRowsResponse` object for reference: +**With data source** + +With the data source, the features `filtering`, `sorting`, `pagination` are automatically set to `server`. + +When the corresponding models update, the data grid calls the `getRows` method with the updated values of type `GridGetRowsParams` to get updated data. ```tsx -interface GetRowsResponse { - /** - * Subset of the rows as per the passed `GetRowsParams` - */ - rows: GridRowModel[]; - /** - * To reflect updates in total `rowCount` (optional) - * Useful when the `rowCount` is inaccurate (for example when filtering) or not available upfront - */ - rowCount?: number; - /** - * Additional `pageInfo` to help the grid determine if there are more rows to fetch (corner-cases) - * `hasNextPage`: When row count is unknown/inaccurate, if `truncated` is set or rowCount is not known, data will keep loading until `hasNextPage` is `false` - * `truncated`: To reflect `rowCount` is inaccurate (will trigger `x-y of many` in pagination after the count of rows fetched is greater than provided `rowCount`) - * It could be useful with: - * 1. Cursor based pagination: - * When rowCount is not known, grid will check for `hasNextPage` to determine - * if there are more rows to fetch. - * 2. Inaccurate `rowCount`: - * `truncated: true` will let the grid know that `rowCount` is estimated/truncated. - * Thus `hasNextPage` will come into play to check more rows are available to fetch after the number becomes >= provided `rowCount` - */ - pageInfo?: { - hasNextPage?: boolean; - truncated?: number; - }; -} + ``` -#### Updating data +The following demo showcases this behavior. -If provided, the method `dataSource.updateRow` will be called with the `GridRowModel` object whenever the user edits a row. This method is optional and you can skip it if you don't need to update the data on the server. It will work in a similar way as the `processRowUpdate` prop. +{{"demo": "ServerSideDataGrid.js", "bg": "inline"}} -#### Data Grid props +:::info +The data source demos use a utility function `useMockServer` to simulate the server-side data fetching. +In a real-world scenario, you should replace this with your own server-side data fetching logic. -These data grid props will work with the server-side data source: +Open info section of the browser console to see the requests being made and the data being fetched in response. +::: -- `dataSource: DataSource`: the data source object that you need to implement -- `rows`: will be ignored, could be skipped when `dataSource` is provided -- `rowCount`: will be used to identify the total number of rows in the grid, if not provided, the grid will check for the _GetRowsResponse.rowCount_ value, unless the feature being used is infinite loading where no `rowCount` is available at all. +## Data caching -Props related to grouped data (`treeData` and `rowGrouping`): +The data source caches fetched data by default. +This means that if the user navigates to a page or expands a node that has already been fetched, the grid will not call the `getRows` function again to avoid unnecessary calls to the server. -- `getGroupKey(row: GridRowModel): string` +The `GridDataSourceCacheDefault` is used by default which is a simple in-memory cache that stores the data in a plain object. It could be seen in action in the demo below. - will be used by the grid to group rows by their parent group - This effectively replaces `getTreeDataPath`. - Consider this structure: +{{"demo": "ServerSideDataGrid.js", "bg": "inline"}} - ```js - - (1) Sarah // groupKey 'Sarah' - - (2) Thomas // groupKey 'Thomas' - ``` +### Customize the cache lifetime - When (2) is expanded, the `getRows` function will be called with group keys `['Sarah', 'Thomas']`. +The `GridDataSourceCacheDefault` has a default Time To Live (`ttl`) of 5 minutes. To customize it, pass the `ttl` option in milliseconds to the `GridDataSourceCacheDefault` constructor, and then pass it as the `unstable_dataSourceCache` prop. -- `hasChildren?(row: GridRowModel): boolean` +```tsx +import { GridDataSourceCacheDefault } from '@mui/x-data-grid-pro'; - Will be used by the grid to determine if a row has children on server +const lowTTLCache = new GridDataSourceCacheDefault({ ttl: 1000 * 10 }); // 10 seconds -- `getChildrenCount?: (row: GridRowModel) => number` +; +``` + +{{"demo": "ServerSideDataGridTTL.js", "bg": "inline"}} + +### Custom cache - Will be used by the grid to determine the number of children of a row on server +To provide a custom cache, use `unstable_dataSourceCache` prop, which could be either written from scratch or based out of another cache library. +This prop accepts a generic interface of type `GridDataSourceCache`. -#### Existing server-side features +```tsx +export interface GridDataSourceCache { + set: (key: GridGetRowsParams, value: GridGetRowsResponse) => void; + get: (key: GridGetRowsParams) => GridGetRowsResponse | undefined; + clear: () => void; +} +``` -The server-side data source will change a bit the way existing server-side features like `filtering`, `sorting`, and `pagination` work. +### Disable cache -**Without data source**: -When there's no data source, the features `filtering`, `sorting`, `pagination` will work on `client` by default. In order for them to work with server-side data, you need to set them to `server` explicitly and listen to the [`onFilterModelChange`](https://mui.com/x/react-data-grid/filtering/server-side/), [`onSortModelChange`](https://mui.com/x/react-data-grid/sorting/#server-side-sorting), [`onPaginationModelChange`](https://mui.com/x/react-data-grid/pagination/#server-side-pagination) events to fetch the data from the server based on the updated variables. +To disable the data source cache, pass `null` to the `unstable_dataSourceCache` prop. ```tsx - { - // fetch data from server - }} - onSortModelChange={(newSortModel) => { - // fetch data from server - }} - onFilterModelChange={(newFilterModel) => { - // fetch data from server - }} + unstable_dataSource={customDataSource} + unstable_dataSourceCache={null} /> ``` -**With data source**: -However, with a valid data source passed the features `filtering`, `sorting`, `pagination` will automatically be set to `server`. +{{"demo": "ServerSideDataGridNoCache.js", "bg": "inline"}} -You just need to implement the `getRows` method and the data grid will call the `getRows` method with the proper params whenever it needs data. +## Error handling + +You could handle the errors with the data source by providing an error handler function using the `unstable_onDataSourceError`. +It will be called whenever there's an error in fetching the data. + +The first argument of this function is the error object, and the second argument is the fetch parameters of type `GridGetRowsParams`. ```tsx { + console.error(error); + }} /> ``` -#### Caching +{{"demo": "ServerSideErrorHandling.js", "bg": "inline"}} + +## Updating data 🚧 + +This feature is yet to be implemented, when completed, the method `unstable_dataSource.updateRow` will be called with the `GridRowModel` whenever the user edits a row. +It will work in a similar way as the `processRowUpdate` prop. -The data grid will cache the data it receives from the server. This means that if the user navigates to a page that has already been fetched, the grid will not call the `getRows` function again. This is to avoid unnecessary calls to the server. +Feel free to upvote the related GitHub [issue](https://github.com/mui/mui-x/issues/13261) to see this feature land faster. ## API diff --git a/docs/data/data-grid/server-side-data/tree-data.md b/docs/data/data-grid/server-side-data/tree-data.md index ba9d93e36719..8e77fe0542bf 100644 --- a/docs/data/data-grid/server-side-data/tree-data.md +++ b/docs/data/data-grid/server-side-data/tree-data.md @@ -2,14 +2,72 @@ title: React Server-side tree data --- -# Data Grid - Server-side tree data [](/x/introduction/licensing/#pro-plan 'Pro plan')🚧 +# Data Grid - Server-side tree data [](/x/introduction/licensing/#pro-plan 'Pro plan')

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

-:::warning -This feature isn't implemented yet. It's coming. +To dynamically load tree data from the server, including lazy-loading of children, you must create a data source and pass the `unstable_dataSource` prop to the Data Grid, as detailed in the [overview section](/x/react-data-grid/server-side-data/). -πŸ‘ Upvote [issue #3377](https://github.com/mui/mui-x/issues/3377) if you want to see it land faster. +The data source also requires some additional props to handle tree data, namely `getGroupKey` and `getChildrenCount`. +If the children count is not available for some reason, but there are some children, `getChildrenCount` should return `-1`. -Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with the [currently proposed workaround](https://mui.com/x/react-data-grid/tree-data/#children-lazy-loading). +```tsx +const customDataSource: GridDataSource = { + getRows: async (params) => { + // Fetch the data from the server + }, + getGroupKey: (row) => { + // Return the group key for the row, e.g. `name` + return row.name; + }, + getChildrenCount: (row) => { + // Return the number of children for the row + return row.childrenCount; + }, +}; +``` + +The following tree data example supports filtering, sorting, and pagination on the server. +It also caches the data by default. + +{{"demo": "ServerSideTreeData.js", "bg": "inline"}} + +:::info +The data source demos use a utility function `useMockServer` to simulate the server-side data fetching. +In a real-world scenario, you would replace this with your own server-side data fetching logic. + +Open the info section of the browser console to see the requests being made and the data being fetched in response. ::: + +## Error handling + +For each row group expansion, the data source is called to fetch the children. If an error occurs during the fetch, the grid will display an error message in the row group cell. `unstable_onDataSourceError` is also triggered with the error and the fetch params. + +The demo below shows a toast apart from the default error message in the grouping cell. Cache has been disabled in this demo for simplicity. + +{{"demo": "ServerSideTreeDataErrorHandling.js", "bg": "inline"}} + +## Group expansion + +The idea behind the group expansion is the same as explained in the [Row grouping](/x/react-data-grid/row-grouping/#group-expansion) section. +The difference is that the data is not initially available and is fetched automatically after the Data Grid is mounted based on the props `defaultGroupingExpansionDepth` and `isGroupExpandedByDefault` in a waterfall manner. + +The following demo uses `defaultGroupingExpansionDepth='-1'` to expand all levels of the tree by default. + +{{"demo": "ServerSideTreeDataGroupExpansion.js", "bg": "inline"}} + +## Custom cache + +The data source uses a cache by default to store the fetched data. +Use the `unstable_dataSourceCache` prop to provide a custom cache if necessary. +See [Data caching](/x/react-data-grid/server-side-data/#data-caching) for more info. + +The following demo uses `QueryClient` from `@tanstack/react-core` as a data source cache. + +{{"demo": "ServerSideTreeDataCustomCache.js", "bg": "inline"}} + +## API + +- [DataGrid](/x/api/data-grid/data-grid/) +- [DataGridPro](/x/api/data-grid/data-grid-pro/) +- [DataGridPremium](/x/api/data-grid/data-grid-premium/) diff --git a/docs/data/data-grid/tree-data/TreeDataLazyLoading.js b/docs/data/data-grid/tree-data/TreeDataLazyLoading.js deleted file mode 100644 index ea3f9c8fd2a4..000000000000 --- a/docs/data/data-grid/tree-data/TreeDataLazyLoading.js +++ /dev/null @@ -1,297 +0,0 @@ -import * as React from 'react'; -import { - DataGridPro, - getDataGridUtilityClass, - useGridApiContext, - useGridApiRef, - useGridRootProps, -} from '@mui/x-data-grid-pro'; -import { unstable_composeClasses as composeClasses, styled } from '@mui/material'; -import Box from '@mui/material/Box'; -import CircularProgress from '@mui/material/CircularProgress'; -import IconButton from '@mui/material/IconButton'; - -export const isNavigationKey = (key) => - key === 'Home' || - key === 'End' || - key.indexOf('Arrow') === 0 || - key.indexOf('Page') === 0 || - key === ' '; - -const ALL_ROWS = [ - { - hierarchy: ['Sarah'], - jobTitle: 'Head of Human Resources', - recruitmentDate: new Date(2020, 8, 12), - id: 0, - }, - { - hierarchy: ['Thomas'], - jobTitle: 'Head of Sales', - recruitmentDate: new Date(2017, 3, 4), - id: 1, - }, - { - hierarchy: ['Thomas', 'Robert'], - jobTitle: 'Sales Person', - recruitmentDate: new Date(2020, 11, 20), - id: 2, - }, - { - hierarchy: ['Thomas', 'Karen'], - jobTitle: 'Sales Person', - recruitmentDate: new Date(2020, 10, 14), - id: 3, - }, - { - hierarchy: ['Thomas', 'Nancy'], - jobTitle: 'Sales Person', - recruitmentDate: new Date(2017, 10, 29), - id: 4, - }, - { - hierarchy: ['Thomas', 'Daniel'], - jobTitle: 'Sales Person', - recruitmentDate: new Date(2020, 7, 21), - id: 5, - }, - { - hierarchy: ['Thomas', 'Christopher'], - jobTitle: 'Sales Person', - recruitmentDate: new Date(2020, 7, 20), - id: 6, - }, - { - hierarchy: ['Thomas', 'Donald'], - jobTitle: 'Sales Person', - recruitmentDate: new Date(2019, 6, 28), - id: 7, - }, - { - hierarchy: ['Mary'], - jobTitle: 'Head of Engineering', - recruitmentDate: new Date(2016, 3, 14), - id: 8, - }, - { - hierarchy: ['Mary', 'Jennifer'], - jobTitle: 'Tech lead front', - recruitmentDate: new Date(2016, 5, 17), - id: 9, - }, - { - hierarchy: ['Mary', 'Jennifer', 'Anna'], - jobTitle: 'Front-end developer', - recruitmentDate: new Date(2019, 11, 7), - id: 10, - }, - { - hierarchy: ['Mary', 'Michael'], - jobTitle: 'Tech lead devops', - recruitmentDate: new Date(2021, 7, 1), - id: 11, - }, - { - hierarchy: ['Mary', 'Linda'], - jobTitle: 'Tech lead back', - recruitmentDate: new Date(2017, 0, 12), - id: 12, - }, - { - hierarchy: ['Mary', 'Linda', 'Elizabeth'], - jobTitle: 'Back-end developer', - recruitmentDate: new Date(2019, 2, 22), - id: 13, - }, - { - hierarchy: ['Mary', 'Linda', 'William'], - jobTitle: 'Back-end developer', - recruitmentDate: new Date(2018, 4, 19), - id: 14, - }, -]; - -const columns = [ - { field: 'jobTitle', headerName: 'Job Title', width: 200 }, - { - field: 'recruitmentDate', - headerName: 'Recruitment Date', - type: 'date', - width: 150, - }, -]; - -const getChildren = (parentPath) => { - const parentPathStr = parentPath.join('-'); - return ALL_ROWS.filter( - (row) => row.hierarchy.slice(0, -1).join('-') === parentPathStr, - ); -}; - -/** - * This is a naive implementation with terrible performances on a real dataset. - * This fake server is only here for demonstration purposes. - */ -const fakeDataFetcher = (parentPath = []) => - new Promise((resolve) => { - setTimeout( - () => { - const rows = getChildren(parentPath).map((row) => ({ - ...row, - descendantCount: getChildren(row.hierarchy).length, - })); - resolve(rows); - }, - 500 + Math.random() * 300, - ); - }); - -const LoadingContainer = styled('div')({ - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - height: '100%', -}); - -const getTreeDataPath = (row) => row.hierarchy; - -const useUtilityClasses = (ownerState) => { - const { classes } = ownerState; - - const slots = { - root: ['treeDataGroupingCell'], - toggle: ['treeDataGroupingCellToggle'], - }; - - return composeClasses(slots, getDataGridUtilityClass, classes); -}; - -/** - * Reproduce the behavior of the `GridTreeDataGroupingCell` component in `@mui/x-data-grid-pro` - * But base the amount of children on a `row.descendantCount` property rather than on the internal lookups. - */ -function GroupingCellWithLazyLoading(props) { - const { id, rowNode, row, hideDescendantCount, formattedValue } = props; - - const rootProps = useGridRootProps(); - const apiRef = useGridApiContext(); - const classes = useUtilityClasses({ classes: rootProps.classes }); - - const isLoading = rowNode.childrenExpanded ? !row.childrenFetched : false; - - const Icon = rowNode.childrenExpanded - ? rootProps.slots.treeDataCollapseIcon - : rootProps.slots.treeDataExpandIcon; - - const handleClick = () => { - apiRef.current.setRowChildrenExpansion(id, !rowNode.childrenExpanded); - }; - - return ( - -
- {row.descendantCount > 0 && - (isLoading ? ( - - - - ) : ( - - - - ))} -
- - {formattedValue === undefined ? rowNode.groupingKey : formattedValue} - {!hideDescendantCount && row.descendantCount > 0 - ? ` (${row.descendantCount})` - : ''} - -
- ); -} - -const CUSTOM_GROUPING_COL_DEF = { - renderCell: (params) => , -}; - -// Optional -const getRowId = (row) => { - if (typeof row?.id === 'string' && row?.id.startsWith('placeholder-children-')) { - return row.id; - } - return row.id; -}; - -function updateRows(apiRef, rows) { - if (!apiRef.current) { - return; - } - const rowsToAdd = [...rows]; - rows.forEach((row) => { - if (row.descendantCount && row.descendantCount > 0) { - // Add a placeholder row to make the row expandable - rowsToAdd.push({ - id: `placeholder-children-${getRowId(row)}`, - hierarchy: [...row.hierarchy, ''], - }); - } - }); - apiRef.current.updateRows(rowsToAdd); -} - -const initialRows = []; - -export default function TreeDataLazyLoading() { - const apiRef = useGridApiRef(); - - React.useEffect(() => { - fakeDataFetcher().then((rowsData) => { - updateRows(apiRef, rowsData); - }); - - const handleRowExpansionChange = async (node) => { - const row = apiRef.current.getRow(node.id); - - if (!node.childrenExpanded || !row || row.childrenFetched) { - return; - } - - const childrenRows = await fakeDataFetcher(row.hierarchy); - updateRows(apiRef, [ - ...childrenRows, - { ...row, childrenFetched: true }, - { id: `placeholder-children-${node.id}`, _action: 'delete' }, - ]); - }; - - return apiRef.current.subscribeEvent( - 'rowExpansionChange', - handleRowExpansionChange, - ); - }, [apiRef]); - - return ( -
- -
- ); -} diff --git a/docs/data/data-grid/tree-data/TreeDataLazyLoading.tsx b/docs/data/data-grid/tree-data/TreeDataLazyLoading.tsx deleted file mode 100644 index 4eb26369ed09..000000000000 --- a/docs/data/data-grid/tree-data/TreeDataLazyLoading.tsx +++ /dev/null @@ -1,329 +0,0 @@ -import * as React from 'react'; -import { - DataGridPro, - GridApi, - getDataGridUtilityClass, - GridColDef, - DataGridProProps, - GridEventListener, - GridGroupingColDefOverride, - GridRenderCellParams, - GridRowModel, - GridRowsProp, - GridGroupNode, - useGridApiContext, - useGridApiRef, - useGridRootProps, - GridRowModelUpdate, - GridRowIdGetter, -} from '@mui/x-data-grid-pro'; -import { unstable_composeClasses as composeClasses, styled } from '@mui/material'; -import Box from '@mui/material/Box'; -import CircularProgress from '@mui/material/CircularProgress'; -import IconButton, { IconButtonProps } from '@mui/material/IconButton'; - -export const isNavigationKey = (key: string) => - key === 'Home' || - key === 'End' || - key.indexOf('Arrow') === 0 || - key.indexOf('Page') === 0 || - key === ' '; - -interface Row { - hierarchy: string[]; - jobTitle: string; - recruitmentDate: Date; - id: number; - descendantCount?: number; - childrenFetched?: boolean; -} - -const ALL_ROWS: GridRowModel[] = [ - { - hierarchy: ['Sarah'], - jobTitle: 'Head of Human Resources', - recruitmentDate: new Date(2020, 8, 12), - id: 0, - }, - { - hierarchy: ['Thomas'], - jobTitle: 'Head of Sales', - recruitmentDate: new Date(2017, 3, 4), - id: 1, - }, - { - hierarchy: ['Thomas', 'Robert'], - jobTitle: 'Sales Person', - recruitmentDate: new Date(2020, 11, 20), - id: 2, - }, - { - hierarchy: ['Thomas', 'Karen'], - jobTitle: 'Sales Person', - recruitmentDate: new Date(2020, 10, 14), - id: 3, - }, - { - hierarchy: ['Thomas', 'Nancy'], - jobTitle: 'Sales Person', - recruitmentDate: new Date(2017, 10, 29), - id: 4, - }, - { - hierarchy: ['Thomas', 'Daniel'], - jobTitle: 'Sales Person', - recruitmentDate: new Date(2020, 7, 21), - id: 5, - }, - { - hierarchy: ['Thomas', 'Christopher'], - jobTitle: 'Sales Person', - recruitmentDate: new Date(2020, 7, 20), - id: 6, - }, - { - hierarchy: ['Thomas', 'Donald'], - jobTitle: 'Sales Person', - recruitmentDate: new Date(2019, 6, 28), - id: 7, - }, - { - hierarchy: ['Mary'], - jobTitle: 'Head of Engineering', - recruitmentDate: new Date(2016, 3, 14), - id: 8, - }, - { - hierarchy: ['Mary', 'Jennifer'], - jobTitle: 'Tech lead front', - recruitmentDate: new Date(2016, 5, 17), - id: 9, - }, - { - hierarchy: ['Mary', 'Jennifer', 'Anna'], - jobTitle: 'Front-end developer', - recruitmentDate: new Date(2019, 11, 7), - id: 10, - }, - { - hierarchy: ['Mary', 'Michael'], - jobTitle: 'Tech lead devops', - recruitmentDate: new Date(2021, 7, 1), - id: 11, - }, - { - hierarchy: ['Mary', 'Linda'], - jobTitle: 'Tech lead back', - recruitmentDate: new Date(2017, 0, 12), - id: 12, - }, - { - hierarchy: ['Mary', 'Linda', 'Elizabeth'], - jobTitle: 'Back-end developer', - recruitmentDate: new Date(2019, 2, 22), - id: 13, - }, - { - hierarchy: ['Mary', 'Linda', 'William'], - jobTitle: 'Back-end developer', - recruitmentDate: new Date(2018, 4, 19), - id: 14, - }, -]; - -const columns: GridColDef[] = [ - { field: 'jobTitle', headerName: 'Job Title', width: 200 }, - { - field: 'recruitmentDate', - headerName: 'Recruitment Date', - type: 'date', - width: 150, - }, -]; - -const getChildren = (parentPath: string[]) => { - const parentPathStr = parentPath.join('-'); - return ALL_ROWS.filter( - (row) => row.hierarchy.slice(0, -1).join('-') === parentPathStr, - ); -}; - -/** - * This is a naive implementation with terrible performances on a real dataset. - * This fake server is only here for demonstration purposes. - */ -const fakeDataFetcher = (parentPath: string[] = []) => - new Promise[]>((resolve) => { - setTimeout( - () => { - const rows = getChildren(parentPath).map((row) => ({ - ...row, - descendantCount: getChildren(row.hierarchy).length, - })); - resolve(rows); - }, - 500 + Math.random() * 300, - ); - }); - -const LoadingContainer = styled('div')({ - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - height: '100%', -}); - -const getTreeDataPath: DataGridProProps['getTreeDataPath'] = (row) => row.hierarchy; - -const useUtilityClasses = (ownerState: { classes: DataGridProProps['classes'] }) => { - const { classes } = ownerState; - - const slots = { - root: ['treeDataGroupingCell'], - toggle: ['treeDataGroupingCellToggle'], - }; - - return composeClasses(slots, getDataGridUtilityClass, classes); -}; - -interface GroupingCellWithLazyLoadingProps - extends GridRenderCellParams { - hideDescendantCount?: boolean; -} - -/** - * Reproduce the behavior of the `GridTreeDataGroupingCell` component in `@mui/x-data-grid-pro` - * But base the amount of children on a `row.descendantCount` property rather than on the internal lookups. - */ -function GroupingCellWithLazyLoading(props: GroupingCellWithLazyLoadingProps) { - const { id, rowNode, row, hideDescendantCount, formattedValue } = props; - - const rootProps = useGridRootProps(); - const apiRef = useGridApiContext(); - const classes = useUtilityClasses({ classes: rootProps.classes }); - - const isLoading = rowNode.childrenExpanded ? !row.childrenFetched : false; - - const Icon = rowNode.childrenExpanded - ? rootProps.slots.treeDataCollapseIcon - : rootProps.slots.treeDataExpandIcon; - - const handleClick: IconButtonProps['onClick'] = () => { - apiRef.current.setRowChildrenExpansion(id, !rowNode.childrenExpanded); - }; - - return ( - -
- {row.descendantCount > 0 && - (isLoading ? ( - - - - ) : ( - - - - ))} -
- - {formattedValue === undefined ? rowNode.groupingKey : formattedValue} - {!hideDescendantCount && row.descendantCount > 0 - ? ` (${row.descendantCount})` - : ''} - -
- ); -} - -const CUSTOM_GROUPING_COL_DEF: GridGroupingColDefOverride = { - renderCell: (params) => ( - - ), -}; - -// Optional -const getRowId: GridRowIdGetter = (row) => { - if (typeof row?.id === 'string' && row?.id.startsWith('placeholder-children-')) { - return row.id; - } - return row.id; -}; - -function updateRows( - apiRef: React.MutableRefObject, - rows: GridRowModelUpdate[], -) { - if (!apiRef.current) { - return; - } - const rowsToAdd = [...rows]; - rows.forEach((row) => { - if (row.descendantCount && row.descendantCount > 0) { - // Add a placeholder row to make the row expandable - rowsToAdd.push({ - id: `placeholder-children-${getRowId(row)}`, - hierarchy: [...row.hierarchy, ''], - }); - } - }); - apiRef.current.updateRows(rowsToAdd); -} - -const initialRows: GridRowsProp = []; - -export default function TreeDataLazyLoading() { - const apiRef = useGridApiRef(); - - React.useEffect(() => { - fakeDataFetcher().then((rowsData) => { - updateRows(apiRef, rowsData); - }); - - const handleRowExpansionChange: GridEventListener<'rowExpansionChange'> = async ( - node, - ) => { - const row = apiRef.current.getRow(node.id) as Row | null; - - if (!node.childrenExpanded || !row || row.childrenFetched) { - return; - } - - const childrenRows = await fakeDataFetcher(row.hierarchy); - updateRows(apiRef, [ - ...childrenRows, - { ...row, childrenFetched: true }, - { id: `placeholder-children-${node.id}`, _action: 'delete' }, - ]); - }; - - return apiRef.current.subscribeEvent( - 'rowExpansionChange', - handleRowExpansionChange, - ); - }, [apiRef]); - - return ( -
- -
- ); -} diff --git a/docs/data/data-grid/tree-data/TreeDataLazyLoading.tsx.preview b/docs/data/data-grid/tree-data/TreeDataLazyLoading.tsx.preview deleted file mode 100644 index 527bdff70663..000000000000 --- a/docs/data/data-grid/tree-data/TreeDataLazyLoading.tsx.preview +++ /dev/null @@ -1,10 +0,0 @@ - \ No newline at end of file diff --git a/docs/data/data-grid/tree-data/tree-data.md b/docs/data/data-grid/tree-data/tree-data.md index fe6fa401e005..3af238f688a3 100644 --- a/docs/data/data-grid/tree-data/tree-data.md +++ b/docs/data/data-grid/tree-data/tree-data.md @@ -126,23 +126,9 @@ const invalidRows = [{ path: ['A'] }, { path: ['B'] }, { path: ['A', 'A'] }]; ::: -## Children lazy-loading 🚧 +## Children lazy-loading -:::warning -This feature isn't implemented yet. It's coming. - -πŸ‘ Upvote [issue #3377](https://github.com/mui/mui-x/issues/3377) if you want to see it land faster. - -Don't hesitate to leave a comment on the same issue to influence what gets built. Especially if you already have a use case for this component, or if you are facing a pain point with your current solution. -::: - -Alternatively, you can achieve a similar behavior by implementing this feature outside the component as shown below. -This implementation does not support every feature of the data grid but can be a good starting point for large datasets. - -The idea is to add a property `descendantCount` on the row and to use it instead of the internal grid state. -To do so, you need to override both the `renderCell` of the grouping column and to manually open the rows by listening to `rowExpansionChange` event. - -{{"demo": "TreeDataLazyLoading.js", "bg": "inline", "defaultCodeOpen": false}} +Check the [Server-side tree data](/x/react-data-grid/server-side-data/tree-data/) section for more information about lazy-loading tree data children. ## Full example diff --git a/docs/data/date-pickers/adapters-locale/adapters-locale.md b/docs/data/date-pickers/adapters-locale/adapters-locale.md index 6ab1f2944f39..26b4113d0f7b 100644 --- a/docs/data/date-pickers/adapters-locale/adapters-locale.md +++ b/docs/data/date-pickers/adapters-locale/adapters-locale.md @@ -79,6 +79,14 @@ import { AdapterLuxon } from '@mui/x-date-pickers/AdapterLuxon'; {{"demo": "LocalizationLuxon.js"}} +:::warning +`AdapterLuxon` does not support `Settings.throwOnInvalid = true` [setting](https://moment.github.io/luxon/api-docs/index.html#settingsthrowoninvalid). + +πŸ‘ Upvote [issue #11853](https://github.com/mui/mui-x/issues/11853) if you need support for it. + +Don't hesitate to leave feedback on how you would like the data entry to behave. +::: + ### With `moment` For `moment`, import the locale and then pass its name to `LocalizationProvider`: diff --git a/docs/data/date-pickers/custom-components/ActionBarComponent.js b/docs/data/date-pickers/custom-components/ActionBarComponent.js index 8071aea4d7f6..4615954c25c1 100644 --- a/docs/data/date-pickers/custom-components/ActionBarComponent.js +++ b/docs/data/date-pickers/custom-components/ActionBarComponent.js @@ -9,11 +9,11 @@ import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import { StaticDatePicker } from '@mui/x-date-pickers/StaticDatePicker'; -import { useLocaleText } from '@mui/x-date-pickers/internals'; +import { usePickersTranslations } from '@mui/x-date-pickers/hooks'; function CustomActionBar(props) { const { onAccept, onClear, onCancel, onSetToday, actions, className } = props; - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const [anchorEl, setAnchorEl] = React.useState(null); const open = Boolean(anchorEl); const id = useId(); @@ -34,7 +34,7 @@ function CustomActionBar(props) { }} key={actionType} > - {localeText.clearButtonLabel} + {translations.clearButtonLabel} ); @@ -47,7 +47,7 @@ function CustomActionBar(props) { }} key={actionType} > - {localeText.cancelButtonLabel} + {translations.cancelButtonLabel} ); @@ -60,7 +60,7 @@ function CustomActionBar(props) { }} key={actionType} > - {localeText.okButtonLabel} + {translations.okButtonLabel} ); @@ -74,7 +74,7 @@ function CustomActionBar(props) { }} key={actionType} > - {localeText.todayButtonLabel} + {translations.todayButtonLabel} ); diff --git a/docs/data/date-pickers/custom-components/ActionBarComponent.tsx b/docs/data/date-pickers/custom-components/ActionBarComponent.tsx index 7985a95c6dfd..7516085bb00e 100644 --- a/docs/data/date-pickers/custom-components/ActionBarComponent.tsx +++ b/docs/data/date-pickers/custom-components/ActionBarComponent.tsx @@ -9,11 +9,11 @@ import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import { StaticDatePicker } from '@mui/x-date-pickers/StaticDatePicker'; import { PickersActionBarProps } from '@mui/x-date-pickers/PickersActionBar'; -import { useLocaleText } from '@mui/x-date-pickers/internals'; +import { usePickersTranslations } from '@mui/x-date-pickers/hooks'; function CustomActionBar(props: PickersActionBarProps) { const { onAccept, onClear, onCancel, onSetToday, actions, className } = props; - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const [anchorEl, setAnchorEl] = React.useState(null); const open = Boolean(anchorEl); const id = useId(); @@ -34,7 +34,7 @@ function CustomActionBar(props: PickersActionBarProps) { }} key={actionType} > - {localeText.clearButtonLabel} + {translations.clearButtonLabel} ); case 'cancel': @@ -46,7 +46,7 @@ function CustomActionBar(props: PickersActionBarProps) { }} key={actionType} > - {localeText.cancelButtonLabel} + {translations.cancelButtonLabel} ); case 'accept': @@ -58,7 +58,7 @@ function CustomActionBar(props: PickersActionBarProps) { }} key={actionType} > - {localeText.okButtonLabel} + {translations.okButtonLabel} ); case 'today': @@ -71,7 +71,7 @@ function CustomActionBar(props: PickersActionBarProps) { }} key={actionType} > - {localeText.todayButtonLabel} + {translations.todayButtonLabel} ); default: diff --git a/docs/data/date-pickers/date-picker/CustomizationExamplesNoSnap.js b/docs/data/date-pickers/date-picker/CustomizationExamplesNoSnap.js index 3b1a1f36bb4c..c61118d8584a 100644 --- a/docs/data/date-pickers/date-picker/CustomizationExamplesNoSnap.js +++ b/docs/data/date-pickers/date-picker/CustomizationExamplesNoSnap.js @@ -4,7 +4,7 @@ import ToggleButton from '@mui/material/ToggleButton'; import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'; import Stack from '@mui/material/Stack'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; -import BrandingProvider from 'docs/src/BrandingProvider'; +import { BrandingProvider } from '@mui/docs/branding'; import CustomizationPlayground from 'docsx/src/modules/components/CustomizationPlayground'; import CircularProgress from '@mui/material/CircularProgress'; import { pickerExamples } from './examplesConfig.styling'; diff --git a/docs/data/date-pickers/localization/UseLocaleText.tsx.preview b/docs/data/date-pickers/localization/UseLocaleText.tsx.preview new file mode 100644 index 000000000000..395c5e40aaea --- /dev/null +++ b/docs/data/date-pickers/localization/UseLocaleText.tsx.preview @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/docs/data/date-pickers/localization/localization.md b/docs/data/date-pickers/localization/localization.md index d461a3946516..0e0cbdcc2a61 100644 --- a/docs/data/date-pickers/localization/localization.md +++ b/docs/data/date-pickers/localization/localization.md @@ -131,3 +131,17 @@ You can [find the source](https://github.com/mui/mui-x/tree/HEAD/packages/x-date To create your own translation or to customize the English text, copy this file to your project, make any changes needed and import the locale from there. Note that these translations of the date and time picker components depend on the [Localization strategy](/material-ui/guides/localization/) of the whole library. + +## Access the translations in slots and subcomponents + +You can use the `usePickersTranslations` hook to access the translations in your custom components. + +```tsx +import { usePickersTranslations } from '@mui/x-date-pickers/hooks'; + +const translations = usePickersTranslations(); +``` + +:::info +See [Custom slots and subcomponentsβ€”Action bar](/x/react-date-pickers/custom-components/#component) for more details. +::: diff --git a/docs/data/date-pickers/overview/overview.md b/docs/data/date-pickers/overview/overview.md index ae699e363d1d..8c73477e1a0a 100644 --- a/docs/data/date-pickers/overview/overview.md +++ b/docs/data/date-pickers/overview/overview.md @@ -11,7 +11,7 @@ waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/datepick

These react date picker and time picker components let users select date or time values.

-{{"component": "modules/components/ComponentLinkHeader.js"}} +{{"component": "@mui/docs/ComponentLinkHeader"}} ## Overview diff --git a/docs/data/pages.ts b/docs/data/pages.ts index 65822bf57988..12a8c186dfc8 100644 --- a/docs/data/pages.ts +++ b/docs/data/pages.ts @@ -87,6 +87,7 @@ const pages: MuiPage[] = [ }, { pathname: '/x/react-data-grid/export' }, { pathname: '/x/react-data-grid/clipboard', title: 'Copy and paste', newFeature: true }, + { pathname: '/x/react-data-grid/overlays', title: 'Overlays' }, { pathname: '/x/react-data-grid/components', title: 'Custom subcomponents' }, { pathname: '/x/react-data-grid/style-group', @@ -115,9 +116,10 @@ const pages: MuiPage[] = [ { pathname: '/x/react-data-grid/server-side-data-group', title: 'Server-side data', - planned: true, + plan: 'pro', children: [ - { pathname: '/x/react-data-grid/server-side-data', title: 'Overview', planned: true }, + { pathname: '/x/react-data-grid/server-side-data', title: 'Overview' }, + { pathname: '/x/react-data-grid/server-side-data/tree-data', plan: 'pro' }, { pathname: '/x/react-data-grid/server-side-data/lazy-loading', plan: 'pro', @@ -128,7 +130,6 @@ const pages: MuiPage[] = [ plan: 'pro', planned: true, }, - { pathname: '/x/react-data-grid/server-side-data/tree-data', plan: 'pro', planned: true }, { pathname: '/x/react-data-grid/server-side-data/row-grouping', plan: 'pro', @@ -423,6 +424,12 @@ const pages: MuiPage[] = [ title: 'Sparkline', }, { pathname: '/x/react-charts/gauge' }, + { + pathname: '/x/react-charts/heatmap', + title: 'Heatmap', + plan: 'pro', + unstable: true, + }, { pathname: '/x/react-charts/common-features', subheader: 'Common features', @@ -435,6 +442,7 @@ const pages: MuiPage[] = [ { pathname: '/x/react-charts/stacking' }, { pathname: '/x/react-charts/styling' }, { pathname: '/x/react-charts/tooltip', title: 'Tooltip & Highlights' }, + { pathname: '/x/react-charts/zoom-and-pan', title: 'Zoom & Pan', plan: 'pro' }, ], }, { @@ -461,12 +469,6 @@ const pages: MuiPage[] = [ children: [ { pathname: '/x/react-charts/radar', planned: true }, { pathname: '/x/react-charts/treemap', title: 'Treemap', planned: true }, - { - pathname: '/x/react-charts/heatmap', - title: 'Heatmap', - plan: 'pro', - planned: true, - }, { pathname: '/x/react-charts/funnel', plan: 'pro', planned: true }, { pathname: '/x/react-charts/sankey', plan: 'pro', planned: true }, { pathname: '/x/react-charts/gantt', plan: 'pro', planned: true }, diff --git a/docs/data/tree-view/overview/overview.md b/docs/data/tree-view/overview/overview.md index 9429bf8a1d30..64c374965652 100644 --- a/docs/data/tree-view/overview/overview.md +++ b/docs/data/tree-view/overview/overview.md @@ -10,7 +10,7 @@ packageName: '@mui/x-tree-view'

The Tree View component lets users navigate hierarchical lists of data with nested levels that can be expanded and collapsed.

-{{"component": "modules/components/ComponentLinkHeader.js"}} +{{"component": "@mui/docs/ComponentLinkHeader"}} ## Available components diff --git a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx.preview b/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx.preview deleted file mode 100644 index 660542f7bf2c..000000000000 --- a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx.preview +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/data/tree-view/rich-tree-view/customization/customization.md b/docs/data/tree-view/rich-tree-view/customization/customization.md index 8f1552b6f0df..4bedda31d764 100644 --- a/docs/data/tree-view/rich-tree-view/customization/customization.md +++ b/docs/data/tree-view/rich-tree-view/customization/customization.md @@ -64,12 +64,6 @@ The demo below shows how to add an avatar and custom typography elements. ## Common examples -### Limit expansion to icon container - -The demo below shows how to trigger the expansion interaction just by clicking on the icon container instead of the whole Tree Item surface. - -{{"demo": "IconExpansionTreeView.js", "defaultCodeOpen": false}} - ### File explorer :::warning diff --git a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.js b/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.js similarity index 55% rename from docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.js rename to docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.js index fa2935769a63..db2d29f0fcfa 100644 --- a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.js +++ b/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.js @@ -1,9 +1,6 @@ import * as React from 'react'; import Box from '@mui/material/Box'; import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; -import { useTreeItem2Utils } from '@mui/x-tree-view/hooks'; - -import { TreeItem2 } from '@mui/x-tree-view/TreeItem2'; const MUI_X_PRODUCTS = [ { @@ -35,37 +32,10 @@ const MUI_X_PRODUCTS = [ }, ]; -const CustomTreeItem = React.forwardRef(function MyTreeItem(props, ref) { - const { interactions } = useTreeItem2Utils({ - itemId: props.itemId, - children: props.children, - }); - - const handleContentClick = (event) => { - event.defaultMuiPrevented = true; - interactions.handleSelection(event); - }; - - const handleIconContainerClick = (event) => { - interactions.handleExpansion(event); - }; - - return ( - - ); -}); - export default function IconExpansionTreeView() { return ( - + ); } diff --git a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx b/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx similarity index 51% rename from docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx rename to docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx index 0d7345a1047d..94b9816b9a89 100644 --- a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx +++ b/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx @@ -1,9 +1,6 @@ import * as React from 'react'; import Box from '@mui/material/Box'; import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; -import { useTreeItem2Utils } from '@mui/x-tree-view/hooks'; -import { UseTreeItem2ContentSlotOwnProps } from '@mui/x-tree-view/useTreeItem2'; -import { TreeItem2, TreeItem2Props } from '@mui/x-tree-view/TreeItem2'; import { TreeViewBaseItem } from '@mui/x-tree-view/models'; const MUI_X_PRODUCTS: TreeViewBaseItem[] = [ @@ -36,40 +33,10 @@ const MUI_X_PRODUCTS: TreeViewBaseItem[] = [ }, ]; -const CustomTreeItem = React.forwardRef(function MyTreeItem( - props: TreeItem2Props, - ref: React.Ref, -) { - const { interactions } = useTreeItem2Utils({ - itemId: props.itemId, - children: props.children, - }); - - const handleContentClick: UseTreeItem2ContentSlotOwnProps['onClick'] = (event) => { - event.defaultMuiPrevented = true; - interactions.handleSelection(event); - }; - - const handleIconContainerClick = (event: React.MouseEvent) => { - interactions.handleExpansion(event); - }; - - return ( - - ); -}); - export default function IconExpansionTreeView() { return ( - + ); } diff --git a/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx.preview b/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx.preview new file mode 100644 index 000000000000..49f8c4e18162 --- /dev/null +++ b/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx.preview @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/data/tree-view/rich-tree-view/expansion/expansion.md b/docs/data/tree-view/rich-tree-view/expansion/expansion.md index e36fe65d20c1..84bcb34b503b 100644 --- a/docs/data/tree-view/rich-tree-view/expansion/expansion.md +++ b/docs/data/tree-view/rich-tree-view/expansion/expansion.md @@ -33,6 +33,12 @@ Use the `onItemExpansionToggle` prop if you want to react to an item expansion c {{"demo": "TrackItemExpansionToggle.js"}} +## Limit expansion to icon container + +You can use the `expansionTrigger` prop to decide if the expansion interaction should be triggered by clicking on the icon container instead of the whole Tree Item content. + +{{"demo": "IconExpansionTreeView.js"}} + ## Imperative API :::success @@ -56,9 +62,10 @@ Use the `setItemExpansion` API method to change the expansion of an item. apiRef.current.setItemExpansion( // The DOM event that triggered the change event, - // The ID of the item to expand or collapse + // The id of the item to expand or collapse itemId, - // `true` if the item should be expanded, `false` if it should be collapsed + // If `true` the item will be expanded + // If `false` the item will be collapsed isExpanded, ); ``` diff --git a/docs/data/tree-view/rich-tree-view/focus/focus.md b/docs/data/tree-view/rich-tree-view/focus/focus.md index 7451953dac48..a293e75b0d20 100644 --- a/docs/data/tree-view/rich-tree-view/focus/focus.md +++ b/docs/data/tree-view/rich-tree-view/focus/focus.md @@ -34,7 +34,7 @@ Use the `focusItem` API method to focus a specific item. apiRef.current.focusItem( // The DOM event that triggered the change event, - // The ID of the item to focus + // The id of the item to focus itemId, ); ``` diff --git a/docs/data/tree-view/rich-tree-view/items/ApiMethodGetItemDOMElement.js b/docs/data/tree-view/rich-tree-view/items/ApiMethodGetItemDOMElement.js new file mode 100644 index 000000000000..560e4412ee84 --- /dev/null +++ b/docs/data/tree-view/rich-tree-view/items/ApiMethodGetItemDOMElement.js @@ -0,0 +1,64 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Stack from '@mui/material/Stack'; +import Button from '@mui/material/Button'; +import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; + +import { useTreeViewApiRef } from '@mui/x-tree-view/hooks/useTreeViewApiRef'; + +const MUI_X_PRODUCTS = [ + { + id: 'grid', + label: 'Data Grid', + children: [ + { id: 'grid-community', label: '@mui/x-data-grid' }, + { id: 'grid-pro', label: '@mui/x-data-grid-pro' }, + { id: 'grid-premium', label: '@mui/x-data-grid-premium' }, + ], + }, + { + id: 'pickers', + label: 'Date and Time Pickers', + children: [ + { id: 'pickers-community', label: '@mui/x-date-pickers' }, + { id: 'pickers-pro', label: '@mui/x-date-pickers-pro' }, + ], + }, + { + id: 'charts', + label: 'Charts', + children: [{ id: 'charts-community', label: '@mui/x-charts' }], + }, + { + id: 'tree-view', + label: 'Tree View', + children: [{ id: 'tree-view-community', label: '@mui/x-tree-view' }], + }, +]; + +export default function ApiMethodGetItemDOMElement() { + const apiRef = useTreeViewApiRef(); + const handleScrollToChartsCommunity = (event) => { + apiRef.current.focusItem(event, 'charts-community'); + apiRef.current + .getItemDOMElement('charts-community') + ?.scrollIntoView({ block: 'center' }); + }; + + return ( + +
+ +
+ + + +
+ ); +} diff --git a/docs/data/tree-view/rich-tree-view/items/ApiMethodGetItemDOMElement.tsx b/docs/data/tree-view/rich-tree-view/items/ApiMethodGetItemDOMElement.tsx new file mode 100644 index 000000000000..caec1f25a7f2 --- /dev/null +++ b/docs/data/tree-view/rich-tree-view/items/ApiMethodGetItemDOMElement.tsx @@ -0,0 +1,64 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Stack from '@mui/material/Stack'; +import Button from '@mui/material/Button'; +import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; +import { TreeViewBaseItem } from '@mui/x-tree-view/models'; +import { useTreeViewApiRef } from '@mui/x-tree-view/hooks/useTreeViewApiRef'; + +const MUI_X_PRODUCTS: TreeViewBaseItem[] = [ + { + id: 'grid', + label: 'Data Grid', + children: [ + { id: 'grid-community', label: '@mui/x-data-grid' }, + { id: 'grid-pro', label: '@mui/x-data-grid-pro' }, + { id: 'grid-premium', label: '@mui/x-data-grid-premium' }, + ], + }, + { + id: 'pickers', + label: 'Date and Time Pickers', + children: [ + { id: 'pickers-community', label: '@mui/x-date-pickers' }, + { id: 'pickers-pro', label: '@mui/x-date-pickers-pro' }, + ], + }, + { + id: 'charts', + label: 'Charts', + children: [{ id: 'charts-community', label: '@mui/x-charts' }], + }, + { + id: 'tree-view', + label: 'Tree View', + children: [{ id: 'tree-view-community', label: '@mui/x-tree-view' }], + }, +]; + +export default function ApiMethodGetItemDOMElement() { + const apiRef = useTreeViewApiRef(); + const handleScrollToChartsCommunity = (event: React.SyntheticEvent) => { + apiRef.current!.focusItem(event, 'charts-community'); + apiRef + .current!.getItemDOMElement('charts-community') + ?.scrollIntoView({ block: 'center' }); + }; + + return ( + +
+ +
+ + + +
+ ); +} diff --git a/docs/data/tree-view/rich-tree-view/items/ApiMethodGetItemDOMElement.tsx.preview b/docs/data/tree-view/rich-tree-view/items/ApiMethodGetItemDOMElement.tsx.preview new file mode 100644 index 000000000000..96b7480941c8 --- /dev/null +++ b/docs/data/tree-view/rich-tree-view/items/ApiMethodGetItemDOMElement.tsx.preview @@ -0,0 +1,12 @@ +
+ +
+ + + \ No newline at end of file diff --git a/docs/data/tree-view/rich-tree-view/items/items.md b/docs/data/tree-view/rich-tree-view/items/items.md index 9370571c23e3..28966a869e08 100644 --- a/docs/data/tree-view/rich-tree-view/items/items.md +++ b/docs/data/tree-view/rich-tree-view/items/items.md @@ -151,9 +151,22 @@ Use the `getItem` API method to get an item by its ID. ```ts const item = apiRef.current.getItem( - // The ID of the item to retrieve + // The id of the item to retrieve itemId, ); ``` {{"demo": "ApiMethodGetItem.js", "defaultCodeOpen": false}} + +### Get an item's DOM element by ID + +Use the `getItemDOMElement` API method to get an item's DOM element by its ID. + +```ts +const itemElement = apiRef.current.getItemDOMElement( + // The id of the item to get the DOM element of + itemId, +); +``` + +{{"demo": "ApiMethodGetItemDOMElement.js", "defaultCodeOpen": false}} diff --git a/docs/data/tree-view/rich-tree-view/selection/ApiMethodSelectItem.js b/docs/data/tree-view/rich-tree-view/selection/ApiMethodSelectItem.js new file mode 100644 index 000000000000..30d2f2d6ed3a --- /dev/null +++ b/docs/data/tree-view/rich-tree-view/selection/ApiMethodSelectItem.js @@ -0,0 +1,59 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Stack from '@mui/material/Stack'; +import Button from '@mui/material/Button'; + +import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; +import { useTreeViewApiRef } from '@mui/x-tree-view/hooks/useTreeViewApiRef'; + +const MUI_X_PRODUCTS = [ + { + id: 'grid', + label: 'Data Grid', + children: [ + { id: 'grid-community', label: '@mui/x-data-grid' }, + { id: 'grid-pro', label: '@mui/x-data-grid-pro' }, + { id: 'grid-premium', label: '@mui/x-data-grid-premium' }, + ], + }, + { + id: 'pickers', + label: 'Date and Time Pickers', + children: [ + { id: 'pickers-community', label: '@mui/x-date-pickers' }, + { id: 'pickers-pro', label: '@mui/x-date-pickers-pro' }, + ], + }, + { + id: 'charts', + label: 'Charts', + children: [{ id: 'charts-community', label: '@mui/x-charts' }], + }, + { + id: 'tree-view', + label: 'Tree View', + children: [{ id: 'tree-view-community', label: '@mui/x-tree-view' }], + }, +]; + +export default function ApiMethodSelectItem() { + const apiRef = useTreeViewApiRef(); + const handleSelectGridPro = (event) => { + apiRef.current?.selectItem({ event, itemId: 'grid-pro' }); + }; + + return ( + +
+ +
+ + + +
+ ); +} diff --git a/docs/data/tree-view/rich-tree-view/selection/ApiMethodSelectItem.tsx b/docs/data/tree-view/rich-tree-view/selection/ApiMethodSelectItem.tsx new file mode 100644 index 000000000000..c8c0ee7bfa33 --- /dev/null +++ b/docs/data/tree-view/rich-tree-view/selection/ApiMethodSelectItem.tsx @@ -0,0 +1,59 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Stack from '@mui/material/Stack'; +import Button from '@mui/material/Button'; +import { TreeViewBaseItem } from '@mui/x-tree-view/models'; +import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; +import { useTreeViewApiRef } from '@mui/x-tree-view/hooks/useTreeViewApiRef'; + +const MUI_X_PRODUCTS: TreeViewBaseItem[] = [ + { + id: 'grid', + label: 'Data Grid', + children: [ + { id: 'grid-community', label: '@mui/x-data-grid' }, + { id: 'grid-pro', label: '@mui/x-data-grid-pro' }, + { id: 'grid-premium', label: '@mui/x-data-grid-premium' }, + ], + }, + { + id: 'pickers', + label: 'Date and Time Pickers', + children: [ + { id: 'pickers-community', label: '@mui/x-date-pickers' }, + { id: 'pickers-pro', label: '@mui/x-date-pickers-pro' }, + ], + }, + { + id: 'charts', + label: 'Charts', + children: [{ id: 'charts-community', label: '@mui/x-charts' }], + }, + { + id: 'tree-view', + label: 'Tree View', + children: [{ id: 'tree-view-community', label: '@mui/x-tree-view' }], + }, +]; + +export default function ApiMethodSelectItem() { + const apiRef = useTreeViewApiRef(); + const handleSelectGridPro = (event: React.SyntheticEvent) => { + apiRef.current?.selectItem({ event, itemId: 'grid-pro' }); + }; + + return ( + +
+ +
+ + + +
+ ); +} diff --git a/docs/data/tree-view/rich-tree-view/selection/ApiMethodSelectItem.tsx.preview b/docs/data/tree-view/rich-tree-view/selection/ApiMethodSelectItem.tsx.preview new file mode 100644 index 000000000000..00d30b33d158 --- /dev/null +++ b/docs/data/tree-view/rich-tree-view/selection/ApiMethodSelectItem.tsx.preview @@ -0,0 +1,10 @@ +
+ +
+ + + \ No newline at end of file diff --git a/docs/data/tree-view/rich-tree-view/selection/ApiMethodSelectItemKeepExistingSelection.js b/docs/data/tree-view/rich-tree-view/selection/ApiMethodSelectItemKeepExistingSelection.js new file mode 100644 index 000000000000..8d6da938ae63 --- /dev/null +++ b/docs/data/tree-view/rich-tree-view/selection/ApiMethodSelectItemKeepExistingSelection.js @@ -0,0 +1,65 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Stack from '@mui/material/Stack'; +import Button from '@mui/material/Button'; + +import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; +import { useTreeViewApiRef } from '@mui/x-tree-view/hooks/useTreeViewApiRef'; + +const MUI_X_PRODUCTS = [ + { + id: 'grid', + label: 'Data Grid', + children: [ + { id: 'grid-community', label: '@mui/x-data-grid' }, + { id: 'grid-pro', label: '@mui/x-data-grid-pro' }, + { id: 'grid-premium', label: '@mui/x-data-grid-premium' }, + ], + }, + { + id: 'pickers', + label: 'Date and Time Pickers', + children: [ + { id: 'pickers-community', label: '@mui/x-date-pickers' }, + { id: 'pickers-pro', label: '@mui/x-date-pickers-pro' }, + ], + }, + { + id: 'charts', + label: 'Charts', + children: [{ id: 'charts-community', label: '@mui/x-charts' }], + }, + { + id: 'tree-view', + label: 'Tree View', + children: [{ id: 'tree-view-community', label: '@mui/x-tree-view' }], + }, +]; + +export default function ApiMethodSelectItemKeepExistingSelection() { + const apiRef = useTreeViewApiRef(); + const handleSelectGridPro = (event) => { + apiRef.current?.selectItem({ + event, + itemId: 'grid-pro', + keepExistingSelection: true, + }); + }; + + return ( + +
+ +
+ + + +
+ ); +} diff --git a/docs/data/tree-view/rich-tree-view/selection/ApiMethodSelectItemKeepExistingSelection.tsx b/docs/data/tree-view/rich-tree-view/selection/ApiMethodSelectItemKeepExistingSelection.tsx new file mode 100644 index 000000000000..d9c562924547 --- /dev/null +++ b/docs/data/tree-view/rich-tree-view/selection/ApiMethodSelectItemKeepExistingSelection.tsx @@ -0,0 +1,65 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Stack from '@mui/material/Stack'; +import Button from '@mui/material/Button'; +import { TreeViewBaseItem } from '@mui/x-tree-view/models'; +import { RichTreeView } from '@mui/x-tree-view/RichTreeView'; +import { useTreeViewApiRef } from '@mui/x-tree-view/hooks/useTreeViewApiRef'; + +const MUI_X_PRODUCTS: TreeViewBaseItem[] = [ + { + id: 'grid', + label: 'Data Grid', + children: [ + { id: 'grid-community', label: '@mui/x-data-grid' }, + { id: 'grid-pro', label: '@mui/x-data-grid-pro' }, + { id: 'grid-premium', label: '@mui/x-data-grid-premium' }, + ], + }, + { + id: 'pickers', + label: 'Date and Time Pickers', + children: [ + { id: 'pickers-community', label: '@mui/x-date-pickers' }, + { id: 'pickers-pro', label: '@mui/x-date-pickers-pro' }, + ], + }, + { + id: 'charts', + label: 'Charts', + children: [{ id: 'charts-community', label: '@mui/x-charts' }], + }, + { + id: 'tree-view', + label: 'Tree View', + children: [{ id: 'tree-view-community', label: '@mui/x-tree-view' }], + }, +]; + +export default function ApiMethodSelectItemKeepExistingSelection() { + const apiRef = useTreeViewApiRef(); + const handleSelectGridPro = (event: React.SyntheticEvent) => { + apiRef.current?.selectItem({ + event, + itemId: 'grid-pro', + keepExistingSelection: true, + }); + }; + + return ( + +
+ +
+ + + +
+ ); +} diff --git a/docs/data/tree-view/rich-tree-view/selection/ApiMethodSelectItemKeepExistingSelection.tsx.preview b/docs/data/tree-view/rich-tree-view/selection/ApiMethodSelectItemKeepExistingSelection.tsx.preview new file mode 100644 index 000000000000..3d14770db217 --- /dev/null +++ b/docs/data/tree-view/rich-tree-view/selection/ApiMethodSelectItemKeepExistingSelection.tsx.preview @@ -0,0 +1,12 @@ +
+ +
+ + + \ No newline at end of file diff --git a/docs/data/tree-view/rich-tree-view/selection/selection.md b/docs/data/tree-view/rich-tree-view/selection/selection.md index 2fb893baee65..2c45bd280411 100644 --- a/docs/data/tree-view/rich-tree-view/selection/selection.md +++ b/docs/data/tree-view/rich-tree-view/selection/selection.md @@ -94,3 +94,45 @@ you can create your own custom solution using the `selectedItems`, `onSelectedItemsChange` and `onItemSelectionToggle` props: {{"demo": "ParentChildrenSelectionRelationship.js"}} + +## Imperative API + +:::success +To use the `apiRef` object, you need to initialize it using the `useTreeViewApiRef` hook as follows: + +```tsx +const apiRef = useTreeViewApiRef(); + +return {children}; +``` + +When your component first renders, `apiRef` will be `undefined`. +After this initial render, `apiRef` holds methods to interact imperatively with the Tree View. +::: + +### Select or deselect an item + +Use the `selectItem` API method to select or deselect an item: + +```ts +apiRef.current.selectItem({ + // The DOM event that triggered the change + event, + // The id of the item to select or deselect + itemId, + // If `true`, the other already selected items will remain selected + // Otherwise, they will be deselected + // This parameter is only relevant when `multiSelect` is `true` + keepExistingSelection, + // If `true` the item will be selected + // If `false` the item will be deselected + // If not defined, the item's new selection status will be the opposite of its current one + shouldBeSelected, +}); +``` + +{{"demo": "ApiMethodSelectItem.js", "defaultCodeOpen": false}} + +You can use the `keepExistingSelection` property to avoid losing the already selected items when using `multiSelect`: + +{{"demo": "ApiMethodSelectItemKeepExistingSelection.js", "defaultCodeOpen": false}} diff --git a/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.js b/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.js deleted file mode 100644 index 36e9e200da11..000000000000 --- a/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.js +++ /dev/null @@ -1,57 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/material/Box'; -import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView'; -import { useTreeItem2Utils } from '@mui/x-tree-view/hooks'; - -import { TreeItem2 } from '@mui/x-tree-view/TreeItem2'; - -const CustomTreeItem = React.forwardRef(function MyTreeItem(props, ref) { - const { interactions } = useTreeItem2Utils({ - itemId: props.itemId, - children: props.children, - }); - - const handleContentClick = (event) => { - event.defaultMuiPrevented = true; - interactions.handleSelection(event); - }; - - const handleIconContainerClick = (event) => { - interactions.handleExpansion(event); - }; - - return ( - - ); -}); - -export default function IconExpansionTreeView() { - return ( - - - - - - - - - - - - - - - - - - - - ); -} diff --git a/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.tsx b/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.tsx deleted file mode 100644 index f0a5de292e60..000000000000 --- a/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import * as React from 'react'; -import Box from '@mui/material/Box'; -import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView'; -import { useTreeItem2Utils } from '@mui/x-tree-view/hooks'; -import { UseTreeItem2ContentSlotOwnProps } from '@mui/x-tree-view/useTreeItem2'; -import { TreeItem2, TreeItem2Props } from '@mui/x-tree-view/TreeItem2'; - -const CustomTreeItem = React.forwardRef(function MyTreeItem( - props: TreeItem2Props, - ref: React.Ref, -) { - const { interactions } = useTreeItem2Utils({ - itemId: props.itemId, - children: props.children, - }); - - const handleContentClick: UseTreeItem2ContentSlotOwnProps['onClick'] = (event) => { - event.defaultMuiPrevented = true; - interactions.handleSelection(event); - }; - - const handleIconContainerClick = (event: React.MouseEvent) => { - interactions.handleExpansion(event); - }; - - return ( - - ); -}); - -export default function IconExpansionTreeView() { - return ( - - - - - - - - - - - - - - - - - - - - ); -} diff --git a/docs/data/tree-view/simple-tree-view/customization/customization.md b/docs/data/tree-view/simple-tree-view/customization/customization.md index e5e70b9e4aa8..7cf009836436 100644 --- a/docs/data/tree-view/simple-tree-view/customization/customization.md +++ b/docs/data/tree-view/simple-tree-view/customization/customization.md @@ -70,19 +70,6 @@ Target the `treeItemClasses.groupTransition` class to add connection borders bet {{"demo": "BorderedTreeView.js", "defaultCodeOpen": false}} -### Limit expansion to icon container - -:::warning -This example is built using the new `TreeItem2` component -which adds several slots to modify the content of the Tree Item or change its behavior. - -You can learn more about this new component in the [Overview page](/x/react-tree-view/#tree-item-components). -::: - -The demo below shows how to trigger the expansion interaction just by clicking on the icon container instead of the whole Tree Item surface. - -{{"demo": "IconExpansionTreeView.js", "defaultCodeOpen": false}} - ### Gmail clone :::warning diff --git a/docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.js b/docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.js new file mode 100644 index 000000000000..3a046031d357 --- /dev/null +++ b/docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.js @@ -0,0 +1,28 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView'; +import { TreeItem } from '@mui/x-tree-view/TreeItem'; + +export default function IconExpansionTreeView() { + return ( + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.tsx b/docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.tsx new file mode 100644 index 000000000000..3a046031d357 --- /dev/null +++ b/docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.tsx @@ -0,0 +1,28 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView'; +import { TreeItem } from '@mui/x-tree-view/TreeItem'; + +export default function IconExpansionTreeView() { + return ( + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/docs/data/tree-view/simple-tree-view/expansion/expansion.md b/docs/data/tree-view/simple-tree-view/expansion/expansion.md index a6b0a3f4e46a..68a069a40243 100644 --- a/docs/data/tree-view/simple-tree-view/expansion/expansion.md +++ b/docs/data/tree-view/simple-tree-view/expansion/expansion.md @@ -32,6 +32,12 @@ Use the `onItemExpansionToggle` prop to trigger an action upon an item being exp {{"demo": "TrackItemExpansionToggle.js"}} +## Limit expansion to icon container + +You can use the `expansionTrigger` prop to decide if the expansion interaction should be triggered by clicking on the icon container instead of the whole Tree Item content. + +{{"demo": "IconExpansionTreeView.js"}} + ## Imperative API :::success @@ -55,9 +61,10 @@ Use the `setItemExpansion` API method to change the expansion of an item. apiRef.current.setItemExpansion( // The DOM event that triggered the change event, - // The ID of the item to expand or collapse + // The id of the item to expand or collapse itemId, - // `true` if the item should be expanded, `false` if it should be collapsed + // If `true` the item will be expanded + // If `false` the item will be collapsed isExpanded, ); ``` diff --git a/docs/data/tree-view/simple-tree-view/focus/focus.md b/docs/data/tree-view/simple-tree-view/focus/focus.md index d1596614823c..ef9cd7d5558e 100644 --- a/docs/data/tree-view/simple-tree-view/focus/focus.md +++ b/docs/data/tree-view/simple-tree-view/focus/focus.md @@ -34,7 +34,7 @@ Use the `focusItem` API method to focus a specific item. apiRef.current.focusItem( // The DOM event that triggered the change event, - // The ID of the item to focus + // The id of the item to focus itemId, ); ``` diff --git a/docs/data/tree-view/simple-tree-view/items/ApiMethodGetItemDOMElement.js b/docs/data/tree-view/simple-tree-view/items/ApiMethodGetItemDOMElement.js new file mode 100644 index 000000000000..74e7dd11ca46 --- /dev/null +++ b/docs/data/tree-view/simple-tree-view/items/ApiMethodGetItemDOMElement.js @@ -0,0 +1,49 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Stack from '@mui/material/Stack'; +import Button from '@mui/material/Button'; +import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView'; +import { TreeItem } from '@mui/x-tree-view/TreeItem'; +import { useTreeViewApiRef } from '@mui/x-tree-view/hooks/useTreeViewApiRef'; + +export default function ApiMethodGetItemDOMElement() { + const apiRef = useTreeViewApiRef(); + const handleScrollToChartsCommunity = (event) => { + apiRef.current.focusItem(event, 'charts-community'); + apiRef.current + .getItemDOMElement('charts-community') + ?.scrollIntoView({ block: 'center' }); + }; + + return ( + +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ ); +} diff --git a/docs/data/tree-view/simple-tree-view/items/ApiMethodGetItemDOMElement.tsx b/docs/data/tree-view/simple-tree-view/items/ApiMethodGetItemDOMElement.tsx new file mode 100644 index 000000000000..5d0e9d77ee8a --- /dev/null +++ b/docs/data/tree-view/simple-tree-view/items/ApiMethodGetItemDOMElement.tsx @@ -0,0 +1,49 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Stack from '@mui/material/Stack'; +import Button from '@mui/material/Button'; +import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView'; +import { TreeItem } from '@mui/x-tree-view/TreeItem'; +import { useTreeViewApiRef } from '@mui/x-tree-view/hooks/useTreeViewApiRef'; + +export default function ApiMethodGetItemDOMElement() { + const apiRef = useTreeViewApiRef(); + const handleScrollToChartsCommunity = (event: React.SyntheticEvent) => { + apiRef.current!.focusItem(event, 'charts-community'); + apiRef + .current!.getItemDOMElement('charts-community') + ?.scrollIntoView({ block: 'center' }); + }; + + return ( + +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ ); +} diff --git a/docs/data/tree-view/simple-tree-view/items/items.md b/docs/data/tree-view/simple-tree-view/items/items.md index a35ce2f3119c..efffddcf5574 100644 --- a/docs/data/tree-view/simple-tree-view/items/items.md +++ b/docs/data/tree-view/simple-tree-view/items/items.md @@ -73,3 +73,18 @@ When it's set to true: - Programmatic focus will focus disabled items. {{"demo": "DisabledItemsFocusable.js", "defaultCodeOpen": false}} + +## Imperative API + +### Get an item's DOM element by ID + +Use the `getItemDOMElement` API method to get an item's DOM element by its ID. + +```ts +const itemElement = apiRef.current.getItemDOMElement( + // The id of the item to get the DOM element of + itemId, +); +``` + +{{"demo": "ApiMethodGetItemDOMElement.js", "defaultCodeOpen": false}} diff --git a/docs/data/tree-view/simple-tree-view/selection/ApiMethodSelectItem.js b/docs/data/tree-view/simple-tree-view/selection/ApiMethodSelectItem.js new file mode 100644 index 000000000000..41a9034a616c --- /dev/null +++ b/docs/data/tree-view/simple-tree-view/selection/ApiMethodSelectItem.js @@ -0,0 +1,41 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Stack from '@mui/material/Stack'; +import Button from '@mui/material/Button'; +import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView'; +import { TreeItem } from '@mui/x-tree-view/TreeItem'; +import { useTreeViewApiRef } from '@mui/x-tree-view/hooks/useTreeViewApiRef'; + +export default function ApiMethodSelectItem() { + const apiRef = useTreeViewApiRef(); + const handleSelectGridPro = (event) => { + apiRef.current?.selectItem({ event, itemId: 'grid-pro' }); + }; + + return ( + +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ ); +} diff --git a/docs/data/tree-view/simple-tree-view/selection/ApiMethodSelectItem.tsx b/docs/data/tree-view/simple-tree-view/selection/ApiMethodSelectItem.tsx new file mode 100644 index 000000000000..24bfef05a393 --- /dev/null +++ b/docs/data/tree-view/simple-tree-view/selection/ApiMethodSelectItem.tsx @@ -0,0 +1,41 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Stack from '@mui/material/Stack'; +import Button from '@mui/material/Button'; +import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView'; +import { TreeItem } from '@mui/x-tree-view/TreeItem'; +import { useTreeViewApiRef } from '@mui/x-tree-view/hooks/useTreeViewApiRef'; + +export default function ApiMethodSelectItem() { + const apiRef = useTreeViewApiRef(); + const handleSelectGridPro = (event: React.SyntheticEvent) => { + apiRef.current?.selectItem({ event, itemId: 'grid-pro' }); + }; + + return ( + +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ ); +} diff --git a/docs/data/tree-view/simple-tree-view/selection/ApiMethodSelectItemKeepExistingSelection.js b/docs/data/tree-view/simple-tree-view/selection/ApiMethodSelectItemKeepExistingSelection.js new file mode 100644 index 000000000000..8a643361ba29 --- /dev/null +++ b/docs/data/tree-view/simple-tree-view/selection/ApiMethodSelectItemKeepExistingSelection.js @@ -0,0 +1,50 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Stack from '@mui/material/Stack'; +import Button from '@mui/material/Button'; +import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView'; +import { TreeItem } from '@mui/x-tree-view/TreeItem'; +import { useTreeViewApiRef } from '@mui/x-tree-view/hooks/useTreeViewApiRef'; + +export default function ApiMethodSelectItemKeepExistingSelection() { + const apiRef = useTreeViewApiRef(); + const handleSelectGridPro = (event) => { + apiRef.current?.selectItem({ + event, + itemId: 'grid-pro', + keepExistingSelection: true, + }); + }; + + return ( + +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ ); +} diff --git a/docs/data/tree-view/simple-tree-view/selection/ApiMethodSelectItemKeepExistingSelection.tsx b/docs/data/tree-view/simple-tree-view/selection/ApiMethodSelectItemKeepExistingSelection.tsx new file mode 100644 index 000000000000..df3a6ae13aea --- /dev/null +++ b/docs/data/tree-view/simple-tree-view/selection/ApiMethodSelectItemKeepExistingSelection.tsx @@ -0,0 +1,50 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Stack from '@mui/material/Stack'; +import Button from '@mui/material/Button'; +import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView'; +import { TreeItem } from '@mui/x-tree-view/TreeItem'; +import { useTreeViewApiRef } from '@mui/x-tree-view/hooks/useTreeViewApiRef'; + +export default function ApiMethodSelectItemKeepExistingSelection() { + const apiRef = useTreeViewApiRef(); + const handleSelectGridPro = (event: React.SyntheticEvent) => { + apiRef.current?.selectItem({ + event, + itemId: 'grid-pro', + keepExistingSelection: true, + }); + }; + + return ( + +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ ); +} diff --git a/docs/data/tree-view/simple-tree-view/selection/selection.md b/docs/data/tree-view/simple-tree-view/selection/selection.md index 434a4284a0a2..aceb02cb7215 100644 --- a/docs/data/tree-view/simple-tree-view/selection/selection.md +++ b/docs/data/tree-view/simple-tree-view/selection/selection.md @@ -73,3 +73,45 @@ Learn more about the _Controlled and uncontrolled_ pattern in the [React documen Use the `onItemSelectionToggle` prop if you want to react to an item selection change: {{"demo": "TrackItemSelectionToggle.js"}} + +## Imperative API + +:::success +To use the `apiRef` object, you need to initialize it using the `useTreeViewApiRef` hook as follows: + +```tsx +const apiRef = useTreeViewApiRef(); + +return {children}; +``` + +When your component first renders, `apiRef` will be `undefined`. +After this initial render, `apiRef` holds methods to interact imperatively with the Tree View. +::: + +### Select or deselect an item + +Use the `selectItem` API method to select or deselect an item: + +```ts +apiRef.current.selectItem({ + // The DOM event that triggered the change + event, + // The id of the item to select or deselect + itemId, + // If `true`, the other already selected items will remain selected + // Otherwise, they will be deselected + // This parameter is only relevant when `multiSelect` is `true` + keepExistingSelection, + // If `true` the item will be selected + // If `false` the item will be deselected + // If not defined, the item's new selection status will be the opposite of its current one + shouldBeSelected, +}); +``` + +{{"demo": "ApiMethodSelectItem.js"}} + +You can use the `keepExistingSelection` property to avoid losing the already selected items when using `multiSelect`: + +{{"demo": "ApiMethodSelectItemKeepExistingSelection.js"}} diff --git a/docs/next.config.mjs b/docs/next.config.mjs index f72e1399a49f..de1ede2b32f4 100644 --- a/docs/next.config.mjs +++ b/docs/next.config.mjs @@ -68,7 +68,7 @@ export default withDocsInfra({ transpilePackages: [ // TODO, those shouldn't be needed in the first place '@mui/monorepo', // Migrate everything to @mui/docs until the @mui/monorepo dependency becomes obsolete - '@mui/docs', + '@mui/docs', // needed to fix slashes in the generated links (https://github.com/mui/mui-x/pull/13713#issuecomment-2205591461, ) ], // Avoid conflicts with the other Next.js apps hosted under https://mui.com/ assetPrefix: process.env.DEPLOY_ENV === 'development' ? undefined : '/x', @@ -104,18 +104,6 @@ export default withDocsInfra({ return { ...config, plugins, - // TODO, this shouldn't be needed in the first place - // Migrate everything from @mui/monorepo to @mui/docs and embed @mui/internal-markdown in @mui/docs - resolveLoader: { - ...config.resolveLoader, - alias: { - ...config.resolveLoader.alias, - '@mui/internal-markdown/loader': path.resolve( - MONOREPO_PATH, - './packages/markdown/loader', - ), - }, - }, resolve: { ...config.resolve, alias: { diff --git a/docs/package.json b/docs/package.json index 3d7c5ce85c38..6d3c83b76fca 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,6 +1,6 @@ { "name": "docs", - "version": "6.7.0", + "version": "7.8.0", "private": true, "author": "MUI Team", "license": "MIT", @@ -28,14 +28,15 @@ "@emotion/server": "^11.11.0", "@emotion/styled": "^11.11.5", "@mui/base": "^5.0.0-beta.40", - "@mui/icons-material": "^5.15.20", - "@mui/joy": "5.0.0-beta.32", - "@mui/lab": "^5.0.0-alpha.170", - "@mui/material": "^5.15.20", + "@mui/docs": "^6.0.0-alpha.14", + "@mui/icons-material": "^5.16.0", + "@mui/joy": "^5.0.0-beta.47", + "@mui/lab": "^5.0.0-alpha.171", + "@mui/material": "^5.16.0", "@mui/material-nextjs": "^5.15.11", - "@mui/styles": "^5.15.20", - "@mui/system": "^5.15.20", - "@mui/utils": "^5.15.20", + "@mui/styles": "^5.16.0", + "@mui/system": "^5.16.0", + "@mui/utils": "^5.16.0", "@mui/x-charts": "workspace:*", "@mui/x-data-grid": "workspace:*", "@mui/x-data-grid-generator": "workspace:*", @@ -45,6 +46,7 @@ "@mui/x-date-pickers-pro": "workspace:*", "@mui/x-tree-view": "workspace:*", "@react-spring/web": "^9.7.3", + "@tanstack/query-core": "^5.50.1", "ast-types": "^0.14.2", "autoprefixer": "^10.4.19", "babel-plugin-module-resolver": "^5.0.2", @@ -58,37 +60,38 @@ "clsx": "^2.1.1", "core-js": "^2.6.12", "cross-env": "^7.0.3", + "d3-scale-chromatic": "^3.1.0", "date-fns": "^2.30.0", "date-fns-jalali": "^2.30.0-0", "dayjs": "^1.11.11", "doctrine": "^3.0.0", "exceljs": "^4.4.0", "fg-loadcss": "^3.1.0", - "jscodeshift": "0.13.1", + "jscodeshift": "0.16.1", "lodash": "^4.17.21", "luxon": "^3.4.4", "lz-string": "^1.5.0", "markdown-to-jsx": "^7.4.7", "moment": "^2.30.1", "moment-hijri": "^2.1.2", - "moment-jalaali": "^0.10.0", + "moment-jalaali": "^0.10.1", "moment-timezone": "^0.5.45", "next": "^14.2.4", "nprogress": "^0.2.0", - "postcss": "^8.4.38", + "postcss": "^8.4.39", "prismjs": "^1.29.0", "prop-types": "^15.8.1", - "react": "^18.2.0", + "react": "^18.3.1", "react-docgen": "^5.4.3", - "react-dom": "^18.2.0", - "react-hook-form": "^7.52.0", - "react-is": "^18.2.0", - "react-router": "^6.23.1", - "react-router-dom": "^6.23.1", + "react-dom": "^18.3.1", + "react-hook-form": "^7.52.1", + "react-is": "^18.3.1", + "react-router": "^6.24.1", + "react-router-dom": "^6.24.1", "react-runner": "^1.0.5", - "react-simple-code-editor": "^0.13.1", + "react-simple-code-editor": "^0.14.1", "recast": "^0.23.9", - "rimraf": "^5.0.7", + "rimraf": "^5.0.8", "rxjs": "^7.8.1", "styled-components": "^6.1.11", "stylis": "^4.3.2", @@ -99,15 +102,16 @@ "@babel/plugin-transform-react-constant-elements": "^7.24.7", "@babel/preset-typescript": "^7.24.7", "@mui/internal-docs-utils": "^1.0.7", - "@mui/internal-scripts": "^1.0.10", + "@mui/internal-scripts": "^1.0.12", "@types/chance": "^1.1.6", "@types/d3-scale": "^4.0.8", + "@types/d3-scale-chromatic": "^3.0.3", "@types/doctrine": "^0.0.9", - "@types/lodash": "^4.17.5", + "@types/lodash": "^4.17.6", "@types/luxon": "^3.4.2", "@types/moment-hijri": "^2.1.4", "@types/moment-jalaali": "^0.7.9", - "@types/react-dom": "18.2.25", + "@types/react-dom": "^18.3.0", "@types/react-router-dom": "^5.3.3", "@types/stylis": "^4.2.6", "@types/webpack-bundle-analyzer": "^4.7.0", diff --git a/docs/pages/_app.js b/docs/pages/_app.js index 69982b1a9e72..08a025daad50 100644 --- a/docs/pages/_app.js +++ b/docs/pages/_app.js @@ -7,17 +7,18 @@ import { loadCSS } from 'fg-loadcss/src/loadCSS'; import NextHead from 'next/head'; import PropTypes from 'prop-types'; import { useRouter } from 'next/router'; +import { LicenseInfo } from '@mui/x-license'; import { ponyfillGlobal } from '@mui/utils'; import PageContext from 'docs/src/modules/components/PageContext'; import GoogleAnalytics from 'docs/src/modules/components/GoogleAnalytics'; +import { CodeCopyProvider } from '@mui/docs/CodeCopy'; import { ThemeProvider } from 'docs/src/modules/components/ThemeContext'; import { CodeVariantProvider } from 'docs/src/modules/utils/codeVariant'; -import { CodeCopyProvider } from 'docs/src/modules/utils/CodeCopy'; +import { CodeStylingProvider } from 'docs/src/modules/utils/codeStylingSolution'; import DocsStyledEngineProvider from 'docs/src/modules/utils/StyledEngineProvider'; -import { pathnameToLanguage } from 'docs/src/modules/utils/helpers'; import createEmotionCache from 'docs/src/createEmotionCache'; import findActivePage from 'docs/src/modules/utils/findActivePage'; -import { LicenseInfo } from '@mui/x-license'; +import { pathnameToLanguage } from 'docs/src/modules/utils/helpers'; import getProductInfoFromUrl from 'docs/src/modules/utils/getProductInfoFromUrl'; import { DocsProvider } from '@mui/docs/DocsProvider'; import { mapTranslations } from '@mui/docs/i18n'; @@ -64,6 +65,7 @@ ponyfillGlobal.muiDocConfig = { '@mui/x-charts-pro': getMuiPackageVersion('x-charts-pro', muiCommitRef), '@mui/x-tree-view': getMuiPackageVersion('x-tree-view', muiCommitRef), '@mui/x-tree-view-pro': getMuiPackageVersion('x-tree-view-pro', muiCommitRef), + '@mui/x-internals': getMuiPackageVersion('x-internals', muiCommitRef), exceljs: 'latest', }; return output; @@ -173,7 +175,6 @@ Tip: you can access the documentation \`theme\` object directly in the console. 'font-family:monospace;color:#1976d2;font-size:12px;', ); } - function AppWrapper(props) { const { children, emotionCache, pageProps } = props; @@ -202,13 +203,6 @@ function AppWrapper(props) { } }, []); - let fonts = []; - if (pathnameToLanguage(router.asPath).canonicalAs.match(/onepirate/)) { - fonts = [ - 'https://fonts.googleapis.com/css?family=Roboto+Condensed:700|Work+Sans:300,400&display=swap', - ]; - } - const pageContextValue = React.useMemo(() => { const { activePage, activePageParents } = findActivePage(pages, router.pathname); const languagePrefix = pageProps.userLanguage === 'en' ? '' : `/${pageProps.userLanguage}`; @@ -299,6 +293,13 @@ function AppWrapper(props) { }; }, [productId, productCategoryId, pageProps.userLanguage, router.pathname]); + let fonts = []; + if (pathnameToLanguage(router.asPath).canonicalAs.match(/onepirate/)) { + fonts = [ + 'https://fonts.googleapis.com/css2?family=Roboto+Condensed:wght@700&family=Work+Sans:wght@300;400&display=swap', + ]; + } + // Replicate change reverted in https://github.com/mui/material-ui/pull/35969/files#r1089572951 // Fixes playground styles in dark mode. const ThemeWrapper = router.pathname.startsWith('/playground') ? React.Fragment : ThemeProvider; @@ -306,6 +307,7 @@ function AppWrapper(props) { return ( + {fonts.map((font) => ( ))} @@ -318,16 +320,18 @@ function AppWrapper(props) { translations={pageProps.translations} > - - - - - {children} - - - - - + + + + + + {children} + + + + + + @@ -343,9 +347,11 @@ AppWrapper.propTypes = { export default function MyApp(props) { const { Component, emotionCache = clientSideEmotionCache, pageProps } = props; + const getLayout = Component.getLayout ?? ((page) => page); + return ( - + {getLayout()} ); } @@ -377,6 +383,7 @@ MyApp.getInitialProps = async ({ ctx, Component }) => { // Track fraction of actual events to prevent exceeding event quota. // Filter sessions instead of individual events so that we can track multiple metrics per device. +// See https://github.com/GoogleChromeLabs/web-vitals-report to use this data const disableWebVitalsReporting = Math.random() > 0.0001; export function reportWebVitals({ id, name, label, delta, value }) { if (disableWebVitalsReporting) { diff --git a/docs/pages/x/api/charts/axis-config.json b/docs/pages/x/api/charts/axis-config.json index 8f826848b286..a3b887bf9d81 100644 --- a/docs/pages/x/api/charts/axis-config.json +++ b/docs/pages/x/api/charts/axis-config.json @@ -3,8 +3,10 @@ "imports": ["import { AxisConfig } from '@mui/x-charts'"], "properties": { "id": { "type": { "description": "AxisId" }, "required": true }, - "scaleType": { "type": { "description": "'linear'" }, "required": true }, - "colorMap": { "type": { "description": "ContinuousColorConfig | PiecewiseColorConfig" } }, + "scaleType": { "type": { "description": "'band'" }, "required": true }, + "colorMap": { + "type": { "description": "OrdinalColorConfig | ContinuousColorConfig | PiecewiseColorConfig" } + }, "data": { "type": { "description": "V[]" } }, "dataKey": { "type": { "description": "string" } }, "hideTooltip": { "type": { "description": "boolean" } }, diff --git a/docs/pages/x/api/charts/chart-container.json b/docs/pages/x/api/charts/chart-container.json index b92a05628f0d..823f299ffea2 100644 --- a/docs/pages/x/api/charts/chart-container.json +++ b/docs/pages/x/api/charts/chart-container.json @@ -48,7 +48,7 @@ "zAxis": { "type": { "name": "arrayOf", - "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string }>" + "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string, max?: number, min?: number }>" } } }, diff --git a/docs/pages/x/api/charts/charts-axis-tooltip-content.js b/docs/pages/x/api/charts/charts-axis-tooltip-content.js deleted file mode 100644 index 9dc6feb6568c..000000000000 --- a/docs/pages/x/api/charts/charts-axis-tooltip-content.js +++ /dev/null @@ -1,23 +0,0 @@ -import * as React from 'react'; -import ApiPage from 'docs/src/modules/components/ApiPage'; -import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; -import jsonPageContent from './charts-axis-tooltip-content.json'; - -export default function Page(props) { - const { descriptions, pageContent } = props; - return ; -} - -Page.getInitialProps = () => { - const req = require.context( - 'docsx/translations/api-docs/charts/charts-axis-tooltip-content', - false, - /\.\/charts-axis-tooltip-content.*.json$/, - ); - const descriptions = mapApiPageTranslations(req); - - return { - descriptions, - pageContent: jsonPageContent, - }; -}; diff --git a/docs/pages/x/api/charts/charts-axis-tooltip-content.json b/docs/pages/x/api/charts/charts-axis-tooltip-content.json deleted file mode 100644 index 377c83930f32..000000000000 --- a/docs/pages/x/api/charts/charts-axis-tooltip-content.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "props": {}, - "name": "ChartsAxisTooltipContent", - "imports": [ - "import { ChartsAxisTooltipContent } from '@mui/x-charts/ChartsTooltip';", - "import { ChartsAxisTooltipContent } from '@mui/x-charts';" - ], - "classes": [ - { - "key": "cell", - "className": "MuiChartsAxisTooltipContent-cell", - "description": "Styles applied to the cell element.", - "isGlobal": false - }, - { - "key": "labelCell", - "className": "MuiChartsAxisTooltipContent-labelCell", - "description": "Styles applied to the labelCell element.", - "isGlobal": false - }, - { - "key": "mark", - "className": "MuiChartsAxisTooltipContent-mark", - "description": "Styles applied to the mark element.", - "isGlobal": false - }, - { - "key": "markCell", - "className": "MuiChartsAxisTooltipContent-markCell", - "description": "Styles applied to the markCell element.", - "isGlobal": false - }, - { - "key": "root", - "className": "MuiChartsAxisTooltipContent-root", - "description": "Styles applied to the root element.", - "isGlobal": false - }, - { - "key": "row", - "className": "MuiChartsAxisTooltipContent-row", - "description": "Styles applied to the row element.", - "isGlobal": false - }, - { - "key": "table", - "className": "MuiChartsAxisTooltipContent-table", - "description": "Styles applied to the table element.", - "isGlobal": false - }, - { - "key": "valueCell", - "className": "MuiChartsAxisTooltipContent-valueCell", - "description": "Styles applied to the valueCell element.", - "isGlobal": false - } - ], - "muiName": "MuiChartsAxisTooltipContent", - "filename": "/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx", - "inheritance": null, - "demos": "", - "cssComponent": false -} diff --git a/docs/pages/x/api/charts/charts-item-tooltip-content.js b/docs/pages/x/api/charts/charts-item-tooltip-content.js deleted file mode 100644 index 3eb3dbfb139a..000000000000 --- a/docs/pages/x/api/charts/charts-item-tooltip-content.js +++ /dev/null @@ -1,23 +0,0 @@ -import * as React from 'react'; -import ApiPage from 'docs/src/modules/components/ApiPage'; -import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; -import jsonPageContent from './charts-item-tooltip-content.json'; - -export default function Page(props) { - const { descriptions, pageContent } = props; - return ; -} - -Page.getInitialProps = () => { - const req = require.context( - 'docsx/translations/api-docs/charts/charts-item-tooltip-content', - false, - /\.\/charts-item-tooltip-content.*.json$/, - ); - const descriptions = mapApiPageTranslations(req); - - return { - descriptions, - pageContent: jsonPageContent, - }; -}; diff --git a/docs/pages/x/api/charts/charts-item-tooltip-content.json b/docs/pages/x/api/charts/charts-item-tooltip-content.json deleted file mode 100644 index e00782f42984..000000000000 --- a/docs/pages/x/api/charts/charts-item-tooltip-content.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "props": {}, - "name": "ChartsItemTooltipContent", - "imports": [ - "import { ChartsItemTooltipContent } from '@mui/x-charts/ChartsTooltip';", - "import { ChartsItemTooltipContent } from '@mui/x-charts';" - ], - "classes": [ - { - "key": "cell", - "className": "MuiChartsItemTooltipContent-cell", - "description": "Styles applied to the cell element.", - "isGlobal": false - }, - { - "key": "labelCell", - "className": "MuiChartsItemTooltipContent-labelCell", - "description": "Styles applied to the labelCell element.", - "isGlobal": false - }, - { - "key": "mark", - "className": "MuiChartsItemTooltipContent-mark", - "description": "Styles applied to the mark element.", - "isGlobal": false - }, - { - "key": "markCell", - "className": "MuiChartsItemTooltipContent-markCell", - "description": "Styles applied to the markCell element.", - "isGlobal": false - }, - { - "key": "root", - "className": "MuiChartsItemTooltipContent-root", - "description": "Styles applied to the root element.", - "isGlobal": false - }, - { - "key": "row", - "className": "MuiChartsItemTooltipContent-row", - "description": "Styles applied to the row element.", - "isGlobal": false - }, - { - "key": "table", - "className": "MuiChartsItemTooltipContent-table", - "description": "Styles applied to the table element.", - "isGlobal": false - }, - { - "key": "valueCell", - "className": "MuiChartsItemTooltipContent-valueCell", - "description": "Styles applied to the valueCell element.", - "isGlobal": false - } - ], - "muiName": "MuiChartsItemTooltipContent", - "filename": "/packages/x-charts/src/ChartsTooltip/ChartsItemTooltipContent.tsx", - "inheritance": null, - "demos": "", - "cssComponent": false -} diff --git a/docs/pages/x/api/charts/responsive-chart-container.json b/docs/pages/x/api/charts/responsive-chart-container.json index f758a3c363d9..b04b83407c93 100644 --- a/docs/pages/x/api/charts/responsive-chart-container.json +++ b/docs/pages/x/api/charts/responsive-chart-container.json @@ -48,7 +48,7 @@ "zAxis": { "type": { "name": "arrayOf", - "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string }>" + "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string, max?: number, min?: number }>" } } }, diff --git a/docs/pages/x/api/charts/scatter-chart.json b/docs/pages/x/api/charts/scatter-chart.json index 42263922241a..96bb86d6ba1e 100644 --- a/docs/pages/x/api/charts/scatter-chart.json +++ b/docs/pages/x/api/charts/scatter-chart.json @@ -101,7 +101,7 @@ "zAxis": { "type": { "name": "arrayOf", - "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string }>" + "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string, max?: number, min?: number }>" } } }, diff --git a/docs/pages/x/api/data-grid/data-grid-premium.json b/docs/pages/x/api/data-grid/data-grid-premium.json index 0e19418dae1c..1c79c35a04e6 100644 --- a/docs/pages/x/api/data-grid/data-grid-premium.json +++ b/docs/pages/x/api/data-grid/data-grid-premium.json @@ -664,6 +664,12 @@ "default": "GridColumnHeaderFilterIconButton", "class": null }, + { + "name": "columnHeaderSortIcon", + "description": "Sort icon component rendered in each column header.", + "default": "GridColumnHeaderSortIcon", + "class": null + }, { "name": "columnMenu", "description": "Column menu component rendered by clicking on the 3 dots \"kebab\" icon in column headers.", @@ -1758,6 +1764,12 @@ "description": "Styles applied to the row's draggable placeholder element inside the special row reorder cell.", "isGlobal": false }, + { + "key": "rowSkeleton", + "className": "MuiDataGridPremium-rowSkeleton", + "description": "Styles applied to the skeleton row element.", + "isGlobal": false + }, { "key": "scrollArea", "className": "MuiDataGridPremium-scrollArea", diff --git a/docs/pages/x/api/data-grid/data-grid-pro.json b/docs/pages/x/api/data-grid/data-grid-pro.json index 6bf884ab4d1c..c3eb24a2ffb8 100644 --- a/docs/pages/x/api/data-grid/data-grid-pro.json +++ b/docs/pages/x/api/data-grid/data-grid-pro.json @@ -599,6 +599,12 @@ "default": "GridColumnHeaderFilterIconButton", "class": null }, + { + "name": "columnHeaderSortIcon", + "description": "Sort icon component rendered in each column header.", + "default": "GridColumnHeaderSortIcon", + "class": null + }, { "name": "columnMenu", "description": "Column menu component rendered by clicking on the 3 dots \"kebab\" icon in column headers.", @@ -1675,6 +1681,12 @@ "description": "Styles applied to the row's draggable placeholder element inside the special row reorder cell.", "isGlobal": false }, + { + "key": "rowSkeleton", + "className": "MuiDataGridPro-rowSkeleton", + "description": "Styles applied to the skeleton row element.", + "isGlobal": false + }, { "key": "scrollArea", "className": "MuiDataGridPro-scrollArea", diff --git a/docs/pages/x/api/data-grid/data-grid.json b/docs/pages/x/api/data-grid/data-grid.json index 2a408aaf08e2..7543c9d9f0ab 100644 --- a/docs/pages/x/api/data-grid/data-grid.json +++ b/docs/pages/x/api/data-grid/data-grid.json @@ -497,6 +497,12 @@ "default": "GridColumnHeaderFilterIconButton", "class": null }, + { + "name": "columnHeaderSortIcon", + "description": "Sort icon component rendered in each column header.", + "default": "GridColumnHeaderSortIcon", + "class": null + }, { "name": "columnMenu", "description": "Column menu component rendered by clicking on the 3 dots \"kebab\" icon in column headers.", @@ -1561,6 +1567,12 @@ "description": "Styles applied to the row's draggable placeholder element inside the special row reorder cell.", "isGlobal": false }, + { + "key": "rowSkeleton", + "className": "MuiDataGrid-rowSkeleton", + "description": "Styles applied to the skeleton row element.", + "isGlobal": false + }, { "key": "scrollArea", "className": "MuiDataGrid-scrollArea", diff --git a/docs/pages/x/api/data-grid/grid-actions-col-def.json b/docs/pages/x/api/data-grid/grid-actions-col-def.json index ca909eb5cbaa..26d5acce67f3 100644 --- a/docs/pages/x/api/data-grid/grid-actions-col-def.json +++ b/docs/pages/x/api/data-grid/grid-actions-col-def.json @@ -10,7 +10,7 @@ "field": { "type": { "description": "string" }, "required": true }, "getActions": { "type": { - "description": "(params: GridRowParams<R>) => React.ReactElement<GridActionsCellItemProps>[]" + "description": "(params: GridRowParams<R>) => readonly React.ReactElement<GridActionsCellItemProps>[]" }, "required": true }, @@ -37,7 +37,9 @@ "display": { "type": { "description": "'text' | 'flex'" } }, "editable": { "type": { "description": "boolean" }, "default": "false" }, "filterable": { "type": { "description": "boolean" }, "default": "true" }, - "filterOperators": { "type": { "description": "GridFilterOperator<R, V, F>[]" } }, + "filterOperators": { + "type": { "description": "readonly GridFilterOperator<R, V, F>[]" } + }, "flex": { "type": { "description": "number" } }, "getApplyQuickFilterFn": { "type": { "description": "GetApplyQuickFilterFn<R, V>" } }, "getSortComparator": { @@ -89,7 +91,7 @@ "resizable": { "type": { "description": "boolean" }, "default": "true" }, "sortable": { "type": { "description": "boolean" }, "default": "true" }, "sortComparator": { "type": { "description": "GridComparatorFn<V>" } }, - "sortingOrder": { "type": { "description": "GridSortDirection[]" } }, + "sortingOrder": { "type": { "description": "readonly GridSortDirection[]" } }, "valueFormatter": { "type": { "description": "GridValueFormatter<R, V, F>" } }, "valueGetter": { "type": { "description": "GridValueGetter<R, V, F>" } }, "valueParser": { "type": { "description": "GridValueParser<R, V, F>" } }, diff --git a/docs/pages/x/api/data-grid/grid-api.json b/docs/pages/x/api/data-grid/grid-api.json index 88b2080043cd..5f5202edf84f 100644 --- a/docs/pages/x/api/data-grid/grid-api.json +++ b/docs/pages/x/api/data-grid/grid-api.json @@ -350,6 +350,7 @@ }, "required": true }, + "setLoading": { "type": { "description": "(loading: boolean) => void" }, "required": true }, "setPage": { "type": { "description": "(page: number) => void" }, "required": true }, "setPageSize": { "type": { "description": "(pageSize: number) => void" }, "required": true }, "setPaginationMeta": { @@ -394,7 +395,7 @@ }, "setRows": { "type": { "description": "(rows: GridRowModel[]) => void" }, "required": true }, "setRowSelectionModel": { - "type": { "description": "(rowIds: GridRowId[]) => void" }, + "type": { "description": "(rowIds: readonly GridRowId[]) => void" }, "required": true }, "setSortModel": { @@ -466,6 +467,11 @@ "required": true, "isProPlan": true }, + "unstable_dataSource": { + "type": { "description": "GridDataSourceApiBase" }, + "required": true, + "isProPlan": true + }, "unstable_replaceRows": { "type": { "description": "(firstRowToReplace: number, newRows: GridRowModel[]) => void" }, "required": true diff --git a/docs/pages/x/api/data-grid/grid-col-def.json b/docs/pages/x/api/data-grid/grid-col-def.json index 6173cc8c314e..bfe97f8a9704 100644 --- a/docs/pages/x/api/data-grid/grid-col-def.json +++ b/docs/pages/x/api/data-grid/grid-col-def.json @@ -30,7 +30,9 @@ "display": { "type": { "description": "'text' | 'flex'" } }, "editable": { "type": { "description": "boolean" }, "default": "false" }, "filterable": { "type": { "description": "boolean" }, "default": "true" }, - "filterOperators": { "type": { "description": "GridFilterOperator<R, V, F>[]" } }, + "filterOperators": { + "type": { "description": "readonly GridFilterOperator<R, V, F>[]" } + }, "flex": { "type": { "description": "number" } }, "getApplyQuickFilterFn": { "type": { "description": "GetApplyQuickFilterFn<R, V>" } }, "getSortComparator": { @@ -82,7 +84,7 @@ "resizable": { "type": { "description": "boolean" }, "default": "true" }, "sortable": { "type": { "description": "boolean" }, "default": "true" }, "sortComparator": { "type": { "description": "GridComparatorFn<V>" } }, - "sortingOrder": { "type": { "description": "GridSortDirection[]" } }, + "sortingOrder": { "type": { "description": "readonly GridSortDirection[]" } }, "type": { "type": { "description": "GridColType" }, "default": "'singleSelect'" }, "valueFormatter": { "type": { "description": "GridValueFormatter<R, V, F>" } }, "valueGetter": { "type": { "description": "GridValueGetter<R, V, F>" } }, diff --git a/docs/pages/x/api/data-grid/grid-pagination-model-api.json b/docs/pages/x/api/data-grid/grid-pagination-model-api.json new file mode 100644 index 000000000000..cb60edc245db --- /dev/null +++ b/docs/pages/x/api/data-grid/grid-pagination-model-api.json @@ -0,0 +1,21 @@ +{ + "name": "GridPaginationModelApi", + "description": "The pagination model API interface that is available in the grid `apiRef`.", + "properties": [ + { + "name": "setPage", + "description": "Sets the displayed page to the value given by page.", + "type": "(page: number) => void" + }, + { + "name": "setPageSize", + "description": "Sets the number of displayed rows to the value given by pageSize.", + "type": "(pageSize: number) => void" + }, + { + "name": "setPaginationModel", + "description": "Sets the paginationModel to a new value.", + "type": "(model: GridPaginationModel) => void" + } + ] +} diff --git a/docs/pages/x/api/data-grid/grid-row-selection-api.json b/docs/pages/x/api/data-grid/grid-row-selection-api.json index 16522e648d1f..4daa27a95dee 100644 --- a/docs/pages/x/api/data-grid/grid-row-selection-api.json +++ b/docs/pages/x/api/data-grid/grid-row-selection-api.json @@ -25,7 +25,7 @@ { "name": "setRowSelectionModel", "description": "Updates the selected rows to be those passed to the rowIds argument. Any row already selected will be unselected.", - "type": "(rowIds: GridRowId[]) => void" + "type": "(rowIds: readonly GridRowId[]) => void" } ] } diff --git a/docs/pages/x/api/data-grid/grid-single-select-col-def.json b/docs/pages/x/api/data-grid/grid-single-select-col-def.json index 2e62dcbf36e9..669318bc4848 100644 --- a/docs/pages/x/api/data-grid/grid-single-select-col-def.json +++ b/docs/pages/x/api/data-grid/grid-single-select-col-def.json @@ -35,7 +35,9 @@ "display": { "type": { "description": "'text' | 'flex'" } }, "editable": { "type": { "description": "boolean" }, "default": "false" }, "filterable": { "type": { "description": "boolean" }, "default": "true" }, - "filterOperators": { "type": { "description": "GridFilterOperator<R, V, F>[]" } }, + "filterOperators": { + "type": { "description": "readonly GridFilterOperator<R, V, F>[]" } + }, "flex": { "type": { "description": "number" } }, "getApplyQuickFilterFn": { "type": { "description": "GetApplyQuickFilterFn<R, V>" } }, "getOptionLabel": { "type": { "description": "(value: ValueOptions) => string" } }, @@ -89,7 +91,7 @@ "resizable": { "type": { "description": "boolean" }, "default": "true" }, "sortable": { "type": { "description": "boolean" }, "default": "true" }, "sortComparator": { "type": { "description": "GridComparatorFn<V>" } }, - "sortingOrder": { "type": { "description": "GridSortDirection[]" } }, + "sortingOrder": { "type": { "description": "readonly GridSortDirection[]" } }, "valueFormatter": { "type": { "description": "GridValueFormatter<R, V, F>" } }, "valueGetter": { "type": { "description": "GridValueGetter<R, V, F>" } }, "valueOptions": { diff --git a/docs/pages/x/api/data-grid/selectors.json b/docs/pages/x/api/data-grid/selectors.json index 10cb5c8c4439..ad0e4aefd23d 100644 --- a/docs/pages/x/api/data-grid/selectors.json +++ b/docs/pages/x/api/data-grid/selectors.json @@ -194,6 +194,20 @@ "description": "Get the filterable columns as a lookup (an object containing the field for keys and the definition for values).", "supportsApiRef": true }, + { + "name": "gridFilteredDescendantRowCountSelector", + "returnType": "number", + "category": "Filtering", + "description": "Get the amount of descendant rows accessible after the filtering process.", + "supportsApiRef": true + }, + { + "name": "gridFilteredRowCountSelector", + "returnType": "number", + "category": "Filtering", + "description": "Get the amount of rows accessible after the filtering process.\nIncludes top level and descendant rows.", + "supportsApiRef": true + }, { "name": "gridFilteredSortedRowEntriesSelector", "returnType": "GridRowEntry[]", diff --git a/docs/pages/x/api/tree-view/rich-tree-view.json b/docs/pages/x/api/tree-view/rich-tree-view.json index 7da4e28d56f0..52784c1c9c04 100644 --- a/docs/pages/x/api/tree-view/rich-tree-view.json +++ b/docs/pages/x/api/tree-view/rich-tree-view.json @@ -3,7 +3,7 @@ "apiRef": { "type": { "name": "shape", - "description": "{ current?: { focusItem: func, getItem: func, setItemExpansion: func } }" + "description": "{ current?: { focusItem: func, getItem: func, getItemDOMElement: func, selectItem: func, setItemExpansion: func } }" } }, "checkboxSelection": { "type": { "name": "bool" }, "default": "false" }, @@ -16,6 +16,10 @@ "disabledItemsFocusable": { "type": { "name": "bool" }, "default": "false" }, "disableSelection": { "type": { "name": "bool" }, "default": "false" }, "expandedItems": { "type": { "name": "arrayOf", "description": "Array<string>" } }, + "expansionTrigger": { + "type": { "name": "enum", "description": "'content'
| 'iconContainer'" }, + "default": "'content'" + }, "experimentalFeatures": { "type": { "name": "shape", "description": "{ indentationAtItemLevel?: bool }" } }, diff --git a/docs/pages/x/api/tree-view/simple-tree-view.json b/docs/pages/x/api/tree-view/simple-tree-view.json index 1c52f9e03646..aaa6b7cf66b2 100644 --- a/docs/pages/x/api/tree-view/simple-tree-view.json +++ b/docs/pages/x/api/tree-view/simple-tree-view.json @@ -3,7 +3,7 @@ "apiRef": { "type": { "name": "shape", - "description": "{ current?: { focusItem: func, getItem: func, setItemExpansion: func } }" + "description": "{ current?: { focusItem: func, getItem: func, getItemDOMElement: func, selectItem: func, setItemExpansion: func } }" } }, "checkboxSelection": { "type": { "name": "bool" }, "default": "false" }, @@ -17,6 +17,10 @@ "disabledItemsFocusable": { "type": { "name": "bool" }, "default": "false" }, "disableSelection": { "type": { "name": "bool" }, "default": "false" }, "expandedItems": { "type": { "name": "arrayOf", "description": "Array<string>" } }, + "expansionTrigger": { + "type": { "name": "enum", "description": "'content'
| 'iconContainer'" }, + "default": "'content'" + }, "experimentalFeatures": { "type": { "name": "shape", "description": "{ indentationAtItemLevel?: bool }" } }, diff --git a/docs/pages/x/api/tree-view/tree-view.json b/docs/pages/x/api/tree-view/tree-view.json index a528b9927844..9162a87809ab 100644 --- a/docs/pages/x/api/tree-view/tree-view.json +++ b/docs/pages/x/api/tree-view/tree-view.json @@ -3,7 +3,7 @@ "apiRef": { "type": { "name": "shape", - "description": "{ current?: { focusItem: func, getItem: func, setItemExpansion: func } }" + "description": "{ current?: { focusItem: func, getItem: func, getItemDOMElement: func, selectItem: func, setItemExpansion: func } }" } }, "checkboxSelection": { "type": { "name": "bool" }, "default": "false" }, @@ -17,6 +17,10 @@ "disabledItemsFocusable": { "type": { "name": "bool" }, "default": "false" }, "disableSelection": { "type": { "name": "bool" }, "default": "false" }, "expandedItems": { "type": { "name": "arrayOf", "description": "Array<string>" } }, + "expansionTrigger": { + "type": { "name": "enum", "description": "'content'
| 'iconContainer'" }, + "default": "'content'" + }, "experimentalFeatures": { "type": { "name": "shape", "description": "{ indentationAtItemLevel?: bool }" } }, diff --git a/docs/pages/x/react-charts/zoom-and-pan.js b/docs/pages/x/react-charts/zoom-and-pan.js new file mode 100644 index 000000000000..4a2393ba8b38 --- /dev/null +++ b/docs/pages/x/react-charts/zoom-and-pan.js @@ -0,0 +1,7 @@ +import * as React from 'react'; +import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; +import * as pageProps from 'docsx/data/charts/zoom-and-pan/zoom-and-pan.md?muiMarkdown'; + +export default function Page() { + return ; +} diff --git a/docs/pages/x/react-data-grid/overlays.js b/docs/pages/x/react-data-grid/overlays.js new file mode 100644 index 000000000000..eecf19cc11c3 --- /dev/null +++ b/docs/pages/x/react-data-grid/overlays.js @@ -0,0 +1,7 @@ +import * as React from 'react'; +import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; +import * as pageProps from 'docsx/data/data-grid/overlays/overlays.md?muiMarkdown'; + +export default function Page() { + return ; +} diff --git a/docs/scripts/createXTypeScriptProjects.ts b/docs/scripts/createXTypeScriptProjects.ts index 3b859b06427a..8d339b2b97c2 100644 --- a/docs/scripts/createXTypeScriptProjects.ts +++ b/docs/scripts/createXTypeScriptProjects.ts @@ -37,6 +37,7 @@ export type XProjectNames = | 'x-date-pickers' | 'x-date-pickers-pro' | 'x-charts' + | 'x-charts-pro' | 'x-tree-view' | 'x-tree-view-pro'; diff --git a/docs/scripts/generateProptypes.ts b/docs/scripts/generateProptypes.ts index 5d7f3c8ec553..c68602a94873 100644 --- a/docs/scripts/generateProptypes.ts +++ b/docs/scripts/generateProptypes.ts @@ -10,6 +10,8 @@ import { import { fixBabelGeneratorIssues, fixLineEndings } from '@mui/internal-docs-utils'; import { createXTypeScriptProjects, XTypeScriptProject } from './createXTypeScriptProjects'; +const COMPONENTS_WITHOUT_PROPTYPES = ['ChartsAxisTooltipContent', 'ChartsItemTooltipContent']; + async function generateProptypes(project: XTypeScriptProject, sourceFile: string) { const isTDate = (name: string) => { if (['x-date-pickers', 'x-date-pickers-pro'].includes(project.name)) { @@ -176,14 +178,20 @@ async function run() { } const componentsWithPropTypes = project.getComponentsWithPropTypes(project); - return componentsWithPropTypes.map>(async (filename) => { - try { - await generateProptypes(project, filename); - } catch (error: any) { - error.message = `${filename}: ${error.message}`; - throw error; - } - }); + return componentsWithPropTypes + .filter((filename) => + COMPONENTS_WITHOUT_PROPTYPES.every( + (ignoredComponent) => !filename.includes(ignoredComponent), + ), + ) + .map>(async (filename) => { + try { + await generateProptypes(project, filename); + } catch (error: any) { + error.message = `${filename}: ${error.message}`; + throw error; + } + }); }); const results = await Promise.allSettled(promises); diff --git a/docs/src/modules/components/ChartFeaturesGrid.js b/docs/src/modules/components/ChartFeaturesGrid.js index 51bc73d2d991..ecff879e95c2 100644 --- a/docs/src/modules/components/ChartFeaturesGrid.js +++ b/docs/src/modules/components/ChartFeaturesGrid.js @@ -1,6 +1,6 @@ import * as React from 'react'; import Grid from '@mui/material/Unstable_Grid2'; -import InfoCard from 'docs/src/components/action/InfoCard'; +import { InfoCard } from '@mui/docs/InfoCard'; import LineAxisRoundedIcon from '@mui/icons-material/LineAxisRounded'; import DashboardCustomizeRoundedIcon from '@mui/icons-material/DashboardCustomizeRounded'; import LegendToggleRoundedIcon from '@mui/icons-material/LegendToggleRounded'; diff --git a/docs/src/modules/components/ChartsUsageDemo.js b/docs/src/modules/components/ChartsUsageDemo.js index 79087370cb16..dc0e4e24c302 100644 --- a/docs/src/modules/components/ChartsUsageDemo.js +++ b/docs/src/modules/components/ChartsUsageDemo.js @@ -1,7 +1,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import Box from '@mui/joy/Box'; -import BrandingProvider from 'docs/src/BrandingProvider'; +import { BrandingProvider } from '@mui/docs/branding'; import { HighlightedCode } from '@mui/docs/HighlightedCode'; import DemoPropsForm from './DemoPropsForm'; diff --git a/docs/src/modules/components/ComponentLinkHeader.js b/docs/src/modules/components/ComponentLinkHeader.js deleted file mode 100644 index c63c24b9473c..000000000000 --- a/docs/src/modules/components/ComponentLinkHeader.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from 'docs/src/modules/components/ComponentLinkHeader'; diff --git a/docs/src/modules/components/CustomizationPlayground.tsx b/docs/src/modules/components/CustomizationPlayground.tsx index 6f131c36a9e6..0e34112f8753 100644 --- a/docs/src/modules/components/CustomizationPlayground.tsx +++ b/docs/src/modules/components/CustomizationPlayground.tsx @@ -1,8 +1,6 @@ import * as React from 'react'; -// @ts-ignore import { HighlightedCode } from '@mui/docs/HighlightedCode'; -// @ts-ignore -import BrandingProvider from 'docs/src/BrandingProvider'; +import { BrandingProvider } from '@mui/docs/branding'; import { styled, Theme, alpha, useTheme } from '@mui/material/styles'; import useMediaQuery from '@mui/material/useMediaQuery'; import Tabs from '@mui/material/Tabs'; diff --git a/docs/src/modules/components/InstallationGrid.js b/docs/src/modules/components/InstallationGrid.js index 1ec5bfc316cb..a5dcda305945 100644 --- a/docs/src/modules/components/InstallationGrid.js +++ b/docs/src/modules/components/InstallationGrid.js @@ -1,6 +1,6 @@ import * as React from 'react'; import Grid from '@mui/material/Unstable_Grid2'; -import InfoCard from 'docs/src/components/action/InfoCard'; +import { InfoCard } from '@mui/docs/InfoCard'; import AccountTreeRounded from '@mui/icons-material/AccountTreeRounded'; import PivotTableChartRoundedIcon from '@mui/icons-material/PivotTableChartRounded'; import CalendarMonthRoundedIcon from '@mui/icons-material/CalendarMonthRounded'; diff --git a/docs/src/modules/components/InstallationInstructions.tsx b/docs/src/modules/components/InstallationInstructions.tsx index 51788eeed8cc..18faa37de0e6 100644 --- a/docs/src/modules/components/InstallationInstructions.tsx +++ b/docs/src/modules/components/InstallationInstructions.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; -// @ts-expect-error -import HighlightedCodeWithTabs from 'docs/src/modules/components/HighlightedCodeWithTabs'; +import HighlightedCodeWithTabs from '@mui/docs/HighlightedCodeWithTabs'; import Stack from '@mui/material/Stack'; import Box from '@mui/material/Box'; import ToggleOptions from './ToggleOptions'; diff --git a/docs/src/modules/components/InterfaceApiPage.js b/docs/src/modules/components/InterfaceApiPage.js index 05b518cd3b87..e0a040209153 100644 --- a/docs/src/modules/components/InterfaceApiPage.js +++ b/docs/src/modules/components/InterfaceApiPage.js @@ -6,7 +6,7 @@ import Typography from '@mui/material/Typography'; import Alert from '@mui/material/Alert'; import VerifiedRoundedIcon from '@mui/icons-material/VerifiedRounded'; import { alpha } from '@mui/material/styles'; -import { useTranslate, useUserLanguage } from 'docs/src/modules/utils/i18n'; +import { useTranslate, useUserLanguage } from '@mui/docs/i18n'; import { HighlightedCode } from '@mui/docs/HighlightedCode'; import { MarkdownElement } from '@mui/docs/MarkdownElement'; import { SectionTitle } from '@mui/docs/SectionTitle'; diff --git a/docs/src/modules/components/PickersPlayground.tsx b/docs/src/modules/components/PickersPlayground.tsx index 079230d5f7aa..2b48de823b10 100644 --- a/docs/src/modules/components/PickersPlayground.tsx +++ b/docs/src/modules/components/PickersPlayground.tsx @@ -38,6 +38,9 @@ import { DesktopDateRangePicker } from '@mui/x-date-pickers-pro/DesktopDateRange import { MobileDateRangePicker } from '@mui/x-date-pickers-pro/MobileDateRangePicker'; import { StaticDateRangePicker } from '@mui/x-date-pickers-pro/StaticDateRangePicker'; import { isDatePickerView, isTimeView } from '@mui/x-date-pickers/internals'; +import { pickersLayoutClasses } from '@mui/x-date-pickers/PickersLayout'; +import { DesktopDateTimeRangePicker } from '@mui/x-date-pickers-pro/DesktopDateTimeRangePicker'; +import { MobileDateTimeRangePicker } from '@mui/x-date-pickers-pro/MobileDateTimeRangePicker'; const ComponentSection = styled('div')(({ theme }) => ({ display: 'flex', @@ -154,13 +157,14 @@ const DEFAULT_VIEWS_MAP: ViewsMap = { seconds: false, }; -type ComponentFamily = 'date' | 'time' | 'date-time' | 'date-range'; +type ComponentFamily = 'date' | 'time' | 'date-time' | 'date-range' | 'date-time-range'; const componentFamilies: { family: ComponentFamily; label: string }[] = [ { family: 'date', label: 'Date' }, { family: 'time', label: 'Time' }, { family: 'date-time', label: 'Date Time' }, { family: 'date-range', label: 'Date Range' }, + { family: 'date-time-range', label: 'Date Time Range' }, ]; interface ComponentFamilySet { @@ -392,6 +396,7 @@ export default function PickersPlayground() { ampm: ampm !== undefined ? ampm : undefined, ampmInClock: ampmInClock !== undefined ? ampmInClock : undefined, displayStaticWrapperAs: isStaticDesktopMode ? 'desktop' : 'mobile', + sx: { [`&.${pickersLayoutClasses.root}`]: { overflowX: 'auto' } }, }), [ ampm, @@ -508,6 +513,22 @@ export default function PickersPlayground() { [commonProps], ); + const DATE_TIME_RANGE_PICKERS: ComponentFamilySet[] = React.useMemo( + () => [ + { + name: 'DesktopDateTimeRangePicker', + component: DesktopDateTimeRangePicker, + props: commonProps, + }, + { + name: 'MobileDateTimeRangePicker', + component: MobileDateTimeRangePicker, + props: commonProps, + }, + ], + [commonProps], + ); + return ( )} + {selectedPickers === 'date-time-range' && ( + + {DATE_TIME_RANGE_PICKERS.map(({ name, component: Component, props }) => ( + + ))} + + )} @@ -622,23 +667,31 @@ export default function PickersPlayground() { {selectedPickers !== 'date-range' && ( )} - - {selectedPickers === 'date-time' && ( - )} + + {selectedPickers === 'date-time' || + (selectedPickers === 'date-time-range' && ( + + ))} - {selectedPickers !== 'date-range' && ( + {selectedPickers !== 'date-range' && selectedPickers !== 'date-time-range' && ( model." }, + "setLoading": { "description": "Sets the internal loading state." }, "setPage": { "description": "Sets the displayed page to the value given by page." }, @@ -243,6 +244,7 @@ }, "toggleDetailPanel": { "description": "Expands or collapses the detail panel of a row." }, "unpinColumn": { "description": "Unpins a column." }, + "unstable_dataSource": { "description": "The data source API." }, "unstable_replaceRows": { "description": "Replace a set of rows with new rows." }, "unstable_setColumnVirtualization": { "description": "Enable/disable column virtualization." }, "unstable_setPinnedRows": { "description": "Changes the pinned rows." }, diff --git a/docs/translations/api-docs/tree-view/rich-tree-view/rich-tree-view.json b/docs/translations/api-docs/tree-view/rich-tree-view/rich-tree-view.json index b866f4dcc07a..ea67296629a8 100644 --- a/docs/translations/api-docs/tree-view/rich-tree-view/rich-tree-view.json +++ b/docs/translations/api-docs/tree-view/rich-tree-view/rich-tree-view.json @@ -21,6 +21,9 @@ "expandedItems": { "description": "Expanded item ids. Used when the item's expansion is controlled." }, + "expansionTrigger": { + "description": "The slot that triggers the item's expansion when clicked." + }, "experimentalFeatures": { "description": "Unstable features, breaking changes might be introduced. For each feature, if the flag is not explicitly set to true, the feature will be fully disabled and any property / method call will not have any effect." }, @@ -51,14 +54,14 @@ "onExpandedItemsChange": { "description": "Callback fired when tree items are expanded/collapsed.", "typeDescriptions": { - "event": "The event source of the callback.", + "event": "The DOM event that triggered the change.", "itemIds": "The ids of the expanded items." } }, "onItemExpansionToggle": { "description": "Callback fired when a tree item is expanded or collapsed.", "typeDescriptions": { - "event": "The event source of the callback.", + "event": "The DOM event that triggered the change.", "itemId": "The itemId of the modified item.", "isExpanded": "true if the item has just been expanded, false if it has just been collapsed." } @@ -66,7 +69,7 @@ "onItemFocus": { "description": "Callback fired when tree items are focused.", "typeDescriptions": { - "event": "The event source of the callback Warning: This is a generic event not a focus event.", + "event": "The DOM event that triggered the change. Warning: This is a generic event not a focus event.", "itemId": "The id of the focused item.", "value": "of the focused item." } @@ -74,7 +77,7 @@ "onItemSelectionToggle": { "description": "Callback fired when a tree item is selected or deselected.", "typeDescriptions": { - "event": "The event source of the callback.", + "event": "The DOM event that triggered the change.", "itemId": "The itemId of the modified item.", "isSelected": "true if the item has just been selected, false if it has just been deselected." } @@ -82,7 +85,7 @@ "onSelectedItemsChange": { "description": "Callback fired when tree items are selected/deselected.", "typeDescriptions": { - "event": "The event source of the callback", + "event": "The DOM event that triggered the change.", "itemIds": "The ids of the selected items. When multiSelect is true, this is an array of strings; when false (default) a string." } }, diff --git a/docs/translations/api-docs/tree-view/simple-tree-view/simple-tree-view.json b/docs/translations/api-docs/tree-view/simple-tree-view/simple-tree-view.json index a12a98351778..bd1994ea533b 100644 --- a/docs/translations/api-docs/tree-view/simple-tree-view/simple-tree-view.json +++ b/docs/translations/api-docs/tree-view/simple-tree-view/simple-tree-view.json @@ -22,6 +22,9 @@ "expandedItems": { "description": "Expanded item ids. Used when the item's expansion is controlled." }, + "expansionTrigger": { + "description": "The slot that triggers the item's expansion when clicked." + }, "experimentalFeatures": { "description": "Unstable features, breaking changes might be introduced. For each feature, if the flag is not explicitly set to true, the feature will be fully disabled and any property / method call will not have any effect." }, @@ -37,14 +40,14 @@ "onExpandedItemsChange": { "description": "Callback fired when tree items are expanded/collapsed.", "typeDescriptions": { - "event": "The event source of the callback.", + "event": "The DOM event that triggered the change.", "itemIds": "The ids of the expanded items." } }, "onItemExpansionToggle": { "description": "Callback fired when a tree item is expanded or collapsed.", "typeDescriptions": { - "event": "The event source of the callback.", + "event": "The DOM event that triggered the change.", "itemId": "The itemId of the modified item.", "isExpanded": "true if the item has just been expanded, false if it has just been collapsed." } @@ -52,7 +55,7 @@ "onItemFocus": { "description": "Callback fired when tree items are focused.", "typeDescriptions": { - "event": "The event source of the callback Warning: This is a generic event not a focus event.", + "event": "The DOM event that triggered the change. Warning: This is a generic event not a focus event.", "itemId": "The id of the focused item.", "value": "of the focused item." } @@ -60,7 +63,7 @@ "onItemSelectionToggle": { "description": "Callback fired when a tree item is selected or deselected.", "typeDescriptions": { - "event": "The event source of the callback.", + "event": "The DOM event that triggered the change.", "itemId": "The itemId of the modified item.", "isSelected": "true if the item has just been selected, false if it has just been deselected." } @@ -68,7 +71,7 @@ "onSelectedItemsChange": { "description": "Callback fired when tree items are selected/deselected.", "typeDescriptions": { - "event": "The event source of the callback", + "event": "The DOM event that triggered the change.", "itemIds": "The ids of the selected items. When multiSelect is true, this is an array of strings; when false (default) a string." } }, diff --git a/docs/translations/api-docs/tree-view/tree-view/tree-view.json b/docs/translations/api-docs/tree-view/tree-view/tree-view.json index c29df2121733..dde9a0faa577 100644 --- a/docs/translations/api-docs/tree-view/tree-view/tree-view.json +++ b/docs/translations/api-docs/tree-view/tree-view/tree-view.json @@ -22,6 +22,9 @@ "expandedItems": { "description": "Expanded item ids. Used when the item's expansion is controlled." }, + "expansionTrigger": { + "description": "The slot that triggers the item's expansion when clicked." + }, "experimentalFeatures": { "description": "Unstable features, breaking changes might be introduced. For each feature, if the flag is not explicitly set to true, the feature will be fully disabled and any property / method call will not have any effect." }, @@ -37,14 +40,14 @@ "onExpandedItemsChange": { "description": "Callback fired when tree items are expanded/collapsed.", "typeDescriptions": { - "event": "The event source of the callback.", + "event": "The DOM event that triggered the change.", "itemIds": "The ids of the expanded items." } }, "onItemExpansionToggle": { "description": "Callback fired when a tree item is expanded or collapsed.", "typeDescriptions": { - "event": "The event source of the callback.", + "event": "The DOM event that triggered the change.", "itemId": "The itemId of the modified item.", "isExpanded": "true if the item has just been expanded, false if it has just been collapsed." } @@ -52,7 +55,7 @@ "onItemFocus": { "description": "Callback fired when tree items are focused.", "typeDescriptions": { - "event": "The event source of the callback Warning: This is a generic event not a focus event.", + "event": "The DOM event that triggered the change. Warning: This is a generic event not a focus event.", "itemId": "The id of the focused item.", "value": "of the focused item." } @@ -60,7 +63,7 @@ "onItemSelectionToggle": { "description": "Callback fired when a tree item is selected or deselected.", "typeDescriptions": { - "event": "The event source of the callback.", + "event": "The DOM event that triggered the change.", "itemId": "The itemId of the modified item.", "isSelected": "true if the item has just been selected, false if it has just been deselected." } @@ -68,7 +71,7 @@ "onSelectedItemsChange": { "description": "Callback fired when tree items are selected/deselected.", "typeDescriptions": { - "event": "The event source of the callback", + "event": "The DOM event that triggered the change.", "itemIds": "The ids of the selected items. When multiSelect is true, this is an array of strings; when false (default) a string." } }, diff --git a/package.json b/package.json index 17f5824b329e..4593a9e15917 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "7.7.1", + "version": "7.9.0", "private": true, "scripts": { "preinstall": "npx only-allow pnpm", @@ -66,7 +66,7 @@ "clean:node_modules": "rimraf --glob \"**/node_modules\"" }, "devDependencies": { - "@argos-ci/core": "^2.2.0", + "@argos-ci/core": "^2.3.0", "@babel/cli": "^7.24.7", "@babel/core": "^7.24.7", "@babel/node": "^7.24.7", @@ -85,39 +85,37 @@ "@emotion/cache": "^11.11.0", "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.5", - "@mnajdova/enzyme-adapter-react-18": "^0.2.0", - "@mui/icons-material": "^5.15.20", - "@mui/internal-markdown": "^1.0.5", - "@mui/internal-test-utils": "^1.0.1", - "@mui/material": "^5.15.20", - "@mui/monorepo": "github:mui/material-ui#22c5206a9e8191b2f81131d6978a0958e55b7032", - "@mui/utils": "^5.15.20", + "@mui/icons-material": "^5.16.0", + "@mui/internal-markdown": "^1.0.7", + "@mui/internal-test-utils": "^1.0.4", + "@mui/material": "^5.16.0", + "@mui/monorepo": "github:mui/material-ui#43cb32700af699cd48baaf6922fbe21343f30e2f", + "@mui/utils": "^5.16.0", "@next/eslint-plugin-next": "14.2.4", - "@octokit/plugin-retry": "^6.0.1", - "@octokit/rest": "^20.1.1", + "@octokit/plugin-retry": "^7.1.1", + "@octokit/rest": "^21.0.0", "@playwright/test": "^1.44.1", - "@types/babel__traverse": "^7.20.6", "@types/babel__core": "^7.20.5", + "@types/babel__traverse": "^7.20.6", "@types/chai": "^4.3.16", "@types/chai-dom": "^1.11.3", - "@types/enzyme": "3.10.12", "@types/fs-extra": "^11.0.4", "@types/karma": "^6.3.8", - "@types/lodash": "^4.17.5", - "@types/mocha": "^10.0.6", - "@types/node": "^18.19.34", - "@types/react": "^18.2.60", - "@types/react-dom": "^18.2.25", + "@types/lodash": "^4.17.6", + "@types/mocha": "^10.0.7", + "@types/node": "^18.19.39", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", "@types/react-test-renderer": "^18.3.0", "@types/requestidlecallback": "^0.3.7", "@types/sinon": "^17.0.3", "@types/yargs": "^17.0.32", - "@typescript-eslint/eslint-plugin": "^7.13.1", - "@typescript-eslint/parser": "^7.13.1", + "@typescript-eslint/eslint-plugin": "^7.15.0", + "@typescript-eslint/parser": "^7.15.0", "autoprefixer": "^10.4.19", "axe-core": "4.9.1", "babel-loader": "^9.1.3", - "babel-plugin-istanbul": "^6.1.1", + "babel-plugin-istanbul": "^7.0.0", "babel-plugin-module-resolver": "^5.0.2", "babel-plugin-optimize-clsx": "^2.6.2", "babel-plugin-react-remove-properties": "^0.3.0", @@ -130,10 +128,9 @@ "concurrently": "^8.2.2", "cpy-cli": "^5.0.0", "cross-env": "^7.0.3", - "danger": "^12.3.1", - "date-fns-jalali-v3": "npm:date-fns-jalali@3.6.0-0", + "danger": "^12.3.3", + "date-fns-jalali-v3": "npm:date-fns-jalali@3.6.0-1", "date-fns-v3": "npm:date-fns@3.6.0", - "enzyme": "^3.11.0", "eslint": "^8.57.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb-typescript": "^18.0.0", @@ -141,12 +138,12 @@ "eslint-import-resolver-webpack": "^0.13.8", "eslint-plugin-filenames": "^1.3.2", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsdoc": "^48.2.12", - "eslint-plugin-jsx-a11y": "^6.8.0", + "eslint-plugin-jsdoc": "^48.5.2", + "eslint-plugin-jsx-a11y": "^6.9.0", "eslint-plugin-material-ui": "workspace:^", "eslint-plugin-mocha": "^10.4.3", "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-react": "^7.34.2", + "eslint-plugin-react": "^7.34.3", "eslint-plugin-react-compiler": "0.0.0-experimental-51a85ea-20240601", "eslint-plugin-react-hooks": "^4.6.2", "fast-glob": "^3.3.2", @@ -165,37 +162,37 @@ "karma-parallel": "^0.3.1", "karma-sourcemap-loader": "^0.4.0", "karma-webpack": "^5.0.1", - "lerna": "^8.1.3", + "lerna": "^8.1.6", "lodash": "^4.17.21", "markdownlint-cli2": "^0.13.0", - "mocha": "^10.4.0", + "mocha": "^10.6.0", "moment": "^2.30.1", "moment-timezone": "^0.5.45", "nyc": "^17.0.0", "prettier": "^3.3.2", "pretty-quick": "^4.0.0", "process": "^0.11.10", - "react": "^18.2.0", - "react-dom": "^18.2.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", "remark": "^13.0.0", - "rimraf": "^5.0.7", + "rimraf": "^5.0.8", "serve": "^14.2.3", "sinon": "^16.1.3", "stream-browserify": "^3.0.0", "string-replace-loader": "^3.1.0", "terser-webpack-plugin": "^5.3.10", - "tsx": "^4.15.5", - "typescript": "^5.4.5", + "tsx": "^4.16.2", + "typescript": "^5.5.3", "unist-util-visit": "^2.0.3", "util": "^0.12.5", - "webpack": "^5.92.0", + "webpack": "^5.92.1", "webpack-bundle-analyzer": "^4.10.2", "webpack-cli": "^5.1.4", "yargs": "^17.7.2" }, "resolutions": { - "react-is": "^18.2.0", - "@types/node": "^18.19.34" + "react-is": "^18.3.1", + "@types/node": "^18.19.39" }, "packageManager": "pnpm@9.4.0", "engines": { diff --git a/packages/eslint-plugin-material-ui/package.json b/packages/eslint-plugin-material-ui/package.json index 347ccb8ca25d..4b55439a52ab 100644 --- a/packages/eslint-plugin-material-ui/package.json +++ b/packages/eslint-plugin-material-ui/package.json @@ -1,13 +1,13 @@ { "name": "eslint-plugin-material-ui", - "version": "6.3.0", + "version": "7.8.0", "private": true, "description": "Custom eslint rules for MUI X.", "main": "src/index.js", "devDependencies": { "@types/eslint": "^8.56.10", - "@typescript-eslint/utils": "^7.13.1", - "@typescript-eslint/parser": "^7.13.1" + "@typescript-eslint/utils": "^7.15.0", + "@typescript-eslint/parser": "^7.15.0" }, "scripts": { "test": "cd ../../ && cross-env NODE_ENV=test mocha 'packages/eslint-plugin-material-ui/**/*.test.js' --timeout 3000" diff --git a/packages/x-charts-pro/package.json b/packages/x-charts-pro/package.json index 945293d1ce0b..c8b36be20a67 100644 --- a/packages/x-charts-pro/package.json +++ b/packages/x-charts-pro/package.json @@ -2,7 +2,7 @@ "name": "@mui/x-charts-pro", "version": "7.7.0", "private": true, - "description": "The community edition of the Charts components (MUI X).", + "description": "The Pro plan edition of the Charts components (MUI X).", "author": "MUI Team", "main": "./src/index.ts", "license": "SEE LICENSE IN LICENSE", @@ -42,8 +42,8 @@ "dependencies": { "@babel/runtime": "^7.24.7", "@mui/base": "^5.0.0-beta.40", - "@mui/system": "^5.15.20", - "@mui/utils": "^5.15.20", + "@mui/system": "^5.16.0", + "@mui/utils": "^5.16.0", "@mui/x-charts": "workspace:*", "@mui/x-license": "workspace:*", "@react-spring/rafz": "^9.7.3", @@ -81,7 +81,7 @@ "@types/d3-shape": "^3.1.6", "@types/prop-types": "^15.7.12", "csstype": "^3.1.3", - "rimraf": "^5.0.7" + "rimraf": "^5.0.8" }, "exports": { ".": { diff --git a/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx b/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx index 4f474bf9de4b..c701d6aa7146 100644 --- a/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx +++ b/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx @@ -9,10 +9,16 @@ import { ChartsAxisHighlight } from '@mui/x-charts/ChartsAxisHighlight'; import { ChartsTooltip } from '@mui/x-charts/ChartsTooltip'; import { ChartsClipPath } from '@mui/x-charts/ChartsClipPath'; import { useBarChartProps } from '@mui/x-charts/internals'; +import { BarPlotProps } from '@mui/x-charts'; import { ResponsiveChartContainerPro } from '../ResponsiveChartContainerPro'; +import { ZoomSetup } from '../context/ZoomProvider/ZoomSetup'; +import { useZoom } from '../context/ZoomProvider/useZoom'; export interface BarChartProProps extends BarChartProps { - // TODO: Add zoom props + /** + * If `true`, the chart will be zoomable. + */ + zoom?: boolean; } /** @@ -27,6 +33,7 @@ export interface BarChartProProps extends BarChartProps { * - [BarChart API](https://mui.com/x/api/charts/bar-chart/) */ const BarChartPro = React.forwardRef(function BarChartPro(props: BarChartProProps, ref) { + const { zoom, ...restProps } = props; const { chartContainerProps, barPlotProps, @@ -39,16 +46,15 @@ const BarChartPro = React.forwardRef(function BarChartPro(props: BarChartProProp axisHighlightProps, legendProps, tooltipProps, - children, - } = useBarChartProps(props); + } = useBarChartProps(restProps); return ( {props.onAxisClick && } {props.grid && } - + @@ -56,9 +62,16 @@ const BarChartPro = React.forwardRef(function BarChartPro(props: BarChartProProp {!props.loading && } + {zoom && } {children} ); }); +function BarChartPlotZoom(props: BarPlotProps) { + const { isInteracting } = useZoom(); + + return ; +} + export { BarChartPro }; diff --git a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx index 8361a9df7882..8c0e759232b2 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx +++ b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx @@ -4,7 +4,6 @@ import { ChartContainerProps } from '@mui/x-charts/ChartContainer'; import { ChartsSurface } from '@mui/x-charts/ChartsSurface'; import { HighlightedProvider, ZAxisContextProvider } from '@mui/x-charts/context'; import { - CartesianContextProvider, ChartsAxesGradients, ColorProvider, DrawingProvider, @@ -14,6 +13,8 @@ import { } from '@mui/x-charts/internals'; import { useLicenseVerifier } from '@mui/x-license/useLicenseVerifier'; import { getReleaseInfo } from '../internals/utils/releaseInfo'; +import { CartesianContextProviderPro } from '../context/CartesianProviderPro'; +import { ZoomProvider } from '../context/ZoomProvider'; const releaseInfo = getReleaseInfo(); @@ -63,35 +64,37 @@ const ChartContainerPro = React.forwardRef(function ChartContainer( dataset={dataset} seriesFormatters={seriesFormatters} > - - - - - + + + + - - {children} - - - - - + + + {children} + + + + + + diff --git a/packages/x-charts-pro/src/Heatmap/DefaultHeatmapTooltip.tsx b/packages/x-charts-pro/src/Heatmap/DefaultHeatmapTooltip.tsx new file mode 100644 index 000000000000..7fc3974a8a8f --- /dev/null +++ b/packages/x-charts-pro/src/Heatmap/DefaultHeatmapTooltip.tsx @@ -0,0 +1,68 @@ +import * as React from 'react'; +import clsx from 'clsx'; +import { + ChartsItemContentProps, + ChartsTooltipPaper, + ChartsTooltipTable, + ChartsTooltipRow, + ChartsTooltipCell, + ChartsTooltipMark, +} from '@mui/x-charts/ChartsTooltip'; +import { useXAxis, useYAxis } from '@mui/x-charts/hooks'; +import { getLabel } from '@mui/x-charts/internals'; + +/** + * @ignore - do not document. + */ +export function DefaultHeatmapTooltip(props: ChartsItemContentProps<'heatmap'>) { + const { series, itemData, sx, classes, getColor } = props; + + const xAxis = useXAxis(); + const yAxis = useYAxis(); + + if (itemData.dataIndex === undefined || !series.data[itemData.dataIndex]) { + return null; + } + + const color = getColor(itemData.dataIndex); + + const valueItem = series.data[itemData.dataIndex]; + const [xIndex, yIndex] = valueItem; + + const formattedX = + xAxis.valueFormatter?.(xAxis.data![xIndex], { location: 'tooltip' }) ?? + xAxis.data![xIndex].toLocaleString(); + const formattedY = + yAxis.valueFormatter?.(yAxis.data![yIndex], { location: 'tooltip' }) ?? + yAxis.data![yIndex].toLocaleString(); + const formattedValue = series.valueFormatter(valueItem, { dataIndex: itemData.dataIndex }); + + const seriesLabel = getLabel(series.label, 'tooltip'); + + return ( + + + + + {formattedX} + {formattedX && formattedY && } + {formattedY} + + + + + + + + + {seriesLabel} + + + {formattedValue} + + + + + + ); +} diff --git a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx new file mode 100644 index 000000000000..af5f928f8330 --- /dev/null +++ b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx @@ -0,0 +1,204 @@ +import * as React from 'react'; +import { interpolateRgbBasis } from 'd3-interpolate'; +import useId from '@mui/utils/useId'; +import { ChartsAxis, ChartsAxisProps } from '@mui/x-charts/ChartsAxis'; +import { + ChartsTooltip, + ChartsTooltipProps, + ChartsTooltipSlotProps, + ChartsTooltipSlots, +} from '@mui/x-charts/ChartsTooltip'; +import { + MakeOptional, + ChartsAxisSlots, + ChartsAxisSlotProps, + ChartsXAxisProps, + ChartsYAxisProps, + AxisConfig, +} from '@mui/x-charts/internals'; +import { ChartsClipPath } from '@mui/x-charts/ChartsClipPath'; +import { + ChartsOnAxisClickHandler, + ChartsOnAxisClickHandlerProps, +} from '@mui/x-charts/ChartsOnAxisClickHandler'; +import { + ChartsOverlay, + ChartsOverlayProps, + ChartsOverlaySlotProps, + ChartsOverlaySlots, +} from '@mui/x-charts/ChartsOverlay'; +import { + ResponsiveChartContainerPro, + ResponsiveChartContainerProProps, +} from '../ResponsiveChartContainerPro'; +import { HeatmapSeriesType } from '../models/seriesType/heatmap'; +import { HeatmapPlot } from './HeatmapPlot'; +import { plugin as heatmapPlugin } from './plugin'; +import { DefaultHeatmapTooltip } from './DefaultHeatmapTooltip'; +import { HeatmapItemSlotProps, HeatmapItemSlots } from './HeatmapItem'; + +export interface HeatmapSlots + extends ChartsAxisSlots, + Omit, 'axisContent'>, + ChartsOverlaySlots, + HeatmapItemSlots {} +export interface HeatmapSlotProps + extends ChartsAxisSlotProps, + Omit, 'axisContent'>, + ChartsOverlaySlotProps, + HeatmapItemSlotProps {} + +export interface HeatmapProps + extends Omit, + Omit, + Omit, + ChartsOnAxisClickHandlerProps { + /** + * The configuration of the x-axes. + * If not provided, a default axis config is used. + * An array of [[AxisConfig]] objects. + */ + xAxis: MakeOptional, 'id' | 'scaleType'>[]; + /** + * The configuration of the y-axes. + * If not provided, a default axis config is used. + * An array of [[AxisConfig]] objects. + */ + yAxis: MakeOptional, 'id' | 'scaleType'>[]; + /** + * The series to display in the bar chart. + * An array of [[HeatmapSeriesType]] objects. + */ + series: MakeOptional[]; + /** + * The configuration of the tooltip. + * @see See {@link https://mui.com/x/react-charts/tooltip/ tooltip docs} for more details. + */ + tooltip?: ChartsTooltipProps<'heatmap'>; + /** + * Overridable component slots. + * @default {} + */ + slots?: HeatmapSlots; + /** + * The props used for each component slot. + * @default {} + */ + slotProps?: HeatmapSlotProps; +} + +// The GnBu: https://github.com/d3/d3-scale-chromatic/blob/main/src/sequential-multi/GnBu.js +const defaultColorMap = interpolateRgbBasis([ + '#f7fcf0', + '#e0f3db', + '#ccebc5', + '#a8ddb5', + '#7bccc4', + '#4eb3d3', + '#2b8cbe', + '#0868ac', + '#084081', +]); + +export const Heatmap = React.forwardRef(function Heatmap(props: HeatmapProps, ref) { + const { + xAxis, + yAxis, + zAxis, + series, + width, + height, + margin, + colors, + dataset, + sx, + tooltip, + topAxis, + leftAxis, + rightAxis, + bottomAxis, + onAxisClick, + children, + slots, + slotProps, + loading, + highlightedItem, + onHighlightChange, + } = props; + + const id = useId(); + const clipPathId = `${id}-clip-path`; + + const defaultizedXAxis = React.useMemo( + () => xAxis.map((axis) => ({ scaleType: 'band' as const, categoryGapRatio: 0, ...axis })), + [xAxis], + ); + + const defaultizedYAxis = React.useMemo( + () => yAxis.map((axis) => ({ scaleType: 'band' as const, categoryGapRatio: 0, ...axis })), + [yAxis], + ); + + const defaultizedZAxis = React.useMemo( + () => + zAxis ?? [ + { + colorMap: { + type: 'continuous', + min: 0, + max: 100, + color: defaultColorMap, + }, + } as const, + ], + [zAxis], + ); + + return ( + ({ + type: 'heatmap', + ...s, + }))} + width={width} + height={height} + margin={margin} + xAxis={defaultizedXAxis} + yAxis={defaultizedYAxis} + zAxis={defaultizedZAxis} + colors={colors} + dataset={dataset} + sx={sx} + disableAxisListener + highlightedItem={highlightedItem} + onHighlightChange={onHighlightChange} + > + {onAxisClick && } + + + + + + + {!loading && ( + + )} + + {children} + + ); +}); diff --git a/packages/x-charts-pro/src/Heatmap/HeatmapItem.tsx b/packages/x-charts-pro/src/Heatmap/HeatmapItem.tsx new file mode 100644 index 000000000000..c82c4b27ba2c --- /dev/null +++ b/packages/x-charts-pro/src/Heatmap/HeatmapItem.tsx @@ -0,0 +1,102 @@ +import * as React from 'react'; +import { styled } from '@mui/material/styles'; +import { useSlotProps } from '@mui/base/utils'; +import composeClasses from '@mui/utils/composeClasses'; +import { useItemHighlighted } from '@mui/x-charts/context'; +import { useInteractionItemProps, SeriesId } from '@mui/x-charts/internals'; +import { HeatmapClasses, getHeatmapUtilityClass } from './heatmapClasses'; + +export interface HeatmapItemSlots { + /** + * The component that renders the heatmap cell. + * @default HeatmapCell + */ + cell?: React.ElementType; +} + +export interface HeatmapItemSlotProps { + cell?: Partial>; +} + +export interface HeatmapItemProps { + dataIndex: number; + seriesId: SeriesId; + value: number; + width: number; + height: number; + x: number; + y: number; + color: string; + /** + * The props used for each component slot. + * @default {} + */ + slotProps?: HeatmapItemSlotProps; + /** + * Overridable component slots. + * @default {} + */ + slots?: HeatmapItemSlots; +} + +export interface HeatmapItemOwnerState { + seriesId: SeriesId; + dataIndex: number; + color: string; + isFaded: boolean; + isHighlighted: boolean; + classes?: Partial; +} + +const HeatmapCell = styled('rect', { + name: 'MuiHeatmap', + slot: 'Cell', + overridesResolver: (_, styles) => styles.arc, +})<{ ownerState: HeatmapItemOwnerState }>(({ ownerState }) => ({ + filter: + (ownerState.isHighlighted && 'saturate(120%)') || + (ownerState.isFaded && 'saturate(80%)') || + undefined, + fill: ownerState.color, + shapeRendering: 'crispEdges', +})); + +const useUtilityClasses = (ownerState: HeatmapItemOwnerState) => { + const { classes, seriesId, isFaded, isHighlighted } = ownerState; + const slots = { + cell: ['cell', `series-${seriesId}`, isFaded && 'faded', isHighlighted && 'highlighted'], + }; + return composeClasses(slots, getHeatmapUtilityClass, classes); +}; + +export function HeatmapItem(props: HeatmapItemProps) { + const { seriesId, dataIndex, color, value, slotProps = {}, slots = {}, ...other } = props; + + const getInteractionItemProps = useInteractionItemProps(); + const { isFaded, isHighlighted } = useItemHighlighted({ + seriesId, + dataIndex, + }); + + const ownerState = { + seriesId, + dataIndex, + color, + value, + isFaded, + isHighlighted, + }; + const classes = useUtilityClasses(ownerState); + + const Cell = slots?.cell ?? HeatmapCell; + const cellProps = useSlotProps({ + elementType: Cell, + additionalProps: { ...getInteractionItemProps({ type: 'heatmap', seriesId, dataIndex }) }, + externalForwardedProps: { ...other }, + externalSlotProps: slotProps.cell, + ownerState, + className: classes.cell, + }); + + return ; +} diff --git a/packages/x-charts-pro/src/Heatmap/HeatmapPlot.tsx b/packages/x-charts-pro/src/Heatmap/HeatmapPlot.tsx new file mode 100644 index 000000000000..42c9d8e0fe4a --- /dev/null +++ b/packages/x-charts-pro/src/Heatmap/HeatmapPlot.tsx @@ -0,0 +1,49 @@ +import * as React from 'react'; +import { useXScale, useYScale, useZColorScale } from '@mui/x-charts/hooks'; +import { useHeatmapSeries } from '../hooks/useSeries'; +import { HeatmapItem, HeatmapItemProps } from './HeatmapItem'; + +export interface HeatmapPlotProps extends Pick {} + +export function HeatmapPlot(props: HeatmapPlotProps) { + const xScale = useXScale<'band'>(); + const yScale = useYScale<'band'>(); + const colorScale = useZColorScale()!; + const series = useHeatmapSeries(); + + const xDomain = xScale.domain(); + const yDomain = yScale.domain(); + + if (!series || series.seriesOrder.length === 0) { + return null; + } + const seriesToDisplay = series.series[series.seriesOrder[0]]; + + return ( + + {seriesToDisplay.data.map(([xIndex, yIndex, value], dataIndex) => { + const x = xScale(xDomain[xIndex]); + const y = yScale(yDomain[yIndex]); + const color = colorScale?.(value); + if (x === undefined || y === undefined || !color) { + return null; + } + return ( + + ); + })} + + ); +} diff --git a/packages/x-charts-pro/src/Heatmap/extremums.ts b/packages/x-charts-pro/src/Heatmap/extremums.ts new file mode 100644 index 000000000000..a0bdab36b726 --- /dev/null +++ b/packages/x-charts-pro/src/Heatmap/extremums.ts @@ -0,0 +1,9 @@ +import { ExtremumGetter } from '@mui/x-charts/internals'; + +export const getBaseExtremum: ExtremumGetter<'heatmap'> = (params) => { + const { axis } = params; + + const minX = Math.min(...(axis.data ?? [])); + const maxX = Math.max(...(axis.data ?? [])); + return [minX, maxX]; +}; diff --git a/packages/x-charts-pro/src/Heatmap/formatter.ts b/packages/x-charts-pro/src/Heatmap/formatter.ts new file mode 100644 index 000000000000..17e0b2a68ae3 --- /dev/null +++ b/packages/x-charts-pro/src/Heatmap/formatter.ts @@ -0,0 +1,23 @@ +import { Formatter, SeriesId } from '@mui/x-charts/internals'; +import { DefaultizedHeatmapSeriesType } from '../models/seriesType/heatmap'; + +const formatter: Formatter<'heatmap'> = (params) => { + const { series, seriesOrder } = params; + + const defaultizedSeries: Record = {}; + Object.keys(series).forEach((seriesId) => { + defaultizedSeries[seriesId] = { + // Defaultize the data and the value formatter. + valueFormatter: (v) => v[2].toString(), + data: [], + ...series[seriesId], + }; + }); + + return { + series: defaultizedSeries, + seriesOrder, + }; +}; + +export default formatter; diff --git a/packages/x-charts-pro/src/Heatmap/getColor.ts b/packages/x-charts-pro/src/Heatmap/getColor.ts new file mode 100644 index 000000000000..f51d38225023 --- /dev/null +++ b/packages/x-charts-pro/src/Heatmap/getColor.ts @@ -0,0 +1,24 @@ +import { DefaultizedSeriesType } from '@mui/x-charts'; +import { AxisDefaultized, ZAxisDefaultized } from '@mui/x-charts/internals'; + +export default function getColor( + series: DefaultizedSeriesType<'heatmap'>, + xAxis?: AxisDefaultized, + yAxis?: AxisDefaultized, + zAxis?: ZAxisDefaultized, +) { + const zColorScale = zAxis?.colorScale; + + if (zColorScale) { + return (dataIndex: number) => { + const value = series.data[dataIndex]; + const color = zColorScale(value[2]); + if (color === null) { + return ''; + } + return color; + }; + } + + return () => ''; +} diff --git a/packages/x-charts-pro/src/Heatmap/heatmapClasses.ts b/packages/x-charts-pro/src/Heatmap/heatmapClasses.ts new file mode 100644 index 000000000000..2f50b4bdfa59 --- /dev/null +++ b/packages/x-charts-pro/src/Heatmap/heatmapClasses.ts @@ -0,0 +1,28 @@ +import { + unstable_generateUtilityClass as generateUtilityClass, + unstable_generateUtilityClasses as generateUtilityClasses, +} from '@mui/utils'; + +export interface HeatmapClasses { + /** Styles applied to the heatmap cells. */ + cell: string; + /** Styles applied to the cell element if highlighted. */ + highlighted: string; + /** Styles applied to the cell element if faded. */ + faded: string; +} + +export type HeatmapClassKey = keyof HeatmapClasses; + +export function getHeatmapUtilityClass(slot: string) { + // Those should be common to all charts + if (['highlighted', 'faded'].includes(slot)) { + return generateUtilityClass('Charts', slot); + } + return generateUtilityClass('MuiHeatmap', slot); +} +export const heatmapClasses: HeatmapClasses = { + ...generateUtilityClasses('MuiHeatmap', ['cell']), + highlighted: 'Charts-highlighted', + faded: 'Charts-faded', +}; diff --git a/packages/x-charts-pro/src/Heatmap/index.ts b/packages/x-charts-pro/src/Heatmap/index.ts new file mode 100644 index 000000000000..042c1a78bacb --- /dev/null +++ b/packages/x-charts-pro/src/Heatmap/index.ts @@ -0,0 +1,4 @@ +export { Heatmap as UnstableHeatmap } from './Heatmap'; +export { HeatmapPlot as UnstableHeatmapPlot } from './HeatmapPlot'; +export * from './DefaultHeatmapTooltip'; +export * from './heatmapClasses'; diff --git a/packages/x-charts-pro/src/Heatmap/plugin.ts b/packages/x-charts-pro/src/Heatmap/plugin.ts new file mode 100644 index 000000000000..c6d7b42077af --- /dev/null +++ b/packages/x-charts-pro/src/Heatmap/plugin.ts @@ -0,0 +1,12 @@ +import { ChartsPluginType } from '@mui/x-charts/models'; +import { getBaseExtremum } from './extremums'; +import formatter from './formatter'; +import getColor from './getColor'; + +export const plugin: ChartsPluginType<'heatmap'> = { + seriesType: 'heatmap', + seriesFormatter: formatter, + colorProcessor: getColor, + xExtremumGetter: getBaseExtremum, + yExtremumGetter: getBaseExtremum, +}; diff --git a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx index 384a56b509a4..108fcb795a57 100644 --- a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx +++ b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx @@ -15,10 +15,16 @@ import { ChartsLegend } from '@mui/x-charts/ChartsLegend'; import { ChartsTooltip } from '@mui/x-charts/ChartsTooltip'; import { ChartsClipPath } from '@mui/x-charts/ChartsClipPath'; import { useLineChartProps } from '@mui/x-charts/internals'; +import { MarkPlotProps } from '@mui/x-charts'; import { ResponsiveChartContainerPro } from '../ResponsiveChartContainerPro'; +import { ZoomSetup } from '../context/ZoomProvider/ZoomSetup'; +import { useZoom } from '../context/ZoomProvider/useZoom'; export interface LineChartProProps extends LineChartProps { - // TODO: Add zoom props + /** + * If `true`, the chart will be zoomable. + */ + zoom?: boolean; } /** @@ -32,6 +38,7 @@ export interface LineChartProProps extends LineChartProps { * - [LineChart API](https://mui.com/x/api/charts/line-chart/) */ const LineChartPro = React.forwardRef(function LineChartPro(props: LineChartProProps, ref) { + const { zoom, ...restProps } = props; const { chartContainerProps, axisClickHandlerProps, @@ -47,9 +54,8 @@ const LineChartPro = React.forwardRef(function LineChartPro(props: LineChartProP lineHighlightPlotProps, legendProps, tooltipProps, - children, - } = useLineChartProps(props); + } = useLineChartProps(restProps); return ( @@ -62,14 +68,20 @@ const LineChartPro = React.forwardRef(function LineChartPro(props: LineChartProP - + {!props.loading && } + {zoom && } {children} ); }); +function MarkPlotZoom(props: MarkPlotProps) { + const { isInteracting } = useZoom(); + return ; +} + export { LineChartPro }; diff --git a/packages/x-charts-pro/src/ResponsiveChartContainerPro/ResponsiveChartContainerPro.test.tsx b/packages/x-charts-pro/src/ResponsiveChartContainerPro/ResponsiveChartContainerPro.test.tsx index 007e7217a8e3..4d5e4565a271 100644 --- a/packages/x-charts-pro/src/ResponsiveChartContainerPro/ResponsiveChartContainerPro.test.tsx +++ b/packages/x-charts-pro/src/ResponsiveChartContainerPro/ResponsiveChartContainerPro.test.tsx @@ -22,7 +22,7 @@ describe(' - License', () => { ).toErrorDev(['MUI X: Missing license key.']); await waitFor(() => { - expect(screen.findAllByText('MUI X Missing license key')).to.not.equal(null); + expect(screen.findAllByText('MUI X Missing license key')).not.to.equal(null); }); }); }); diff --git a/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx b/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx index ad91bb1f9005..557bbf228be6 100644 --- a/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx +++ b/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx @@ -10,9 +10,13 @@ import { ChartsAxisHighlight } from '@mui/x-charts/ChartsAxisHighlight'; import { ChartsTooltip } from '@mui/x-charts/ChartsTooltip'; import { useScatterChartProps } from '@mui/x-charts/internals'; import { ResponsiveChartContainerPro } from '../ResponsiveChartContainerPro'; +import { ZoomSetup } from '../context/ZoomProvider/ZoomSetup'; export interface ScatterChartProProps extends ScatterChartProps { - // TODO: Add zoom props + /** + * If `true`, the chart will be zoomable. + */ + zoom?: boolean; } /** @@ -29,6 +33,7 @@ const ScatterChartPro = React.forwardRef(function ScatterChartPro( props: ScatterChartProProps, ref, ) { + const { zoom, ...restProps } = props; const { chartContainerProps, zAxisProps, @@ -41,7 +46,7 @@ const ScatterChartPro = React.forwardRef(function ScatterChartPro( axisHighlightProps, tooltipProps, children, - } = useScatterChartProps(props); + } = useScatterChartProps(restProps); return ( @@ -53,6 +58,7 @@ const ScatterChartPro = React.forwardRef(function ScatterChartPro( {!props.loading && } + {zoom && } {children} diff --git a/packages/x-charts-pro/src/context/CartesianProviderPro/CartesianProviderPro.tsx b/packages/x-charts-pro/src/context/CartesianProviderPro/CartesianProviderPro.tsx new file mode 100644 index 000000000000..a3b30b79037d --- /dev/null +++ b/packages/x-charts-pro/src/context/CartesianProviderPro/CartesianProviderPro.tsx @@ -0,0 +1,59 @@ +import * as React from 'react'; +import { + useDrawingArea, + useSeries, + CartesianContext, + CartesianContextProviderProps, + cartesianProviderUtils, +} from '@mui/x-charts/internals'; +import { useZoom } from '../ZoomProvider/useZoom'; + +const { normalizeAxis, computeValue } = cartesianProviderUtils; + +export interface CartesianContextProviderProProps extends CartesianContextProviderProps {} + +function CartesianContextProviderPro(props: CartesianContextProviderProProps) { + const { + xAxis: inXAxis, + yAxis: inYAxis, + dataset, + xExtremumGetters, + yExtremumGetters, + children, + } = props; + + const formattedSeries = useSeries(); + const drawingArea = useDrawingArea(); + const { zoomRange } = useZoom(); + + const xAxis = React.useMemo(() => normalizeAxis(inXAxis, dataset, 'x'), [inXAxis, dataset]); + + const yAxis = React.useMemo(() => normalizeAxis(inYAxis, dataset, 'y'), [inYAxis, dataset]); + + const xValues = React.useMemo( + () => computeValue(drawingArea, formattedSeries, xAxis, xExtremumGetters, 'x', zoomRange), + [drawingArea, formattedSeries, xAxis, xExtremumGetters, zoomRange], + ); + + const yValues = React.useMemo( + () => computeValue(drawingArea, formattedSeries, yAxis, yExtremumGetters, 'y'), + [drawingArea, formattedSeries, yAxis, yExtremumGetters], + ); + + const value = React.useMemo( + () => ({ + isInitialized: true, + data: { + xAxis: xValues.axis, + yAxis: yValues.axis, + xAxisIds: xValues.axisIds, + yAxisIds: yValues.axisIds, + }, + }), + [xValues, yValues], + ); + + return {children}; +} + +export { CartesianContextProviderPro }; diff --git a/packages/x-charts-pro/src/context/CartesianProviderPro/index.ts b/packages/x-charts-pro/src/context/CartesianProviderPro/index.ts new file mode 100644 index 000000000000..6b24b2347017 --- /dev/null +++ b/packages/x-charts-pro/src/context/CartesianProviderPro/index.ts @@ -0,0 +1 @@ +export * from './CartesianProviderPro'; diff --git a/packages/x-charts-pro/src/context/ZoomProvider/ZoomContext.ts b/packages/x-charts-pro/src/context/ZoomProvider/ZoomContext.ts new file mode 100644 index 000000000000..aa7ae3688708 --- /dev/null +++ b/packages/x-charts-pro/src/context/ZoomProvider/ZoomContext.ts @@ -0,0 +1,23 @@ +import * as React from 'react'; +import { Initializable } from '@mui/x-charts/internals'; + +export type ZoomState = { + zoomRange: [number, number]; + setZoomRange: (range: [number, number]) => void; + isInteracting: boolean; + setIsInteracting: (isInteracting: boolean) => void; +}; + +export const ZoomContext = React.createContext>({ + isInitialized: false, + data: { + zoomRange: [0, 100], + setZoomRange: () => {}, + isInteracting: false, + setIsInteracting: () => {}, + }, +}); + +if (process.env.NODE_ENV !== 'production') { + ZoomContext.displayName = 'ZoomContext'; +} diff --git a/packages/x-charts-pro/src/context/ZoomProvider/ZoomProvider.tsx b/packages/x-charts-pro/src/context/ZoomProvider/ZoomProvider.tsx new file mode 100644 index 000000000000..a2d235f5a5ef --- /dev/null +++ b/packages/x-charts-pro/src/context/ZoomProvider/ZoomProvider.tsx @@ -0,0 +1,26 @@ +import * as React from 'react'; +import { ZoomContext } from './ZoomContext'; + +type ZoomProviderProps = { + children: React.ReactNode; +}; + +export function ZoomProvider({ children }: ZoomProviderProps) { + const [zoomRange, setZoomRange] = React.useState<[number, number]>([0, 100]); + const [isInteracting, setIsInteracting] = React.useState(false); + + const value = React.useMemo( + () => ({ + isInitialized: true, + data: { + zoomRange, + setZoomRange, + isInteracting, + setIsInteracting, + }, + }), + [zoomRange, setZoomRange, isInteracting, setIsInteracting], + ); + + return {children}; +} diff --git a/packages/x-charts-pro/src/context/ZoomProvider/ZoomSetup.ts b/packages/x-charts-pro/src/context/ZoomProvider/ZoomSetup.ts new file mode 100644 index 000000000000..072baa872d42 --- /dev/null +++ b/packages/x-charts-pro/src/context/ZoomProvider/ZoomSetup.ts @@ -0,0 +1,10 @@ +import { useSetupPan } from './useSetupPan'; +import { useSetupZoom } from './useSetupZoom'; + +function ZoomSetup() { + useSetupZoom(); + useSetupPan(); + return null; +} + +export { ZoomSetup }; diff --git a/packages/x-charts-pro/src/context/ZoomProvider/index.ts b/packages/x-charts-pro/src/context/ZoomProvider/index.ts new file mode 100644 index 000000000000..04bb323d80ae --- /dev/null +++ b/packages/x-charts-pro/src/context/ZoomProvider/index.ts @@ -0,0 +1,3 @@ +export * from './ZoomContext'; +export * from './ZoomProvider'; +export * from './useSetupZoom'; diff --git a/packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts b/packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts new file mode 100644 index 000000000000..65f954405932 --- /dev/null +++ b/packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts @@ -0,0 +1,113 @@ +import * as React from 'react'; +import { useDrawingArea, useSvgRef } from '@mui/x-charts/hooks'; +import { getSVGPoint } from '@mui/x-charts/internals'; +import { useZoom } from './useZoom'; + +const MAX_RANGE = 100; +const MIN_RANGE = 0; + +const isPointOutside = ( + point: { x: number; y: number }, + area: { left: number; top: number; width: number; height: number }, +) => { + const outsideX = point.x < area.left || point.x > area.left + area.width; + const outsideY = point.y < area.top || point.y > area.top + area.height; + return outsideX || outsideY; +}; + +export const useSetupPan = () => { + const { zoomRange, setZoomRange, setIsInteracting } = useZoom(); + const area = useDrawingArea(); + + const svgRef = useSvgRef(); + + const isDraggingRef = React.useRef(false); + const touchStartRef = React.useRef<{ x: number; minX: number; maxX: number } | null>(null); + const eventCacheRef = React.useRef([]); + + React.useEffect(() => { + const element = svgRef.current; + if (element === null) { + return () => {}; + } + + const handlePan = (event: PointerEvent) => { + if (element === null || !isDraggingRef.current || eventCacheRef.current.length > 1) { + return; + } + + if (touchStartRef.current == null) { + return; + } + + const point = getSVGPoint(element, event); + const movementX = point.x - touchStartRef.current.x; + + const max = touchStartRef.current.maxX; + const min = touchStartRef.current.minX; + const span = max - min; + + let newMinRange = min - (movementX / area.width) * span; + let newMaxRange = max - (movementX / area.width) * span; + + if (newMinRange < MIN_RANGE) { + newMinRange = MIN_RANGE; + newMaxRange = span; + } + + if (newMaxRange > MAX_RANGE) { + newMaxRange = MAX_RANGE; + newMinRange = MAX_RANGE - span; + } + + setZoomRange([newMinRange, newMaxRange]); + }; + + const handleDown = (event: PointerEvent) => { + eventCacheRef.current.push(event); + const point = getSVGPoint(element, event); + + if (isPointOutside(point, area)) { + return; + } + + // If there is only one pointer, prevent selecting text + if (eventCacheRef.current.length === 1) { + event.preventDefault(); + } + + isDraggingRef.current = true; + setIsInteracting(true); + + touchStartRef.current = { + x: point.x, + minX: zoomRange[0], + maxX: zoomRange[1], + }; + }; + + const handleUp = (event: PointerEvent) => { + eventCacheRef.current.splice( + eventCacheRef.current.findIndex((e) => e.pointerId === event.pointerId), + 1, + ); + setIsInteracting(false); + isDraggingRef.current = false; + touchStartRef.current = null; + }; + + element.addEventListener('pointerdown', handleDown); + document.addEventListener('pointermove', handlePan); + document.addEventListener('pointerup', handleUp); + document.addEventListener('pointercancel', handleUp); + document.addEventListener('pointerleave', handleUp); + + return () => { + element.removeEventListener('pointerdown', handleDown); + document.removeEventListener('pointermove', handlePan); + document.removeEventListener('pointerup', handleUp); + document.removeEventListener('pointercancel', handleUp); + document.removeEventListener('pointerleave', handleUp); + }; + }, [area, svgRef, isDraggingRef, zoomRange, setZoomRange, setIsInteracting]); +}; diff --git a/packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts b/packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts new file mode 100644 index 000000000000..c32ef62edd90 --- /dev/null +++ b/packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts @@ -0,0 +1,280 @@ +import * as React from 'react'; +import { useDrawingArea, useSvgRef } from '@mui/x-charts/hooks'; +import { getSVGPoint } from '@mui/x-charts/internals'; +import { useZoom } from './useZoom'; + +const MAX_RANGE = 100; +const MIN_RANGE = 0; + +const MIN_ALLOWED_SPAN = 10; +const MAX_ALLOWED_SPAN = 100; + +/** + * Helper to get the range (in percents of a reference range) corresponding to a given scale. + * @param centerRatio {number} The ratio of the point that should not move between the previous and next range. + * @param scaleRatio {number} The target scale ratio. + * @returns The range to display. + */ +const zoomAtPoint = ( + centerRatio: number, + scaleRatio: number, + currentRange: readonly [number, number], +) => { + const [minRange, maxRange] = currentRange; + + const point = minRange + centerRatio * (maxRange - minRange); + + let newMinRange = (minRange + point * (scaleRatio - 1)) / scaleRatio; + let newMaxRange = (maxRange + point * (scaleRatio - 1)) / scaleRatio; + + let minSpillover = 0; + let maxSpillover = 0; + + if (newMinRange < MIN_RANGE) { + minSpillover = Math.abs(newMinRange); + newMinRange = MIN_RANGE; + } + if (newMaxRange > MAX_RANGE) { + maxSpillover = Math.abs(newMaxRange - MAX_RANGE); + newMaxRange = MAX_RANGE; + } + + if (minSpillover > 0 && maxSpillover > 0) { + return [MIN_RANGE, MAX_RANGE]; + } + + newMaxRange += minSpillover; + newMinRange -= maxSpillover; + + newMinRange = Math.min(MAX_RANGE - MIN_ALLOWED_SPAN, Math.max(MIN_RANGE, newMinRange)); + newMaxRange = Math.max(MIN_ALLOWED_SPAN, Math.min(MAX_RANGE, newMaxRange)); + + return [newMinRange, newMaxRange]; +}; + +const isPointOutside = ( + point: { x: number; y: number }, + area: { left: number; top: number; width: number; height: number }, +) => { + const outsideX = point.x < area.left || point.x > area.left + area.width; + const outsideY = point.y < area.top || point.y > area.top + area.height; + return outsideX || outsideY; +}; + +export const useSetupZoom = () => { + const { zoomRange, setZoomRange } = useZoom(); + const area = useDrawingArea(); + + const svgRef = useSvgRef(); + const eventCacheRef = React.useRef([]); + const eventPrevDiff = React.useRef(0); + + React.useEffect(() => { + const element = svgRef.current; + if (element === null) { + return () => {}; + } + + const wheelHandler = (event: WheelEvent) => { + if (element === null) { + return; + } + + const point = getSVGPoint(element, event); + + if (isPointOutside(point, area)) { + return; + } + + event.preventDefault(); + + const centerRatio = getHorizontalCenterRatio(point, area); + + // TODO: make step a config option. + const step = 5; + const { scaleRatio, isZoomIn } = getWheelScaleRatio(event, step); + + const [newMinRange, newMaxRange] = zoomAtPoint(centerRatio, scaleRatio, zoomRange); + + // TODO: make span a config option. + if (!isSpanValid(newMinRange, newMaxRange, isZoomIn)) { + return; + } + + setZoomRange([newMinRange, newMaxRange]); + }; + + function pointerDownHandler(event: PointerEvent) { + eventCacheRef.current.push(event); + } + + function pointerMoveHandler(event: PointerEvent) { + if (element === null) { + return; + } + + const index = eventCacheRef.current.findIndex( + (cachedEv) => cachedEv.pointerId === event.pointerId, + ); + eventCacheRef.current[index] = event; + + // If two pointers are down, check for pinch gestures + if (eventCacheRef.current.length === 2) { + // TODO: make step configurable + const step = 5; + const { scaleRatio, isZoomIn, curDiff, firstEvent } = getPinchScaleRatio( + eventCacheRef.current, + eventPrevDiff.current, + step, + ); + + // If the scale ratio is 0, it means the pinch gesture is not valid. + if (scaleRatio === 0) { + eventPrevDiff.current = curDiff; + return; + } + + const point = getSVGPoint(element, firstEvent); + + const centerRatio = getHorizontalCenterRatio(point, area); + + const [newMinRange, newMaxRange] = zoomAtPoint(centerRatio, scaleRatio, zoomRange); + + // TODO: make span a config option. + if (!isSpanValid(newMinRange, newMaxRange, isZoomIn)) { + eventPrevDiff.current = curDiff; + return; + } + + eventPrevDiff.current = curDiff; + setZoomRange([newMinRange, newMaxRange]); + } + } + + function pointerUpHandler(event: PointerEvent) { + eventCacheRef.current.splice( + eventCacheRef.current.findIndex((e) => e.pointerId === event.pointerId), + 1, + ); + + if (eventCacheRef.current.length < 2) { + eventPrevDiff.current = 0; + } + } + + element.addEventListener('wheel', wheelHandler); + element.addEventListener('pointerdown', pointerDownHandler); + element.addEventListener('pointermove', pointerMoveHandler); + element.addEventListener('pointerup', pointerUpHandler); + element.addEventListener('pointercancel', pointerUpHandler); + element.addEventListener('pointerout', pointerUpHandler); + element.addEventListener('pointerleave', pointerUpHandler); + + // Prevent zooming the entire page on touch devices + element.addEventListener('touchstart', preventDefault); + element.addEventListener('touchmove', preventDefault); + + return () => { + element.removeEventListener('wheel', wheelHandler); + element.removeEventListener('pointerdown', pointerDownHandler); + element.removeEventListener('pointermove', pointerMoveHandler); + element.removeEventListener('pointerup', pointerUpHandler); + element.removeEventListener('pointercancel', pointerUpHandler); + element.removeEventListener('pointerout', pointerUpHandler); + element.removeEventListener('pointerleave', pointerUpHandler); + element.removeEventListener('touchstart', preventDefault); + element.removeEventListener('touchmove', preventDefault); + }; + }, [svgRef, setZoomRange, zoomRange, area]); +}; + +/** + * Checks if the new span is valid. + */ +function isSpanValid(minRange: number, maxRange: number, isZoomIn: boolean) { + const newSpanPercent = maxRange - minRange; + + // TODO: make span a config option. + if ( + (isZoomIn && newSpanPercent < MIN_ALLOWED_SPAN) || + (!isZoomIn && newSpanPercent > MAX_ALLOWED_SPAN) + ) { + return false; + } + + return true; +} + +function getMultiplier(event: WheelEvent) { + const ctrlMultiplier = event.ctrlKey ? 3 : 1; + + // DeltaMode: 0 is pixel, 1 is line, 2 is page + // This is defined by the browser. + if (event.deltaMode === 1) { + return 1 * ctrlMultiplier; + } + if (event.deltaMode) { + return 10 * ctrlMultiplier; + } + return 0.2 * ctrlMultiplier; +} + +/** + * Get the scale ratio and if it's a zoom in or out from a wheel event. + */ +function getWheelScaleRatio(event: WheelEvent, step: number) { + const deltaY = -event.deltaY; + const multiplier = getMultiplier(event); + const scaledStep = (step * multiplier * deltaY) / 1000; + // Clamp the scale ratio between 0.1 and 1.9 so that the zoom is not too big or too small. + const scaleRatio = Math.min(Math.max(1 + scaledStep, 0.1), 1.9); + const isZoomIn = deltaY > 0; + return { scaleRatio, isZoomIn }; +} + +/** + * Get the scale ratio and if it's a zoom in or out from a pinch gesture. + */ +function getPinchScaleRatio(eventCache: PointerEvent[], prevDiff: number, step: number) { + const scaledStep = step / 1000; + let scaleRatio: number = 0; + let isZoomIn: boolean = false; + + const [firstEvent, secondEvent] = eventCache; + + // Calculate the distance between the two pointers + const curDiff = Math.hypot( + firstEvent.pageX - secondEvent.pageX, + firstEvent.pageY - secondEvent.pageY, + ); + + const hasMoved = prevDiff > 0; + + if (hasMoved && curDiff > prevDiff) { + // The distance between the two pointers has increased + scaleRatio = 1 + scaledStep; + isZoomIn = true; + } + if (hasMoved && curDiff < prevDiff) { + // The distance between the two pointers has decreased + scaleRatio = 1 - scaledStep; + isZoomIn = false; + } + + return { scaleRatio, isZoomIn, curDiff, firstEvent }; +} + +/** + * Get the ratio of the point in the horizontal center of the area. + */ +function getHorizontalCenterRatio( + point: { x: number; y: number }, + area: { left: number; width: number }, +) { + const { left, width } = area; + return (point.x - left) / width; +} + +function preventDefault(event: TouchEvent) { + event.preventDefault(); +} diff --git a/packages/x-charts-pro/src/context/ZoomProvider/useZoom.ts b/packages/x-charts-pro/src/context/ZoomProvider/useZoom.ts new file mode 100644 index 000000000000..59bda96ca395 --- /dev/null +++ b/packages/x-charts-pro/src/context/ZoomProvider/useZoom.ts @@ -0,0 +1,7 @@ +import * as React from 'react'; +import { ZoomContext } from './ZoomContext'; + +export const useZoom = () => { + const { data } = React.useContext(ZoomContext); + return data; +}; diff --git a/packages/x-charts-pro/src/hooks/index.ts b/packages/x-charts-pro/src/hooks/index.ts new file mode 100644 index 000000000000..efe4654a2e1f --- /dev/null +++ b/packages/x-charts-pro/src/hooks/index.ts @@ -0,0 +1 @@ +export { useHeatmapSeries as unstable_useHeatmapSeries } from './useSeries'; diff --git a/packages/x-charts-pro/src/hooks/useSeries.ts b/packages/x-charts-pro/src/hooks/useSeries.ts new file mode 100644 index 000000000000..81ff3ebc30cb --- /dev/null +++ b/packages/x-charts-pro/src/hooks/useSeries.ts @@ -0,0 +1,15 @@ +import * as React from 'react'; +import { useSeries } from '@mui/x-charts/internals'; + +/** + * Get access to the internal state of heatmap series. + * The returned object contains: + * - series: a mapping from ids to series attributes. + * - seriesOrder: the array of series ids. + * @returns { series: Record; seriesOrder: SeriesId[]; } | undefined heatmapSeries + */ +export function useHeatmapSeries() { + const series = useSeries(); + + return React.useMemo(() => series.heatmap, [series.heatmap]); +} diff --git a/packages/x-charts-pro/src/index.ts b/packages/x-charts-pro/src/index.ts index 63807ba5f1f2..eade0525b940 100644 --- a/packages/x-charts-pro/src/index.ts +++ b/packages/x-charts-pro/src/index.ts @@ -1,3 +1,6 @@ +import {} from './typeOverloads/modules'; + +// exports from MIT package export * from '@mui/x-charts/constants'; export * from '@mui/x-charts/context'; export * from '@mui/x-charts/hooks'; @@ -23,8 +26,10 @@ export * from '@mui/x-charts/SparkLineChart'; export * from '@mui/x-charts/Gauge'; export * from '@mui/x-charts/ChartsSurface'; +// Pro components +export * from './Heatmap'; export * from './ResponsiveChartContainerPro'; +export * from './ChartContainerPro'; export * from './ScatterChartPro'; export * from './BarChartPro'; export * from './LineChartPro'; -export * from './ChartContainerPro'; diff --git a/packages/x-charts-pro/src/models/index.ts b/packages/x-charts-pro/src/models/index.ts new file mode 100644 index 000000000000..d06c5e1be13a --- /dev/null +++ b/packages/x-charts-pro/src/models/index.ts @@ -0,0 +1 @@ +export * from './seriesType'; diff --git a/packages/x-charts-pro/src/models/seriesType/heatmap.ts b/packages/x-charts-pro/src/models/seriesType/heatmap.ts new file mode 100644 index 000000000000..9444f4af60a2 --- /dev/null +++ b/packages/x-charts-pro/src/models/seriesType/heatmap.ts @@ -0,0 +1,39 @@ +import { + DefaultizedProps, + CommonDefaultizedProps, + CommonSeriesType, + CartesianSeriesType, +} from '@mui/x-charts/internals'; + +export type HeatmapValueType = [number, number, number]; + +export interface HeatmapSeriesType + extends Omit, 'color'>, + CartesianSeriesType { + type: 'heatmap'; + /** + * Data associated to each bar. + */ + data?: HeatmapValueType[]; + /** + * The key used to retrieve data from the dataset. + */ + dataKey?: string; + /** + * The label to display on the tooltip or the legend. It can be a string or a function. + */ + label?: string | ((location: 'tooltip' | 'legend') => string); +} + +/** + * An object that allows to identify a single bar. + * Used for item interaction + */ +export type HeatmapItemIdentifier = { + type: 'heatmap'; + seriesId: DefaultizedHeatmapSeriesType['id']; + dataIndex: number; +}; + +export interface DefaultizedHeatmapSeriesType + extends DefaultizedProps {} diff --git a/packages/x-charts-pro/src/models/seriesType/index.ts b/packages/x-charts-pro/src/models/seriesType/index.ts new file mode 100644 index 000000000000..8b355086c208 --- /dev/null +++ b/packages/x-charts-pro/src/models/seriesType/index.ts @@ -0,0 +1 @@ +export * from './heatmap'; diff --git a/packages/x-charts-pro/src/typeOverloads/index.ts b/packages/x-charts-pro/src/typeOverloads/index.ts new file mode 100644 index 000000000000..4f6953ed9a94 --- /dev/null +++ b/packages/x-charts-pro/src/typeOverloads/index.ts @@ -0,0 +1 @@ +export {} from './modules'; diff --git a/packages/x-charts-pro/src/typeOverloads/modules.ts b/packages/x-charts-pro/src/typeOverloads/modules.ts new file mode 100644 index 000000000000..f9a2db62ac1a --- /dev/null +++ b/packages/x-charts-pro/src/typeOverloads/modules.ts @@ -0,0 +1,18 @@ +import { DefaultizedProps } from '@mui/x-charts/internals'; +import { + HeatmapItemIdentifier, + HeatmapSeriesType, + DefaultizedHeatmapSeriesType, +} from '../models/seriesType/heatmap'; + +declare module '@mui/x-charts/internals' { + interface ChartsSeriesConfig { + heatmap: { + seriesInput: DefaultizedProps; + series: DefaultizedHeatmapSeriesType; + seriesProp: HeatmapSeriesType; + itemIdentifier: HeatmapItemIdentifier; + cartesian: true; + }; + } +} diff --git a/packages/x-charts/package.json b/packages/x-charts/package.json index 3630e0d32fe4..49e3b1339945 100644 --- a/packages/x-charts/package.json +++ b/packages/x-charts/package.json @@ -1,6 +1,6 @@ { "name": "@mui/x-charts", - "version": "7.7.1", + "version": "7.9.0", "description": "The community edition of the Charts components (MUI X).", "author": "MUI Team", "main": "./src/index.js", @@ -41,8 +41,8 @@ "dependencies": { "@babel/runtime": "^7.24.7", "@mui/base": "^5.0.0-beta.40", - "@mui/system": "^5.15.20", - "@mui/utils": "^5.15.20", + "@mui/system": "^5.16.0", + "@mui/utils": "^5.16.0", "@react-spring/rafz": "^9.7.3", "@react-spring/web": "^9.7.3", "clsx": "^2.1.1", @@ -69,7 +69,7 @@ } }, "devDependencies": { - "@mui/internal-test-utils": "^1.0.1", + "@mui/internal-test-utils": "^1.0.4", "@react-spring/core": "^9.7.3", "@react-spring/shared": "^9.7.3", "@types/d3-color": "^3.1.3", @@ -79,7 +79,7 @@ "@types/d3-shape": "^3.1.6", "@types/prop-types": "^15.7.12", "csstype": "^3.1.3", - "rimraf": "^5.0.7" + "rimraf": "^5.0.8" }, "exports": { ".": { diff --git a/packages/x-charts/src/BarChart/BarChart.tsx b/packages/x-charts/src/BarChart/BarChart.tsx index 9cafc9ab03e1..1a07d17ba047 100644 --- a/packages/x-charts/src/BarChart/BarChart.tsx +++ b/packages/x-charts/src/BarChart/BarChart.tsx @@ -40,13 +40,13 @@ export interface BarChartSlots extends ChartsAxisSlots, BarPlotSlots, ChartsLegendSlots, - ChartsTooltipSlots, + ChartsTooltipSlots<'bar'>, ChartsOverlaySlots {} export interface BarChartSlotProps extends ChartsAxisSlotProps, BarPlotSlotProps, ChartsLegendSlotProps, - ChartsTooltipSlotProps, + ChartsTooltipSlotProps<'bar'>, ChartsOverlaySlotProps {} export interface BarChartProps @@ -64,7 +64,7 @@ export interface BarChartProps * The configuration of the tooltip. * @see See {@link https://mui.com/x/react-charts/tooltip/ tooltip docs} for more details. */ - tooltip?: ChartsTooltipProps; + tooltip?: ChartsTooltipProps<'bar'>; /** * Option to display a cartesian grid in the background. */ diff --git a/packages/x-charts/src/BarChart/useBarChartProps.ts b/packages/x-charts/src/BarChart/useBarChartProps.ts index b8c9e00ceea9..4370f5d67389 100644 --- a/packages/x-charts/src/BarChart/useBarChartProps.ts +++ b/packages/x-charts/src/BarChart/useBarChartProps.ts @@ -1,6 +1,16 @@ import useId from '@mui/utils/useId'; import type { BarChartProps } from './BarChart'; import { DEFAULT_X_AXIS_KEY, DEFAULT_Y_AXIS_KEY } from '../constants'; +import { ResponsiveChartContainerProps } from '../ResponsiveChartContainer'; +import { BarPlotProps } from './BarPlot'; +import { ChartsOnAxisClickHandlerProps } from '../ChartsOnAxisClickHandler'; +import { ChartsGridProps } from '../ChartsGrid'; +import { ChartsClipPathProps } from '../ChartsClipPath'; +import { ChartsOverlayProps } from '../ChartsOverlay'; +import { ChartsAxisProps } from '../ChartsAxis'; +import { ChartsAxisHighlightProps } from '../ChartsAxisHighlight'; +import { ChartsLegendProps } from '../ChartsLegend'; +import { ChartsTooltipProps } from '../ChartsTooltip'; /** * A helper function that extracts BarChartProps from the input props @@ -57,7 +67,7 @@ export const useBarChartProps = (props: BarChartProps) => { ), } as const; - const chartContainerProps = { + const chartContainerProps: ResponsiveChartContainerProps = { series: series.map((s) => ({ type: 'bar' as const, ...s, @@ -84,7 +94,7 @@ export const useBarChartProps = (props: BarChartProps) => { !onAxisClick, }; - const barPlotProps = { + const barPlotProps: BarPlotProps = { onItemClick, slots, slotProps, @@ -93,11 +103,11 @@ export const useBarChartProps = (props: BarChartProps) => { barLabel, }; - const axisClickHandlerProps = { + const axisClickHandlerProps: ChartsOnAxisClickHandlerProps = { onAxisClick, }; - const gridProps = { + const gridProps: ChartsGridProps = { vertical: grid?.vertical, horizontal: grid?.horizontal, }; @@ -106,17 +116,17 @@ export const useBarChartProps = (props: BarChartProps) => { clipPath: `url(#${clipPathId})`, }; - const clipPathProps = { + const clipPathProps: ChartsClipPathProps = { id: clipPathId, }; - const overlayProps = { + const overlayProps: ChartsOverlayProps = { slots, slotProps, loading, }; - const chartsAxisProps = { + const chartsAxisProps: ChartsAxisProps = { topAxis, leftAxis, rightAxis, @@ -125,18 +135,18 @@ export const useBarChartProps = (props: BarChartProps) => { slotProps, }; - const axisHighlightProps = { + const axisHighlightProps: ChartsAxisHighlightProps = { ...(hasHorizontalSeries ? ({ y: 'band' } as const) : ({ x: 'band' } as const)), ...axisHighlight, }; - const legendProps = { + const legendProps: ChartsLegendProps = { ...legend, slots, slotProps, }; - const tooltipProps = { + const tooltipProps: ChartsTooltipProps<'bar'> = { ...tooltip, slots, slotProps, diff --git a/packages/x-charts/src/ChartContainer/ChartContainer.tsx b/packages/x-charts/src/ChartContainer/ChartContainer.tsx index fb4431c77881..1305694424e5 100644 --- a/packages/x-charts/src/ChartContainer/ChartContainer.tsx +++ b/packages/x-charts/src/ChartContainer/ChartContainer.tsx @@ -369,6 +369,8 @@ ChartContainer.propTypes = { data: PropTypes.array, dataKey: PropTypes.string, id: PropTypes.string, + max: PropTypes.number, + min: PropTypes.number, }), ), } as any; diff --git a/packages/x-charts/src/ChartsAxisHighlight/ChartsAxisHighlight.tsx b/packages/x-charts/src/ChartsAxisHighlight/ChartsAxisHighlight.tsx index 6485c9c3f4d6..38f77bcc6b36 100644 --- a/packages/x-charts/src/ChartsAxisHighlight/ChartsAxisHighlight.tsx +++ b/packages/x-charts/src/ChartsAxisHighlight/ChartsAxisHighlight.tsx @@ -80,11 +80,34 @@ function ChartsAxisHighlight(props: ChartsAxisHighlightProps) { const getXPosition = getValueToPositionMapper(xScale); const getYPosition = getValueToPositionMapper(yScale); + + const axisX = axis.x; + const axisY = axis.y; + + const isBandScaleX = xAxisHighlight === 'band' && axisX !== null && isBandScale(xScale); + const isBandScaleY = yAxisHighlight === 'band' && axisY !== null && isBandScale(yScale); + + if (process.env.NODE_ENV !== 'production') { + const isXError = isBandScaleX && xScale(axisX.value) === undefined; + const isYError = isBandScaleY && yScale(axisY.value) === undefined; + + if (isXError || isYError) { + console.error( + [ + `MUI X Charts: The position value provided for the axis is not valid for the current scale.`, + `This probably means something is wrong with the data passed to the chart.`, + `The ChartsAxisHighlight component will not be displayed.`, + ].join('\n'), + ); + } + } + return ( - {xAxisHighlight === 'band' && axis.x !== null && isBandScale(xScale) && ( + {isBandScaleX && xScale(axisX.value) !== undefined && ( )} - {yAxisHighlight === 'band' && axis.y !== null && isBandScale(yScale) && ( + {isBandScaleY && yScale(axisY.value) !== undefined && ( ({})); +})(() => ({ + // This prevents default touch actions when using the svg on mobile devices. + // For example, prevent page scroll & zoom. + touchAction: 'none', +})); const ChartsSurface = React.forwardRef(function ChartsSurface( props: ChartsSurfaceProps, diff --git a/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx b/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx index e4e9487f7ab7..4784d5559bf7 100644 --- a/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx +++ b/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import PropTypes from 'prop-types'; import { SxProps, Theme } from '@mui/material/styles'; import { useSlotProps } from '@mui/base/utils'; import { AxisInteractionData } from '../context/InteractionProvider'; @@ -45,6 +44,9 @@ export type ChartsAxisContentProps = { sx?: SxProps; }; +/** + * @ignore - internal component. + */ function ChartsAxisTooltipContent(props: { axisData: AxisInteractionData; content?: React.ElementType; @@ -128,58 +130,4 @@ function ChartsAxisTooltipContent(props: { return ; } -ChartsAxisTooltipContent.propTypes = { - // ----------------------------- Warning -------------------------------- - // | These PropTypes are generated from the TypeScript type definitions | - // | To update them edit the TypeScript types and run "pnpm proptypes" | - // ---------------------------------------------------------------------- - axisData: PropTypes.shape({ - x: PropTypes.shape({ - index: PropTypes.number, - value: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - }), - y: PropTypes.shape({ - index: PropTypes.number, - value: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - }), - }).isRequired, - classes: PropTypes.object.isRequired, - content: PropTypes.elementType, - contentProps: PropTypes.shape({ - axis: PropTypes.object, - axisData: PropTypes.shape({ - x: PropTypes.shape({ - index: PropTypes.number, - value: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - }), - y: PropTypes.shape({ - index: PropTypes.number, - value: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - }), - }), - axisValue: PropTypes.oneOfType([ - PropTypes.instanceOf(Date), - PropTypes.number, - PropTypes.string, - ]), - classes: PropTypes.object, - dataIndex: PropTypes.number, - series: PropTypes.arrayOf(PropTypes.object), - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), - }), - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), -} as any; - export { ChartsAxisTooltipContent }; diff --git a/packages/x-charts/src/ChartsTooltip/ChartsItemTooltipContent.tsx b/packages/x-charts/src/ChartsTooltip/ChartsItemTooltipContent.tsx index f4356bbcfc1a..099921b4bf33 100644 --- a/packages/x-charts/src/ChartsTooltip/ChartsItemTooltipContent.tsx +++ b/packages/x-charts/src/ChartsTooltip/ChartsItemTooltipContent.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import PropTypes from 'prop-types'; import { SxProps, Theme } from '@mui/material/styles'; import { useSlotProps } from '@mui/base/utils'; import { ItemInteractionData } from '../context/InteractionProvider'; @@ -11,7 +10,7 @@ import { ZAxisContext } from '../context/ZAxisContextProvider'; import { useColorProcessor } from '../hooks/useColor'; import { useSeries } from '../hooks/useSeries'; -export type ChartsItemContentProps = { +export interface ChartsItemContentProps { /** * The data used to identify the triggered item. */ @@ -31,15 +30,22 @@ export type ChartsItemContentProps */ getColor: (dataIndex: number) => string; sx?: SxProps; -}; +} -function ChartsItemTooltipContent(props: { +export interface ChartsItemTooltipContentProps { itemData: ItemInteractionData; content?: React.ElementType>; contentProps?: Partial>; sx?: SxProps; classes: ChartsItemContentProps['classes']; -}) { +} + +/** + * @ignore - internal component. + */ +function ChartsItemTooltipContent( + props: ChartsItemTooltipContentProps, +) { const { content, itemData, sx, classes, contentProps } = props; const series = useSeries()[itemData.type]!.series[itemData.seriesId] as ChartSeriesDefaultized; @@ -76,38 +82,4 @@ function ChartsItemTooltipContent(props: { return ; } -ChartsItemTooltipContent.propTypes = { - // ----------------------------- Warning -------------------------------- - // | These PropTypes are generated from the TypeScript type definitions | - // | To update them edit the TypeScript types and run "pnpm proptypes" | - // ---------------------------------------------------------------------- - classes: PropTypes.object.isRequired, - content: PropTypes.elementType, - contentProps: PropTypes.shape({ - classes: PropTypes.object, - getColor: PropTypes.func, - itemData: PropTypes.shape({ - dataIndex: PropTypes.number, - seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - type: PropTypes.oneOf(['bar', 'line', 'pie', 'scatter']).isRequired, - }), - series: PropTypes.object, - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), - }), - itemData: PropTypes.shape({ - dataIndex: PropTypes.number, - seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - type: PropTypes.oneOf(['bar', 'line', 'pie', 'scatter']).isRequired, - }).isRequired, - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), -} as any; - export { ChartsItemTooltipContent }; diff --git a/packages/x-charts/src/ChartsTooltip/ChartsTooltip.tsx b/packages/x-charts/src/ChartsTooltip/ChartsTooltip.tsx index 1b321df5522d..5f2d8fb96b2e 100644 --- a/packages/x-charts/src/ChartsTooltip/ChartsTooltip.tsx +++ b/packages/x-charts/src/ChartsTooltip/ChartsTooltip.tsx @@ -28,7 +28,7 @@ export type PopperProps = BasePopperProps & { sx?: SxProps; }; -export interface ChartsTooltipSlots { +export interface ChartsTooltipSlots { /** * Custom component for the tooltip popper. * @default ChartsTooltipRoot @@ -43,16 +43,16 @@ export interface ChartsTooltipSlots { * Custom component for displaying tooltip content when triggered by item event. * @default DefaultChartsItemTooltipContent */ - itemContent?: React.ElementType; + itemContent?: React.ElementType>; } -export interface ChartsTooltipSlotProps { +export interface ChartsTooltipSlotProps { popper?: Partial; axisContent?: Partial; - itemContent?: Partial; + itemContent?: Partial>; } -export type ChartsTooltipProps = { +export interface ChartsTooltipProps { /** * Select the kind of tooltip to display * - 'item': Shows data about the item below the mouse. @@ -79,15 +79,17 @@ export type ChartsTooltipProps = { * Overridable component slots. * @default {} */ - slots?: ChartsTooltipSlots; + slots?: ChartsTooltipSlots; /** * The props used for each component slot. * @default {} */ - slotProps?: ChartsTooltipSlotProps; -}; + slotProps?: ChartsTooltipSlotProps; +} -const useUtilityClasses = (ownerState: { classes: ChartsTooltipProps['classes'] }) => { +const useUtilityClasses = (ownerState: { + classes: ChartsTooltipProps['classes']; +}) => { const { classes } = ownerState; const slots = { @@ -122,7 +124,7 @@ const ChartsTooltipRoot = styled(Popper, { * * - [ChartsTooltip API](https://mui.com/x/api/charts/charts-tool-tip/) */ -function ChartsTooltip(props: ChartsTooltipProps) { +function ChartsTooltip(props: ChartsTooltipProps) { const themeProps = useThemeProps({ props, name: 'MuiChartsTooltip', @@ -146,8 +148,17 @@ function ChartsTooltip(props: ChartsTooltipProps) { externalSlotProps: slotProps?.popper, additionalProps: { open: popperOpen, - placement: 'right-start' as const, + placement: + mousePosition?.pointerType === 'mouse' ? ('right-start' as const) : ('top' as const), anchorEl: generateVirtualElement(mousePosition), + modifiers: [ + { + name: 'offset', + options: { + offset: [0, mousePosition?.pointerType === 'touch' ? 40 - mousePosition.height : 0], + }, + }, + ], }, ownerState: {}, }); @@ -162,9 +173,9 @@ function ChartsTooltip(props: ChartsTooltipProps) { {trigger === 'item' ? ( } - content={slots?.itemContent ?? itemContent} - contentProps={slotProps?.itemContent} + itemData={displayedData as ItemInteractionData} + content={(slots?.itemContent ?? itemContent) as any} + contentProps={slotProps?.itemContent as Partial>} sx={{ mx: 2 }} classes={classes} /> diff --git a/packages/x-charts/src/ChartsTooltip/ChartsTooltipTable.ts b/packages/x-charts/src/ChartsTooltip/ChartsTooltipTable.ts index 1e1073914c63..a83a70ae9e5b 100644 --- a/packages/x-charts/src/ChartsTooltip/ChartsTooltipTable.ts +++ b/packages/x-charts/src/ChartsTooltip/ChartsTooltipTable.ts @@ -2,6 +2,9 @@ import { styled } from '@mui/material/styles'; import { shouldForwardProp } from '@mui/system'; import { chartsTooltipClasses } from './chartsTooltipClasses'; +/** + * @ignore - internal component. + */ export const ChartsTooltipPaper = styled('div', { name: 'MuiChartsTooltip', slot: 'Container', @@ -13,6 +16,9 @@ export const ChartsTooltipPaper = styled('div', { borderRadius: theme.shape.borderRadius, })); +/** + * @ignore - internal component. + */ export const ChartsTooltipTable = styled('table', { name: 'MuiChartsTooltip', slot: 'Table', @@ -23,6 +29,9 @@ export const ChartsTooltipTable = styled('table', { }, })); +/** + * @ignore - internal component. + */ export const ChartsTooltipRow = styled('tr', { name: 'MuiChartsTooltip', slot: 'Row', @@ -35,6 +44,9 @@ export const ChartsTooltipRow = styled('tr', { }, })); +/** + * @ignore - internal component. + */ export const ChartsTooltipCell = styled('td', { name: 'MuiChartsTooltip', slot: 'Cell', @@ -56,6 +68,9 @@ export const ChartsTooltipCell = styled('td', { }, })); +/** + * @ignore - internal component. + */ export const ChartsTooltipMark = styled('div', { name: 'MuiChartsTooltip', slot: 'Mark', diff --git a/packages/x-charts/src/ChartsTooltip/index.ts b/packages/x-charts/src/ChartsTooltip/index.ts index f1ec9209697d..dc13976d1d75 100644 --- a/packages/x-charts/src/ChartsTooltip/index.ts +++ b/packages/x-charts/src/ChartsTooltip/index.ts @@ -6,3 +6,5 @@ export * from './ChartsItemTooltipContent'; export * from './DefaultChartsAxisTooltipContent'; export * from './DefaultChartsItemTooltipContent'; + +export * from './ChartsTooltipTable'; diff --git a/packages/x-charts/src/ChartsTooltip/utils.tsx b/packages/x-charts/src/ChartsTooltip/utils.tsx index 95e2d849abbb..8a7ad4a359a9 100644 --- a/packages/x-charts/src/ChartsTooltip/utils.tsx +++ b/packages/x-charts/src/ChartsTooltip/utils.tsx @@ -3,7 +3,14 @@ import { AxisInteractionData, ItemInteractionData } from '../context/Interaction import { ChartSeriesType } from '../models/seriesType/config'; import { useSvgRef } from '../hooks'; -export function generateVirtualElement(mousePosition: { x: number; y: number } | null) { +type MousePosition = { + x: number; + y: number; + pointerType: 'mouse' | 'touch' | 'pen'; + height: number; +}; + +export function generateVirtualElement(mousePosition: MousePosition | null) { if (mousePosition === null) { return { getBoundingClientRect: () => ({ @@ -20,18 +27,20 @@ export function generateVirtualElement(mousePosition: { x: number; y: number } | }; } const { x, y } = mousePosition; + const boundingBox = { + width: 0, + height: 0, + x, + y, + top: y, + right: x, + bottom: y, + left: x, + }; return { getBoundingClientRect: () => ({ - width: 0, - height: 0, - x, - y, - top: y, - right: x, - bottom: y, - left: x, - toJSON: () => - JSON.stringify({ width: 0, height: 0, x, y, top: y, right: x, bottom: y, left: x }), + ...boundingBox, + toJSON: () => JSON.stringify(boundingBox), }), }; } @@ -40,7 +49,7 @@ export function useMouseTracker() { const svgRef = useSvgRef(); // Use a ref to avoid rerendering on every mousemove event. - const [mousePosition, setMousePosition] = React.useState(null); + const [mousePosition, setMousePosition] = React.useState(null); React.useEffect(() => { const element = svgRef.current; @@ -52,23 +61,23 @@ export function useMouseTracker() { setMousePosition(null); }; - const handleMove = (event: MouseEvent | TouchEvent) => { - const target = 'targetTouches' in event ? event.targetTouches[0] : event; + const handleMove = (event: PointerEvent) => { setMousePosition({ - x: target.clientX, - y: target.clientY, + x: event.clientX, + y: event.clientY, + height: event.height, + pointerType: event.pointerType as MousePosition['pointerType'], }); }; - element.addEventListener('mouseout', handleOut); - element.addEventListener('mousemove', handleMove); - element.addEventListener('touchend', handleOut); - element.addEventListener('touchmove', handleMove); + element.addEventListener('pointerdown', handleMove); + element.addEventListener('pointermove', handleMove); + element.addEventListener('pointerup', handleOut); + return () => { - element.removeEventListener('mouseout', handleOut); - element.removeEventListener('mousemove', handleMove); - element.addEventListener('touchend', handleOut); - element.addEventListener('touchmove', handleMove); + element.removeEventListener('pointerdown', handleMove); + element.removeEventListener('pointermove', handleMove); + element.removeEventListener('pointerup', handleOut); }; }, [svgRef]); diff --git a/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx b/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx index d9812c0b3baa..da1cba1cdac4 100644 --- a/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx +++ b/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx @@ -5,7 +5,7 @@ import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; import { InteractionContext } from '../context/InteractionProvider'; import { useCartesianContext } from '../context/CartesianProvider'; import { getValueToPositionMapper } from '../hooks/useScale'; -import { getSVGPoint } from '../internals/utils'; +import { getSVGPoint } from '../internals/getSVGPoint'; import { ScatterItemIdentifier } from '../models'; import { SeriesId } from '../models/seriesType/common'; import { useDrawingArea, useSvgRef } from '../hooks'; @@ -97,7 +97,7 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) { | 'outside-voronoi-max-radius' | 'no-point-found' { // Get mouse coordinate in global SVG space - const svgPoint = getSVGPoint(svgRef.current!, event); + const svgPoint = getSVGPoint(element, event); const outsideX = svgPoint.x < left || svgPoint.x > left + width; const outsideY = svgPoint.y < top || svgPoint.y > top + height; @@ -180,12 +180,12 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) { onItemClick(event, { type: 'scatter', seriesId, dataIndex }); }; - element.addEventListener('mouseout', handleMouseOut); - element.addEventListener('mousemove', handleMouseMove); + element.addEventListener('pointerout', handleMouseOut); + element.addEventListener('pointermove', handleMouseMove); element.addEventListener('click', handleMouseClick); return () => { - element.removeEventListener('mouseout', handleMouseOut); - element.removeEventListener('mousemove', handleMouseMove); + element.removeEventListener('pointerout', handleMouseOut); + element.removeEventListener('pointermove', handleMouseMove); element.removeEventListener('click', handleMouseClick); }; }, [ diff --git a/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx b/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx index ea796b2e333e..247a7ba5a7de 100644 --- a/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx +++ b/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx @@ -205,38 +205,39 @@ function ChartsXAxis(inProps: ChartsXAxisProps) { className={classes.root} > {!disableLine && ( - + )} - {xTicksWithDimension.map(({ formattedValue, offset, labelOffset, skipLabel }, index) => { - const xTickLabel = labelOffset ?? 0; - const yTickLabel = positionSign * (tickSize + 3); - return ( - - {!disableTicks && ( - - )} + {xTicksWithDimension + .filter((tick) => tick.offset >= left - 1 && tick.offset <= left + width + 1) + .map(({ formattedValue, offset, labelOffset, skipLabel }, index) => { + const xTickLabel = labelOffset ?? 0; + const yTickLabel = positionSign * (tickSize + 3); - {formattedValue !== undefined && !skipLabel && ( - - )} - - ); - })} + const showTick = offset >= left - 1 && offset <= left + width + 1; + const showTickLabel = + offset + xTickLabel >= left - 1 && offset + xTickLabel <= left + width + 1; + return ( + + {!disableTicks && showTick && ( + + )} + + {formattedValue !== undefined && !skipLabel && showTickLabel && ( + + )} + + ); + })} {label && ( diff --git a/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx b/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx index 44475ad90f1f..b26587275373 100644 --- a/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx +++ b/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx @@ -74,6 +74,8 @@ function ChartsYAxis(inProps: ChartsYAxisProps) { } = defaultizedProps; const theme = useTheme(); + const isRTL = theme.direction === 'rtl'; + const classes = useUtilityClasses({ ...defaultizedProps, theme }); const { left, top, width, height } = useDrawingArea(); @@ -101,13 +103,14 @@ function ChartsYAxis(inProps: ChartsYAxisProps) { const TickLabel = slots?.axisTickLabel ?? ChartsText; const Label = slots?.axisLabel ?? ChartsText; + const revertAnchor = (!isRTL && position === 'right') || (isRTL && position !== 'right'); const axisTickLabelProps = useSlotProps({ elementType: TickLabel, externalSlotProps: slotProps?.axisTickLabel, additionalProps: { style: { fontSize: tickFontSize, - textAnchor: position === 'right' ? 'start' : 'end', + textAnchor: revertAnchor ? 'start' : 'end', dominantBaseline: 'central', ...tickLabelStyle, }, diff --git a/packages/x-charts/src/LineChart/LineChart.tsx b/packages/x-charts/src/LineChart/LineChart.tsx index 3a865af2044c..fbce1924fe3c 100644 --- a/packages/x-charts/src/LineChart/LineChart.tsx +++ b/packages/x-charts/src/LineChart/LineChart.tsx @@ -50,7 +50,7 @@ export interface LineChartSlots MarkPlotSlots, LineHighlightPlotSlots, ChartsLegendSlots, - ChartsTooltipSlots, + ChartsTooltipSlots<'line'>, ChartsOverlaySlots {} export interface LineChartSlotProps extends ChartsAxisSlotProps, @@ -59,7 +59,7 @@ export interface LineChartSlotProps MarkPlotSlotProps, LineHighlightPlotSlotProps, ChartsLegendSlotProps, - ChartsTooltipSlotProps, + ChartsTooltipSlotProps<'line'>, ChartsOverlaySlotProps {} export interface LineChartProps @@ -77,7 +77,7 @@ export interface LineChartProps * @see See {@link https://mui.com/x/react-charts/tooltip/ tooltip docs} for more details. * @default { trigger: 'item' } */ - tooltip?: ChartsTooltipProps; + tooltip?: ChartsTooltipProps<'line'>; /** * Option to display a cartesian grid in the background. */ diff --git a/packages/x-charts/src/LineChart/MarkPlot.tsx b/packages/x-charts/src/LineChart/MarkPlot.tsx index ceecfbb0b6f7..7498c3f3eb4f 100644 --- a/packages/x-charts/src/LineChart/MarkPlot.tsx +++ b/packages/x-charts/src/LineChart/MarkPlot.tsx @@ -9,6 +9,7 @@ import { LineItemIdentifier } from '../models/seriesType/line'; import { cleanId } from '../internals/utils'; import getColor from './getColor'; import { useLineSeries } from '../hooks/useSeries'; +import { useDrawingArea } from '../hooks/useDrawingArea'; export interface MarkPlotSlots { mark?: React.JSXElementConstructor; @@ -58,6 +59,7 @@ function MarkPlot(props: MarkPlotProps) { const seriesData = useLineSeries(); const axisData = useCartesianContext(); const chartId = useChartId(); + const { left, width } = useDrawingArea(); const Mark = slots?.mark ?? MarkElement; @@ -89,11 +91,10 @@ function MarkPlot(props: MarkPlotProps) { const yScale = yAxis[yAxisKey].scale; const xData = xAxis[xAxisKey].data; - const xRange = xAxis[xAxisKey].scale.range(); const yRange = yScale.range(); const isInRange = ({ x, y }: { x: number; y: number }) => { - if (x < Math.min(...xRange) || x > Math.max(...xRange)) { + if (x < left || x > left + width) { return false; } if (y < Math.min(...yRange) || y > Math.max(...yRange)) { diff --git a/packages/x-charts/src/LineChart/useLineChartProps.ts b/packages/x-charts/src/LineChart/useLineChartProps.ts index 226061be2a17..47bbcbc7bd42 100644 --- a/packages/x-charts/src/LineChart/useLineChartProps.ts +++ b/packages/x-charts/src/LineChart/useLineChartProps.ts @@ -1,6 +1,19 @@ import useId from '@mui/utils/useId'; import { DEFAULT_X_AXIS_KEY } from '../constants'; import type { LineChartProps } from './LineChart'; +import { ResponsiveChartContainerProps } from '../ResponsiveChartContainer'; +import { ChartsOnAxisClickHandlerProps } from '../ChartsOnAxisClickHandler'; +import { ChartsGridProps } from '../ChartsGrid'; +import { ChartsClipPathProps } from '../ChartsClipPath'; +import { AreaPlotProps } from './AreaPlot'; +import { LinePlotProps } from './LinePlot'; +import { MarkPlotProps } from './MarkPlot'; +import { ChartsOverlayProps } from '../ChartsOverlay'; +import { ChartsAxisProps } from '../ChartsAxis'; +import { ChartsAxisHighlightProps } from '../ChartsAxisHighlight'; +import { LineHighlightPlotProps } from './LineHighlightPlot'; +import { ChartsLegendProps } from '../ChartsLegend'; +import { ChartsTooltipProps } from '../ChartsTooltip'; /** * A helper function that extracts LineChartProps from the input props @@ -45,7 +58,7 @@ export const useLineChartProps = (props: LineChartProps) => { const id = useId(); const clipPathId = `${id}-clip-path`; - const chartContainerProps = { + const chartContainerProps: ResponsiveChartContainerProps = { series: series.map((s) => ({ disableHighlight: !!disableLineItemHighlight, type: 'line' as const, @@ -77,11 +90,11 @@ export const useLineChartProps = (props: LineChartProps) => { !onAxisClick, }; - const axisClickHandlerProps = { + const axisClickHandlerProps: ChartsOnAxisClickHandlerProps = { onAxisClick, }; - const gridProps = { + const gridProps: ChartsGridProps = { vertical: grid?.vertical, horizontal: grid?.horizontal, }; @@ -90,38 +103,38 @@ export const useLineChartProps = (props: LineChartProps) => { clipPath: `url(#${clipPathId})`, }; - const clipPathProps = { + const clipPathProps: ChartsClipPathProps = { id: clipPathId, }; - const areaPlotProps = { + const areaPlotProps: AreaPlotProps = { slots, slotProps, - onAreaClick, + onItemClick: onAreaClick, skipAnimation, }; - const linePlotProps = { + const linePlotProps: LinePlotProps = { slots, slotProps, - onLineClick, + onItemClick: onLineClick, skipAnimation, }; - const markPlotProps = { + const markPlotProps: MarkPlotProps = { slots, slotProps, - onMarkClick, + onItemClick: onMarkClick, skipAnimation, }; - const overlayProps = { + const overlayProps: ChartsOverlayProps = { slots, slotProps, loading, }; - const chartsAxisProps = { + const chartsAxisProps: ChartsAxisProps = { topAxis, leftAxis, rightAxis, @@ -130,23 +143,23 @@ export const useLineChartProps = (props: LineChartProps) => { slotProps, }; - const axisHighlightProps = { + const axisHighlightProps: ChartsAxisHighlightProps = { x: 'line' as const, ...axisHighlight, }; - const lineHighlightPlotProps = { + const lineHighlightPlotProps: LineHighlightPlotProps = { slots, slotProps, }; - const legendProps = { + const legendProps: ChartsLegendProps = { ...legend, slots, slotProps, }; - const tooltipProps = { + const tooltipProps: ChartsTooltipProps<'line'> = { ...tooltip, slots, slotProps, diff --git a/packages/x-charts/src/PieChart/PieChart.tsx b/packages/x-charts/src/PieChart/PieChart.tsx index bf00ee9effaa..856052afdc28 100644 --- a/packages/x-charts/src/PieChart/PieChart.tsx +++ b/packages/x-charts/src/PieChart/PieChart.tsx @@ -41,14 +41,14 @@ export interface PieChartSlots extends ChartsAxisSlots, PiePlotSlots, ChartsLegendSlots, - ChartsTooltipSlots, + ChartsTooltipSlots<'pie'>, ChartsOverlaySlots {} export interface PieChartSlotProps extends ChartsAxisSlotProps, PiePlotSlotProps, ChartsLegendSlotProps, - ChartsTooltipSlotProps, + ChartsTooltipSlotProps<'pie'>, ChartsOverlaySlotProps {} export interface PieChartProps @@ -81,7 +81,7 @@ export interface PieChartProps * @see See {@link https://mui.com/x/react-charts/tooltip/ tooltip docs} for more details. * @default { trigger: 'item' } */ - tooltip?: ChartsTooltipProps; + tooltip?: ChartsTooltipProps<'pie'>; /** * The configuration of axes highlight. * @see See {@link https://mui.com/x/react-charts/tooltip/#highlights highlight docs} for more details. diff --git a/packages/x-charts/src/ResponsiveChartContainer/ResponsiveChartContainer.tsx b/packages/x-charts/src/ResponsiveChartContainer/ResponsiveChartContainer.tsx index d33fbcf1590e..8ea518934c3b 100644 --- a/packages/x-charts/src/ResponsiveChartContainer/ResponsiveChartContainer.tsx +++ b/packages/x-charts/src/ResponsiveChartContainer/ResponsiveChartContainer.tsx @@ -288,6 +288,8 @@ ResponsiveChartContainer.propTypes = { data: PropTypes.array, dataKey: PropTypes.string, id: PropTypes.string, + max: PropTypes.number, + min: PropTypes.number, }), ), } as any; diff --git a/packages/x-charts/src/ScatterChart/Scatter.tsx b/packages/x-charts/src/ScatterChart/Scatter.tsx index 782c58ef531e..abead767285e 100644 --- a/packages/x-charts/src/ScatterChart/Scatter.tsx +++ b/packages/x-charts/src/ScatterChart/Scatter.tsx @@ -10,6 +10,7 @@ import { useInteractionItemProps } from '../hooks/useInteractionItemProps'; import { InteractionContext } from '../context/InteractionProvider'; import { D3Scale } from '../models/axis'; import { useHighlighted } from '../context'; +import { useDrawingArea } from '../hooks/useDrawingArea'; export interface ScatterProps { series: DefaultizedScatterSeriesType; @@ -42,6 +43,8 @@ export interface ScatterProps { function Scatter(props: ScatterProps) { const { series, xScale, yScale, color, colorGetter, markerSize, onItemClick } = props; + const { left, width } = useDrawingArea(); + const { useVoronoiInteraction } = React.useContext(InteractionContext); const skipInteractionHandlers = useVoronoiInteraction || series.disableHover; @@ -51,11 +54,9 @@ function Scatter(props: ScatterProps) { const cleanData = React.useMemo(() => { const getXPosition = getValueToPositionMapper(xScale); const getYPosition = getValueToPositionMapper(yScale); - const xRange = xScale.range(); + const yRange = yScale.range(); - const minXRange = Math.min(...xRange); - const maxXRange = Math.max(...xRange); const minYRange = Math.min(...yRange); const maxYRange = Math.max(...yRange); @@ -73,7 +74,7 @@ function Scatter(props: ScatterProps) { const x = getXPosition(scatterPoint.x); const y = getYPosition(scatterPoint.y); - const isInRange = x >= minXRange && x <= maxXRange && y >= minYRange && y <= maxYRange; + const isInRange = x >= left && x <= left + width && y >= minYRange && y <= maxYRange; const pointCtx = { type: 'scatter' as const, seriesId: series.id, dataIndex: i }; @@ -100,13 +101,15 @@ function Scatter(props: ScatterProps) { }, [ xScale, yScale, + left, + width, series.data, series.id, + isHighlighted, + isFaded, getInteractionItemProps, - color, colorGetter, - isFaded, - isHighlighted, + color, ]); return ( diff --git a/packages/x-charts/src/ScatterChart/ScatterChart.tsx b/packages/x-charts/src/ScatterChart/ScatterChart.tsx index f86111b66408..84ca039c4f4c 100644 --- a/packages/x-charts/src/ScatterChart/ScatterChart.tsx +++ b/packages/x-charts/src/ScatterChart/ScatterChart.tsx @@ -45,13 +45,13 @@ export interface ScatterChartSlots extends ChartsAxisSlots, ScatterPlotSlots, ChartsLegendSlots, - ChartsTooltipSlots, + ChartsTooltipSlots<'scatter'>, ChartsOverlaySlots {} export interface ScatterChartSlotProps extends ChartsAxisSlotProps, ScatterPlotSlotProps, ChartsLegendSlotProps, - ChartsTooltipSlotProps, + ChartsTooltipSlotProps<'scatter'>, ChartsOverlaySlotProps {} export interface ScatterChartProps @@ -70,7 +70,7 @@ export interface ScatterChartProps * @see See {@link https://mui.com/x/react-charts/tooltip/ tooltip docs} for more details. * @default { trigger: 'item' } */ - tooltip?: ChartsTooltipProps; + tooltip?: ChartsTooltipProps<'scatter'>; /** * The configuration of axes highlight. * @see See {@link https://mui.com/x/react-charts/tooltip/#highlights highlight docs} for more details. @@ -497,6 +497,8 @@ ScatterChart.propTypes = { data: PropTypes.array, dataKey: PropTypes.string, id: PropTypes.string, + max: PropTypes.number, + min: PropTypes.number, }), ), } as any; diff --git a/packages/x-charts/src/ScatterChart/useScatterChartProps.ts b/packages/x-charts/src/ScatterChart/useScatterChartProps.ts index 9f57a8c01c74..b3fe96a66fc6 100644 --- a/packages/x-charts/src/ScatterChart/useScatterChartProps.ts +++ b/packages/x-charts/src/ScatterChart/useScatterChartProps.ts @@ -1,4 +1,12 @@ +import { ChartsAxisProps } from '../ChartsAxis'; +import { ChartsAxisHighlightProps } from '../ChartsAxisHighlight'; +import { ChartsGridProps } from '../ChartsGrid'; +import { ChartsLegendProps } from '../ChartsLegend'; +import { ChartsOverlayProps } from '../ChartsOverlay'; +import { ChartsTooltipProps } from '../ChartsTooltip'; import type { ChartsVoronoiHandlerProps } from '../ChartsVoronoiHandler'; +import { ResponsiveChartContainerProps } from '../ResponsiveChartContainer'; +import { ZAxisContextProviderProps } from '../context'; import type { ScatterChartProps } from './ScatterChart'; import type { ScatterPlotProps } from './ScatterPlot'; @@ -39,7 +47,7 @@ export const useScatterChartProps = (props: ScatterChartProps) => { onHighlightChange, } = props; - const chartContainerProps = { + const chartContainerProps: ResponsiveChartContainerProps = { series: series.map((s) => ({ type: 'scatter' as const, ...s })), width, height, @@ -51,14 +59,14 @@ export const useScatterChartProps = (props: ScatterChartProps) => { highlightedItem, onHighlightChange, }; - const zAxisProps = { + const zAxisProps: Omit = { zAxis, }; - const voronoiHandlerProps = { + const voronoiHandlerProps: ChartsVoronoiHandlerProps = { voronoiMaxRadius, onItemClick: onItemClick as ChartsVoronoiHandlerProps['onItemClick'], }; - const chartsAxisProps = { + const chartsAxisProps: ChartsAxisProps = { topAxis, leftAxis, rightAxis, @@ -67,36 +75,36 @@ export const useScatterChartProps = (props: ScatterChartProps) => { slotProps, }; - const gridProps = { + const gridProps: ChartsGridProps = { vertical: grid?.vertical, horizontal: grid?.horizontal, }; - const scatterPlotProps = { + const scatterPlotProps: ScatterPlotProps = { onItemClick: disableVoronoi ? (onItemClick as ScatterPlotProps['onItemClick']) : undefined, slots, slotProps, }; - const overlayProps = { + const overlayProps: ChartsOverlayProps = { loading, slots, slotProps, }; - const legendProps = { + const legendProps: ChartsLegendProps = { ...legend, slots, slotProps, }; - const axisHighlightProps = { + const axisHighlightProps: ChartsAxisHighlightProps = { y: 'none' as const, x: 'none' as const, ...axisHighlight, }; - const tooltipProps = { + const tooltipProps: ChartsTooltipProps<'scatter'> = { trigger: 'item' as const, ...tooltip, slots, diff --git a/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx b/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx index 028db19f4acf..d46ac24e85bd 100644 --- a/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx +++ b/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx @@ -30,14 +30,14 @@ export interface SparkLineChartSlots MarkPlotSlots, LineHighlightPlotSlots, Omit, - ChartsTooltipSlots {} + ChartsTooltipSlots<'line' | 'bar'> {} export interface SparkLineChartSlotProps extends AreaPlotSlotProps, LinePlotSlotProps, MarkPlotSlotProps, LineHighlightPlotSlotProps, BarPlotSlotProps, - ChartsTooltipSlotProps {} + ChartsTooltipSlotProps<'line' | 'bar'> {} export interface SparkLineChartProps extends Omit< @@ -54,7 +54,7 @@ export interface SparkLineChartProps * Notice it is a single [[AxisConfig]] object, not an array of configuration. */ yAxis?: MakeOptional, 'id'>; - tooltip?: ChartsTooltipProps; + tooltip?: ChartsTooltipProps<'line' | 'bar'>; axisHighlight?: ChartsAxisHighlightProps; /** * Type of plot used. diff --git a/packages/x-charts/src/context/CartesianProvider/computeValue.ts b/packages/x-charts/src/context/CartesianProvider/computeValue.ts index 053b51cf1afd..0d7da4f5b40d 100644 --- a/packages/x-charts/src/context/CartesianProvider/computeValue.ts +++ b/packages/x-charts/src/context/CartesianProvider/computeValue.ts @@ -1,4 +1,4 @@ -import { scaleBand, scalePoint } from 'd3-scale'; +import { scaleBand, scalePoint, scaleTime } from 'd3-scale'; import { DEFAULT_X_AXIS_KEY, DEFAULT_Y_AXIS_KEY } from '../../constants'; import { AxisConfig, ScaleName } from '../../models'; import { @@ -27,6 +27,29 @@ const getRange = (drawingArea: DrawingArea, axisName: 'x' | 'y', isReverse?: boo return isReverse ? range.reverse() : range; }; +const zoomedScaleRange = (scaleRange: [number, number] | number[], zoomRange: [number, number]) => { + const rangeGap = scaleRange[1] - scaleRange[0]; + const zoomGap = zoomRange[1] - zoomRange[0]; + + // If current zoom show the scale between p1 and p2 percents + // The range should be extended by adding [0, p1] and [p2, 100] segments + const min = scaleRange[0] - (zoomRange[0] * rangeGap) / zoomGap; + const max = scaleRange[1] + ((100 - zoomRange[1]) * rangeGap) / zoomGap; + + return [min, max]; +}; +const isDateData = (data?: any[]): data is Date[] => data?.[0] instanceof Date; + +function createDateFormatter( + axis: AxisConfig<'band' | 'point', any, ChartsAxisProps>, + range: number[], +): AxisConfig<'band' | 'point', any, ChartsAxisProps>['valueFormatter'] { + const timeScale = scaleTime(axis.data!, range); + + return (v, { location }) => + location === 'tick' ? timeScale.tickFormat(axis.tickNumber)(v) : `${v.toLocaleString()}`; +} + const DEFAULT_CATEGORY_GAP_RATIO = 0.2; const DEFAULT_BAR_GAP_RATIO = 0.1; @@ -36,6 +59,7 @@ export function computeValue( axis: MakeOptional, 'id'>[] | undefined, extremumGetters: { [K in CartesianChartSeriesType]?: ExtremumGetter }, axisName: 'y', + zoomRange?: [number, number], ): { axis: DefaultizedAxisConfig; axisIds: string[]; @@ -46,6 +70,7 @@ export function computeValue( inAxis: MakeOptional, 'id'>[] | undefined, extremumGetters: { [K in CartesianChartSeriesType]?: ExtremumGetter }, axisName: 'x', + zoomRange?: [number, number], ): { axis: DefaultizedAxisConfig; axisIds: string[]; @@ -56,6 +81,7 @@ export function computeValue( inAxis: MakeOptional, 'id'>[] | undefined, extremumGetters: { [K in CartesianChartSeriesType]?: ExtremumGetter }, axisName: 'x' | 'y', + zoomRange: [number, number] = [0, 100], ) { const DEFAULT_AXIS_KEY = axisName === 'x' ? DEFAULT_X_AXIS_KEY : DEFAULT_Y_AXIS_KEY; @@ -84,12 +110,13 @@ export function computeValue( const barGapRatio = axis.barGapRatio ?? DEFAULT_BAR_GAP_RATIO; // Reverse range because ordinal scales are presented from top to bottom on y-axis const scaleRange = axisName === 'x' ? range : [range[1], range[0]]; + const zoomedRange = zoomedScaleRange(scaleRange, zoomRange); completeAxis[axis.id] = { categoryGapRatio, barGapRatio, ...axis, - scale: scaleBand(axis.data!, scaleRange) + scale: scaleBand(axis.data!, zoomedRange) .paddingInner(categoryGapRatio) .paddingOuter(categoryGapRatio / 2), tickNumber: axis.data!.length, @@ -99,13 +126,19 @@ export function computeValue( ? getOrdinalColorScale({ values: axis.data, ...axis.colorMap }) : getColorScale(axis.colorMap)), }; + + if (isDateData(axis.data)) { + const dateFormatter = createDateFormatter(axis, scaleRange); + completeAxis[axis.id].valueFormatter = axis.valueFormatter ?? dateFormatter; + } } if (isPointScaleConfig(axis)) { const scaleRange = axisName === 'x' ? range : [...range].reverse(); + const zoomedRange = zoomedScaleRange(scaleRange, zoomRange); completeAxis[axis.id] = { ...axis, - scale: scalePoint(axis.data!, scaleRange), + scale: scalePoint(axis.data!, zoomedRange), tickNumber: axis.data!.length, colorScale: axis.colorMap && @@ -113,6 +146,11 @@ export function computeValue( ? getOrdinalColorScale({ values: axis.data, ...axis.colorMap }) : getColorScale(axis.colorMap)), }; + + if (isDateData(axis.data)) { + const dateFormatter = createDateFormatter(axis, scaleRange); + completeAxis[axis.id].valueFormatter = axis.valueFormatter ?? dateFormatter; + } } if (axis.scaleType === 'band' || axis.scaleType === 'point') { // Could be merged with the two previous "if conditions" but then TS does not get that `axis.scaleType` can't be `band` or `point`. @@ -122,9 +160,13 @@ export function computeValue( const scaleType = axis.scaleType ?? ('linear' as const); const extremums = [axis.min ?? minData, axis.max ?? maxData]; - const tickNumber = getTickNumber({ ...axis, range, domain: extremums }); + const rawTickNumber = getTickNumber({ ...axis, range, domain: extremums }); + const tickNumber = rawTickNumber / ((zoomRange[1] - zoomRange[0]) / 100); + + const zoomedRange = zoomedScaleRange(range, zoomRange); - const scale = getScale(scaleType, extremums, range).nice(tickNumber); + // TODO: move nice to prop? Disable when there is zoom? + const scale = getScale(scaleType, extremums, zoomedRange).nice(rawTickNumber); const [minDomain, maxDomain] = scale.domain(); const domain = [axis.min ?? minDomain, axis.max ?? maxDomain]; diff --git a/packages/x-charts/src/context/ZAxisContextProvider.tsx b/packages/x-charts/src/context/ZAxisContextProvider.tsx index fa24fd59a979..413dc0fad32f 100644 --- a/packages/x-charts/src/context/ZAxisContextProvider.tsx +++ b/packages/x-charts/src/context/ZAxisContextProvider.tsx @@ -69,7 +69,11 @@ function ZAxisContextProvider(props: ZAxisContextProviderProps) { axis.colorMap && (axis.colorMap.type === 'ordinal' && axis.data ? getOrdinalColorScale({ values: axis.data, ...axis.colorMap }) - : getColorScale(axis.colorMap)), + : getColorScale( + axis.colorMap.type === 'continuous' + ? { min: axis.min, max: axis.max, ...axis.colorMap } + : axis.colorMap, + )), }; }); @@ -127,6 +131,8 @@ ZAxisContextProvider.propTypes = { data: PropTypes.array, dataKey: PropTypes.string, id: PropTypes.string, + max: PropTypes.number, + min: PropTypes.number, }), ), } as any; diff --git a/packages/x-charts/src/hooks/index.ts b/packages/x-charts/src/hooks/index.ts index 148bf66d030b..7f6e5dcdbdaf 100644 --- a/packages/x-charts/src/hooks/index.ts +++ b/packages/x-charts/src/hooks/index.ts @@ -1,6 +1,7 @@ export * from './useDrawingArea'; export * from './useChartId'; export * from './useScale'; +export * from './useAxis'; export * from './useColorScale'; export * from './useSvgRef'; export { diff --git a/packages/x-charts/src/hooks/useAxis.ts b/packages/x-charts/src/hooks/useAxis.ts new file mode 100644 index 000000000000..d3f3fd2325ba --- /dev/null +++ b/packages/x-charts/src/hooks/useAxis.ts @@ -0,0 +1,17 @@ +import { useCartesianContext } from '../context/CartesianProvider'; + +export function useXAxis(identifier?: number | string) { + const { xAxis, xAxisIds } = useCartesianContext(); + + const id = typeof identifier === 'string' ? identifier : xAxisIds[identifier ?? 0]; + + return xAxis[id]; +} + +export function useYAxis(identifier?: number | string) { + const { yAxis, yAxisIds } = useCartesianContext(); + + const id = typeof identifier === 'string' ? identifier : yAxisIds[identifier ?? 0]; + + return yAxis[id]; +} diff --git a/packages/x-charts/src/hooks/useAxisEvents.ts b/packages/x-charts/src/hooks/useAxisEvents.ts index 855ec5985c1a..2679b53e313a 100644 --- a/packages/x-charts/src/hooks/useAxisEvents.ts +++ b/packages/x-charts/src/hooks/useAxisEvents.ts @@ -3,7 +3,7 @@ import { InteractionContext } from '../context/InteractionProvider'; import { useCartesianContext } from '../context/CartesianProvider'; import { isBandScale } from '../internals/isBandScale'; import { AxisDefaultized } from '../models/axis'; -import { getSVGPoint } from '../internals/utils'; +import { getSVGPoint } from '../internals/getSVGPoint'; import { useSvgRef } from './useSvgRef'; import { useDrawingArea } from './useDrawingArea'; @@ -31,10 +31,7 @@ export const useAxisEvents = (disableAxisListener: boolean) => { return () => {}; } - const getUpdate = (axisConfig: AxisDefaultized, mouseValue: number) => { - if (usedXAxis === null) { - return null; - } + function getNewAxisState(axisConfig: AxisDefaultized, mouseValue: number) { const { scale, data: axisData, reverse } = axisConfig; if (!isBandScale(scale)) { @@ -93,7 +90,7 @@ export const useAxisEvents = (disableAxisListener: boolean) => { index: dataIndex, value: axisData![dataIndex], }; - }; + } const handleOut = () => { mousePosition.current = { @@ -105,7 +102,7 @@ export const useAxisEvents = (disableAxisListener: boolean) => { const handleMove = (event: MouseEvent | TouchEvent) => { const target = 'targetTouches' in event ? event.targetTouches[0] : event; - const svgPoint = getSVGPoint(svgRef.current!, target); + const svgPoint = getSVGPoint(element, target); mousePosition.current = { x: svgPoint.x, @@ -118,21 +115,34 @@ export const useAxisEvents = (disableAxisListener: boolean) => { dispatch({ type: 'exitChart' }); return; } - const newStateX = getUpdate(xAxis[usedXAxis], svgPoint.x); - const newStateY = getUpdate(yAxis[usedYAxis], svgPoint.y); + const newStateX = getNewAxisState(xAxis[usedXAxis], svgPoint.x); + const newStateY = getNewAxisState(yAxis[usedYAxis], svgPoint.y); dispatch({ type: 'updateAxis', data: { x: newStateX, y: newStateY } }); }; - element.addEventListener('mouseout', handleOut); - element.addEventListener('mousemove', handleMove); - element.addEventListener('touchend', handleOut); - element.addEventListener('touchmove', handleMove); + const handleDown = (event: PointerEvent) => { + const target = event.currentTarget; + if (!target) { + return; + } + + if ((target as HTMLElement).hasPointerCapture(event.pointerId)) { + (target as HTMLElement).releasePointerCapture(event.pointerId); + } + }; + + element.addEventListener('pointerdown', handleDown); + element.addEventListener('pointermove', handleMove); + element.addEventListener('pointerout', handleOut); + element.addEventListener('pointercancel', handleOut); + element.addEventListener('pointerleave', handleOut); return () => { - element.removeEventListener('mouseout', handleOut); - element.removeEventListener('mousemove', handleMove); - element.removeEventListener('touchend', handleOut); - element.removeEventListener('touchmove', handleMove); + element.removeEventListener('pointerdown', handleDown); + element.removeEventListener('pointermove', handleMove); + element.removeEventListener('pointerout', handleOut); + element.removeEventListener('pointercancel', handleOut); + element.removeEventListener('pointerleave', handleOut); }; }, [ svgRef, diff --git a/packages/x-charts/src/hooks/useColor.ts b/packages/x-charts/src/hooks/useColor.ts index c124c75cd796..68b6ecc59fa5 100644 --- a/packages/x-charts/src/hooks/useColor.ts +++ b/packages/x-charts/src/hooks/useColor.ts @@ -1,5 +1,5 @@ import * as React from 'react'; -import { ChartSeriesType } from '../internals'; +import { ChartSeriesType } from '../models/seriesType/config'; import { ColorContext } from '../context/ColorProvider'; import { ColorProcessorsConfig } from '../models/plugin'; diff --git a/packages/x-charts/src/hooks/useInteractionItemProps.ts b/packages/x-charts/src/hooks/useInteractionItemProps.ts index 07d9dc7dccbd..12ef0ce071c4 100644 --- a/packages/x-charts/src/hooks/useInteractionItemProps.ts +++ b/packages/x-charts/src/hooks/useInteractionItemProps.ts @@ -11,7 +11,12 @@ export const useInteractionItemProps = (skip?: boolean) => { return () => ({}); } const getInteractionItemProps = (data: SeriesItemIdentifier) => { - const onMouseEnter = () => { + const onPointerDown = (event: React.PointerEvent) => { + if (event.currentTarget.hasPointerCapture(event.pointerId)) { + event.currentTarget.releasePointerCapture(event.pointerId); + } + }; + const onPointerEnter = () => { dispatchInteraction({ type: 'enterItem', data, @@ -21,13 +26,15 @@ export const useInteractionItemProps = (skip?: boolean) => { dataIndex: data.dataIndex, }); }; - const onMouseLeave = () => { + const onPointerLeave = (event: React.PointerEvent) => { + event.currentTarget.releasePointerCapture(event.pointerId); dispatchInteraction({ type: 'leaveItem', data }); clearHighlighted(); }; return { - onMouseEnter, - onMouseLeave, + onPointerEnter, + onPointerLeave, + onPointerDown, }; }; return getInteractionItemProps; diff --git a/packages/x-charts/src/hooks/useScale.ts b/packages/x-charts/src/hooks/useScale.ts index 3af08f437bbf..62755e68f8cd 100644 --- a/packages/x-charts/src/hooks/useScale.ts +++ b/packages/x-charts/src/hooks/useScale.ts @@ -1,6 +1,6 @@ -import { useCartesianContext } from '../context/CartesianProvider'; import { isBandScale } from '../internals/isBandScale'; import { AxisScaleConfig, D3Scale, ScaleName } from '../models/axis'; +import { useXAxis, useYAxis } from './useAxis'; /** * For a given scale return a function that map value to their position. @@ -10,7 +10,7 @@ import { AxisScaleConfig, D3Scale, ScaleName } from '../models/axis'; */ export function getValueToPositionMapper(scale: D3Scale) { if (isBandScale(scale)) { - return (value: any) => scale(value)! + scale.bandwidth() / 2; + return (value: any) => (scale(value) ?? 0) + scale.bandwidth() / 2; } return (value: any) => scale(value) as number; } @@ -18,19 +18,15 @@ export function getValueToPositionMapper(scale: D3Scale) { export function useXScale( identifier?: number | string, ): AxisScaleConfig[S]['scale'] { - const { xAxis, xAxisIds } = useCartesianContext(); + const axis = useXAxis(identifier); - const id = typeof identifier === 'string' ? identifier : xAxisIds[identifier ?? 0]; - - return xAxis[id].scale; + return axis.scale; } export function useYScale( identifier?: number | string, ): AxisScaleConfig[S]['scale'] { - const { yAxis, yAxisIds } = useCartesianContext(); - - const id = typeof identifier === 'string' ? identifier : yAxisIds[identifier ?? 0]; + const axis = useYAxis(identifier); - return yAxis[id].scale; + return axis.scale; } diff --git a/packages/x-charts/src/hooks/useTicks.ts b/packages/x-charts/src/hooks/useTicks.ts index 8049ebe780d1..ecc42b5727fe 100644 --- a/packages/x-charts/src/hooks/useTicks.ts +++ b/packages/x-charts/src/hooks/useTicks.ts @@ -101,8 +101,12 @@ export function useTicks( if (scale.bandwidth() > 0) { // scale type = 'band' + const filteredDomain = + (typeof tickInterval === 'function' && domain.filter(tickInterval)) || + (typeof tickInterval === 'object' && tickInterval) || + domain; return [ - ...domain.map((value) => ({ + ...filteredDomain.map((value) => ({ value, formattedValue: valueFormatter?.(value, { location: 'tick' }) ?? `${value}`, offset: diff --git a/packages/x-charts/src/internals/getSVGPoint.ts b/packages/x-charts/src/internals/getSVGPoint.ts new file mode 100644 index 000000000000..379752cdb307 --- /dev/null +++ b/packages/x-charts/src/internals/getSVGPoint.ts @@ -0,0 +1,11 @@ +/** + * Transform mouse event position to coordinates inside the SVG. + * @param svg The SVG element + * @param event The mouseEvent to transform + */ +export function getSVGPoint(svg: SVGSVGElement, event: Pick) { + const pt = svg.createSVGPoint(); + pt.x = event.clientX; + pt.y = event.clientY; + return pt.matrixTransform(svg.getScreenCTM()!.inverse()); +} diff --git a/packages/x-charts/src/internals/index.ts b/packages/x-charts/src/internals/index.ts index ba3ecc5de8a8..924017fab51c 100644 --- a/packages/x-charts/src/internals/index.ts +++ b/packages/x-charts/src/internals/index.ts @@ -7,6 +7,8 @@ export * from '../ResponsiveChartContainer/ResizableContainer'; // hooks export { useReducedMotion } from '../hooks/useReducedMotion'; export { useSeries } from '../hooks/useSeries'; +export { useInteractionItemProps } from '../hooks/useInteractionItemProps'; +export { useDrawingArea } from '../hooks/useDrawingArea'; export { useChartContainerHooks } from '../ChartContainer/useChartContainerHooks'; export { useScatterChartProps } from '../ScatterChart/useScatterChartProps'; export { useLineChartProps } from '../LineChart/useLineChartProps'; @@ -15,6 +17,8 @@ export { useBarChartProps } from '../BarChart/useBarChartProps'; // utils export * from './defaultizeValueFormatter'; export * from './configInit'; +export * from './getLabel'; +export * from './getSVGPoint'; // contexts diff --git a/packages/x-charts/src/internals/utils.ts b/packages/x-charts/src/internals/utils.ts index 2896ea166b64..1517334d6e2a 100644 --- a/packages/x-charts/src/internals/utils.ts +++ b/packages/x-charts/src/internals/utils.ts @@ -9,18 +9,6 @@ export function getSymbol(shape: SymbolsTypes): number { type Without = { [P in Exclude]?: never }; export type XOR = T | U extends object ? (Without & U) | (Without & T) : T | U; -/** - * Transform mouse event position to coordinates inside the SVG. - * @param svg The SVG element - * @param event The mouseEvent to transform - */ -export function getSVGPoint(svg: SVGSVGElement, event: Pick) { - const pt = svg.createSVGPoint(); - pt.x = event.clientX; - pt.y = event.clientY; - return pt.matrixTransform(svg.getScreenCTM()!.inverse()); -} - /** * Helper that converts values and percentages into values. * @param value The value provided by the developer. Can either be a number or a string with '%' or 'px'. diff --git a/packages/x-charts/src/models/axis.ts b/packages/x-charts/src/models/axis.ts index 2ca13a4836ff..651612e1ec52 100644 --- a/packages/x-charts/src/models/axis.ts +++ b/packages/x-charts/src/models/axis.ts @@ -156,7 +156,7 @@ export interface ChartsXAxisProps extends ChartsAxisProps { position?: 'top' | 'bottom'; } -export type ScaleName = 'linear' | 'band' | 'point' | 'log' | 'pow' | 'sqrt' | 'time' | 'utc'; +export type ScaleName = keyof AxisScaleConfig; export type ContinuousScaleName = 'linear' | 'log' | 'pow' | 'sqrt' | 'time' | 'utc'; export interface AxisScaleConfig { diff --git a/packages/x-charts/src/models/colorMapping.ts b/packages/x-charts/src/models/colorMapping.ts index ba5dd13ecd5a..f14cf41cf89a 100644 --- a/packages/x-charts/src/models/colorMapping.ts +++ b/packages/x-charts/src/models/colorMapping.ts @@ -13,7 +13,7 @@ export interface ContinuousColorConfig { /** * The colors to render. It can be an array with the extremum colors, or an interpolation function. */ - color: [string, string] | ((t: number) => string); + color: readonly [string, string] | ((t: number) => string); } export interface PiecewiseColorConfig { diff --git a/packages/x-charts/src/models/z-axis.ts b/packages/x-charts/src/models/z-axis.ts index 0a493f5d8f68..194622049534 100644 --- a/packages/x-charts/src/models/z-axis.ts +++ b/packages/x-charts/src/models/z-axis.ts @@ -8,6 +8,14 @@ export interface ZAxisConfig { * The key used to retrieve `data` from the `dataset` prop. */ dataKey?: string; + /** + * The minimal value of the scale. + */ + min?: number; + /** + * The maximal value of the scale. + */ + max?: number; colorMap?: OrdinalColorConfig | ContinuousColorConfig | PiecewiseColorConfig; } diff --git a/packages/x-charts/src/themeAugmentation/props.d.ts b/packages/x-charts/src/themeAugmentation/props.d.ts index 0189a5b19e67..7dc62f397400 100644 --- a/packages/x-charts/src/themeAugmentation/props.d.ts +++ b/packages/x-charts/src/themeAugmentation/props.d.ts @@ -13,6 +13,7 @@ import { LineChartProps } from '../LineChart/LineChart'; import { ScatterProps } from '../ScatterChart/Scatter'; import { ScatterChartProps } from '../ScatterChart/ScatterChart'; import { ChartsXAxisProps, ChartsYAxisProps } from '../models/axis'; +import { ChartSeriesType } from '../models/seriesType/config'; export interface ChartsComponentsPropsList { MuiChartsAxis: ChartsAxisProps; @@ -22,7 +23,7 @@ export interface ChartsComponentsPropsList { MuiChartsClipPath: ChartsClipPathProps; MuiChartsGrid: ChartsGridProps; MuiChartsLegend: ChartsLegendProps; - MuiChartsTooltip: ChartsTooltipProps; + MuiChartsTooltip: ChartsTooltipProps; MuiChartsSurface: ChartsSurfaceProps; // BarChart components diff --git a/packages/x-codemod/package.json b/packages/x-codemod/package.json index 2b97f82feb4e..1f87794b337f 100644 --- a/packages/x-codemod/package.json +++ b/packages/x-codemod/package.json @@ -1,6 +1,6 @@ { "name": "@mui/x-codemod", - "version": "7.7.0", + "version": "7.9.0", "bin": "./codemod.js", "private": false, "author": "MUI Team", @@ -35,15 +35,14 @@ "@babel/core": "^7.24.7", "@babel/runtime": "^7.24.7", "@babel/traverse": "^7.24.7", - "jscodeshift": "0.13.1", - "jscodeshift-add-imports": "^1.0.10", + "jscodeshift": "0.16.1", "yargs": "^17.7.2" }, "devDependencies": { - "@types/jscodeshift": "^0.11.5", + "@types/jscodeshift": "^0.11.11", "dayjs": "^1.11.11", "moment-timezone": "^0.5.45", - "rimraf": "^5.0.7" + "rimraf": "^5.0.8" }, "sideEffects": false, "publishConfig": { diff --git a/packages/x-codemod/src/codemod.ts b/packages/x-codemod/src/codemod.ts index 99580a0b38c9..1ecceba57d8e 100755 --- a/packages/x-codemod/src/codemod.ts +++ b/packages/x-codemod/src/codemod.ts @@ -72,7 +72,7 @@ Not all use cases are covered by codemods. In some scenarios, like props spreadi For example, if a codemod tries to rename a prop, but this prop is hidden with the spread operator, it won't be transformed as expected. -After running the codemods, make sure to test your application and that you don't have any console errors. +After running the codemods, make sure to test your application and that you don't have any formatting or console errors. `); const jscodeshiftProcess = childProcess.spawnSync('node', args, { stdio: 'inherit' }); diff --git a/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/actual-community-root-imports.spec.tsx b/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/actual-community-root-imports.spec.tsx index d86c75b8498b..72f7d3f7c3f0 100644 --- a/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/actual-community-root-imports.spec.tsx +++ b/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/actual-community-root-imports.spec.tsx @@ -7,6 +7,7 @@ import { GridFilterItemProps, } from '@mui/x-data-grid'; +// prettier-ignore function App({ column, hideMenu }: GridFilterItemProps) { return ( diff --git a/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/actual-premium-root-imports.spec.tsx b/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/actual-premium-root-imports.spec.tsx index 373cef5160ff..711e1e82945d 100644 --- a/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/actual-premium-root-imports.spec.tsx +++ b/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/actual-premium-root-imports.spec.tsx @@ -9,6 +9,7 @@ import { GridFilterItemProps, } from '@mui/x-data-grid-premium'; +// prettier-ignore function App({ column, hideMenu }: GridFilterItemProps) { return ( diff --git a/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/actual-pro-root-imports.spec.tsx b/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/actual-pro-root-imports.spec.tsx index 6b342d1530e2..8edf7f57624e 100644 --- a/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/actual-pro-root-imports.spec.tsx +++ b/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/actual-pro-root-imports.spec.tsx @@ -8,6 +8,7 @@ import { GridFilterItemProps, } from '@mui/x-data-grid-pro'; +// prettier-ignore function App({ column, hideMenu }: GridFilterItemProps) { return ( diff --git a/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/expected-community-root-imports.spec.tsx b/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/expected-community-root-imports.spec.tsx index 70823212a0dd..98144b1db844 100644 --- a/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/expected-community-root-imports.spec.tsx +++ b/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/expected-community-root-imports.spec.tsx @@ -7,13 +7,14 @@ import { GridColumnMenuItemProps, } from '@mui/x-data-grid'; +// prettier-ignore function App({ column, hideMenu }: GridColumnMenuItemProps) { return ( - + ( - + ) ); } diff --git a/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/expected-premium-root-imports.spec.tsx b/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/expected-premium-root-imports.spec.tsx index 93e452123d61..bf7d1a63e435 100644 --- a/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/expected-premium-root-imports.spec.tsx +++ b/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/expected-premium-root-imports.spec.tsx @@ -9,15 +9,16 @@ import { GridColumnMenuItemProps, } from '@mui/x-data-grid-premium'; +// prettier-ignore function App({ column, hideMenu }: GridColumnMenuItemProps) { return ( - + ( - + ) ); } diff --git a/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/expected-pro-root-imports.spec.tsx b/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/expected-pro-root-imports.spec.tsx index 4ca25b6153b1..6fee5b0a9cdd 100644 --- a/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/expected-pro-root-imports.spec.tsx +++ b/packages/x-codemod/src/v6.0.0/data-grid/column-menu-components-rename/expected-pro-root-imports.spec.tsx @@ -8,14 +8,15 @@ import { GridColumnMenuItemProps, } from '@mui/x-data-grid-pro'; +// prettier-ignore function App({ column, hideMenu }: GridColumnMenuItemProps) { return ( - + ( - + ) ); } diff --git a/packages/x-codemod/src/v6.0.0/data-grid/preset-safe/expected.spec.js b/packages/x-codemod/src/v6.0.0/data-grid/preset-safe/expected.spec.js index 41477addc458..f9fae32f4404 100644 --- a/packages/x-codemod/src/v6.0.0/data-grid/preset-safe/expected.spec.js +++ b/packages/x-codemod/src/v6.0.0/data-grid/preset-safe/expected.spec.js @@ -9,7 +9,7 @@ function App({ column, hideMenu, apiRef, handleEvent }) { event.defaultMuiPrevented = true; }; return ( - + ( - + ) ); } diff --git a/packages/x-codemod/src/v6.0.0/data-grid/remove-disableExtendRowFullWidth-prop/expected.spec.js b/packages/x-codemod/src/v6.0.0/data-grid/remove-disableExtendRowFullWidth-prop/expected.spec.js index 21890a001622..808794c5a841 100644 --- a/packages/x-codemod/src/v6.0.0/data-grid/remove-disableExtendRowFullWidth-prop/expected.spec.js +++ b/packages/x-codemod/src/v6.0.0/data-grid/remove-disableExtendRowFullWidth-prop/expected.spec.js @@ -5,11 +5,11 @@ import { DataGridPremium } from '@mui/x-data-grid-premium'; function App() { return ( - + ( - + ) ); } diff --git a/packages/x-codemod/src/v6.0.0/data-grid/remove-stabilized-experimentalFeatures/expected.spec.js b/packages/x-codemod/src/v6.0.0/data-grid/remove-stabilized-experimentalFeatures/expected.spec.js index b1e7d1fab199..4d325b05607f 100644 --- a/packages/x-codemod/src/v6.0.0/data-grid/remove-stabilized-experimentalFeatures/expected.spec.js +++ b/packages/x-codemod/src/v6.0.0/data-grid/remove-stabilized-experimentalFeatures/expected.spec.js @@ -5,7 +5,7 @@ import { DataGridPremium } from '@mui/x-data-grid-premium'; function App() { return ( - + ( - + ) ); } diff --git a/packages/x-codemod/src/v6.0.0/data-grid/rename-components-to-slots/expected.spec.js b/packages/x-codemod/src/v6.0.0/data-grid/rename-components-to-slots/expected.spec.js index d0b73a667a41..352cda988bb7 100644 --- a/packages/x-codemod/src/v6.0.0/data-grid/rename-components-to-slots/expected.spec.js +++ b/packages/x-codemod/src/v6.0.0/data-grid/rename-components-to-slots/expected.spec.js @@ -5,7 +5,7 @@ import { Button, Checkbox, TextField } from '@mui/material'; export default function App() { return ( -
+ (
-
+
) ); }; diff --git a/packages/x-codemod/src/v6.0.0/data-grid/rename-filter-item-props/actual.spec.tsx b/packages/x-codemod/src/v6.0.0/data-grid/rename-filter-item-props/actual.spec.tsx index a814c59a1771..6ff73a803484 100644 --- a/packages/x-codemod/src/v6.0.0/data-grid/rename-filter-item-props/actual.spec.tsx +++ b/packages/x-codemod/src/v6.0.0/data-grid/rename-filter-item-props/actual.spec.tsx @@ -11,6 +11,7 @@ const rows = [ { id: 3, column: 'c', name: 'James', score: 300 }, ]; +// prettier-ignore function App() { const [proFilterModel, setProFilterModel] = React.useState({ items: [ diff --git a/packages/x-codemod/src/v6.0.0/data-grid/rename-filter-item-props/expected.spec.tsx b/packages/x-codemod/src/v6.0.0/data-grid/rename-filter-item-props/expected.spec.tsx index fa41bdc0b0dc..f3ec4e5f0d1d 100644 --- a/packages/x-codemod/src/v6.0.0/data-grid/rename-filter-item-props/expected.spec.tsx +++ b/packages/x-codemod/src/v6.0.0/data-grid/rename-filter-item-props/expected.spec.tsx @@ -11,6 +11,7 @@ const rows = [ { id: 3, column: 'c', name: 'James', score: 300 }, ]; +// prettier-ignore function App() { const [proFilterModel, setProFilterModel] = React.useState({ items: [ @@ -31,7 +32,7 @@ function App() { ], }); return ( - + ( - + ) ); } diff --git a/packages/x-codemod/src/v6.0.0/data-grid/rename-linkOperators-logicOperators/expected.spec.js b/packages/x-codemod/src/v6.0.0/data-grid/rename-linkOperators-logicOperators/expected.spec.js index ac53997eca3b..591a632901f9 100644 --- a/packages/x-codemod/src/v6.0.0/data-grid/rename-linkOperators-logicOperators/expected.spec.js +++ b/packages/x-codemod/src/v6.0.0/data-grid/rename-linkOperators-logicOperators/expected.spec.js @@ -38,7 +38,7 @@ function App ({ apiRef, initialState }) { const rowIndex = apiRef.current.getRowIndexRelativeToVisibleRows(1); const localeText = apiRef.current.getLocaleText('filterPanelLogicOperator'); return ( - + ( - + ) ); } diff --git a/packages/x-codemod/src/v6.0.0/data-grid/replace-onCellFocusOut-prop/expected.spec.js b/packages/x-codemod/src/v6.0.0/data-grid/replace-onCellFocusOut-prop/expected.spec.js index 7501bace84fc..6d5753ccf0bd 100644 --- a/packages/x-codemod/src/v6.0.0/data-grid/replace-onCellFocusOut-prop/expected.spec.js +++ b/packages/x-codemod/src/v6.0.0/data-grid/replace-onCellFocusOut-prop/expected.spec.js @@ -9,7 +9,7 @@ function App() { event.defaultMuiPrevented = true; }; return ( - + ( - + ) ); } diff --git a/packages/x-codemod/src/v6.0.0/data-grid/row-selection-props-rename/expected.spec.js b/packages/x-codemod/src/v6.0.0/data-grid/row-selection-props-rename/expected.spec.js index 6c32968793cc..db5d4bd8092a 100644 --- a/packages/x-codemod/src/v6.0.0/data-grid/row-selection-props-rename/expected.spec.js +++ b/packages/x-codemod/src/v6.0.0/data-grid/row-selection-props-rename/expected.spec.js @@ -5,7 +5,7 @@ import { DataGridPremium } from '@mui/x-data-grid-premium' function App () { return ( - + ( {}} @@ -33,7 +33,7 @@ function App () { showColumnVerticalBorder columnHeaderHeight={56} /> - + ) ); } diff --git a/packages/x-codemod/src/v6.0.0/pickers/preset-safe/expected.spec.js b/packages/x-codemod/src/v6.0.0/pickers/preset-safe/expected.spec.js index ab2e84985496..fde3443109c5 100644 --- a/packages/x-codemod/src/v6.0.0/pickers/preset-safe/expected.spec.js +++ b/packages/x-codemod/src/v6.0.0/pickers/preset-safe/expected.spec.js @@ -10,7 +10,7 @@ const theme = createTheme({}); function App() { return ( - + ( - + ) ); } diff --git a/packages/x-codemod/src/v6.0.0/pickers/view-components-rename/actual-community-nested-imports.spec.tsx b/packages/x-codemod/src/v6.0.0/pickers/view-components-rename/actual-community-nested-imports.spec.tsx index cedfe91decf7..005ae673eff3 100644 --- a/packages/x-codemod/src/v6.0.0/pickers/view-components-rename/actual-community-nested-imports.spec.tsx +++ b/packages/x-codemod/src/v6.0.0/pickers/view-components-rename/actual-community-nested-imports.spec.tsx @@ -43,6 +43,7 @@ import { getCalendarPickerSkeletonUtilityClass, } from '@mui/x-date-pickers/CalendarPickerSkeleton'; +// prettier-ignore function App() { type DateProps = CalendarPickerProps; type MonthProps = MonthPickerProps; diff --git a/packages/x-codemod/src/v6.0.0/pickers/view-components-rename/expected-community-nested-imports.spec.tsx b/packages/x-codemod/src/v6.0.0/pickers/view-components-rename/expected-community-nested-imports.spec.tsx index b3f1a2f1f3fe..c62416dda35e 100644 --- a/packages/x-codemod/src/v6.0.0/pickers/view-components-rename/expected-community-nested-imports.spec.tsx +++ b/packages/x-codemod/src/v6.0.0/pickers/view-components-rename/expected-community-nested-imports.spec.tsx @@ -43,6 +43,7 @@ import { getDayCalendarSkeletonUtilityClass, } from '@mui/x-date-pickers/DayCalendarSkeleton'; +// prettier-ignore function App() { type DateProps = DateCalendarProps; type MonthProps = MonthCalendarProps; @@ -57,12 +58,12 @@ function App() { getDayCalendarSkeletonUtilityClass('root'); return ( - + ( {}} /> {}} /> {}} /> {}} /> - + ) ); } diff --git a/packages/x-codemod/src/v6.0.0/preset-safe/expected.spec.js b/packages/x-codemod/src/v6.0.0/preset-safe/expected.spec.js index f7ac5f8c1d41..62bd3c968096 100644 --- a/packages/x-codemod/src/v6.0.0/preset-safe/expected.spec.js +++ b/packages/x-codemod/src/v6.0.0/preset-safe/expected.spec.js @@ -10,7 +10,7 @@ const theme = createTheme({}); function App() { return ( - + (
- + ) ); } diff --git a/packages/x-codemod/src/v7.0.0/data-grid/preset-safe/expected.spec.js b/packages/x-codemod/src/v7.0.0/data-grid/preset-safe/expected.spec.js index 179570a7c8d6..46659a519cbe 100644 --- a/packages/x-codemod/src/v7.0.0/data-grid/preset-safe/expected.spec.js +++ b/packages/x-codemod/src/v7.0.0/data-grid/preset-safe/expected.spec.js @@ -5,7 +5,7 @@ import { Button, Checkbox, TextField } from '@mui/material'; export default function App() { return ( -
+ (
-
+
) ); }; diff --git a/packages/x-codemod/src/v7.0.0/data-grid/remove-stabilized-experimentalFeatures/expected.spec.js b/packages/x-codemod/src/v7.0.0/data-grid/remove-stabilized-experimentalFeatures/expected.spec.js index 85baca51c531..d1a1271fa523 100644 --- a/packages/x-codemod/src/v7.0.0/data-grid/remove-stabilized-experimentalFeatures/expected.spec.js +++ b/packages/x-codemod/src/v7.0.0/data-grid/remove-stabilized-experimentalFeatures/expected.spec.js @@ -5,12 +5,12 @@ import { DataGridPremium } from '@mui/x-data-grid-premium'; function App() { return ( - + ( - + ) ); } diff --git a/packages/x-codemod/src/v7.0.0/data-grid/rename-cell-selection-props/expected.spec.js b/packages/x-codemod/src/v7.0.0/data-grid/rename-cell-selection-props/expected.spec.js index 98d4af7b179a..811da03b32f8 100644 --- a/packages/x-codemod/src/v7.0.0/data-grid/rename-cell-selection-props/expected.spec.js +++ b/packages/x-codemod/src/v7.0.0/data-grid/rename-cell-selection-props/expected.spec.js @@ -5,11 +5,11 @@ import { DataGridPremium } from '@mui/x-data-grid-premium' function App () { return ( - {}} - /> + />) ); } diff --git a/packages/x-codemod/src/v7.0.0/preset-safe/expected.spec.js b/packages/x-codemod/src/v7.0.0/preset-safe/expected.spec.js index cb903bbf3063..42467180d72c 100644 --- a/packages/x-codemod/src/v7.0.0/preset-safe/expected.spec.js +++ b/packages/x-codemod/src/v7.0.0/preset-safe/expected.spec.js @@ -9,7 +9,7 @@ const theme = createTheme({}); function App() { return ( - + ( - + ) ); } diff --git a/packages/x-data-grid-generator/package.json b/packages/x-data-grid-generator/package.json index ce85b0dcf6da..99f993d5a7fd 100644 --- a/packages/x-data-grid-generator/package.json +++ b/packages/x-data-grid-generator/package.json @@ -1,6 +1,6 @@ { "name": "@mui/x-data-grid-generator", - "version": "7.7.1", + "version": "7.9.0", "description": "Generate fake data for demo purposes only.", "author": "MUI Team", "main": "src/index.ts", @@ -38,12 +38,11 @@ "@mui/x-data-grid-premium": "workspace:*", "chance": "^1.1.11", "clsx": "^2.1.1", - "lru-cache": "^7.18.3" + "lru-cache": "^10.3.0" }, "devDependencies": { "@types/chance": "^1.1.6", - "@types/lru-cache": "^7.10.10", - "rimraf": "^5.0.7" + "rimraf": "^5.0.8" }, "peerDependencies": { "@mui/icons-material": "^5.4.1", diff --git a/packages/x-data-grid-generator/src/hooks/index.ts b/packages/x-data-grid-generator/src/hooks/index.ts index 06e612fa89c8..84dd7368aea4 100644 --- a/packages/x-data-grid-generator/src/hooks/index.ts +++ b/packages/x-data-grid-generator/src/hooks/index.ts @@ -2,3 +2,6 @@ export * from './useDemoData'; export * from './useBasicDemoData'; export * from './useMovieData'; export * from './useQuery'; +export * from './useMockServer'; +export { loadServerRows } from './serverUtils'; +export type { QueryOptions } from './serverUtils'; diff --git a/packages/x-data-grid-generator/src/hooks/serverUtils.ts b/packages/x-data-grid-generator/src/hooks/serverUtils.ts new file mode 100644 index 000000000000..095893126643 --- /dev/null +++ b/packages/x-data-grid-generator/src/hooks/serverUtils.ts @@ -0,0 +1,492 @@ +import { + GridRowModel, + GridFilterModel, + GridSortModel, + GridLogicOperator, + GridFilterOperator, + GridColDef, + GridRowId, + GridPaginationModel, + GridValidRowModel, +} from '@mui/x-data-grid-pro'; +import { GridStateColDef } from '@mui/x-data-grid-pro/internals'; +import { UseDemoDataOptions } from './useDemoData'; +import { randomInt } from '../services/random-generator'; + +export interface FakeServerResponse { + returnedRows: GridRowModel[]; + nextCursor?: string; + hasNextPage?: boolean; + totalRowCount: number; +} + +export interface PageInfo { + totalRowCount?: number; + nextCursor?: string; + hasNextPage?: boolean; + pageSize?: number; +} + +export interface DefaultServerOptions { + minDelay: number; + maxDelay: number; + useCursorPagination?: boolean; +} + +export type ServerOptions = Partial; + +export interface QueryOptions { + cursor?: GridRowId; + page?: number; + pageSize?: number; + filterModel?: GridFilterModel; + sortModel?: GridSortModel; + firstRowToRender?: number; + lastRowToRender?: number; +} + +export interface ServerSideQueryOptions { + cursor?: GridRowId; + paginationModel?: GridPaginationModel; + groupKeys?: string[]; + filterModel?: GridFilterModel; + sortModel?: GridSortModel; + firstRowToRender?: number; + lastRowToRender?: number; +} + +export const DEFAULT_DATASET_OPTIONS: UseDemoDataOptions = { + dataSet: 'Commodity', + rowLength: 100, + maxColumns: 6, +}; + +declare const DISABLE_CHANCE_RANDOM: any; +export const disableDelay = typeof DISABLE_CHANCE_RANDOM !== 'undefined' && DISABLE_CHANCE_RANDOM; + +export const DEFAULT_SERVER_OPTIONS: DefaultServerOptions = { + minDelay: disableDelay ? 0 : 100, + maxDelay: disableDelay ? 0 : 300, + useCursorPagination: true, +}; + +const apiRef = {} as any; + +const simplifiedValueGetter = (field: string, colDef: GridColDef) => (row: GridRowModel) => { + return colDef.valueGetter?.(row[row.id] as never, row, colDef, apiRef) || row[field]; +}; + +const getRowComparator = ( + sortModel: GridSortModel | undefined, + columnsWithDefaultColDef: GridColDef[], +) => { + if (!sortModel) { + const comparator = () => 0; + return comparator; + } + const sortOperators = sortModel.map((sortItem) => { + const columnField = sortItem.field; + const colDef = columnsWithDefaultColDef.find(({ field }) => field === columnField) as any; + return { + ...sortItem, + valueGetter: simplifiedValueGetter(columnField, colDef), + sortComparator: colDef.sortComparator, + }; + }); + + const comparator = (row1: GridRowModel, row2: GridRowModel) => + sortOperators.reduce((acc, { valueGetter, sort, sortComparator }) => { + if (acc !== 0) { + return acc; + } + const v1 = valueGetter(row1); + const v2 = valueGetter(row2); + return sort === 'desc' ? -1 * sortComparator(v1, v2) : sortComparator(v1, v2); + }, 0); + + return comparator; +}; + +const buildQuickFilterApplier = (filterModel: GridFilterModel, columns: GridColDef[]) => { + const quickFilterValues = filterModel.quickFilterValues?.filter(Boolean) ?? []; + if (quickFilterValues.length === 0) { + return null; + } + + const appliersPerField = [] as { + column: GridColDef; + appliers: { + fn: null | ((...args: any[]) => boolean); + }[]; + }[]; + + const stubApiRef = { + current: { + getRowFormattedValue: (row: GridValidRowModel, c: GridColDef) => { + const field = c.field; + return row[field]; + }, + }, + }; + + columns.forEach((column) => { + const getApplyQuickFilterFn = column?.getApplyQuickFilterFn; + + if (getApplyQuickFilterFn) { + appliersPerField.push({ + column, + appliers: quickFilterValues.map((quickFilterValue) => { + return { + fn: getApplyQuickFilterFn( + quickFilterValue, + column as GridStateColDef, + stubApiRef as any, + ), + }; + }), + }); + } + }); + + return function isRowMatchingQuickFilter( + row: GridValidRowModel, + shouldApplyFilter?: (field: string) => boolean, + ) { + const result = {} as Record; + + /* eslint-disable no-labels */ + outer: for (let v = 0; v < quickFilterValues.length; v += 1) { + const filterValue = quickFilterValues[v]; + + for (let i = 0; i < appliersPerField.length; i += 1) { + const { column, appliers } = appliersPerField[i]; + const { field } = column; + + if (shouldApplyFilter && !shouldApplyFilter(field)) { + continue; + } + + const applier = appliers[v]; + const value = row[field]; + + if (applier.fn === null) { + continue; + } + const isMatching = applier.fn(value, row, column, stubApiRef); + + if (isMatching) { + result[filterValue] = true; + continue outer; + } + } + + result[filterValue] = false; + } + /* eslint-enable no-labels */ + + return result; + }; +}; + +const getQuicklyFilteredRows = ( + rows: GridRowModel[], + filterModel: GridFilterModel | undefined, + columnsWithDefaultColDef: GridColDef[], +) => { + if (filterModel === undefined || filterModel.quickFilterValues?.length === 0) { + return rows; + } + + const isRowMatchingQuickFilter = buildQuickFilterApplier(filterModel, columnsWithDefaultColDef); + + if (isRowMatchingQuickFilter) { + return rows.filter((row) => { + const result = isRowMatchingQuickFilter(row); + return filterModel.quickFilterLogicOperator === GridLogicOperator.And + ? Object.values(result).every(Boolean) + : Object.values(result).some(Boolean); + }); + } + return rows; +}; + +const getFilteredRows = ( + rows: GridRowModel[], + filterModel: GridFilterModel | undefined, + columnsWithDefaultColDef: GridColDef[], +) => { + if (filterModel === undefined || filterModel.items.length === 0) { + return rows; + } + + const valueGetters = filterModel.items.map(({ field }) => + simplifiedValueGetter( + field, + columnsWithDefaultColDef.find((column) => column.field === field) as any, + ), + ); + + const filterFunctions = filterModel.items.map((filterItem) => { + const { field, operator } = filterItem; + const colDef: GridColDef = columnsWithDefaultColDef.find( + (column) => column.field === field, + ) as any; + + if (!colDef.filterOperators) { + throw new Error(`MUI: No filter operator found for column '${field}'.`); + } + const filterOperator: any = colDef.filterOperators.find( + ({ value }: GridFilterOperator) => operator === value, + ); + + let parsedValue = filterItem.value; + + if (colDef.valueParser) { + const parser = colDef.valueParser; + parsedValue = Array.isArray(filterItem.value) + ? filterItem.value?.map((x) => parser(x, {}, colDef, apiRef)) + : parser(filterItem.value, {}, colDef, apiRef); + } + + return filterOperator.getApplyFilterFn({ filterItem, value: parsedValue }, colDef); + }); + + if (filterModel.logicOperator === GridLogicOperator.Or) { + return rows.filter((row: GridRowModel) => + filterModel.items.some((_, index) => { + const value = valueGetters[index](row); + return filterFunctions[index] === null ? true : filterFunctions[index](value); + }), + ); + } + return rows.filter((row: GridRowModel) => + filterModel.items.every((_, index) => { + const value = valueGetters[index](row); + return filterFunctions[index] === null ? true : filterFunctions[index](value); + }), + ); +}; + +/** + * Simulates server data loading + */ +export const loadServerRows = ( + rows: GridRowModel[], + queryOptions: QueryOptions, + serverOptions: ServerOptions, + columnsWithDefaultColDef: GridColDef[], +): Promise => { + const { minDelay = 100, maxDelay = 300, useCursorPagination } = serverOptions; + + if (maxDelay < minDelay) { + throw new Error('serverOptions.minDelay is larger than serverOptions.maxDelay '); + } + const delay = randomInt(minDelay, maxDelay); + + const { cursor, page = 0, pageSize } = queryOptions; + + let nextCursor; + let firstRowIndex; + let lastRowIndex; + + let filteredRows = getFilteredRows(rows, queryOptions.filterModel, columnsWithDefaultColDef); + + const rowComparator = getRowComparator(queryOptions.sortModel, columnsWithDefaultColDef); + filteredRows = [...filteredRows].sort(rowComparator); + + const totalRowCount = filteredRows.length; + if (!pageSize) { + firstRowIndex = 0; + lastRowIndex = filteredRows.length; + } else if (useCursorPagination) { + firstRowIndex = cursor ? filteredRows.findIndex(({ id }) => id === cursor) : 0; + firstRowIndex = Math.max(firstRowIndex, 0); // if cursor not found return 0 + lastRowIndex = firstRowIndex + pageSize; + + nextCursor = lastRowIndex >= filteredRows.length ? undefined : filteredRows[lastRowIndex].id; + } else { + firstRowIndex = page * pageSize; + lastRowIndex = (page + 1) * pageSize; + } + const hasNextPage = lastRowIndex < filteredRows.length - 1; + const response: FakeServerResponse = { + returnedRows: filteredRows.slice(firstRowIndex, lastRowIndex), + hasNextPage, + nextCursor, + totalRowCount, + }; + + return new Promise((resolve) => { + setTimeout(() => { + resolve(response); + }, delay); // simulate network latency + }); +}; + +interface ProcessTreeDataRowsResponse { + rows: GridRowModel[]; + rootRowCount: number; +} + +const findTreeDataRowChildren = ( + allRows: GridRowModel[], + parentPath: string[], + pathKey: string = 'path', + depth: number = 1, // the depth of the children to find relative to parentDepth, `-1` to find all +) => { + const parentDepth = parentPath.length; + const children = []; + for (let i = 0; i < allRows.length; i += 1) { + const row = allRows[i]; + const rowPath = row[pathKey]; + if (!rowPath) { + continue; + } + if ( + ((depth < 0 && rowPath.length > parentDepth) || rowPath.length === parentDepth + depth) && + parentPath.every((value, index) => value === rowPath[index]) + ) { + children.push(row); + } + } + return children; +}; + +type GetTreeDataFilteredRows = ( + rows: GridValidRowModel[], + filterModel: GridFilterModel | undefined, + columnsWithDefaultColDef: GridColDef[], +) => GridValidRowModel; + +const getTreeDataFilteredRows: GetTreeDataFilteredRows = ( + rows, + filterModel, + columnsWithDefaultColDef, +): GridValidRowModel[] => { + let filteredRows = [...rows]; + if (filterModel && filterModel.quickFilterValues?.length! > 0) { + filteredRows = getQuicklyFilteredRows(rows, filterModel, columnsWithDefaultColDef); + } + if ((filterModel?.items.length ?? 0) > 0) { + filteredRows = getFilteredRows(filteredRows, filterModel, columnsWithDefaultColDef); + } + + if (filteredRows.length === rows.length || filteredRows.length === 0) { + return filteredRows; + } + + const pathsToIndexesMap = new Map(); + rows.forEach((row: GridValidRowModel, index: number) => { + pathsToIndexesMap.set(row.path.join(','), index); + }); + + const includedPaths = new Set(); + filteredRows.forEach((row) => { + includedPaths.add(row.path.join(',')); + }); + + const missingChildren: GridValidRowModel[] = []; + + // include missing children of filtered rows + filteredRows.forEach((row) => { + const path = row.path; + if (path) { + const children = findTreeDataRowChildren(rows, path, 'path', -1); + children.forEach((child) => { + const subPath = child.path.join(','); + if (!includedPaths.has(subPath)) { + missingChildren.push(child); + } + }); + } + }); + + filteredRows = missingChildren.concat(filteredRows); + + const missingParents: GridValidRowModel[] = []; + + // include missing parents of filtered rows + filteredRows.forEach((row) => { + const path = row.path; + if (path) { + includedPaths.add(path.join(',')); + for (let i = 0; i < path.length - 1; i += 1) { + const subPath = path.slice(0, i + 1).join(','); + if (!includedPaths.has(subPath)) { + const index = pathsToIndexesMap.get(subPath); + if (index !== undefined) { + missingParents.push(rows[index]); + includedPaths.add(subPath); + } + } + } + } + }); + + return missingParents.concat(filteredRows); +}; + +/** + * Simulates server data loading + */ +export const processTreeDataRows = ( + rows: GridRowModel[], + queryOptions: ServerSideQueryOptions, + serverOptions: ServerOptions, + columnsWithDefaultColDef: GridColDef[], +): Promise => { + const { minDelay = 100, maxDelay = 300 } = serverOptions; + const pathKey = 'path'; + // TODO: Support filtering and cursor based pagination + if (maxDelay < minDelay) { + throw new Error('serverOptions.minDelay is larger than serverOptions.maxDelay '); + } + + if (queryOptions.groupKeys == null) { + throw new Error('serverOptions.groupKeys must be defined to compute tree data '); + } + + const delay = randomInt(minDelay, maxDelay); + + // apply plain filtering + const filteredRows = getTreeDataFilteredRows( + rows, + queryOptions.filterModel, + columnsWithDefaultColDef, + ) as GridValidRowModel[]; + + // get root row count + const rootRowCount = findTreeDataRowChildren(filteredRows, []).length; + + // find direct children referring to the `parentPath` + const childRows = findTreeDataRowChildren(filteredRows, queryOptions.groupKeys); + + let childRowsWithDescendantCounts = childRows.map((row) => { + const descendants = findTreeDataRowChildren(filteredRows, row[pathKey], pathKey, -1); + const descendantCount = descendants.length; + return { ...row, descendantCount } as GridRowModel; + }); + + if (queryOptions.sortModel) { + // apply sorting + const rowComparator = getRowComparator(queryOptions.sortModel, columnsWithDefaultColDef); + childRowsWithDescendantCounts = [...childRowsWithDescendantCounts].sort(rowComparator); + } + + if (queryOptions.paginationModel && queryOptions.groupKeys.length === 0) { + // Only paginate root rows, grid should refetch root rows when `paginationModel` updates + const { pageSize, page } = queryOptions.paginationModel; + if (pageSize < childRowsWithDescendantCounts.length) { + childRowsWithDescendantCounts = childRowsWithDescendantCounts.slice( + page * pageSize, + (page + 1) * pageSize, + ); + } + } + + return new Promise((resolve) => { + setTimeout(() => { + resolve({ rows: childRowsWithDescendantCounts, rootRowCount }); + }, delay); // simulate network latency + }); +}; diff --git a/packages/x-data-grid-generator/src/hooks/useDemoData.ts b/packages/x-data-grid-generator/src/hooks/useDemoData.ts index 28ad937181b9..2030e6db8240 100644 --- a/packages/x-data-grid-generator/src/hooks/useDemoData.ts +++ b/packages/x-data-grid-generator/src/hooks/useDemoData.ts @@ -1,5 +1,5 @@ import * as React from 'react'; -import LRUCache from 'lru-cache'; +import { LRUCache } from 'lru-cache'; import { GridColumnVisibilityModel } from '@mui/x-data-grid-premium'; import { GridDemoData, getRealGridData } from '../services/real-data-service'; import { getCommodityColumns } from '../columns/commodities.columns'; @@ -37,7 +37,10 @@ export interface UseDemoDataOptions { // Generate fake data from a seed. // It's about x20 faster than getRealData. -async function extrapolateSeed(rowLength: number, data: GridDemoData): Promise { +export async function extrapolateSeed( + rowLength: number, + data: GridDemoData, +): Promise { return new Promise((resolve) => { const seed = data.rows; const rows = data.rows.slice(); @@ -70,7 +73,7 @@ async function extrapolateSeed(rowLength: number, data: GridDemoData): Promise(object: T): T => { +export const deepFreeze = (object: T): T => { // Retrieve the property names defined on object const propNames = Object.getOwnPropertyNames(object); diff --git a/packages/x-data-grid-generator/src/hooks/useMockServer.ts b/packages/x-data-grid-generator/src/hooks/useMockServer.ts new file mode 100644 index 000000000000..cf38b1fa3c85 --- /dev/null +++ b/packages/x-data-grid-generator/src/hooks/useMockServer.ts @@ -0,0 +1,278 @@ +import * as React from 'react'; +import { LRUCache } from 'lru-cache'; +import { + getGridDefaultColumnTypes, + GridRowModel, + GridGetRowsParams, + GridGetRowsResponse, + GridColDef, + GridInitialState, + GridColumnVisibilityModel, +} from '@mui/x-data-grid-pro'; +import { + UseDemoDataOptions, + getColumnsFromOptions, + extrapolateSeed, + deepFreeze, +} from './useDemoData'; +import { GridColDefGenerator } from '../services/gridColDefGenerator'; +import { getRealGridData, GridDemoData } from '../services/real-data-service'; +import { addTreeDataOptionsToDemoData } from '../services/tree-data-generator'; +import { + loadServerRows, + processTreeDataRows, + DEFAULT_DATASET_OPTIONS, + DEFAULT_SERVER_OPTIONS, +} from './serverUtils'; +import type { ServerOptions } from './serverUtils'; +import { randomInt } from '../services'; + +const dataCache = new LRUCache({ + max: 10, + ttl: 60 * 5 * 1e3, // 5 minutes +}); + +export const BASE_URL = 'https://mui.com/x/api/data-grid'; + +type UseMockServerResponse = { + columns: GridColDef[]; + initialState: GridInitialState; + getGroupKey?: (row: GridRowModel) => string; + getChildrenCount?: (row: GridRowModel) => number; + fetchRows: (url: string) => Promise; + loadNewData: () => void; +}; + +function decodeParams(url: string): GridGetRowsParams { + const params = new URL(url).searchParams; + const decodedParams = {} as any; + const array = Array.from(params.entries()); + + for (const [key, value] of array) { + try { + decodedParams[key] = JSON.parse(decodeURIComponent(value)); + } catch (e) { + decodedParams[key] = value; + } + } + + return decodedParams as GridGetRowsParams; +} + +const getInitialState = (columns: GridColDefGenerator[], groupingField?: string) => { + const columnVisibilityModel: GridColumnVisibilityModel = {}; + columns.forEach((col) => { + if (col.hide) { + columnVisibilityModel[col.field] = false; + } + }); + + if (groupingField) { + columnVisibilityModel![groupingField] = false; + } + + return { columns: { columnVisibilityModel } }; +}; + +const defaultColDef = getGridDefaultColumnTypes(); + +export const useMockServer = ( + dataSetOptions?: Partial, + serverOptions?: ServerOptions & { verbose?: boolean }, + shouldRequestsFail?: boolean, +): UseMockServerResponse => { + const [data, setData] = React.useState(); + const [index, setIndex] = React.useState(0); + const shouldRequestsFailRef = React.useRef(shouldRequestsFail ?? false); + + React.useEffect(() => { + if (shouldRequestsFail !== undefined) { + shouldRequestsFailRef.current = shouldRequestsFail; + } + }, [shouldRequestsFail]); + + const options = { ...DEFAULT_DATASET_OPTIONS, ...dataSetOptions }; + + const columns = React.useMemo(() => { + return getColumnsFromOptions({ + dataSet: options.dataSet, + editable: options.editable, + maxColumns: options.maxColumns, + visibleFields: options.visibleFields, + }); + }, [options.dataSet, options.editable, options.maxColumns, options.visibleFields]); + + const initialState = React.useMemo( + () => getInitialState(columns, options.treeData?.groupingField), + [columns, options.treeData?.groupingField], + ); + + const columnsWithDefaultColDef: GridColDef[] = React.useMemo( + () => + columns.map((column) => ({ + ...defaultColDef[column.type || 'string'], + ...column, + })), + [columns], + ); + + const isTreeData = options.treeData?.groupingField != null; + + const getGroupKey = React.useMemo(() => { + if (isTreeData) { + return (row: GridRowModel): string => row[options.treeData!.groupingField!]; + } + return undefined; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [options.treeData?.groupingField, isTreeData]); + + const getChildrenCount = React.useMemo(() => { + if (isTreeData) { + return (row: GridRowModel): number => row.descendantCount; + } + return undefined; + }, [isTreeData]); + + React.useEffect(() => { + const cacheKey = `${options.dataSet}-${options.rowLength}-${index}-${options.maxColumns}`; + + // Cache to allow fast switch between the JavaScript and TypeScript version + // of the demos. + if (dataCache.has(cacheKey)) { + const newData = dataCache.get(cacheKey)!; + setData(newData); + return undefined; + } + + let active = true; + + (async () => { + let rowData; + const rowLength = options.rowLength; + if (rowLength > 1000) { + rowData = await getRealGridData(1000, columns); + rowData = await extrapolateSeed(rowLength, rowData); + } else { + rowData = await getRealGridData(rowLength, columns); + } + + if (!active) { + return; + } + + if (isTreeData) { + rowData = addTreeDataOptionsToDemoData(rowData, { + maxDepth: options.treeData?.maxDepth, + groupingField: options.treeData?.groupingField, + averageChildren: options.treeData?.averageChildren, + }); + } + + if (process.env.NODE_ENV !== 'production') { + deepFreeze(rowData); + } + + dataCache.set(cacheKey, rowData); + setData(rowData); + })(); + + return () => { + active = false; + }; + }, [ + columns, + isTreeData, + options.rowLength, + options.treeData?.maxDepth, + options.treeData?.groupingField, + options.treeData?.averageChildren, + options.dataSet, + options.maxColumns, + index, + ]); + + const fetchRows = React.useCallback( + async (requestUrl: string): Promise => { + if (!data || !requestUrl) { + return new Promise((resolve) => { + resolve({ rows: [], rowCount: 0 }); + }); + } + const params = decodeParams(requestUrl); + const verbose = serverOptions?.verbose ?? true; + // eslint-disable-next-line no-console + const print = console.info; + if (verbose) { + print('MUI X: DATASOURCE REQUEST', params); + } + let getRowsResponse: GridGetRowsResponse; + const serverOptionsWithDefault = { + minDelay: serverOptions?.minDelay ?? DEFAULT_SERVER_OPTIONS.minDelay, + maxDelay: serverOptions?.maxDelay ?? DEFAULT_SERVER_OPTIONS.maxDelay, + useCursorPagination: + serverOptions?.useCursorPagination ?? DEFAULT_SERVER_OPTIONS.useCursorPagination, + }; + + if (shouldRequestsFailRef.current) { + const { minDelay, maxDelay } = serverOptionsWithDefault; + const delay = randomInt(minDelay, maxDelay); + return new Promise((_, reject) => { + if (verbose) { + print('MUI X: DATASOURCE REQUEST FAILURE', params); + } + setTimeout(() => reject(new Error('Could not fetch the data')), delay); + }); + } + + if (isTreeData /* || TODO: `isRowGrouping` */) { + const { rows, rootRowCount } = await processTreeDataRows( + data.rows, + params, + serverOptionsWithDefault, + columnsWithDefaultColDef, + ); + + getRowsResponse = { + rows: rows.slice().map((row) => ({ ...row, path: undefined })), + rowCount: rootRowCount, + }; + } else { + // plain data + const { returnedRows, nextCursor, totalRowCount } = await loadServerRows( + data.rows, + { ...params, ...params.paginationModel }, + serverOptionsWithDefault, + columnsWithDefaultColDef, + ); + getRowsResponse = { rows: returnedRows, rowCount: totalRowCount, pageInfo: { nextCursor } }; + } + + return new Promise((resolve) => { + if (verbose) { + print('MUI X: DATASOURCE RESPONSE', params, getRowsResponse); + } + resolve(getRowsResponse); + }); + }, + [ + data, + serverOptions?.verbose, + serverOptions?.minDelay, + serverOptions?.maxDelay, + serverOptions?.useCursorPagination, + isTreeData, + columnsWithDefaultColDef, + ], + ); + + return { + columns: columnsWithDefaultColDef, + initialState, + getGroupKey, + getChildrenCount, + fetchRows, + loadNewData: () => { + setIndex((oldIndex) => oldIndex + 1); + }, + }; +}; diff --git a/packages/x-data-grid-generator/src/hooks/useQuery.ts b/packages/x-data-grid-generator/src/hooks/useQuery.ts index 55adae6cb6a7..62ae140bcdcd 100644 --- a/packages/x-data-grid-generator/src/hooks/useQuery.ts +++ b/packages/x-data-grid-generator/src/hooks/useQuery.ts @@ -1,14 +1,5 @@ import * as React from 'react'; -import { - getGridDefaultColumnTypes, - GridRowModel, - GridFilterModel, - GridSortModel, - GridRowId, - GridLogicOperator, - GridFilterOperator, - GridColDef, -} from '@mui/x-data-grid-pro'; +import { getGridDefaultColumnTypes, GridRowModel } from '@mui/x-data-grid-pro'; import { isDeepEqual } from '@mui/x-data-grid/internals'; import { useDemoData, @@ -16,198 +7,8 @@ import { getColumnsFromOptions, getInitialState, } from './useDemoData'; -import { randomInt } from '../services/random-generator'; - -const apiRef = {} as any; - -const simplifiedValueGetter = (field: string, colDef: GridColDef) => (row: GridRowModel) => { - return colDef.valueGetter?.(row[row.id] as never, row, colDef, apiRef) || row[field]; -}; - -const getRowComparator = ( - sortModel: GridSortModel | undefined, - columnsWithDefaultColDef: GridColDef[], -) => { - if (!sortModel) { - const comparator = () => 0; - return comparator; - } - const sortOperators = sortModel.map((sortItem) => { - const columnField = sortItem.field; - const colDef = columnsWithDefaultColDef.find(({ field }) => field === columnField) as any; - return { - ...sortItem, - valueGetter: simplifiedValueGetter(columnField, colDef), - sortComparator: colDef.sortComparator, - }; - }); - - const comparator = (row1: GridRowModel, row2: GridRowModel) => - sortOperators.reduce((acc, { valueGetter, sort, sortComparator }) => { - if (acc !== 0) { - return acc; - } - const v1 = valueGetter(row1); - const v2 = valueGetter(row2); - return sort === 'desc' ? -1 * sortComparator(v1, v2) : sortComparator(v1, v2); - }, 0); - - return comparator; -}; - -const getFilteredRows = ( - rows: GridRowModel[], - filterModel: GridFilterModel | undefined, - columnsWithDefaultColDef: GridColDef[], -) => { - if (filterModel === undefined || filterModel.items.length === 0) { - return rows; - } - - const valueGetters = filterModel.items.map(({ field }) => - simplifiedValueGetter( - field, - columnsWithDefaultColDef.find((column) => column.field === field) as any, - ), - ); - const filterFunctions = filterModel.items.map((filterItem) => { - const { field, operator } = filterItem; - const colDef = columnsWithDefaultColDef.find((column) => column.field === field) as any; - - const filterOperator: any = colDef.filterOperators.find( - ({ value }: GridFilterOperator) => operator === value, - ); - - let parsedValue = filterItem.value; - if (colDef.valueParser) { - const parser = colDef.valueParser; - parsedValue = Array.isArray(filterItem.value) - ? filterItem.value?.map((x) => parser(x)) - : parser(filterItem.value); - } - - return filterOperator?.getApplyFilterFn({ filterItem, value: parsedValue }, colDef); - }); - - if (filterModel.logicOperator === GridLogicOperator.Or) { - return rows.filter((row: GridRowModel) => - filterModel.items.some((_, index) => { - const value = valueGetters[index](row); - return filterFunctions[index] === null ? true : filterFunctions[index]({ value }); - }), - ); - } - return rows.filter((row: GridRowModel) => - filterModel.items.every((_, index) => { - const value = valueGetters[index](row); - return filterFunctions[index] === null ? true : filterFunctions[index](value); - }), - ); -}; - -/** - * Simulates server data loading - */ -export const loadServerRows = ( - rows: GridRowModel[], - queryOptions: QueryOptions, - serverOptions: ServerOptions, - columnsWithDefaultColDef: GridColDef[], -): Promise => { - const { minDelay = 100, maxDelay = 300, useCursorPagination } = serverOptions; - - if (maxDelay < minDelay) { - throw new Error('serverOptions.minDelay is larger than serverOptions.maxDelay '); - } - const delay = randomInt(minDelay, maxDelay); - - const { cursor, page = 0, pageSize } = queryOptions; - - let nextCursor; - let firstRowIndex; - let lastRowIndex; - - let filteredRows = getFilteredRows(rows, queryOptions.filterModel, columnsWithDefaultColDef); - - const rowComparator = getRowComparator(queryOptions.sortModel, columnsWithDefaultColDef); - filteredRows = [...filteredRows].sort(rowComparator); - - const totalRowCount = filteredRows.length; - if (!pageSize) { - firstRowIndex = 0; - lastRowIndex = filteredRows.length; - } else if (useCursorPagination) { - firstRowIndex = cursor ? filteredRows.findIndex(({ id }) => id === cursor) : 0; - firstRowIndex = Math.max(firstRowIndex, 0); // if cursor not found return 0 - lastRowIndex = firstRowIndex + pageSize; - - nextCursor = lastRowIndex >= filteredRows.length ? undefined : filteredRows[lastRowIndex].id; - } else { - firstRowIndex = page * pageSize; - lastRowIndex = (page + 1) * pageSize; - } - const hasNextPage = lastRowIndex < filteredRows.length - 1; - const response: FakeServerResponse = { - returnedRows: filteredRows.slice(firstRowIndex, lastRowIndex), - nextCursor, - hasNextPage, - totalRowCount, - }; - - return new Promise((resolve) => { - setTimeout(() => { - resolve(response); - }, delay); // simulate network latency - }); -}; - -interface FakeServerResponse { - returnedRows: GridRowModel[]; - nextCursor?: string; - hasNextPage: boolean; - totalRowCount: number; -} - -interface PageInfo { - totalRowCount?: number; - nextCursor?: string; - hasNextPage?: boolean; - pageSize?: number; -} - -interface DefaultServerOptions { - minDelay: number; - maxDelay: number; - useCursorPagination?: boolean; -} - -type ServerOptions = Partial; - -export interface QueryOptions { - cursor?: GridRowId; - page?: number; - pageSize?: number; - // TODO: implement the behavior liked to following models - filterModel?: GridFilterModel; - sortModel?: GridSortModel; - firstRowToRender?: number; - lastRowToRender?: number; -} - -const DEFAULT_DATASET_OPTIONS: UseDemoDataOptions = { - dataSet: 'Commodity', - rowLength: 100, - maxColumns: 6, -}; - -declare const DISABLE_CHANCE_RANDOM: any; -const disableDelay = typeof DISABLE_CHANCE_RANDOM !== 'undefined' && DISABLE_CHANCE_RANDOM; - -const DEFAULT_SERVER_OPTIONS: DefaultServerOptions = { - minDelay: disableDelay ? 0 : 100, - maxDelay: disableDelay ? 0 : 300, - useCursorPagination: true, -}; +import { DEFAULT_DATASET_OPTIONS, DEFAULT_SERVER_OPTIONS, loadServerRows } from './serverUtils'; +import type { ServerOptions, QueryOptions, PageInfo } from './serverUtils'; export const createFakeServer = ( dataSetOptions?: Partial, diff --git a/packages/x-data-grid-premium/package.json b/packages/x-data-grid-premium/package.json index 732d7f83e502..1f8caf9f7e98 100644 --- a/packages/x-data-grid-premium/package.json +++ b/packages/x-data-grid-premium/package.json @@ -1,6 +1,6 @@ { "name": "@mui/x-data-grid-premium", - "version": "7.7.1", + "version": "7.9.0", "description": "The Premium plan edition of the Data Grid Components (MUI X).", "author": "MUI Team", "main": "src/index.ts", @@ -44,10 +44,11 @@ }, "dependencies": { "@babel/runtime": "^7.24.7", - "@mui/system": "^5.15.20", - "@mui/utils": "^5.15.20", + "@mui/system": "^5.16.0", + "@mui/utils": "^5.16.0", "@mui/x-data-grid": "workspace:*", "@mui/x-data-grid-pro": "workspace:*", + "@mui/x-internals": "workspace:*", "@mui/x-license": "workspace:*", "@types/format-util": "^1.0.4", "clsx": "^2.1.1", @@ -61,10 +62,10 @@ "react-dom": "^17.0.0 || ^18.0.0" }, "devDependencies": { - "@mui/internal-test-utils": "^1.0.1", + "@mui/internal-test-utils": "^1.0.4", "@types/prop-types": "^15.7.12", "date-fns": "^2.30.0", - "rimraf": "^5.0.7" + "rimraf": "^5.0.8" }, "engines": { "node": ">=14.0.0" diff --git a/packages/x-data-grid-premium/src/DataGridPremium/DataGridPremium.tsx b/packages/x-data-grid-premium/src/DataGridPremium/DataGridPremium.tsx index c07ee1336733..13c08a00b7e1 100644 --- a/packages/x-data-grid-premium/src/DataGridPremium/DataGridPremium.tsx +++ b/packages/x-data-grid-premium/src/DataGridPremium/DataGridPremium.tsx @@ -64,21 +64,6 @@ const DataGridPremiumRaw = React.forwardRef(function DataGridPremium ); }); -interface DataGridPremiumComponent { - ( - props: DataGridPremiumProps & React.RefAttributes, - ): React.JSX.Element; - propTypes?: any; -} - -/** - * Demos: - * - [DataGridPremium](https://mui.com/x/react-data-grid/demo/) - * - * API: - * - [DataGridPremium API](https://mui.com/x/api/data-grid/data-grid-premium/) - */ -export const DataGridPremium = React.memo(DataGridPremiumRaw) as DataGridPremiumComponent; DataGridPremiumRaw.propTypes = { // ----------------------------- Warning -------------------------------- @@ -1060,4 +1045,32 @@ DataGridPremiumRaw.propTypes = { * @default false */ treeData: PropTypes.bool, + unstable_dataSource: PropTypes.shape({ + getChildrenCount: PropTypes.func, + getGroupKey: PropTypes.func, + getRows: PropTypes.func.isRequired, + updateRow: PropTypes.func, + }), + unstable_dataSourceCache: PropTypes.shape({ + clear: PropTypes.func.isRequired, + get: PropTypes.func.isRequired, + set: PropTypes.func.isRequired, + }), + unstable_onDataSourceError: PropTypes.func, } as any; + +interface DataGridPremiumComponent { + ( + props: DataGridPremiumProps & React.RefAttributes, + ): React.JSX.Element; + propTypes?: any; +} + +/** + * Demos: + * - [DataGridPremium](https://mui.com/x/react-data-grid/demo/) + * + * API: + * - [DataGridPremium API](https://mui.com/x/api/data-grid/data-grid-premium/) + */ +export const DataGridPremium = React.memo(DataGridPremiumRaw) as DataGridPremiumComponent; diff --git a/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx b/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx index c1d5bf49973a..b61e63a1f927 100644 --- a/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx +++ b/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumComponent.tsx @@ -65,6 +65,9 @@ import { useGridHeaderFiltering, virtualizationStateInitializer, useGridVirtualization, + useGridDataSourceTreeDataPreProcessors, + useGridDataSource, + dataSourceStateInitializer, } from '@mui/x-data-grid-pro/internals'; import { GridApiPremium, GridPrivateApiPremium } from '../models/gridApiPremium'; import { DataGridPremiumProcessedProps } from '../models/dataGridPremiumProps'; @@ -99,6 +102,7 @@ export const useDataGridPremiumComponent = ( useGridRowReorderPreProcessors(apiRef, props); useGridRowGroupingPreProcessors(apiRef, props); useGridTreeDataPreProcessors(apiRef, props); + useGridDataSourceTreeDataPreProcessors(apiRef, props); useGridLazyLoaderPreProcessors(apiRef, props); useGridRowPinningPreProcessors(apiRef); useGridAggregationPreProcessors(apiRef, props); @@ -135,10 +139,11 @@ export const useDataGridPremiumComponent = ( useGridInitializeState(columnMenuStateInitializer, apiRef, props); useGridInitializeState(columnGroupsStateInitializer, apiRef, props); useGridInitializeState(virtualizationStateInitializer, apiRef, props); + useGridInitializeState(dataSourceStateInitializer, apiRef, props); useGridRowGrouping(apiRef, props); useGridHeaderFiltering(apiRef, props); - useGridTreeData(apiRef); + useGridTreeData(apiRef, props); useGridAggregation(apiRef, props); useGridKeyboardNavigation(apiRef, props); useGridRowSelection(apiRef, props); @@ -174,6 +179,7 @@ export const useDataGridPremiumComponent = ( useGridDimensions(apiRef, props); useGridEvents(apiRef, props); useGridStatePersistence(apiRef); + useGridDataSource(apiRef, props); useGridVirtualization(apiRef, props); return apiRef; diff --git a/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumProps.ts b/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumProps.ts index c77bc51f8c99..0d50f1b0a819 100644 --- a/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumProps.ts +++ b/packages/x-data-grid-premium/src/DataGridPremium/useDataGridPremiumProps.ts @@ -1,6 +1,10 @@ import * as React from 'react'; import { useThemeProps } from '@mui/material/styles'; -import { DATA_GRID_PRO_PROPS_DEFAULT_VALUES, GRID_DEFAULT_LOCALE_TEXT } from '@mui/x-data-grid-pro'; +import { + DATA_GRID_PRO_PROPS_DEFAULT_VALUES, + GRID_DEFAULT_LOCALE_TEXT, + DataGridProProps, +} from '@mui/x-data-grid-pro'; import { computeSlots, useProps } from '@mui/x-data-grid-pro/internals'; import { DataGridPremiumProps, @@ -11,6 +15,26 @@ import { GridPremiumSlotsComponent } from '../models'; import { GRID_AGGREGATION_FUNCTIONS } from '../hooks/features/aggregation'; import { DATA_GRID_PREMIUM_DEFAULT_SLOTS_COMPONENTS } from '../constants/dataGridPremiumDefaultSlotsComponents'; +interface GetDataGridPremiumPropsDefaultValues extends DataGridPremiumProps {} + +type DataGridProForcedProps = { + [key in keyof DataGridProProps]?: DataGridPremiumProcessedProps[key]; +}; +type GetDataGridProForcedProps = ( + themedProps: GetDataGridPremiumPropsDefaultValues, +) => DataGridProForcedProps; + +const getDataGridPremiumForcedProps: GetDataGridProForcedProps = (themedProps) => ({ + signature: 'DataGridPremium', + ...(themedProps.unstable_dataSource + ? { + filterMode: 'server', + sortingMode: 'server', + paginationMode: 'server', + } + : {}), +}); + /** * The default values of `DataGridPremiumPropsWithDefaultValue` to inject in the props of DataGridPremium. */ @@ -63,7 +87,7 @@ export const useDataGridPremiumProps = (inProps: DataGridPremiumProps) => { ...themedProps, localeText, slots, - signature: 'DataGridPremium', + ...getDataGridPremiumForcedProps(themedProps), }), [themedProps, localeText, slots], ); diff --git a/packages/x-data-grid-premium/src/models/gridApiPremium.ts b/packages/x-data-grid-premium/src/models/gridApiPremium.ts index c9a1c7f911a9..999a16685997 100644 --- a/packages/x-data-grid-premium/src/models/gridApiPremium.ts +++ b/packages/x-data-grid-premium/src/models/gridApiPremium.ts @@ -8,6 +8,8 @@ import { GridRowMultiSelectionApi, GridColumnReorderApi, GridRowProApi, + GridDataSourceApi, + GridDataSourcePrivateApi, } from '@mui/x-data-grid-pro'; import { GridInitialStatePremium, GridStatePremium } from './gridStatePremium'; import type { GridRowGroupingApi, GridExcelExportApi, GridAggregationApi } from '../hooks'; @@ -27,6 +29,7 @@ export interface GridApiPremium GridExcelExportApi, GridAggregationApi, GridRowPinningApi, + GridDataSourceApi, GridCellSelectionApi, // APIs that are private in Community plan, but public in Pro and Premium plans GridRowMultiSelectionApi, @@ -35,4 +38,5 @@ export interface GridApiPremium export interface GridPrivateApiPremium extends GridApiPremium, GridPrivateOnlyApiCommon, + GridDataSourcePrivateApi, GridDetailPanelPrivateApi {} diff --git a/packages/x-data-grid-premium/src/tests/clipboard.DataGridPremium.test.tsx b/packages/x-data-grid-premium/src/tests/clipboard.DataGridPremium.test.tsx index 1be69796afdd..22cd738034d8 100644 --- a/packages/x-data-grid-premium/src/tests/clipboard.DataGridPremium.test.tsx +++ b/packages/x-data-grid-premium/src/tests/clipboard.DataGridPremium.test.tsx @@ -119,12 +119,14 @@ describe(' - Clipboard', () => { { id: 2, brand: 'Puma' }, ]; render( - , +
+ +
, ); const cell = getCell(0, 0); @@ -143,15 +145,17 @@ describe(' - Clipboard', () => { it('should not escape double quotes when copying multiple cells to clipboard', () => { render( - , +
+ +
, ); const cell = getCell(0, 0); diff --git a/packages/x-data-grid-premium/src/tests/license.DataGridPremium.test.tsx b/packages/x-data-grid-premium/src/tests/license.DataGridPremium.test.tsx index 1773384ed9a0..9879b1d18260 100644 --- a/packages/x-data-grid-premium/src/tests/license.DataGridPremium.test.tsx +++ b/packages/x-data-grid-premium/src/tests/license.DataGridPremium.test.tsx @@ -31,7 +31,7 @@ describe(' - License', () => { ]); await waitFor(() => { - expect(screen.getByText('MUI X Missing license key')).to.not.equal(null); + expect(screen.getByText('MUI X Missing license key')).not.to.equal(null); }); }); }); diff --git a/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx b/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx index 69f2268255ea..824d610884a2 100644 --- a/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx +++ b/packages/x-data-grid-premium/src/tests/rowGrouping.DataGridPremium.test.tsx @@ -34,6 +34,10 @@ import { spy } from 'sinon'; const isJSDOM = /jsdom/.test(window.navigator.userAgent); +interface BaselineProps extends DataGridPremiumProps { + rows: GridRowsProp; +} + const rows: GridRowsProp = [ { id: 0, category1: 'Cat A', category2: 'Cat 1' }, { id: 1, category1: 'Cat A', category2: 'Cat 2' }, @@ -51,7 +55,7 @@ const unbalancedRows: GridRowsProp = [ { id: 5, category1: null }, ]; -const baselineProps: DataGridPremiumProps = { +const baselineProps: BaselineProps = { autoHeight: isJSDOM, disableVirtualization: true, rows, diff --git a/packages/x-data-grid-premium/tsconfig.build.json b/packages/x-data-grid-premium/tsconfig.build.json index 3f1870534100..35dae5af1b78 100644 --- a/packages/x-data-grid-premium/tsconfig.build.json +++ b/packages/x-data-grid-premium/tsconfig.build.json @@ -14,7 +14,8 @@ "references": [ { "path": "../x-data-grid/tsconfig.build.json" }, { "path": "../x-data-grid-pro/tsconfig.build.json" }, - { "path": "../x-license/tsconfig.build.json" } + { "path": "../x-license/tsconfig.build.json" }, + { "path": "../x-internals/tsconfig.build.json" } ], "include": ["src/**/*.ts*"], "exclude": ["src/**/*.spec.ts*", "src/**/*.test.ts*"] diff --git a/packages/x-data-grid-premium/tsconfig.json b/packages/x-data-grid-premium/tsconfig.json index 6afc65000e94..3769236bfa90 100644 --- a/packages/x-data-grid-premium/tsconfig.json +++ b/packages/x-data-grid-premium/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "types": ["@mui/material/themeCssVarsAugmentation", "chai-dom", "mocha"] + "types": ["@mui/material/themeCssVarsAugmentation", "chai-dom", "mocha", "node"] }, "include": ["src/**/*"] } diff --git a/packages/x-data-grid-pro/package.json b/packages/x-data-grid-pro/package.json index 651df24fa461..86126d041862 100644 --- a/packages/x-data-grid-pro/package.json +++ b/packages/x-data-grid-pro/package.json @@ -1,6 +1,6 @@ { "name": "@mui/x-data-grid-pro", - "version": "7.7.1", + "version": "7.9.0", "description": "The Pro plan edition of the Data Grid components (MUI X).", "author": "MUI Team", "main": "src/index.ts", @@ -44,9 +44,10 @@ }, "dependencies": { "@babel/runtime": "^7.24.7", - "@mui/system": "^5.15.20", - "@mui/utils": "^5.15.20", + "@mui/system": "^5.16.0", + "@mui/utils": "^5.16.0", "@mui/x-data-grid": "workspace:*", + "@mui/x-internals": "workspace:*", "@mui/x-license": "workspace:*", "@types/format-util": "^1.0.4", "clsx": "^2.1.1", @@ -59,9 +60,9 @@ "react-dom": "^17.0.0 || ^18.0.0" }, "devDependencies": { - "@mui/internal-test-utils": "^1.0.1", + "@mui/internal-test-utils": "^1.0.4", "@types/prop-types": "^15.7.12", - "rimraf": "^5.0.7" + "rimraf": "^5.0.8" }, "engines": { "node": ">=14.0.0" diff --git a/packages/x-data-grid-pro/src/DataGridPro/DataGridPro.tsx b/packages/x-data-grid-pro/src/DataGridPro/DataGridPro.tsx index 824c3c3d6297..1cacac533b70 100644 --- a/packages/x-data-grid-pro/src/DataGridPro/DataGridPro.tsx +++ b/packages/x-data-grid-pro/src/DataGridPro/DataGridPro.tsx @@ -944,4 +944,16 @@ DataGridProRaw.propTypes = { * @default false */ treeData: PropTypes.bool, + unstable_dataSource: PropTypes.shape({ + getChildrenCount: PropTypes.func, + getGroupKey: PropTypes.func, + getRows: PropTypes.func.isRequired, + updateRow: PropTypes.func, + }), + unstable_dataSourceCache: PropTypes.shape({ + clear: PropTypes.func.isRequired, + get: PropTypes.func.isRequired, + set: PropTypes.func.isRequired, + }), + unstable_onDataSourceError: PropTypes.func, } as any; diff --git a/packages/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx b/packages/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx index 3357ebbaf7eb..d902aa413bb6 100644 --- a/packages/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx +++ b/packages/x-data-grid-pro/src/DataGridPro/useDataGridProComponent.tsx @@ -58,6 +58,7 @@ import { } from '../hooks/features/columnReorder/useGridColumnReorder'; import { useGridTreeData } from '../hooks/features/treeData/useGridTreeData'; import { useGridTreeDataPreProcessors } from '../hooks/features/treeData/useGridTreeDataPreProcessors'; +import { useGridDataSourceTreeDataPreProcessors } from '../hooks/features/serverSideTreeData/useGridDataSourceTreeDataPreProcessors'; import { useGridColumnPinning, columnPinningStateInitializer, @@ -77,6 +78,10 @@ import { rowPinningStateInitializer, } from '../hooks/features/rowPinning/useGridRowPinning'; import { useGridRowPinningPreProcessors } from '../hooks/features/rowPinning/useGridRowPinningPreProcessors'; +import { + useGridDataSource, + dataSourceStateInitializer, +} from '../hooks/features/dataSource/useGridDataSource'; export const useDataGridProComponent = ( inputApiRef: React.MutableRefObject | undefined, @@ -90,6 +95,7 @@ export const useDataGridProComponent = ( useGridRowSelectionPreProcessors(apiRef, props); useGridRowReorderPreProcessors(apiRef, props); useGridTreeDataPreProcessors(apiRef, props); + useGridDataSourceTreeDataPreProcessors(apiRef, props); useGridLazyLoaderPreProcessors(apiRef, props); useGridRowPinningPreProcessors(apiRef); useGridDetailPanelPreProcessors(apiRef, props); @@ -122,9 +128,10 @@ export const useDataGridProComponent = ( useGridInitializeState(columnMenuStateInitializer, apiRef, props); useGridInitializeState(columnGroupsStateInitializer, apiRef, props); useGridInitializeState(virtualizationStateInitializer, apiRef, props); + useGridInitializeState(dataSourceStateInitializer, apiRef, props); useGridHeaderFiltering(apiRef, props); - useGridTreeData(apiRef); + useGridTreeData(apiRef, props); useGridKeyboardNavigation(apiRef, props); useGridRowSelection(apiRef, props); useGridColumnPinning(apiRef, props); @@ -157,6 +164,7 @@ export const useDataGridProComponent = ( useGridEvents(apiRef, props); useGridStatePersistence(apiRef); useGridVirtualization(apiRef, props); + useGridDataSource(apiRef, props); return apiRef; }; diff --git a/packages/x-data-grid-pro/src/DataGridPro/useDataGridProProps.ts b/packages/x-data-grid-pro/src/DataGridPro/useDataGridProProps.ts index 33791fca9b48..b970dfdd4645 100644 --- a/packages/x-data-grid-pro/src/DataGridPro/useDataGridProProps.ts +++ b/packages/x-data-grid-pro/src/DataGridPro/useDataGridProProps.ts @@ -14,6 +14,24 @@ import { import { GridProSlotsComponent } from '../models'; import { DATA_GRID_PRO_DEFAULT_SLOTS_COMPONENTS } from '../constants/dataGridProDefaultSlotsComponents'; +interface GetDataGridProPropsDefaultValues extends DataGridProProps {} + +type DataGridProForcedProps = { [key in keyof DataGridProProps]?: DataGridProProcessedProps[key] }; +type GetDataGridProForcedProps = ( + themedProps: GetDataGridProPropsDefaultValues, +) => DataGridProForcedProps; + +const getDataGridProForcedProps: GetDataGridProForcedProps = (themedProps) => ({ + signature: 'DataGridPro', + ...(themedProps.unstable_dataSource + ? { + filterMode: 'server', + sortingMode: 'server', + paginationMode: 'server', + } + : {}), +}); + /** * The default values of `DataGridProPropsWithDefaultValue` to inject in the props of DataGridPro. */ @@ -65,7 +83,7 @@ export const useDataGridProProps = (inProps: DataGr ...themedProps, localeText, slots, - signature: 'DataGridPro', + ...getDataGridProForcedProps(themedProps), }), [themedProps, localeText, slots], ); diff --git a/packages/x-data-grid-pro/src/components/GridDataSourceTreeDataGroupingCell.tsx b/packages/x-data-grid-pro/src/components/GridDataSourceTreeDataGroupingCell.tsx new file mode 100644 index 000000000000..d03c28e675c4 --- /dev/null +++ b/packages/x-data-grid-pro/src/components/GridDataSourceTreeDataGroupingCell.tsx @@ -0,0 +1,132 @@ +import * as React from 'react'; +import { unstable_composeClasses as composeClasses } from '@mui/utils'; +import Box from '@mui/material/Box'; +import Badge from '@mui/material/Badge'; +import { + getDataGridUtilityClass, + GridRenderCellParams, + GridDataSourceGroupNode, + useGridSelector, +} from '@mui/x-data-grid'; +import CircularProgress from '@mui/material/CircularProgress'; +import { useGridRootProps } from '../hooks/utils/useGridRootProps'; +import { useGridPrivateApiContext } from '../hooks/utils/useGridPrivateApiContext'; +import { DataGridProProcessedProps } from '../models/dataGridProProps'; +import { GridPrivateApiPro } from '../models/gridApiPro'; +import { GridStatePro } from '../models/gridStatePro'; + +type OwnerState = DataGridProProcessedProps; + +const useUtilityClasses = (ownerState: OwnerState) => { + const { classes } = ownerState; + + const slots = { + root: ['treeDataGroupingCell'], + toggle: ['treeDataGroupingCellToggle'], + loadingContainer: ['treeDataGroupingCellLoadingContainer'], + }; + + return composeClasses(slots, getDataGridUtilityClass, classes); +}; + +interface GridTreeDataGroupingCellProps + extends GridRenderCellParams { + hideDescendantCount?: boolean; + /** + * The cell offset multiplier used for calculating cell offset (`rowNode.depth * offsetMultiplier` px). + * @default 2 + */ + offsetMultiplier?: number; +} + +interface GridTreeDataGroupingCellIconProps + extends Pick { + descendantCount: number; +} + +function GridTreeDataGroupingCellIcon(props: GridTreeDataGroupingCellIconProps) { + const apiRef = useGridPrivateApiContext() as React.MutableRefObject; + const rootProps = useGridRootProps(); + const classes = useUtilityClasses(rootProps); + const { rowNode, id, field, descendantCount } = props; + + const loadingSelector = (state: GridStatePro) => state.dataSource.loading[id] ?? false; + const errorSelector = (state: GridStatePro) => state.dataSource.errors[id]; + const isDataLoading = useGridSelector(apiRef, loadingSelector); + const error = useGridSelector(apiRef, errorSelector); + + const handleClick = (event: React.MouseEvent) => { + if (!rowNode.childrenExpanded) { + // always fetch/get from cache the children when the node is expanded + apiRef.current.unstable_dataSource.fetchRows(id); + } else { + apiRef.current.setRowChildrenExpansion(id, !rowNode.childrenExpanded); + } + apiRef.current.setCellFocus(id, field); + event.stopPropagation(); // TODO remove event.stopPropagation + }; + + const Icon = rowNode.childrenExpanded + ? rootProps.slots.treeDataCollapseIcon + : rootProps.slots.treeDataExpandIcon; + + if (isDataLoading) { + return ( +
+ +
+ ); + } + return descendantCount > 0 ? ( + + + + + + + + ) : null; +} + +export function GridDataSourceTreeDataGroupingCell(props: GridTreeDataGroupingCellProps) { + const { id, field, formattedValue, rowNode, hideDescendantCount, offsetMultiplier = 2 } = props; + + const rootProps = useGridRootProps(); + const apiRef = useGridPrivateApiContext(); + const rowSelector = (state: GridStatePro) => state.rows.dataRowIdToModelLookup[id]; + const row = useGridSelector(apiRef, rowSelector); + const classes = useUtilityClasses(rootProps); + + let descendantCount = 0; + if (row) { + descendantCount = Math.max(rootProps.unstable_dataSource?.getChildrenCount?.(row) ?? 0, 0); + } + + return ( + +
+ +
+ + {formattedValue === undefined ? rowNode.groupingKey : formattedValue} + {!hideDescendantCount && descendantCount > 0 ? ` (${descendantCount})` : ''} + +
+ ); +} diff --git a/packages/x-data-grid-pro/src/components/GridDetailPanel.tsx b/packages/x-data-grid-pro/src/components/GridDetailPanel.tsx index 82577308cb75..a37b3e4bc807 100644 --- a/packages/x-data-grid-pro/src/components/GridDetailPanel.tsx +++ b/packages/x-data-grid-pro/src/components/GridDetailPanel.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { styled } from '@mui/material/styles'; import { GridRowId } from '@mui/x-data-grid'; -import { useResizeObserver } from '@mui/x-data-grid/internals'; +import { useResizeObserver } from '@mui/x-internals/useResizeObserver'; import { useGridRootProps } from '../hooks/utils/useGridRootProps'; import { useGridPrivateApiContext } from '../hooks/utils/useGridPrivateApiContext'; import { DataGridProProcessedProps } from '../models/dataGridProProps'; diff --git a/packages/x-data-grid-pro/src/components/GridTreeDataGroupingCell.tsx b/packages/x-data-grid-pro/src/components/GridTreeDataGroupingCell.tsx index 8e1e85688d89..673b637ee038 100644 --- a/packages/x-data-grid-pro/src/components/GridTreeDataGroupingCell.tsx +++ b/packages/x-data-grid-pro/src/components/GridTreeDataGroupingCell.tsx @@ -13,7 +13,7 @@ import { useGridRootProps } from '../hooks/utils/useGridRootProps'; import { useGridApiContext } from '../hooks/utils/useGridApiContext'; import { DataGridProProcessedProps } from '../models/dataGridProProps'; -type OwnerState = { classes: DataGridProProcessedProps['classes'] }; +type OwnerState = DataGridProProcessedProps; const useUtilityClasses = (ownerState: OwnerState) => { const { classes } = ownerState; @@ -40,8 +40,7 @@ function GridTreeDataGroupingCell(props: GridTreeDataGroupingCellProps) { const rootProps = useGridRootProps(); const apiRef = useGridApiContext(); - const ownerState: OwnerState = { classes: rootProps.classes }; - const classes = useUtilityClasses(ownerState); + const classes = useUtilityClasses(rootProps); const filteredDescendantCountLookup = useGridSelector( apiRef, gridFilteredDescendantCountLookupSelector, diff --git a/packages/x-data-grid-pro/src/hooks/features/dataSource/cache.ts b/packages/x-data-grid-pro/src/hooks/features/dataSource/cache.ts new file mode 100644 index 000000000000..dde8cad3d39f --- /dev/null +++ b/packages/x-data-grid-pro/src/hooks/features/dataSource/cache.ts @@ -0,0 +1,53 @@ +import { GridGetRowsParams, GridGetRowsResponse } from '../../../models'; + +type GridDataSourceCacheDefaultConfig = { + /** + * Time To Live for each cache entry in milliseconds. + * After this time the cache entry will become stale and the next query will result in cache miss. + * @default 300000 (5 minutes) + */ + ttl?: number; +}; + +function getKey(params: GridGetRowsParams) { + return JSON.stringify([ + params.paginationModel, + params.filterModel, + params.sortModel, + params.groupKeys, + ]); +} + +export class GridDataSourceCacheDefault { + private cache: Record; + + private ttl: number; + + constructor({ ttl = 300000 }: GridDataSourceCacheDefaultConfig) { + this.cache = {}; + this.ttl = ttl; + } + + set(key: GridGetRowsParams, value: GridGetRowsResponse) { + const keyString = getKey(key); + const expiry = Date.now() + this.ttl; + this.cache[keyString] = { value, expiry }; + } + + get(key: GridGetRowsParams): GridGetRowsResponse | undefined { + const keyString = getKey(key); + const entry = this.cache[keyString]; + if (!entry) { + return undefined; + } + if (Date.now() > entry.expiry) { + delete this.cache[keyString]; + return undefined; + } + return entry.value; + } + + clear() { + this.cache = {}; + } +} diff --git a/packages/x-data-grid-pro/src/hooks/features/dataSource/gridDataSourceSelector.ts b/packages/x-data-grid-pro/src/hooks/features/dataSource/gridDataSourceSelector.ts new file mode 100644 index 000000000000..a7bee9eec1d9 --- /dev/null +++ b/packages/x-data-grid-pro/src/hooks/features/dataSource/gridDataSourceSelector.ts @@ -0,0 +1,43 @@ +import { + GridPaginationModel, + gridFilterModelSelector, + gridSortModelSelector, + gridPaginationModelSelector, +} from '@mui/x-data-grid'; +import { createSelector } from '@mui/x-data-grid/internals'; +import { GridStatePro } from '../../../models/gridStatePro'; + +const computeStartEnd = (paginationModel: GridPaginationModel) => { + const start = paginationModel.page * paginationModel.pageSize; + const end = start + paginationModel.pageSize - 1; + return { start, end }; +}; + +export const gridGetRowsParamsSelector = createSelector( + gridFilterModelSelector, + gridSortModelSelector, + gridPaginationModelSelector, + (filterModel, sortModel, paginationModel) => { + return { + groupKeys: [], + // TODO: Implement with `rowGrouping` + groupFields: [], + paginationModel, + sortModel, + filterModel, + ...computeStartEnd(paginationModel), + }; + }, +); + +export const gridDataSourceStateSelector = (state: GridStatePro) => state.dataSource; + +export const gridDataSourceLoadingSelector = createSelector( + gridDataSourceStateSelector, + (dataSource) => dataSource.loading, +); + +export const gridDataSourceErrorsSelector = createSelector( + gridDataSourceStateSelector, + (dataSource) => dataSource.errors, +); diff --git a/packages/x-data-grid-pro/src/hooks/features/dataSource/interfaces.ts b/packages/x-data-grid-pro/src/hooks/features/dataSource/interfaces.ts new file mode 100644 index 000000000000..90bfc4ed39de --- /dev/null +++ b/packages/x-data-grid-pro/src/hooks/features/dataSource/interfaces.ts @@ -0,0 +1,53 @@ +import { GridRowId } from '@mui/x-data-grid'; +import { GridDataSourceCache } from '../../../models'; + +export interface GridDataSourceState { + loading: Record; + errors: Record; +} + +/** + * The base data source API interface that is available in the grid [[apiRef]]. + */ +export interface GridDataSourceApiBase { + /** + * Set the loading state of a parent row. + * @param {string} parentId The id of the parent node. + * @param {boolean} loading The loading state to set. + */ + setChildrenLoading: (parentId: GridRowId, loading: boolean) => void; + /** + * Set error occured while fetching the children of a row. + * @param {string} parentId The id of the parent node. + * @param {Error} error The error of type `Error` or `null`. + */ + setChildrenFetchError: (parentId: GridRowId, error: Error | null) => void; + /** + * Fetches the rows from the server for a given `parentId`. + * If no `parentId` is provided, it fetches the root rows. + * @param {string} parentId The id of the group to be fetched. + */ + fetchRows: (parentId?: GridRowId) => void; + /** + * The data source cache object. + */ + cache: GridDataSourceCache; +} + +export interface GridDataSourceApi { + /** + * The data source API. + */ + unstable_dataSource: GridDataSourceApiBase; +} +export interface GridDataSourcePrivateApi { + /** + * Initiates the fetch of the children of a row. + * @param {string} id The id of the group to be fetched. + */ + fetchRowChildren: (id: GridRowId) => void; + /** + * Resets the data source state. + */ + resetDataSourceState: () => void; +} diff --git a/packages/x-data-grid-pro/src/hooks/features/dataSource/useGridDataSource.ts b/packages/x-data-grid-pro/src/hooks/features/dataSource/useGridDataSource.ts new file mode 100644 index 000000000000..b948c0a48745 --- /dev/null +++ b/packages/x-data-grid-pro/src/hooks/features/dataSource/useGridDataSource.ts @@ -0,0 +1,299 @@ +import * as React from 'react'; +import useLazyRef from '@mui/utils/useLazyRef'; +import { + useGridApiEventHandler, + gridRowsLoadingSelector, + useGridApiMethod, + GridDataSourceGroupNode, + useGridSelector, + GridRowId, +} from '@mui/x-data-grid'; +import { gridRowGroupsToFetchSelector, GridStateInitializer } from '@mui/x-data-grid/internals'; +import { GridPrivateApiPro } from '../../../models/gridApiPro'; +import { DataGridProProcessedProps } from '../../../models/dataGridProProps'; +import { gridGetRowsParamsSelector, gridDataSourceErrorsSelector } from './gridDataSourceSelector'; +import { GridDataSourceApi, GridDataSourceApiBase, GridDataSourcePrivateApi } from './interfaces'; +import { runIfServerMode, NestedDataManager, RequestStatus } from './utils'; +import { GridDataSourceCache } from '../../../models'; +import { GridDataSourceCacheDefault } from './cache'; + +const INITIAL_STATE = { + loading: {}, + errors: {}, +}; + +const noopCache: GridDataSourceCache = { + clear: () => {}, + get: () => undefined, + set: () => {}, +}; + +function getCache(cacheProp?: GridDataSourceCache | null) { + if (cacheProp === null) { + return noopCache; + } + return cacheProp ?? new GridDataSourceCacheDefault({}); +} + +export const dataSourceStateInitializer: GridStateInitializer = (state) => { + return { + ...state, + dataSource: INITIAL_STATE, + }; +}; + +export const useGridDataSource = ( + apiRef: React.MutableRefObject, + props: Pick< + DataGridProProcessedProps, + | 'unstable_dataSource' + | 'unstable_dataSourceCache' + | 'unstable_onDataSourceError' + | 'sortingMode' + | 'filterMode' + | 'paginationMode' + | 'treeData' + >, +) => { + const nestedDataManager = useLazyRef( + () => new NestedDataManager(apiRef), + ).current; + const groupsToAutoFetch = useGridSelector(apiRef, gridRowGroupsToFetchSelector); + const scheduledGroups = React.useRef(0); + const onError = props.unstable_onDataSourceError; + + const [cache, setCache] = React.useState(() => + getCache(props.unstable_dataSourceCache), + ); + + const fetchRows = React.useCallback( + async (parentId?: GridRowId) => { + const getRows = props.unstable_dataSource?.getRows; + if (!getRows) { + return; + } + + if (parentId) { + nestedDataManager.queue([parentId]); + return; + } + + nestedDataManager.clear(); + scheduledGroups.current = 0; + const dataSourceState = apiRef.current.state.dataSource; + if (dataSourceState !== INITIAL_STATE) { + apiRef.current.resetDataSourceState(); + } + + const fetchParams = gridGetRowsParamsSelector(apiRef); + + const cachedData = apiRef.current.unstable_dataSource.cache.get(fetchParams); + + if (cachedData !== undefined) { + const rows = cachedData.rows; + apiRef.current.setRows(rows); + if (cachedData.rowCount) { + apiRef.current.setRowCount(cachedData.rowCount); + } + return; + } + + const isLoading = gridRowsLoadingSelector(apiRef); + if (!isLoading) { + apiRef.current.setLoading(true); + } + + try { + const getRowsResponse = await getRows(fetchParams); + apiRef.current.unstable_dataSource.cache.set(fetchParams, getRowsResponse); + if (getRowsResponse.rowCount) { + apiRef.current.setRowCount(getRowsResponse.rowCount); + } + apiRef.current.setRows(getRowsResponse.rows); + apiRef.current.setLoading(false); + } catch (error) { + apiRef.current.setRows([]); + apiRef.current.setLoading(false); + onError?.(error as Error, fetchParams); + } + }, + [nestedDataManager, apiRef, props.unstable_dataSource?.getRows, onError], + ); + + const fetchRowChildren = React.useCallback( + async (id) => { + if (!props.treeData) { + nestedDataManager.clearPendingRequest(id); + return; + } + const getRows = props.unstable_dataSource?.getRows; + if (!getRows) { + nestedDataManager.clearPendingRequest(id); + return; + } + + const rowNode = apiRef.current.getRowNode(id); + if (!rowNode) { + nestedDataManager.clearPendingRequest(id); + return; + } + + const fetchParams = { ...gridGetRowsParamsSelector(apiRef), groupKeys: rowNode.path }; + + const cachedData = apiRef.current.unstable_dataSource.cache.get(fetchParams); + + if (cachedData !== undefined) { + const rows = cachedData.rows; + nestedDataManager.setRequestSettled(id); + apiRef.current.updateServerRows(rows, rowNode.path); + if (cachedData.rowCount) { + apiRef.current.setRowCount(cachedData.rowCount); + } + apiRef.current.setRowChildrenExpansion(id, true); + apiRef.current.unstable_dataSource.setChildrenLoading(id, false); + return; + } + + const existingError = gridDataSourceErrorsSelector(apiRef)[id] ?? null; + if (existingError) { + apiRef.current.unstable_dataSource.setChildrenFetchError(id, null); + } + + try { + const getRowsResponse = await getRows(fetchParams); + if (!apiRef.current.getRowNode(id)) { + // The row has been removed from the grid + nestedDataManager.clearPendingRequest(id); + return; + } + if (nestedDataManager.getRequestStatus(id) === RequestStatus.UNKNOWN) { + apiRef.current.unstable_dataSource.setChildrenLoading(id, false); + return; + } + nestedDataManager.setRequestSettled(id); + apiRef.current.unstable_dataSource.cache.set(fetchParams, getRowsResponse); + if (getRowsResponse.rowCount) { + apiRef.current.setRowCount(getRowsResponse.rowCount); + } + apiRef.current.updateServerRows(getRowsResponse.rows, rowNode.path); + apiRef.current.setRowChildrenExpansion(id, true); + } catch (error) { + const e = error as Error; + apiRef.current.unstable_dataSource.setChildrenFetchError(id, e); + onError?.(e, fetchParams); + } finally { + apiRef.current.unstable_dataSource.setChildrenLoading(id, false); + nestedDataManager.setRequestSettled(id); + } + }, + [nestedDataManager, onError, apiRef, props.treeData, props.unstable_dataSource?.getRows], + ); + + const setChildrenLoading = React.useCallback( + (parentId, isLoading) => { + apiRef.current.setState((state) => { + if (!state.dataSource.loading[parentId] && isLoading === false) { + return state; + } + const newLoadingState = { ...state.dataSource.loading }; + if (isLoading === false) { + delete newLoadingState[parentId]; + } else { + newLoadingState[parentId] = isLoading; + } + return { + ...state, + dataSource: { + ...state.dataSource, + loading: newLoadingState, + }, + }; + }); + }, + [apiRef], + ); + + const setChildrenFetchError = React.useCallback( + (parentId, error) => { + apiRef.current.setState((state) => { + const newErrorsState = { ...state.dataSource.errors }; + if (error === null && newErrorsState[parentId] !== undefined) { + delete newErrorsState[parentId]; + } else { + newErrorsState[parentId] = error; + } + return { + ...state, + dataSource: { + ...state.dataSource, + errors: newErrorsState, + }, + }; + }); + }, + [apiRef], + ); + + const resetDataSourceState = React.useCallback(() => { + apiRef.current.setState((state) => { + return { + ...state, + dataSource: INITIAL_STATE, + }; + }); + }, [apiRef]); + + const dataSourceApi: GridDataSourceApi = { + unstable_dataSource: { + setChildrenLoading, + setChildrenFetchError, + fetchRows, + cache, + }, + }; + + const dataSourcePrivateApi: GridDataSourcePrivateApi = { + fetchRowChildren, + resetDataSourceState, + }; + + useGridApiMethod(apiRef, dataSourceApi, 'public'); + useGridApiMethod(apiRef, dataSourcePrivateApi, 'private'); + + useGridApiEventHandler(apiRef, 'sortModelChange', runIfServerMode(props.sortingMode, fetchRows)); + useGridApiEventHandler(apiRef, 'filterModelChange', runIfServerMode(props.filterMode, fetchRows)); + useGridApiEventHandler( + apiRef, + 'paginationModelChange', + runIfServerMode(props.paginationMode, fetchRows), + ); + + const isFirstRender = React.useRef(true); + React.useEffect(() => { + if (isFirstRender.current) { + isFirstRender.current = false; + return; + } + const newCache = getCache(props.unstable_dataSourceCache); + setCache((prevCache) => (prevCache !== newCache ? newCache : prevCache)); + }, [props.unstable_dataSourceCache]); + + React.useEffect(() => { + if (props.unstable_dataSource) { + apiRef.current.unstable_dataSource.cache.clear(); + apiRef.current.unstable_dataSource.fetchRows(); + } + }, [apiRef, props.unstable_dataSource]); + + React.useEffect(() => { + if ( + groupsToAutoFetch && + groupsToAutoFetch.length && + scheduledGroups.current < groupsToAutoFetch.length + ) { + const groupsToSchedule = groupsToAutoFetch.slice(scheduledGroups.current); + nestedDataManager.queue(groupsToSchedule); + scheduledGroups.current = groupsToAutoFetch.length; + } + }, [apiRef, nestedDataManager, groupsToAutoFetch]); +}; diff --git a/packages/x-data-grid-pro/src/hooks/features/dataSource/utils.ts b/packages/x-data-grid-pro/src/hooks/features/dataSource/utils.ts new file mode 100644 index 000000000000..dafc6d9783f2 --- /dev/null +++ b/packages/x-data-grid-pro/src/hooks/features/dataSource/utils.ts @@ -0,0 +1,114 @@ +import { GridRowId } from '@mui/x-data-grid'; +import { GridPrivateApiPro } from '../../../models/gridApiPro'; + +const MAX_CONCURRENT_REQUESTS = Infinity; + +export const runIfServerMode = (modeProp: 'server' | 'client', fn: Function) => () => { + if (modeProp === 'server') { + fn(); + } +}; + +export enum RequestStatus { + QUEUED, + PENDING, + SETTLED, + UNKNOWN, +} + +/** + * Fetches row children from the server with option to limit the number of concurrent requests + * Determines the status of a request based on the enum `RequestStatus` + * Uses `GridRowId` to uniquely identify a request + */ +export class NestedDataManager { + private pendingRequests: Set = new Set(); + + private queuedRequests: Set = new Set(); + + private settledRequests: Set = new Set(); + + private api: GridPrivateApiPro; + + private maxConcurrentRequests: number; + + constructor( + privateApiRef: React.MutableRefObject, + maxConcurrentRequests = MAX_CONCURRENT_REQUESTS, + ) { + this.api = privateApiRef.current; + this.maxConcurrentRequests = maxConcurrentRequests; + } + + private processQueue = async () => { + if (this.queuedRequests.size === 0 || this.pendingRequests.size >= this.maxConcurrentRequests) { + return; + } + const loopLength = Math.min( + this.maxConcurrentRequests - this.pendingRequests.size, + this.queuedRequests.size, + ); + if (loopLength === 0) { + return; + } + const fetchQueue = Array.from(this.queuedRequests); + + for (let i = 0; i < loopLength; i += 1) { + const id = fetchQueue[i]; + this.queuedRequests.delete(id); + this.pendingRequests.add(id); + this.api.fetchRowChildren(id); + } + }; + + public queue = async (ids: GridRowId[]) => { + const loadingIds: Record = {}; + ids.forEach((id) => { + this.queuedRequests.add(id); + loadingIds[id] = true; + }); + this.api.setState((state) => ({ + ...state, + dataSource: { + ...state.dataSource, + loading: { + ...state.dataSource.loading, + ...loadingIds, + }, + }, + })); + this.processQueue(); + }; + + public setRequestSettled = (id: GridRowId) => { + this.pendingRequests.delete(id); + this.settledRequests.add(id); + this.processQueue(); + }; + + public clear = () => { + this.queuedRequests.clear(); + Array.from(this.pendingRequests).forEach((id) => this.clearPendingRequest(id)); + }; + + public clearPendingRequest = (id: GridRowId) => { + this.api.unstable_dataSource.setChildrenLoading(id, false); + this.pendingRequests.delete(id); + this.processQueue(); + }; + + public getRequestStatus = (id: GridRowId) => { + if (this.pendingRequests.has(id)) { + return RequestStatus.PENDING; + } + if (this.queuedRequests.has(id)) { + return RequestStatus.QUEUED; + } + if (this.settledRequests.has(id)) { + return RequestStatus.SETTLED; + } + return RequestStatus.UNKNOWN; + }; + + public getActiveRequestsCount = () => this.pendingRequests.size + this.queuedRequests.size; +} diff --git a/packages/x-data-grid-pro/src/hooks/features/index.ts b/packages/x-data-grid-pro/src/hooks/features/index.ts index ea390a65dc61..dd9209be6a53 100644 --- a/packages/x-data-grid-pro/src/hooks/features/index.ts +++ b/packages/x-data-grid-pro/src/hooks/features/index.ts @@ -5,3 +5,5 @@ export * from './rowReorder'; export * from './treeData'; export * from './detailPanel'; export * from './rowPinning'; +export * from './dataSource/interfaces'; +export * from './dataSource/cache'; diff --git a/packages/x-data-grid-pro/src/hooks/features/serverSideTreeData/useGridDataSourceTreeDataPreProcessors.tsx b/packages/x-data-grid-pro/src/hooks/features/serverSideTreeData/useGridDataSourceTreeDataPreProcessors.tsx new file mode 100644 index 000000000000..6c182e6c04d1 --- /dev/null +++ b/packages/x-data-grid-pro/src/hooks/features/serverSideTreeData/useGridDataSourceTreeDataPreProcessors.tsx @@ -0,0 +1,256 @@ +import * as React from 'react'; +import { + gridRowTreeSelector, + useFirstRender, + GridColDef, + GridRenderCellParams, + GridDataSourceGroupNode, + GridRowId, + GRID_CHECKBOX_SELECTION_FIELD, +} from '@mui/x-data-grid'; +import { + GridPipeProcessor, + GridRowsPartialUpdates, + GridStrategyProcessor, + useGridRegisterPipeProcessor, + useGridRegisterStrategyProcessor, +} from '@mui/x-data-grid/internals'; +import { + GRID_TREE_DATA_GROUPING_COL_DEF, + GRID_TREE_DATA_GROUPING_COL_DEF_FORCED_PROPERTIES, +} from '../treeData/gridTreeDataGroupColDef'; +import { DataGridProProcessedProps } from '../../../models/dataGridProProps'; +import { skipFiltering, skipSorting } from './utils'; +import { GridPrivateApiPro } from '../../../models/gridApiPro'; +import { + GridGroupingColDefOverride, + GridGroupingColDefOverrideParams, +} from '../../../models/gridGroupingColDefOverride'; +import { GridDataSourceTreeDataGroupingCell } from '../../../components/GridDataSourceTreeDataGroupingCell'; +import { createRowTree } from '../../../utils/tree/createRowTree'; +import { + GridTreePathDuplicateHandler, + RowTreeBuilderGroupingCriterion, +} from '../../../utils/tree/models'; +import { updateRowTree } from '../../../utils/tree/updateRowTree'; +import { getVisibleRowsLookup } from '../../../utils/tree/utils'; + +const DATA_SOURCE_TREE_DATA_STRATEGY = 'dataSourceTreeData'; + +export const useGridDataSourceTreeDataPreProcessors = ( + privateApiRef: React.MutableRefObject, + props: Pick< + DataGridProProcessedProps, + | 'treeData' + | 'groupingColDef' + | 'disableChildrenSorting' + | 'disableChildrenFiltering' + | 'defaultGroupingExpansionDepth' + | 'isGroupExpandedByDefault' + | 'unstable_dataSource' + >, +) => { + const setStrategyAvailability = React.useCallback(() => { + privateApiRef.current.setStrategyAvailability( + 'rowTree', + DATA_SOURCE_TREE_DATA_STRATEGY, + props.treeData && props.unstable_dataSource ? () => true : () => false, + ); + }, [privateApiRef, props.treeData, props.unstable_dataSource]); + + const getGroupingColDef = React.useCallback(() => { + const groupingColDefProp = props.groupingColDef; + + let colDefOverride: GridGroupingColDefOverride | null | undefined; + if (typeof groupingColDefProp === 'function') { + const params: GridGroupingColDefOverrideParams = { + groupingName: DATA_SOURCE_TREE_DATA_STRATEGY, + fields: [], + }; + + colDefOverride = groupingColDefProp(params); + } else { + colDefOverride = groupingColDefProp; + } + + const { hideDescendantCount, ...colDefOverrideProperties } = colDefOverride ?? {}; + + const commonProperties: Omit = { + ...GRID_TREE_DATA_GROUPING_COL_DEF, + renderCell: (params) => ( + )} + hideDescendantCount={hideDescendantCount} + /> + ), + headerName: privateApiRef.current.getLocaleText('treeDataGroupingHeaderName'), + }; + + return { + ...commonProperties, + ...colDefOverrideProperties, + ...GRID_TREE_DATA_GROUPING_COL_DEF_FORCED_PROPERTIES, + }; + }, [privateApiRef, props.groupingColDef]); + + const updateGroupingColumn = React.useCallback>( + (columnsState) => { + if (!props.unstable_dataSource) { + return columnsState; + } + const groupingColDefField = GRID_TREE_DATA_GROUPING_COL_DEF_FORCED_PROPERTIES.field; + + const shouldHaveGroupingColumn = props.treeData; + const prevGroupingColumn = columnsState.lookup[groupingColDefField]; + + if (shouldHaveGroupingColumn) { + const newGroupingColumn = getGroupingColDef(); + if (prevGroupingColumn) { + newGroupingColumn.width = prevGroupingColumn.width; + newGroupingColumn.flex = prevGroupingColumn.flex; + } + columnsState.lookup[groupingColDefField] = newGroupingColumn; + if (prevGroupingColumn == null) { + const index = columnsState.orderedFields[0] === GRID_CHECKBOX_SELECTION_FIELD ? 1 : 0; + columnsState.orderedFields = [ + ...columnsState.orderedFields.slice(0, index), + groupingColDefField, + ...columnsState.orderedFields.slice(index), + ]; + } + } else if (!shouldHaveGroupingColumn && prevGroupingColumn) { + delete columnsState.lookup[groupingColDefField]; + columnsState.orderedFields = columnsState.orderedFields.filter( + (field) => field !== groupingColDefField, + ); + } + + return columnsState; + }, + [props.treeData, props.unstable_dataSource, getGroupingColDef], + ); + + const createRowTreeForTreeData = React.useCallback>( + (params) => { + const getGroupKey = props.unstable_dataSource?.getGroupKey; + if (!getGroupKey) { + throw new Error('MUI X: No `getGroupKey` method provided with the dataSource.'); + } + + const getChildrenCount = props.unstable_dataSource?.getChildrenCount; + if (!getChildrenCount) { + throw new Error('MUI X: No `getChildrenCount` method provided with the dataSource.'); + } + + const parentPath = (params.updates as GridRowsPartialUpdates).groupKeys ?? []; + + const getRowTreeBuilderNode = (rowId: GridRowId) => { + const count = getChildrenCount(params.dataRowIdToModelLookup[rowId]); + return { + id: rowId, + path: [...parentPath, getGroupKey(params.dataRowIdToModelLookup[rowId])].map( + (key): RowTreeBuilderGroupingCriterion => ({ key, field: null }), + ), + hasServerChildren: !!count && count !== 0, + }; + }; + + const onDuplicatePath: GridTreePathDuplicateHandler = (firstId, secondId, path) => { + throw new Error( + [ + 'MUI X: The values returned by `getGroupKey` for all the sibling rows should be unique.', + `The rows with id #${firstId} and #${secondId} have the same.`, + `Path: ${JSON.stringify(path.map((step) => step.key))}.`, + ].join('\n'), + ); + }; + + if (params.updates.type === 'full') { + return createRowTree({ + previousTree: params.previousTree, + nodes: params.updates.rows.map(getRowTreeBuilderNode), + defaultGroupingExpansionDepth: props.defaultGroupingExpansionDepth, + isGroupExpandedByDefault: props.isGroupExpandedByDefault, + groupingName: DATA_SOURCE_TREE_DATA_STRATEGY, + onDuplicatePath, + }); + } + + return updateRowTree({ + nodes: { + inserted: params.updates.actions.insert.map(getRowTreeBuilderNode), + modified: params.updates.actions.modify.map(getRowTreeBuilderNode), + removed: params.updates.actions.remove, + }, + previousTree: params.previousTree!, + previousGroupsToFetch: params.previousGroupsToFetch, + previousTreeDepth: params.previousTreeDepths!, + defaultGroupingExpansionDepth: props.defaultGroupingExpansionDepth, + isGroupExpandedByDefault: props.isGroupExpandedByDefault, + groupingName: DATA_SOURCE_TREE_DATA_STRATEGY, + }); + }, + [ + props.unstable_dataSource, + props.defaultGroupingExpansionDepth, + props.isGroupExpandedByDefault, + ], + ); + + const filterRows = React.useCallback>(() => { + const rowTree = gridRowTreeSelector(privateApiRef); + + return skipFiltering(rowTree); + }, [privateApiRef]); + + const sortRows = React.useCallback>(() => { + const rowTree = gridRowTreeSelector(privateApiRef); + + return skipSorting(rowTree); + }, [privateApiRef]); + + useGridRegisterPipeProcessor(privateApiRef, 'hydrateColumns', updateGroupingColumn); + useGridRegisterStrategyProcessor( + privateApiRef, + DATA_SOURCE_TREE_DATA_STRATEGY, + 'rowTreeCreation', + createRowTreeForTreeData, + ); + useGridRegisterStrategyProcessor( + privateApiRef, + DATA_SOURCE_TREE_DATA_STRATEGY, + 'filtering', + filterRows, + ); + useGridRegisterStrategyProcessor( + privateApiRef, + DATA_SOURCE_TREE_DATA_STRATEGY, + 'sorting', + sortRows, + ); + useGridRegisterStrategyProcessor( + privateApiRef, + DATA_SOURCE_TREE_DATA_STRATEGY, + 'visibleRowsLookupCreation', + getVisibleRowsLookup, + ); + + /** + * 1ST RENDER + */ + useFirstRender(() => { + setStrategyAvailability(); + }); + + /** + * EFFECTS + */ + const isFirstRender = React.useRef(true); + React.useEffect(() => { + if (!isFirstRender.current) { + setStrategyAvailability(); + } else { + isFirstRender.current = false; + } + }, [setStrategyAvailability]); +}; diff --git a/packages/x-data-grid-pro/src/hooks/features/serverSideTreeData/utils.ts b/packages/x-data-grid-pro/src/hooks/features/serverSideTreeData/utils.ts new file mode 100644 index 000000000000..e1314f6aef1d --- /dev/null +++ b/packages/x-data-grid-pro/src/hooks/features/serverSideTreeData/utils.ts @@ -0,0 +1,22 @@ +import { GridRowId, GridRowTreeConfig, GRID_ROOT_GROUP_ID } from '@mui/x-data-grid'; +import { getTreeNodeDescendants } from '@mui/x-data-grid/internals'; + +export function skipFiltering(rowTree: GridRowTreeConfig) { + const filteredRowsLookup: Record = {}; + const filteredDescendantCountLookup: Record = {}; + + const nodes = Object.values(rowTree); + for (let i = 0; i < nodes.length; i += 1) { + const node: any = nodes[i]; + filteredRowsLookup[node.id] = true; + } + + return { + filteredRowsLookup, + filteredDescendantCountLookup, + }; +} + +export function skipSorting(rowTree: GridRowTreeConfig) { + return getTreeNodeDescendants(rowTree, GRID_ROOT_GROUP_ID, false); +} diff --git a/packages/x-data-grid-pro/src/hooks/features/treeData/useGridTreeData.tsx b/packages/x-data-grid-pro/src/hooks/features/treeData/useGridTreeData.tsx index f2410669db0f..8f09f695627d 100644 --- a/packages/x-data-grid-pro/src/hooks/features/treeData/useGridTreeData.tsx +++ b/packages/x-data-grid-pro/src/hooks/features/treeData/useGridTreeData.tsx @@ -1,9 +1,14 @@ import * as React from 'react'; import { useGridApiEventHandler, GridEventListener } from '@mui/x-data-grid'; import { GridApiPro } from '../../../models/gridApiPro'; +import { DataGridProProcessedProps } from '../../../models/dataGridProProps'; + import { GRID_TREE_DATA_GROUPING_FIELD } from './gridTreeDataGroupColDef'; -export const useGridTreeData = (apiRef: React.MutableRefObject) => { +export const useGridTreeData = ( + apiRef: React.MutableRefObject, + props: Pick, +) => { /** * EVENTS */ @@ -19,10 +24,15 @@ export const useGridTreeData = (apiRef: React.MutableRefObject) => { return; } + if (props.unstable_dataSource && !params.rowNode.childrenExpanded) { + apiRef.current.unstable_dataSource.fetchRows(params.id); + return; + } + apiRef.current.setRowChildrenExpansion(params.id, !params.rowNode.childrenExpanded); } }, - [apiRef], + [apiRef, props.unstable_dataSource], ); useGridApiEventHandler(apiRef, 'cellKeyDown', handleCellKeyDown); diff --git a/packages/x-data-grid-pro/src/hooks/features/treeData/useGridTreeDataPreProcessors.tsx b/packages/x-data-grid-pro/src/hooks/features/treeData/useGridTreeDataPreProcessors.tsx index be47c0bd6bb1..74c0fcfcda38 100644 --- a/packages/x-data-grid-pro/src/hooks/features/treeData/useGridTreeDataPreProcessors.tsx +++ b/packages/x-data-grid-pro/src/hooks/features/treeData/useGridTreeDataPreProcessors.tsx @@ -46,15 +46,16 @@ export const useGridTreeDataPreProcessors = ( | 'disableChildrenFiltering' | 'defaultGroupingExpansionDepth' | 'isGroupExpandedByDefault' + | 'unstable_dataSource' >, ) => { const setStrategyAvailability = React.useCallback(() => { privateApiRef.current.setStrategyAvailability( 'rowTree', TREE_DATA_STRATEGY, - props.treeData ? () => true : () => false, + props.treeData && !props.unstable_dataSource ? () => true : () => false, ); - }, [privateApiRef, props.treeData]); + }, [privateApiRef, props.treeData, props.unstable_dataSource]); const getGroupingColDef = React.useCallback(() => { const groupingColDefProp = props.groupingColDef; @@ -93,6 +94,9 @@ export const useGridTreeDataPreProcessors = ( const updateGroupingColumn = React.useCallback>( (columnsState) => { + if (props.unstable_dataSource) { + return columnsState; + } const groupingColDefField = GRID_TREE_DATA_GROUPING_COL_DEF_FORCED_PROPERTIES.field; const shouldHaveGroupingColumn = props.treeData; @@ -122,7 +126,7 @@ export const useGridTreeDataPreProcessors = ( return columnsState; }, - [props.treeData, getGroupingColDef], + [props.treeData, props.unstable_dataSource, getGroupingColDef], ); const createRowTreeForTreeData = React.useCallback>( diff --git a/packages/x-data-grid-pro/src/internals/index.ts b/packages/x-data-grid-pro/src/internals/index.ts index 83f507d992b1..28b184e2bd42 100644 --- a/packages/x-data-grid-pro/src/internals/index.ts +++ b/packages/x-data-grid-pro/src/internals/index.ts @@ -15,6 +15,7 @@ export { useGridColumnReorder, columnReorderStateInitializer, } from '../hooks/features/columnReorder/useGridColumnReorder'; +export { useGridDataSourceTreeDataPreProcessors } from '../hooks/features/serverSideTreeData/useGridDataSourceTreeDataPreProcessors'; export { useGridDetailPanel, detailPanelStateInitializer, @@ -36,6 +37,10 @@ export { } from '../hooks/features/rowPinning/useGridRowPinningPreProcessors'; export { useGridLazyLoader } from '../hooks/features/lazyLoader/useGridLazyLoader'; export { useGridLazyLoaderPreProcessors } from '../hooks/features/lazyLoader/useGridLazyLoaderPreProcessors'; +export { + useGridDataSource, + dataSourceStateInitializer, +} from '../hooks/features/dataSource/useGridDataSource'; export type { GridExperimentalProFeatures, diff --git a/packages/x-data-grid-pro/src/internals/propValidation.ts b/packages/x-data-grid-pro/src/internals/propValidation.ts index b93320993aab..13f138529d47 100644 --- a/packages/x-data-grid-pro/src/internals/propValidation.ts +++ b/packages/x-data-grid-pro/src/internals/propValidation.ts @@ -16,6 +16,7 @@ export const propValidatorsDataGridPro: PropValidator (props) => (props.treeData && props.filterMode === 'server' && + !props.unstable_dataSource && 'MUI X: The `filterMode="server"` prop is not available when the `treeData` is enabled.') || undefined, (props) => diff --git a/packages/x-data-grid-pro/src/models/dataGridProProps.ts b/packages/x-data-grid-pro/src/models/dataGridProProps.ts index 9ffc76113476..4d611b57ea06 100644 --- a/packages/x-data-grid-pro/src/models/dataGridProProps.ts +++ b/packages/x-data-grid-pro/src/models/dataGridProProps.ts @@ -8,7 +8,7 @@ import { GridGroupNode, GridFeatureMode, } from '@mui/x-data-grid'; -import { +import type { GridExperimentalFeatures, DataGridPropsWithoutDefaultValue, DataGridPropsWithDefaultValues, @@ -17,6 +17,8 @@ import { GridPinnedColumnFields, DataGridProSharedPropsWithDefaultValue, DataGridProSharedPropsWithoutDefaultValue, + GridDataSourceCache, + GridGetRowsParams, } from '@mui/x-data-grid/internals'; import type { GridPinnedRowsProp } from '../hooks/features/rowPinning'; import { GridApiPro } from './gridApiPro'; @@ -137,11 +139,30 @@ export interface DataGridProPropsWithDefaultValue void; +} + +interface DataGridProRegularProps { + /** + * Determines the path of a row in the tree data. + * For instance, a row with the path ["A", "B"] is the child of the row with the path ["A"]. + * Note that all paths must contain at least one element. + * @template R + * @param {R} row The row from which we want the path. + * @returns {string[]} The path to the row. + */ + getTreeDataPath?: (row: R) => string[]; +} + export interface DataGridProPropsWithoutDefaultValue extends Omit< DataGridPropsWithoutDefaultValue, 'initialState' | 'componentsProps' | 'slotProps' >, + DataGridProRegularProps, + DataGridProDataSourceProps, DataGridProSharedPropsWithoutDefaultValue { /** * The ref object that allows grid manipulation. Can be instantiated with `useGridApiRef()`. @@ -158,15 +179,6 @@ export interface DataGridProPropsWithoutDefaultValue; - /** - * Determines the path of a row in the tree data. - * For instance, a row with the path ["A", "B"] is the child of the row with the path ["A"]. - * Note that all paths must contain at least one element. - * @template R - * @param {R} row The row from which we want the path. - * @returns {string[]} The path to the row. - */ - getTreeDataPath?: (row: R) => string[]; /** * Callback fired when scrolling to the bottom of the grid viewport. * @param {GridRowScrollEndParams} params With all properties from [[GridRowScrollEndParams]]. diff --git a/packages/x-data-grid-pro/src/models/dataSource.ts b/packages/x-data-grid-pro/src/models/dataSource.ts deleted file mode 100644 index 53bb071e6b4f..000000000000 --- a/packages/x-data-grid-pro/src/models/dataSource.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { - GridSortModel, - GridFilterModel, - GridColDef, - GridRowModel, - GridPaginationModel, -} from '@mui/x-data-grid'; - -interface GetRowsParams { - sortModel: GridSortModel; - filterModel: GridFilterModel; - /** - * Alternate to `start` and `end`, maps to `GridPaginationModel` interface. - */ - paginationModel: GridPaginationModel; - /** - * First row index to fetch (number) or cursor information (number | string). - */ - start: number | string; - /** - * Last row index to fetch. - */ - end: number; // last row index to fetch - /** - * Array of keys returned by `getGroupKey` of all the parent rows until the row for which the data is requested - * `getGroupKey` prop must be implemented to use this. - * Useful for `treeData` and `rowGrouping` only. - */ - groupKeys: string[]; - /** - * List of grouped columns (only applicable with `rowGrouping`). - */ - groupFields: GridColDef['field'][]; -} - -interface GetRowsResponse { - rows: GridRowModel[]; - /** - * To reflect updates in total `rowCount` (optional). - * Useful when the `rowCount` is inaccurate (for example when filtering) or not available upfront. - */ - rowCount?: number; - /** - * Additional `pageInfo` to help the grid determine if there are more rows to fetch (corner-cases). - * `hasNextPage`: When row count is unknown/inaccurate, if `truncated` is set or rowCount is not known, data will keep loading until `hasNextPage` is `false` - * `truncated`: To reflect `rowCount` is inaccurate (will trigger `x-y of many` in pagination after the count of rows fetched is greater than provided `rowCount`) - * It could be useful with: - * 1. Cursor based pagination: - * When rowCount is not known, grid will check for `hasNextPage` to determine - * if there are more rows to fetch. - * 2. Inaccurate `rowCount`: - * `truncated: true` will let the grid know that `rowCount` is estimated/truncated. - * Thus `hasNextPage` will come into play to check more rows are available to fetch after the number becomes >= provided `rowCount` - */ - pageInfo?: { - hasNextPage?: boolean; - truncated?: number; - }; -} - -export interface DataSource { - /** - * Fetcher Functions: - * - `getRows` is required - * - `updateRow` is optional - * - * `getRows` will be used by the grid to fetch data for the current page or children for the current parent group. - * It may return a `rowCount` to update the total count of rows in the grid along with the optional `pageInfo`. - */ - getRows(params: GetRowsParams): Promise; - updateRow?(rows: GridRowModel): Promise; -} diff --git a/packages/x-data-grid-pro/src/models/gridApiPro.ts b/packages/x-data-grid-pro/src/models/gridApiPro.ts index 33e5f884a0d4..0f0f56261ef5 100644 --- a/packages/x-data-grid-pro/src/models/gridApiPro.ts +++ b/packages/x-data-grid-pro/src/models/gridApiPro.ts @@ -11,6 +11,8 @@ import type { GridDetailPanelApi, GridRowPinningApi, GridDetailPanelPrivateApi, + GridDataSourceApi, + GridDataSourcePrivateApi, } from '../hooks'; import type { DataGridProProcessedProps } from './dataGridProProps'; @@ -23,6 +25,7 @@ export interface GridApiPro GridColumnPinningApi, GridDetailPanelApi, GridRowPinningApi, + GridDataSourceApi, // APIs that are private in Community plan, but public in Pro and Premium plans GridRowMultiSelectionApi, GridColumnReorderApi {} @@ -31,4 +34,5 @@ export interface GridPrivateApiPro extends GridApiPro, GridPrivateOnlyApiCommon, GridDetailPanelPrivateApi, - GridInfiniteLoaderPrivateApi {} + GridInfiniteLoaderPrivateApi, + GridDataSourcePrivateApi {} diff --git a/packages/x-data-grid-pro/src/models/gridStatePro.ts b/packages/x-data-grid-pro/src/models/gridStatePro.ts index 662a9bed10b0..e26694abd3e8 100644 --- a/packages/x-data-grid-pro/src/models/gridStatePro.ts +++ b/packages/x-data-grid-pro/src/models/gridStatePro.ts @@ -9,6 +9,7 @@ import type { GridDetailPanelInitialState, GridColumnReorderState, } from '../hooks'; +import type { GridDataSourceState } from '../hooks/features/dataSource/interfaces'; /** * The state of `DataGridPro`. @@ -17,6 +18,7 @@ export interface GridStatePro extends GridStateCommunity { columnReorder: GridColumnReorderState; pinnedColumns: GridColumnPinningState; detailPanel: GridDetailPanelState; + dataSource: GridDataSourceState; } /** diff --git a/packages/x-data-grid-pro/src/models/index.ts b/packages/x-data-grid-pro/src/models/index.ts index 36deff5c944b..8110b6c70a91 100644 --- a/packages/x-data-grid-pro/src/models/index.ts +++ b/packages/x-data-grid-pro/src/models/index.ts @@ -1,3 +1,9 @@ +export type { + GridGetRowsParams, + GridGetRowsResponse, + GridDataSource, + GridDataSourceCache, +} from '@mui/x-data-grid/internals'; export * from './gridApiPro'; export * from './gridGroupingColDefOverride'; export * from './gridRowScrollEndParams'; diff --git a/packages/x-data-grid-pro/src/tests/columnPinning.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/columnPinning.DataGridPro.test.tsx index 97615142218a..7508c219422f 100644 --- a/packages/x-data-grid-pro/src/tests/columnPinning.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/columnPinning.DataGridPro.test.tsx @@ -229,7 +229,7 @@ describe(' - Column pinning', () => { const borderLeftWidth = computedStyle.getPropertyValue('border-left-width'); expect(borderLeftWidth).to.equal('1px'); // should not be transparent - expect(borderLeftColor).to.not.equal('rgba(0, 0, 0, 0)'); + expect(borderLeftColor).not.to.equal('rgba(0, 0, 0, 0)'); }); // https://github.com/mui/mui-x/issues/12431 diff --git a/packages/x-data-grid-pro/src/tests/filterPanel.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/filterPanel.DataGridPro.test.tsx index 4b4722fe3a89..1a924b004b82 100644 --- a/packages/x-data-grid-pro/src/tests/filterPanel.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/filterPanel.DataGridPro.test.tsx @@ -37,7 +37,7 @@ describe(' - Filter panel', () => { act(() => apiRef.current.showFilterPanel('brand')); const model = gridFilterModelSelector(apiRef); expect(model.items).to.have.length(1); - expect(model.items[0].id).to.not.equal(null); - expect(model.items[0].operator).to.not.equal(null); + expect(model.items[0].id).not.to.equal(null); + expect(model.items[0].operator).not.to.equal(null); }); }); diff --git a/packages/x-data-grid-pro/src/tests/lazyLoader.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/lazyLoader.DataGridPro.test.tsx index b7915e7c6878..1f2dbac26b93 100644 --- a/packages/x-data-grid-pro/src/tests/lazyLoader.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/lazyLoader.DataGridPro.test.tsx @@ -166,8 +166,8 @@ describe(' - Lazy loader', () => { const updatedAllRows = apiRef.current.getRowNode(GRID_ROOT_GROUP_ID)!.children; expect(updatedAllRows.slice(4, 6)).to.deep.equal([4, 5]); - expect(apiRef.current.getRowNode(4)).to.not.equal(null); - expect(apiRef.current.getRowNode(5)).to.not.equal(null); + expect(apiRef.current.getRowNode(4)).not.to.equal(null); + expect(apiRef.current.getRowNode(5)).not.to.equal(null); }); it('should update rows when `apiRef.current.updateRows` with data reversed', () => { diff --git a/packages/x-data-grid-pro/src/tests/license.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/license.DataGridPro.test.tsx index 0e4b3abd433b..e65d7ff55bf0 100644 --- a/packages/x-data-grid-pro/src/tests/license.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/license.DataGridPro.test.tsx @@ -15,7 +15,7 @@ describe(' - License', () => { ]); await waitFor(() => { - expect(screen.getByText('MUI X Missing license key')).to.not.equal(null); + expect(screen.getByText('MUI X Missing license key')).not.to.equal(null); }); }); }); diff --git a/packages/x-data-grid-pro/src/tests/pagination.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/pagination.DataGridPro.test.tsx index 0f9a0952b616..5561eb1afc5e 100644 --- a/packages/x-data-grid-pro/src/tests/pagination.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/pagination.DataGridPro.test.tsx @@ -105,7 +105,11 @@ describe(' - Pagination', () => { it('should log an error if rowCount is used with client-side pagination', () => { expect(() => { - render(); + render( +
+ +
, + ); }).toErrorDev([ 'MUI X: Usage of the `rowCount` prop with client side pagination (`paginationMode="client"`) has no effect. `rowCount` is only meant to be used with `paginationMode="server"`.', ]); diff --git a/packages/x-data-grid-pro/src/tests/rows.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/rows.DataGridPro.test.tsx index f0704d4fb4fd..101bc83e0420 100644 --- a/packages/x-data-grid-pro/src/tests/rows.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/rows.DataGridPro.test.tsx @@ -27,8 +27,12 @@ import { useBasicDemoData, getBasicGridData } from '@mui/x-data-grid-generator'; const isJSDOM = /jsdom/.test(window.navigator.userAgent); +interface BaselineProps extends DataGridProProps { + rows: GridValidRowModel[]; +} + describe(' - Rows', () => { - let baselineProps: DataGridProProps & { rows: GridValidRowModel }; + let baselineProps: BaselineProps; const { clock, render } = createRenderer({ clock: 'fake' }); diff --git a/packages/x-data-grid-pro/src/tests/statePersistence.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/statePersistence.DataGridPro.test.tsx index 637907681341..2fb247eaabcb 100644 --- a/packages/x-data-grid-pro/src/tests/statePersistence.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/statePersistence.DataGridPro.test.tsx @@ -249,7 +249,7 @@ describe(' - State persistence', () => { expect(getColumnValues(0)).to.deep.equal(['3', '2']); // Preference panel - expect(screen.getByRole('button', { name: /Add Filter/i })).to.not.equal(null); + expect(screen.getByRole('button', { name: /Add Filter/i })).not.to.equal(null); // Columns visibility expect(getColumnHeadersTextContent()).to.deep.equal(['id', 'category']); diff --git a/packages/x-data-grid-pro/src/utils/tree/createRowTree.ts b/packages/x-data-grid-pro/src/utils/tree/createRowTree.ts index 09675aa21548..6f79cc1c727c 100644 --- a/packages/x-data-grid-pro/src/utils/tree/createRowTree.ts +++ b/packages/x-data-grid-pro/src/utils/tree/createRowTree.ts @@ -22,6 +22,7 @@ export const createRowTree = (params: CreateRowTreeParams): GridRowTreeCreationV [GRID_ROOT_GROUP_ID]: buildRootGroup(), }; const treeDepths: GridRowTreeCreationValue['treeDepths'] = {}; + const groupsToFetch = new Set(); for (let i = 0; i < params.nodes.length; i += 1) { const node = params.nodes[i]; @@ -32,10 +33,12 @@ export const createRowTree = (params: CreateRowTreeParams): GridRowTreeCreationV previousTree: params.previousTree, id: node.id, path: node.path, + hasServerChildren: node.hasServerChildren, onDuplicatePath: params.onDuplicatePath, treeDepths, isGroupExpandedByDefault: params.isGroupExpandedByDefault, defaultGroupingExpansionDepth: params.defaultGroupingExpansionDepth, + groupsToFetch, }); } @@ -44,5 +47,6 @@ export const createRowTree = (params: CreateRowTreeParams): GridRowTreeCreationV treeDepths, groupingName: params.groupingName, dataRowIds, + groupsToFetch: Array.from(groupsToFetch), }; }; diff --git a/packages/x-data-grid-pro/src/utils/tree/insertDataRowInTree.ts b/packages/x-data-grid-pro/src/utils/tree/insertDataRowInTree.ts index a79fbdcc759e..86cd27e02026 100644 --- a/packages/x-data-grid-pro/src/utils/tree/insertDataRowInTree.ts +++ b/packages/x-data-grid-pro/src/utils/tree/insertDataRowInTree.ts @@ -4,10 +4,12 @@ import { GridLeafNode, GridRowId, GridRowTreeConfig, + GridDataSourceGroupNode, } from '@mui/x-data-grid'; import { GridTreeDepths, GridRowTreeUpdatedGroupsManager } from '@mui/x-data-grid/internals'; import { updateGroupDefaultExpansion, + checkGroupChildrenExpansion, getGroupRowIdFromPath, insertNodeInTree, updateGroupNodeIdAndAutoGenerated, @@ -57,6 +59,8 @@ interface InsertDataRowInTreeParams { onDuplicatePath?: GridTreePathDuplicateHandler; isGroupExpandedByDefault?: DataGridProProps['isGroupExpandedByDefault']; defaultGroupingExpansionDepth: number; + hasServerChildren?: boolean; + groupsToFetch?: Set; } /** @@ -75,6 +79,8 @@ export const insertDataRowInTree = ({ onDuplicatePath, isGroupExpandedByDefault, defaultGroupingExpansionDepth, + hasServerChildren, + groupsToFetch, }: InsertDataRowInTreeParams) => { let parentNodeId = GRID_ROOT_GROUP_ID; @@ -92,17 +98,43 @@ export const insertDataRowInTree = ({ // If no node matches the full path, // We create a leaf node for the data row. if (existingNodeIdWithPartialPath == null) { - const leafNode: GridLeafNode = { - type: 'leaf', - id, - depth, - parent: parentNodeId, - groupingKey: key, - }; + let node: GridLeafNode | GridDataSourceGroupNode; + if (hasServerChildren) { + node = { + type: 'group', + id, + parent: parentNodeId, + path: path.map((step) => step.key as string), + depth, + isAutoGenerated: false, + groupingKey: key, + groupingField: field, + children: [], + childrenFromPath: {}, + childrenExpanded: false, + hasServerChildren: true, + }; + const shouldFetchChildren = checkGroupChildrenExpansion( + node, + defaultGroupingExpansionDepth, + isGroupExpandedByDefault, + ); + if (shouldFetchChildren) { + groupsToFetch?.add(id); + } + } else { + node = { + type: 'leaf', + id, + depth, + parent: parentNodeId, + groupingKey: key, + }; + } updatedGroupsManager?.addAction(parentNodeId, 'insertChildren'); - insertNodeInTree(leafNode, tree, treeDepths, previousTree); + insertNodeInTree(node, tree, treeDepths, previousTree); } else { const existingNodeWithPartialPath = tree[existingNodeIdWithPartialPath]; diff --git a/packages/x-data-grid-pro/src/utils/tree/models.ts b/packages/x-data-grid-pro/src/utils/tree/models.ts index 5eef120e37ff..871d3fc86c97 100644 --- a/packages/x-data-grid-pro/src/utils/tree/models.ts +++ b/packages/x-data-grid-pro/src/utils/tree/models.ts @@ -8,6 +8,7 @@ export interface RowTreeBuilderGroupingCriterion { export interface RowTreeBuilderNode { id: GridRowId; path: RowTreeBuilderGroupingCriterion[]; + hasServerChildren?: boolean; } /** diff --git a/packages/x-data-grid-pro/src/utils/tree/updateRowTree.ts b/packages/x-data-grid-pro/src/utils/tree/updateRowTree.ts index ad87141ef647..0c7ddc514403 100644 --- a/packages/x-data-grid-pro/src/utils/tree/updateRowTree.ts +++ b/packages/x-data-grid-pro/src/utils/tree/updateRowTree.ts @@ -24,15 +24,19 @@ interface UpdateRowTreeParams { isGroupExpandedByDefault?: (node: GridGroupNode) => boolean; groupingName: string; onDuplicatePath?: GridTreePathDuplicateHandler; + previousGroupsToFetch?: GridRowId[]; } export const updateRowTree = (params: UpdateRowTreeParams): GridRowTreeCreationValue => { const tree = { ...params.previousTree }; const treeDepths = { ...params.previousTreeDepth }; const updatedGroupsManager = createUpdatedGroupsManager(); + const groupsToFetch = params.previousGroupsToFetch + ? new Set([...params.previousGroupsToFetch]) + : new Set([]); for (let i = 0; i < params.nodes.inserted.length; i += 1) { - const { id, path } = params.nodes.inserted[i]; + const { id, path, hasServerChildren } = params.nodes.inserted[i]; insertDataRowInTree({ previousTree: params.previousTree, @@ -41,9 +45,11 @@ export const updateRowTree = (params: UpdateRowTreeParams): GridRowTreeCreationV updatedGroupsManager, id, path, + hasServerChildren, onDuplicatePath: params.onDuplicatePath, isGroupExpandedByDefault: params.isGroupExpandedByDefault, defaultGroupingExpansionDepth: params.defaultGroupingExpansionDepth, + groupsToFetch, }); } @@ -59,7 +65,7 @@ export const updateRowTree = (params: UpdateRowTreeParams): GridRowTreeCreationV } for (let i = 0; i < params.nodes.modified.length; i += 1) { - const { id, path } = params.nodes.modified[i]; + const { id, path, hasServerChildren } = params.nodes.modified[i]; const pathInPreviousTree = getNodePathInTree({ tree, id }); const isInSameGroup = isDeepEqual(pathInPreviousTree, path); @@ -78,9 +84,11 @@ export const updateRowTree = (params: UpdateRowTreeParams): GridRowTreeCreationV updatedGroupsManager, id, path, + hasServerChildren, onDuplicatePath: params.onDuplicatePath, isGroupExpandedByDefault: params.isGroupExpandedByDefault, defaultGroupingExpansionDepth: params.defaultGroupingExpansionDepth, + groupsToFetch, }); } else { updatedGroupsManager?.addAction(tree[id].parent!, 'modifyChildren'); @@ -96,5 +104,6 @@ export const updateRowTree = (params: UpdateRowTreeParams): GridRowTreeCreationV groupingName: params.groupingName, dataRowIds, updatedGroupsManager, + groupsToFetch: Array.from(groupsToFetch), }; }; diff --git a/packages/x-data-grid-pro/src/utils/tree/utils.ts b/packages/x-data-grid-pro/src/utils/tree/utils.ts index 5de194769e5c..fba2f4c9bfa2 100644 --- a/packages/x-data-grid-pro/src/utils/tree/utils.ts +++ b/packages/x-data-grid-pro/src/utils/tree/utils.ts @@ -49,7 +49,7 @@ export const getNodePathInTree = ({ return path; }; -export const updateGroupDefaultExpansion = ( +export const checkGroupChildrenExpansion = ( node: GridGroupNode, defaultGroupingExpansionDepth: number, isGroupExpandedByDefault?: DataGridProProps['isGroupExpandedByDefault'], @@ -64,8 +64,20 @@ export const updateGroupDefaultExpansion = ( defaultGroupingExpansionDepth === -1 || defaultGroupingExpansionDepth > node.depth; } - node.childrenExpanded = childrenExpanded; + return childrenExpanded; +}; +export const updateGroupDefaultExpansion = ( + node: GridGroupNode, + defaultGroupingExpansionDepth: number, + isGroupExpandedByDefault?: DataGridProProps['isGroupExpandedByDefault'], +) => { + const childrenExpanded = checkGroupChildrenExpansion( + node, + defaultGroupingExpansionDepth, + isGroupExpandedByDefault, + ); + node.childrenExpanded = childrenExpanded; return node; }; diff --git a/packages/x-data-grid-pro/tsconfig.build.json b/packages/x-data-grid-pro/tsconfig.build.json index 3649d7b11677..c5eab772f678 100644 --- a/packages/x-data-grid-pro/tsconfig.build.json +++ b/packages/x-data-grid-pro/tsconfig.build.json @@ -13,7 +13,8 @@ }, "references": [ { "path": "../x-data-grid/tsconfig.build.json" }, - { "path": "../x-license/tsconfig.build.json" } + { "path": "../x-license/tsconfig.build.json" }, + { "path": "../x-internals/tsconfig.build.json" } ], "include": ["src/**/*.ts*"], "exclude": ["src/**/*.spec.ts*", "src/**/*.test.ts*"] diff --git a/packages/x-data-grid-pro/tsconfig.json b/packages/x-data-grid-pro/tsconfig.json index aba8438e2441..a95beb1e8020 100644 --- a/packages/x-data-grid-pro/tsconfig.json +++ b/packages/x-data-grid-pro/tsconfig.json @@ -5,7 +5,8 @@ "@mui/internal-test-utils/initMatchers", "@mui/material/themeCssVarsAugmentation", "chai-dom", - "mocha" + "mocha", + "node" ] }, "include": ["src/**/*"] diff --git a/packages/x-data-grid/package.json b/packages/x-data-grid/package.json index 3749f544f50d..71626d62f370 100644 --- a/packages/x-data-grid/package.json +++ b/packages/x-data-grid/package.json @@ -1,6 +1,6 @@ { "name": "@mui/x-data-grid", - "version": "7.7.1", + "version": "7.9.0", "description": "The Community plan edition of the Data Grid components (MUI X).", "author": "MUI Team", "main": "src/index.ts", @@ -48,8 +48,9 @@ }, "dependencies": { "@babel/runtime": "^7.24.7", - "@mui/system": "^5.15.20", - "@mui/utils": "^5.15.20", + "@mui/system": "^5.16.0", + "@mui/utils": "^5.16.0", + "@mui/x-internals": "workspace:*", "clsx": "^2.1.1", "prop-types": "^15.8.1", "reselect": "^4.1.8" @@ -60,11 +61,11 @@ "react-dom": "^17.0.0 || ^18.0.0" }, "devDependencies": { - "@mui/internal-test-utils": "^1.0.1", - "@mui/joy": "5.0.0-beta.32", + "@mui/internal-test-utils": "^1.0.4", + "@mui/joy": "^5.0.0-beta.47", "@mui/types": "^7.2.14", "@types/prop-types": "^15.7.12", - "rimraf": "^5.0.7" + "rimraf": "^5.0.8" }, "engines": { "node": ">=14.0.0" diff --git a/packages/x-data-grid/src/DataGrid/useDataGridProps.ts b/packages/x-data-grid/src/DataGrid/useDataGridProps.ts index d807385e16cb..1cd75b30f70b 100644 --- a/packages/x-data-grid/src/DataGrid/useDataGridProps.ts +++ b/packages/x-data-grid/src/DataGrid/useDataGridProps.ts @@ -105,14 +105,26 @@ export const useDataGridProps = (inProps: DataGridP [themedProps.slots], ); + const injectDefaultProps = React.useMemo(() => { + return ( + Object.keys(DATA_GRID_PROPS_DEFAULT_VALUES) as Array< + keyof DataGridPropsWithDefaultValues + > + ).reduce((acc, key) => { + // @ts-ignore + acc[key] = themedProps[key] ?? DATA_GRID_PROPS_DEFAULT_VALUES[key]; + return acc; + }, {} as DataGridPropsWithDefaultValues); + }, [themedProps]); + return React.useMemo>( () => ({ - ...DATA_GRID_PROPS_DEFAULT_VALUES, ...themedProps, + ...injectDefaultProps, localeText, slots, ...DATA_GRID_FORCED_PROPS, }), - [themedProps, localeText, slots], + [themedProps, localeText, slots, injectDefaultProps], ); }; diff --git a/packages/x-data-grid/src/components/GridLoadingOverlay.tsx b/packages/x-data-grid/src/components/GridLoadingOverlay.tsx index 2bcb4eed7a89..dc68ffccc6d8 100644 --- a/packages/x-data-grid/src/components/GridLoadingOverlay.tsx +++ b/packages/x-data-grid/src/components/GridLoadingOverlay.tsx @@ -1,13 +1,63 @@ import * as React from 'react'; import PropTypes from 'prop-types'; +import LinearProgress from '@mui/material/LinearProgress'; import CircularProgress from '@mui/material/CircularProgress'; import { GridOverlay, GridOverlayProps } from './containers/GridOverlay'; +import { GridSkeletonLoadingOverlay } from './GridSkeletonLoadingOverlay'; +import { useGridApiContext } from '../hooks/utils/useGridApiContext'; +import { gridRowCountSelector, useGridSelector } from '../hooks'; -const GridLoadingOverlay = React.forwardRef( +export type GridLoadingOverlayVariant = 'circular-progress' | 'linear-progress' | 'skeleton'; + +export interface GridLoadingOverlayProps extends GridOverlayProps { + /** + * The variant of the overlay. + * @default 'circular-progress' + */ + variant?: GridLoadingOverlayVariant; + /** + * The variant of the overlay when no rows are displayed. + * @default 'circular-progress' + */ + noRowsVariant?: GridLoadingOverlayVariant; +} + +const LOADING_VARIANTS: Record< + GridLoadingOverlayVariant, + { + component: React.ComponentType; + style: React.CSSProperties; + } +> = { + 'circular-progress': { + component: CircularProgress, + style: {}, + }, + 'linear-progress': { + component: LinearProgress, + style: { display: 'block' }, + }, + skeleton: { + component: GridSkeletonLoadingOverlay, + style: { display: 'block' }, + }, +}; + +const GridLoadingOverlay = React.forwardRef( function GridLoadingOverlay(props, ref) { + const { + variant = 'circular-progress', + noRowsVariant = 'circular-progress', + style, + ...other + } = props; + const apiRef = useGridApiContext(); + const rowsCount = useGridSelector(apiRef, gridRowCountSelector); + const activeVariant = LOADING_VARIANTS[rowsCount === 0 ? noRowsVariant : variant]; + return ( - - + + ); }, @@ -18,11 +68,21 @@ GridLoadingOverlay.propTypes = { // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- + /** + * The variant of the overlay when no rows are displayed. + * @default 'circular-progress' + */ + noRowsVariant: PropTypes.oneOf(['circular-progress', 'linear-progress', 'skeleton']), sx: PropTypes.oneOfType([ PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object, ]), + /** + * The variant of the overlay. + * @default 'circular-progress' + */ + variant: PropTypes.oneOf(['circular-progress', 'linear-progress', 'skeleton']), } as any; export { GridLoadingOverlay }; diff --git a/packages/x-data-grid/src/components/GridRow.tsx b/packages/x-data-grid/src/components/GridRow.tsx index 134786356f65..917deae2ba62 100644 --- a/packages/x-data-grid/src/components/GridRow.tsx +++ b/packages/x-data-grid/src/components/GridRow.tsx @@ -376,10 +376,11 @@ const GridRow = React.forwardRef(function GridRow( return ( ); } diff --git a/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx b/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx new file mode 100644 index 000000000000..62643bb382f3 --- /dev/null +++ b/packages/x-data-grid/src/components/GridSkeletonLoadingOverlay.tsx @@ -0,0 +1,265 @@ +import * as React from 'react'; +import clsx from 'clsx'; +import { styled } from '@mui/system'; +import useForkRef from '@mui/utils/useForkRef'; +import composeClasses from '@mui/utils/composeClasses'; +import { useGridApiContext } from '../hooks/utils/useGridApiContext'; +import { useGridRootProps } from '../hooks/utils/useGridRootProps'; +import { + GridPinnedColumnPosition, + gridColumnPositionsSelector, + gridColumnsTotalWidthSelector, + gridDimensionsSelector, + gridVisibleColumnDefinitionsSelector, + gridVisiblePinnedColumnDefinitionsSelector, + useGridApiEventHandler, + useGridSelector, +} from '../hooks'; +import { GridEventListener } from '../models'; +import { DataGridProcessedProps } from '../models/props/DataGridProps'; +import { getDataGridUtilityClass, gridClasses } from '../constants/gridClasses'; +import { getPinnedCellOffset } from '../internals/utils/getPinnedCellOffset'; +import { shouldCellShowLeftBorder, shouldCellShowRightBorder } from '../utils/cellBorderUtils'; +import { escapeOperandAttributeSelector } from '../utils/domUtils'; +import { GridScrollbarFillerCell } from './GridScrollbarFillerCell'; + +const SkeletonOverlay = styled('div', { + name: 'MuiDataGrid', + slot: 'SkeletonLoadingOverlay', + overridesResolver: (props, styles) => styles.skeletonLoadingOverlay, +})({ + minWidth: '100%', + width: 'max-content', // prevents overflow: clip; cutting off the x axis + height: '100%', + overflow: 'clip', // y axis is hidden while the x axis is allowed to overflow +}); + +type OwnerState = { classes: DataGridProcessedProps['classes'] }; + +const useUtilityClasses = (ownerState: OwnerState) => { + const { classes } = ownerState; + + const slots = { + root: ['skeletonLoadingOverlay'], + }; + + return composeClasses(slots, getDataGridUtilityClass, classes); +}; + +const getColIndex = (el: HTMLElement) => parseInt(el.getAttribute('data-colindex')!, 10); + +const GridSkeletonLoadingOverlay = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(function GridSkeletonLoadingOverlay(props, forwardedRef) { + const rootProps = useGridRootProps(); + const { slots } = rootProps; + const classes = useUtilityClasses({ classes: rootProps.classes }); + const ref = React.useRef(null); + const handleRef = useForkRef(ref, forwardedRef); + const apiRef = useGridApiContext(); + const dimensions = useGridSelector(apiRef, gridDimensionsSelector); + const viewportHeight = dimensions?.viewportInnerSize.height ?? 0; + const skeletonRowsCount = Math.ceil(viewportHeight / dimensions.rowHeight); + const totalWidth = useGridSelector(apiRef, gridColumnsTotalWidthSelector); + const positions = useGridSelector(apiRef, gridColumnPositionsSelector); + const inViewportCount = React.useMemo( + () => positions.filter((value) => value <= totalWidth).length, + [totalWidth, positions], + ); + const allVisibleColumns = useGridSelector(apiRef, gridVisibleColumnDefinitionsSelector); + const columns = React.useMemo( + () => allVisibleColumns.slice(0, inViewportCount), + [allVisibleColumns, inViewportCount], + ); + const pinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector); + + const getPinnedStyle = React.useCallback( + (computedWidth: number, index: number, position: GridPinnedColumnPosition) => { + const pinnedOffset = getPinnedCellOffset( + position, + computedWidth, + index, + positions, + dimensions, + ); + return { [position]: pinnedOffset } as const; + }, + [dimensions, positions], + ); + + const getPinnedPosition = React.useCallback( + (field: string) => { + if (pinnedColumns.left.findIndex((col) => col.field === field) !== -1) { + return GridPinnedColumnPosition.LEFT; + } + if (pinnedColumns.right.findIndex((col) => col.field === field) !== -1) { + return GridPinnedColumnPosition.RIGHT; + } + return undefined; + }, + [pinnedColumns.left, pinnedColumns.right], + ); + + const children = React.useMemo(() => { + const array: React.ReactNode[] = []; + + for (let i = 0; i < skeletonRowsCount; i += 1) { + const rowCells: React.ReactNode[] = []; + + for (let colIndex = 0; colIndex < columns.length; colIndex += 1) { + const column = columns[colIndex]; + const pinnedPosition = getPinnedPosition(column.field); + const isPinnedLeft = pinnedPosition === GridPinnedColumnPosition.LEFT; + const isPinnedRight = pinnedPosition === GridPinnedColumnPosition.RIGHT; + const sectionLength = pinnedPosition + ? pinnedColumns[pinnedPosition].length // pinned section + : columns.length - pinnedColumns.left.length - pinnedColumns.right.length; // middle section + const sectionIndex = pinnedPosition + ? pinnedColumns[pinnedPosition].findIndex((col) => col.field === column.field) // pinned section + : colIndex - pinnedColumns.left.length; // middle section + const pinnedStyle = + pinnedPosition && getPinnedStyle(column.computedWidth, colIndex, pinnedPosition); + const gridHasFiller = dimensions.columnsTotalWidth < dimensions.viewportOuterSize.width; + const showRightBorder = shouldCellShowRightBorder( + pinnedPosition, + sectionIndex, + sectionLength, + rootProps.showCellVerticalBorder, + gridHasFiller, + ); + const showLeftBorder = shouldCellShowLeftBorder(pinnedPosition, sectionIndex); + const isLastColumn = colIndex === columns.length - 1; + const isFirstPinnedRight = isPinnedRight && sectionIndex === 0; + const hasFillerBefore = isFirstPinnedRight && gridHasFiller; + const hasFillerAfter = isLastColumn && !isFirstPinnedRight && gridHasFiller; + const expandedWidth = dimensions.viewportOuterSize.width - dimensions.columnsTotalWidth; + const emptyCellWidth = Math.max(0, expandedWidth); + const emptyCell = ( + + ); + const scrollbarWidth = dimensions.hasScrollY ? dimensions.scrollbarSize : 0; + const hasScrollbarFiller = isLastColumn && scrollbarWidth !== 0; + + if (hasFillerBefore) { + rowCells.push(emptyCell); + } + + rowCells.push( + , + ); + + if (hasFillerAfter) { + rowCells.push(emptyCell); + } + + if (hasScrollbarFiller) { + rowCells.push( 0} />); + } + } + + array.push( +
+ {rowCells} +
, + ); + } + return array; + }, [ + slots, + columns, + pinnedColumns, + skeletonRowsCount, + rootProps.showCellVerticalBorder, + dimensions.columnsTotalWidth, + dimensions.viewportOuterSize.width, + dimensions.rowHeight, + dimensions.hasScrollY, + dimensions.scrollbarSize, + getPinnedPosition, + getPinnedStyle, + ]); + + // Sync the column resize of the overlay columns with the grid + const handleColumnResize: GridEventListener<'columnResize'> = (params) => { + const { colDef, width } = params; + const cells = ref.current?.querySelectorAll( + `[data-field="${escapeOperandAttributeSelector(colDef.field)}"]`, + ); + + if (!cells) { + throw new Error('MUI X: Expected skeleton cells to be defined with `data-field` attribute.'); + } + + const resizedColIndex = columns.findIndex((col) => col.field === colDef.field); + const pinnedPosition = getPinnedPosition(colDef.field); + const isPinnedLeft = pinnedPosition === GridPinnedColumnPosition.LEFT; + const isPinnedRight = pinnedPosition === GridPinnedColumnPosition.RIGHT; + const currentWidth = getComputedStyle(cells[0]).getPropertyValue('--width'); + const delta = parseInt(currentWidth, 10) - width; + + if (cells) { + cells.forEach((element) => { + element.style.setProperty('--width', `${width}px`); + }); + } + + if (isPinnedLeft) { + const pinnedCells = ref.current?.querySelectorAll( + `.${gridClasses['cell--pinnedLeft']}`, + ); + pinnedCells?.forEach((element) => { + const colIndex = getColIndex(element); + if (colIndex > resizedColIndex) { + element.style.left = `${parseInt(getComputedStyle(element).left, 10) - delta}px`; + } + }); + } + + if (isPinnedRight) { + const pinnedCells = ref.current?.querySelectorAll( + `.${gridClasses['cell--pinnedRight']}`, + ); + pinnedCells?.forEach((element) => { + const colIndex = getColIndex(element); + if (colIndex < resizedColIndex) { + element.style.right = `${parseInt(getComputedStyle(element).right, 10) + delta}px`; + } + }); + } + }; + + useGridApiEventHandler(apiRef, 'columnResize', handleColumnResize); + + return ( + + {children} + + ); +}); + +export { GridSkeletonLoadingOverlay }; diff --git a/packages/x-data-grid/src/components/base/GridOverlays.tsx b/packages/x-data-grid/src/components/base/GridOverlays.tsx index 2e214bc219ff..169763a4633c 100644 --- a/packages/x-data-grid/src/components/base/GridOverlays.tsx +++ b/packages/x-data-grid/src/components/base/GridOverlays.tsx @@ -4,40 +4,47 @@ import { styled } from '@mui/system'; import { unstable_composeClasses as composeClasses } from '@mui/utils'; import clsx from 'clsx'; import { useGridSelector } from '../../hooks/utils/useGridSelector'; -import { gridExpandedRowCountSelector } from '../../hooks/features/filter/gridFilterSelector'; -import { - gridRowCountSelector, - gridRowsLoadingSelector, -} from '../../hooks/features/rows/gridRowsSelector'; import { gridDimensionsSelector } from '../../hooks/features/dimensions'; +import { GridOverlayType } from '../../hooks/features/overlays/useGridOverlays'; import { useGridApiContext } from '../../hooks/utils/useGridApiContext'; import { useGridRootProps } from '../../hooks/utils/useGridRootProps'; import { useGridVisibleRows } from '../../hooks/utils/useGridVisibleRows'; import { getMinimalContentHeight } from '../../hooks/features/rows/gridRowsUtils'; import { DataGridProcessedProps } from '../../models/props/DataGridProps'; import { getDataGridUtilityClass } from '../../constants/gridClasses'; +import { GridLoadingOverlayVariant } from '../GridLoadingOverlay'; + +interface GridOverlaysProps { + overlayType: GridOverlayType; + loadingOverlayVariant: GridLoadingOverlayVariant | null; +} const GridOverlayWrapperRoot = styled('div', { name: 'MuiDataGrid', slot: 'OverlayWrapper', - shouldForwardProp: (prop) => prop !== 'overlayType', + shouldForwardProp: (prop) => prop !== 'overlayType' && prop !== 'loadingOverlayVariant', overridesResolver: (props, styles) => styles.overlayWrapper, -})<{ overlayType: 'loadingOverlay' | string }>(({ overlayType }) => ({ - position: 'sticky', // To stay in place while scrolling - top: 'var(--DataGrid-headersTotalHeight)', - left: 0, - width: 0, // To stay above the content instead of shifting it down - height: 0, // To stay above the content instead of shifting it down - zIndex: - overlayType === 'loadingOverlay' - ? 5 // Should be above pinned columns, pinned rows, and detail panel - : 4, // Should be above pinned columns and detail panel -})); +})(({ overlayType, loadingOverlayVariant }) => + // Skeleton overlay should flow with the scroll container and not be sticky + loadingOverlayVariant !== 'skeleton' + ? { + position: 'sticky', // To stay in place while scrolling + top: 'var(--DataGrid-headersTotalHeight)', + left: 0, + width: 0, // To stay above the content instead of shifting it down + height: 0, // To stay above the content instead of shifting it down + zIndex: + overlayType === 'loadingOverlay' + ? 5 // Should be above pinned columns, pinned rows, and detail panel + : 4, // Should be above pinned columns and detail panel + } + : {}, +); const GridOverlayWrapperInner = styled('div', { name: 'MuiDataGrid', slot: 'OverlayWrapperInner', - shouldForwardProp: (prop) => prop !== 'overlayType', + shouldForwardProp: (prop) => prop !== 'overlayType' && prop !== 'loadingOverlayVariant', overridesResolver: (props, styles) => styles.overlayWrapperInner, })({}); @@ -54,7 +61,7 @@ const useUtilityClasses = (ownerState: OwnerState) => { return composeClasses(slots, getDataGridUtilityClass, classes); }; -function GridOverlayWrapper(props: React.PropsWithChildren<{ overlayType: string }>) { +function GridOverlayWrapper(props: React.PropsWithChildren) { const apiRef = useGridApiContext(); const rootProps = useGridRootProps(); const currentPage = useGridVisibleRows(apiRef, rootProps); @@ -62,7 +69,8 @@ function GridOverlayWrapper(props: React.PropsWithChildren<{ overlayType: string let height: React.CSSProperties['height'] = dimensions.viewportOuterSize.height - - dimensions.headersTotalHeight - + dimensions.topContainerHeight - + dimensions.bottomContainerHeight - (dimensions.hasScrollX ? dimensions.scrollbarSize : 0); if ((rootProps.autoHeight && currentPage.rows.length === 0) || height === 0) { @@ -72,7 +80,7 @@ function GridOverlayWrapper(props: React.PropsWithChildren<{ overlayType: string const classes = useUtilityClasses({ ...props, classes: rootProps.classes }); return ( - + 0 && visibleRowCount === 0; - - let overlay: React.JSX.Element | null = null; - let overlayType = ''; - - if (showNoRowsOverlay) { - overlay = ; - overlayType = 'noRowsOverlay'; - } - - if (showNoResultsOverlay) { - overlay = ; - overlayType = 'noResultsOverlay'; - } - - if (loading) { - overlay = ; - overlayType = 'loadingOverlay'; - } - - if (overlay === null) { + if (!overlayType) { return null; } - return {overlay}; + const Overlay = rootProps.slots?.[overlayType]; + const overlayProps = rootProps.slotProps?.[overlayType]; + + return ( + + + + ); } diff --git a/packages/x-data-grid/src/components/cell/GridSkeletonCell.tsx b/packages/x-data-grid/src/components/cell/GridSkeletonCell.tsx index fef4188a67f0..28a25539b706 100644 --- a/packages/x-data-grid/src/components/cell/GridSkeletonCell.tsx +++ b/packages/x-data-grid/src/components/cell/GridSkeletonCell.tsx @@ -5,45 +5,101 @@ import { unstable_composeClasses as composeClasses, unstable_capitalize as capitalize, } from '@mui/utils'; +import clsx from 'clsx'; import { fastMemo } from '../../utils/fastMemo'; -import { randomNumberBetween } from '../../utils/utils'; +import { createRandomNumberGenerator } from '../../utils/utils'; import { useGridRootProps } from '../../hooks/utils/useGridRootProps'; import { getDataGridUtilityClass } from '../../constants/gridClasses'; import { DataGridProcessedProps } from '../../models/props/DataGridProps'; +import { GridColType } from '../../models'; -const randomWidth = randomNumberBetween(10000, 20, 80); +const CIRCULAR_CONTENT_SIZE = '1.3em'; -export interface GridSkeletonCellProps { - width: number; - height: number | 'auto'; - field: string; - align: string; +const CONTENT_HEIGHT = '1.2em'; + +const DEFAULT_CONTENT_WIDTH_RANGE = [40, 80] as const; + +const CONTENT_WIDTH_RANGE_BY_TYPE: Partial> = { + number: [40, 60], + string: [40, 80], + date: [40, 60], + dateTime: [60, 80], + singleSelect: [40, 80], +} as const; + +export interface GridSkeletonCellProps extends React.HTMLAttributes { + type?: GridColType; + width?: number | string; + height?: number | 'auto'; + field?: string; + align?: string; + /** + * If `true`, the cell will not display the skeleton but still reserve the cell space. + * @default false + */ + empty?: boolean; } -type OwnerState = Pick & { +type OwnerState = Pick & { classes?: DataGridProcessedProps['classes']; }; const useUtilityClasses = (ownerState: OwnerState) => { - const { align, classes } = ownerState; + const { align, classes, empty } = ownerState; const slots = { - root: ['cell', 'cellSkeleton', `cell--text${capitalize(align)}`, 'withBorderColor'], + root: [ + 'cell', + 'cellSkeleton', + `cell--text${align ? capitalize(align) : 'Left'}`, + empty && 'cellEmpty', + ], }; return composeClasses(slots, getDataGridUtilityClass, classes); }; -function GridSkeletonCell(props: React.HTMLAttributes & GridSkeletonCellProps) { - const { field, align, width, height, ...other } = props; +const randomNumberGenerator = createRandomNumberGenerator(12345); + +function GridSkeletonCell(props: GridSkeletonCellProps) { + const { field, type, align, width, height, empty = false, style, className, ...other } = props; const rootProps = useGridRootProps(); - const ownerState = { classes: rootProps.classes, align }; + const ownerState = { classes: rootProps.classes, align, empty }; const classes = useUtilityClasses(ownerState); - const contentWidth = Math.round(randomWidth()); + + // Memo prevents the non-circular skeleton widths changing to random widths on every render + const skeletonProps = React.useMemo(() => { + const isCircularContent = type === 'boolean' || type === 'actions'; + + if (isCircularContent) { + return { + variant: 'circular', + width: CIRCULAR_CONTENT_SIZE, + height: CIRCULAR_CONTENT_SIZE, + } as const; + } + + // The width of the skeleton is a random number between the min and max values + // The min and max values are determined by the type of the column + const [min, max] = type + ? CONTENT_WIDTH_RANGE_BY_TYPE[type] ?? DEFAULT_CONTENT_WIDTH_RANGE + : DEFAULT_CONTENT_WIDTH_RANGE; + + return { + variant: 'text', + width: `${Math.round(randomNumberGenerator(min, max))}%`, + height: CONTENT_HEIGHT, + } as const; + }, [type]); return ( -
- +
+ {!empty && }
); } @@ -53,10 +109,25 @@ GridSkeletonCell.propTypes = { // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- - align: PropTypes.string.isRequired, - field: PropTypes.string.isRequired, - height: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number]).isRequired, - width: PropTypes.number.isRequired, + align: PropTypes.string, + /** + * If `true`, the cell will not display the skeleton but still reserve the cell space. + * @default false + */ + empty: PropTypes.bool, + field: PropTypes.string, + height: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number]), + type: PropTypes.oneOf([ + 'actions', + 'boolean', + 'custom', + 'date', + 'dateTime', + 'number', + 'singleSelect', + 'string', + ]), + width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), } as any; const Memoized = fastMemo(GridSkeletonCell); diff --git a/packages/x-data-grid/src/components/columnHeaders/GridColumnHeaderItem.tsx b/packages/x-data-grid/src/components/columnHeaders/GridColumnHeaderItem.tsx index 2822705bf090..920c197c6da7 100644 --- a/packages/x-data-grid/src/components/columnHeaders/GridColumnHeaderItem.tsx +++ b/packages/x-data-grid/src/components/columnHeaders/GridColumnHeaderItem.tsx @@ -6,7 +6,6 @@ import { fastMemo } from '../../utils/fastMemo'; import { GridStateColDef } from '../../models/colDef/gridColDef'; import { GridSortDirection } from '../../models/gridSortModel'; import { useGridPrivateApiContext } from '../../hooks/utils/useGridPrivateApiContext'; -import { GridColumnHeaderSortIcon } from './GridColumnHeaderSortIcon'; import { GridColumnHeaderSeparatorProps } from './GridColumnHeaderSeparator'; import { ColumnHeaderMenuIcon } from './ColumnHeaderMenuIcon'; import { GridColumnHeaderMenu } from '../menu/columnMenu/GridColumnHeaderMenu'; @@ -248,11 +247,13 @@ function GridColumnHeaderItem(props: GridColumnHeaderItemProps) { )} {showSortIcon && ( - )} diff --git a/packages/x-data-grid/src/components/columnHeaders/GridColumnHeaderSortIcon.tsx b/packages/x-data-grid/src/components/columnHeaders/GridColumnHeaderSortIcon.tsx index d9e069df341a..c10c6225402f 100644 --- a/packages/x-data-grid/src/components/columnHeaders/GridColumnHeaderSortIcon.tsx +++ b/packages/x-data-grid/src/components/columnHeaders/GridColumnHeaderSortIcon.tsx @@ -11,6 +11,7 @@ import { DataGridProcessedProps } from '../../models/props/DataGridProps'; import { GridIconButtonContainer } from './GridIconButtonContainer'; export interface GridColumnHeaderSortIconProps { + field: string; direction: GridSortDirection; index: number | undefined; sortingOrder: readonly GridSortDirection[]; @@ -51,7 +52,7 @@ function getIcon( } function GridColumnHeaderSortIconRaw(props: GridColumnHeaderSortIconProps) { - const { direction, index, sortingOrder, disabled } = props; + const { direction, index, sortingOrder, disabled, ...other } = props; const apiRef = useGridApiContext(); const rootProps = useGridRootProps(); const ownerState = { ...props, classes: rootProps.classes }; @@ -70,6 +71,7 @@ function GridColumnHeaderSortIconRaw(props: GridColumnHeaderSortIconProps) { size="small" disabled={disabled} {...rootProps.slotProps?.baseIconButton} + {...other} > {iconElement} @@ -78,7 +80,7 @@ function GridColumnHeaderSortIconRaw(props: GridColumnHeaderSortIconProps) { return ( {index != null && ( - + {iconButton} )} @@ -97,6 +99,7 @@ GridColumnHeaderSortIconRaw.propTypes = { // ---------------------------------------------------------------------- direction: PropTypes.oneOf(['asc', 'desc']), disabled: PropTypes.bool, + field: PropTypes.string.isRequired, index: PropTypes.number, sortingOrder: PropTypes.arrayOf(PropTypes.oneOf(['asc', 'desc'])).isRequired, } as any; diff --git a/packages/x-data-grid/src/components/containers/GridRootStyles.ts b/packages/x-data-grid/src/components/containers/GridRootStyles.ts index 0d5e88de51f6..bdfd79712cd3 100644 --- a/packages/x-data-grid/src/components/containers/GridRootStyles.ts +++ b/packages/x-data-grid/src/components/containers/GridRootStyles.ts @@ -115,6 +115,9 @@ export const GridRootStyles = styled('div', { { [`& .${c.withBorderColor}`]: styles.withBorderColor }, { [`& .${c.treeDataGroupingCell}`]: styles.treeDataGroupingCell }, { [`& .${c.treeDataGroupingCellToggle}`]: styles.treeDataGroupingCellToggle }, + { + [`& .${c.treeDataGroupingCellLoadingContainer}`]: styles.treeDataGroupingCellLoadingContainer, + }, { [`& .${c.detailPanelToggleCell}`]: styles.detailPanelToggleCell }, { [`& .${c['detailPanelToggleCell--expanded']}`]: styles['detailPanelToggleCell--expanded'], @@ -145,7 +148,7 @@ export const GridRootStyles = styled('div', { const selectedHoverBackground = t.vars ? `rgba(${t.vars.palette.primary.mainChannel} / calc( - ${t.vars.palette.action.selectedOpacity} + + ${t.vars.palette.action.selectedOpacity} + ${t.vars.palette.action.hoverOpacity} ))` : alpha( @@ -433,6 +436,9 @@ export const GridRootStyles = styled('div', { backgroundColor: 'transparent', }, }, + [`&.${c.rowSkeleton}:hover`]: { + backgroundColor: 'transparent', + }, '&.Mui-selected': selectedStyles, }, [`& .${c['container--top']}, & .${c['container--bottom']}`]: { @@ -620,6 +626,12 @@ export const GridRootStyles = styled('div', { alignSelf: 'stretch', marginRight: t.spacing(2), }, + [`& .${c.treeDataGroupingCellLoadingContainer}`]: { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + height: '100%', + }, [`& .${c.groupingCriteriaCell}`]: { display: 'flex', alignItems: 'center', @@ -636,7 +648,7 @@ export const GridRootStyles = styled('div', { minWidth: 'calc(var(--DataGrid-hasScrollY) * var(--DataGrid-scrollbarSize))', alignSelf: 'stretch', [`&.${c['scrollbarFiller--borderTop']}`]: { - borderTop: '1px solid var(--DataGrid-rowBorderColor)', + borderTop: '1px solid var(--rowBorderColor)', }, [`&.${c['scrollbarFiller--pinnedRight']}`]: { backgroundColor: 'var(--DataGrid-pinnedBackground)', @@ -651,6 +663,13 @@ export const GridRootStyles = styled('div', { [`& .${c['filler--borderTop']}`]: { borderTop: '1px solid var(--DataGrid-rowBorderColor)', }, + + /* Hide grid rows and vertical scrollbar when skeleton overlay is visible */ + [`& .${c['main--hasSkeletonLoadingOverlay']}`]: { + [`& .${c.virtualScrollerContent}, & .${c['scrollbar--vertical']}, & .${c.pinnedRows}`]: { + display: 'none', + }, + }, }; return gridStyle; diff --git a/packages/x-data-grid/src/components/panel/GridPanel.test.tsx b/packages/x-data-grid/src/components/panel/GridPanel.test.tsx index 225f13469abf..4e82d0de7ddd 100644 --- a/packages/x-data-grid/src/components/panel/GridPanel.test.tsx +++ b/packages/x-data-grid/src/components/panel/GridPanel.test.tsx @@ -33,18 +33,13 @@ describe('', () => { classes: classes as any, inheritComponent: Popper, muiName: 'MuiGridPanel', - render: (node: React.ReactElement) => render({node}), - wrapMount: - (baseMount: (node: React.ReactElement) => import('enzyme').ReactWrapper) => - (node: React.ReactNode) => { - const wrapper = baseMount( - -
- {node} - , - ); - return wrapper.find('span').childAt(0); - }, + render: (node: React.ReactElement) => + render( + +
+ {node} + , + ), refInstanceof: window.HTMLDivElement, only: ['mergeClassName', 'propsSpread', 'refForwarding', 'rootClass'], })); diff --git a/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx b/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx index aa17ed93be6d..5afc96f930fc 100644 --- a/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx +++ b/packages/x-data-grid/src/components/virtualization/GridVirtualScroller.tsx @@ -9,7 +9,8 @@ import { getDataGridUtilityClass } from '../../constants/gridClasses'; import { DataGridProcessedProps } from '../../models/props/DataGridProps'; import { GridDimensions, gridDimensionsSelector } from '../../hooks/features/dimensions'; import { useGridVirtualScroller } from '../../hooks/features/virtualization/useGridVirtualScroller'; -import { GridOverlays } from '../base/GridOverlays'; +import { useGridOverlays } from '../../hooks/features/overlays/useGridOverlays'; +import { GridOverlays as Overlays } from '../base/GridOverlays'; import { GridHeaders } from '../GridHeaders'; import { GridMainContainer as Container } from './GridMainContainer'; import { GridTopContainer as TopContainer } from './GridTopContainer'; @@ -18,14 +19,23 @@ import { GridVirtualScrollerContent as Content } from './GridVirtualScrollerCont import { GridVirtualScrollerFiller as SpaceFiller } from './GridVirtualScrollerFiller'; import { GridVirtualScrollerRenderZone as RenderZone } from './GridVirtualScrollerRenderZone'; import { GridVirtualScrollbar as Scrollbar } from './GridVirtualScrollbar'; +import { GridLoadingOverlayVariant } from '../GridLoadingOverlay'; type OwnerState = DataGridProcessedProps; -const useUtilityClasses = (ownerState: OwnerState, dimensions: GridDimensions) => { +const useUtilityClasses = ( + ownerState: OwnerState, + dimensions: GridDimensions, + loadingOverlayVariant: GridLoadingOverlayVariant | null, +) => { const { classes } = ownerState; const slots = { - root: ['main', dimensions.rightPinnedWidth > 0 && 'main--hasPinnedRight'], + root: [ + 'main', + dimensions.rightPinnedWidth > 0 && 'main--hasPinnedRight', + loadingOverlayVariant === 'skeleton' && 'main--hasSkeletonLoadingOverlay', + ], scroller: ['virtualScroller'], }; @@ -61,7 +71,8 @@ function GridVirtualScroller(props: GridVirtualScrollerProps) { const apiRef = useGridApiContext(); const rootProps = useGridRootProps(); const dimensions = useGridSelector(apiRef, gridDimensionsSelector); - const classes = useUtilityClasses(rootProps, dimensions); + const overlaysProps = useGridOverlays(); + const classes = useUtilityClasses(rootProps, dimensions, overlaysProps.loadingOverlayVariant); const virtualScroller = useGridVirtualScroller(); const { @@ -86,7 +97,7 @@ function GridVirtualScroller(props: GridVirtualScrollerProps) { - + @@ -95,7 +106,7 @@ function GridVirtualScroller(props: GridVirtualScrollerProps) { - {rows.length > 0 && } + diff --git a/packages/x-data-grid/src/components/virtualization/GridVirtualScrollerFiller.tsx b/packages/x-data-grid/src/components/virtualization/GridVirtualScrollerFiller.tsx index eeaafcdd67ad..718a449a6ee5 100644 --- a/packages/x-data-grid/src/components/virtualization/GridVirtualScrollerFiller.tsx +++ b/packages/x-data-grid/src/components/virtualization/GridVirtualScrollerFiller.tsx @@ -17,24 +17,29 @@ const Pinned = styled('div')({ position: 'sticky', height: '100%', boxSizing: 'border-box', - borderTop: '1px solid var(--DataGrid-rowBorderColor)', + borderTop: '1px solid var(--rowBorderColor)', backgroundColor: 'var(--DataGrid-pinnedBackground)', }); const PinnedLeft = styled(Pinned)({ left: 0, - borderRight: '1px solid var(--DataGrid-rowBorderColor)', + borderRight: '1px solid var(--rowBorderColor)', }); const PinnedRight = styled(Pinned)({ right: 0, - borderLeft: '1px solid var(--DataGrid-rowBorderColor)', + borderLeft: '1px solid var(--rowBorderColor)', }); const Main = styled('div')({ flexGrow: 1, - borderTop: '1px solid var(--DataGrid-rowBorderColor)', + borderTop: '1px solid var(--rowBorderColor)', }); -function GridVirtualScrollerFiller() { +type Props = { + /** The number of rows */ + rowsLength: number; +}; + +function GridVirtualScrollerFiller({ rowsLength }: Props) { const apiRef = useGridApiContext(); const { viewportOuterSize, @@ -54,7 +59,16 @@ function GridVirtualScrollerFiller() { } return ( - + {leftPinnedWidth > 0 && ( ('MuiDataGrid', [ 'iconSeparator', 'main', 'main--hasPinnedRight', + 'main--hasSkeletonLoadingOverlay', 'menu', 'menuIcon', 'menuIconButton', @@ -727,6 +742,7 @@ export const gridClasses = generateUtilityClasses('MuiDataGrid', [ 'rowReorderCellContainer', 'rowReorderCell', 'rowReorderCell--draggable', + 'rowSkeleton', 'scrollArea--left', 'scrollArea--right', 'scrollArea', @@ -754,6 +770,7 @@ export const gridClasses = generateUtilityClasses('MuiDataGrid', [ 'columnHeader--withLeftBorder', 'treeDataGroupingCell', 'treeDataGroupingCellToggle', + 'treeDataGroupingCellLoadingContainer', 'groupingCriteriaCell', 'groupingCriteriaCellToggle', 'pinnedRows', diff --git a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts index 9727b8b19c03..6d423b29d931 100644 --- a/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts +++ b/packages/x-data-grid/src/hooks/features/dimensions/useGridDimensions.ts @@ -86,6 +86,7 @@ export function useGridDimensions( const logger = useGridLogger(apiRef, 'useResizeContainer'); const errorShown = React.useRef(false); const rootDimensionsRef = React.useRef(EMPTY_SIZE); + const dimensionsState = useGridSelector(apiRef, gridDimensionsSelector); const rowsMeta = useGridSelector(apiRef, gridRowsMetaSelector); const pinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector); const densityFactor = useGridSelector(apiRef, gridDensityFactorSelector); @@ -302,26 +303,25 @@ export function useGridDimensions( }, [apiRef, savedSize, updateDimensions]); const root = apiRef.current.rootElementRef.current; - const dimensions = apiRef.current.state.dimensions; useEnhancedEffect(() => { if (!root) { return; } const set = (k: string, v: string) => root.style.setProperty(k, v); - set('--DataGrid-width', `${dimensions.viewportOuterSize.width}px`); - set('--DataGrid-hasScrollX', `${Number(dimensions.hasScrollX)}`); - set('--DataGrid-hasScrollY', `${Number(dimensions.hasScrollY)}`); - set('--DataGrid-scrollbarSize', `${dimensions.scrollbarSize}px`); - set('--DataGrid-rowWidth', `${dimensions.rowWidth}px`); - set('--DataGrid-columnsTotalWidth', `${dimensions.columnsTotalWidth}px`); - set('--DataGrid-leftPinnedWidth', `${dimensions.leftPinnedWidth}px`); - set('--DataGrid-rightPinnedWidth', `${dimensions.rightPinnedWidth}px`); - set('--DataGrid-headerHeight', `${dimensions.headerHeight}px`); - set('--DataGrid-headersTotalHeight', `${dimensions.headersTotalHeight}px`); - set('--DataGrid-topContainerHeight', `${dimensions.topContainerHeight}px`); - set('--DataGrid-bottomContainerHeight', `${dimensions.bottomContainerHeight}px`); - set('--height', `${dimensions.rowHeight}px`); - }, [root, dimensions]); + set('--DataGrid-width', `${dimensionsState.viewportOuterSize.width}px`); + set('--DataGrid-hasScrollX', `${Number(dimensionsState.hasScrollX)}`); + set('--DataGrid-hasScrollY', `${Number(dimensionsState.hasScrollY)}`); + set('--DataGrid-scrollbarSize', `${dimensionsState.scrollbarSize}px`); + set('--DataGrid-rowWidth', `${dimensionsState.rowWidth}px`); + set('--DataGrid-columnsTotalWidth', `${dimensionsState.columnsTotalWidth}px`); + set('--DataGrid-leftPinnedWidth', `${dimensionsState.leftPinnedWidth}px`); + set('--DataGrid-rightPinnedWidth', `${dimensionsState.rightPinnedWidth}px`); + set('--DataGrid-headerHeight', `${dimensionsState.headerHeight}px`); + set('--DataGrid-headersTotalHeight', `${dimensionsState.headersTotalHeight}px`); + set('--DataGrid-topContainerHeight', `${dimensionsState.topContainerHeight}px`); + set('--DataGrid-bottomContainerHeight', `${dimensionsState.bottomContainerHeight}px`); + set('--height', `${dimensionsState.rowHeight}px`); + }, [root, dimensionsState]); const isFirstSizing = React.useRef(true); const handleResize = React.useCallback>( diff --git a/packages/x-data-grid/src/hooks/features/export/useGridPrintExport.tsx b/packages/x-data-grid/src/hooks/features/export/useGridPrintExport.tsx index 5ba08b587cdc..3421133554eb 100644 --- a/packages/x-data-grid/src/hooks/features/export/useGridPrintExport.tsx +++ b/packages/x-data-grid/src/hooks/features/export/useGridPrintExport.tsx @@ -177,15 +177,18 @@ export const useGridPrintExport = ( // The height above does not include grid border width, so we need to exclude it gridClone.style.boxSizing = 'content-box'; - // the footer is always being placed at the bottom of the page as if all rows are exported - // so if getRowsToExport is being used to only export a subset of rows then we need to - // adjust the footer position to be correctly placed at the bottom of the grid - const gridFooterElement: HTMLElement | null = gridClone.querySelector( - `.${gridClasses.footerContainer}`, - ); - gridFooterElement!.style.position = 'absolute'; - gridFooterElement!.style.width = '100%'; - gridFooterElement!.style.top = `${computedTotalHeight - gridFooterElementHeight}px`; + if (!normalizeOptions.hideFooter) { + // the footer is always being placed at the bottom of the page as if all rows are exported + // so if getRowsToExport is being used to only export a subset of rows then we need to + // adjust the footer position to be correctly placed at the bottom of the grid + const gridFooterElement: HTMLElement | null = gridClone.querySelector( + `.${gridClasses.footerContainer}`, + )!; + + gridFooterElement.style.position = 'absolute'; + gridFooterElement.style.width = '100%'; + gridFooterElement.style.top = `${computedTotalHeight - gridFooterElementHeight}px`; + } // printDoc.body.appendChild(gridClone); should be enough but a clone isolation bug in Safari // prevents us to do it diff --git a/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts b/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts index 40fa6d9c6a3b..9d376a2321f2 100644 --- a/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts +++ b/packages/x-data-grid/src/hooks/features/filter/gridFilterSelector.ts @@ -131,6 +131,26 @@ export const gridFilteredTopLevelRowCountSelector = createSelector( (visibleSortedTopLevelRows) => visibleSortedTopLevelRows.length, ); +/** + * Get the amount of rows accessible after the filtering process. + * Includes top level and descendant rows. + * @category Filtering + */ +export const gridFilteredRowCountSelector = createSelector( + gridFilteredSortedRowEntriesSelector, + (filteredSortedRowEntries) => filteredSortedRowEntries.length, +); + +/** + * Get the amount of descendant rows accessible after the filtering process. + * @category Filtering + */ +export const gridFilteredDescendantRowCountSelector = createSelector( + gridFilteredRowCountSelector, + gridFilteredTopLevelRowCountSelector, + (totalRowCount, topLevelRowCount) => totalRowCount - topLevelRowCount, +); + /** * @category Filtering * @ignore - do not document. diff --git a/packages/x-data-grid/src/hooks/features/overlays/useGridOverlays.ts b/packages/x-data-grid/src/hooks/features/overlays/useGridOverlays.ts new file mode 100644 index 000000000000..f3f9f3998423 --- /dev/null +++ b/packages/x-data-grid/src/hooks/features/overlays/useGridOverlays.ts @@ -0,0 +1,47 @@ +import { useGridSelector } from '../../utils'; +import { useGridApiContext } from '../../utils/useGridApiContext'; +import { useGridRootProps } from '../../utils/useGridRootProps'; +import { gridExpandedRowCountSelector } from '../filter'; +import { gridRowCountSelector, gridRowsLoadingSelector } from '../rows'; +import { GridLoadingOverlayVariant } from '../../../components/GridLoadingOverlay'; +import { GridSlotsComponent } from '../../../models/gridSlotsComponent'; + +export type GridOverlayType = + | keyof Pick + | null; + +/** + * Uses the grid state to determine which overlay to display. + * Returns the active overlay type and the active loading overlay variant. + */ +export const useGridOverlays = () => { + const apiRef = useGridApiContext(); + const rootProps = useGridRootProps(); + + const totalRowCount = useGridSelector(apiRef, gridRowCountSelector); + const visibleRowCount = useGridSelector(apiRef, gridExpandedRowCountSelector); + const noRows = totalRowCount === 0; + const loading = useGridSelector(apiRef, gridRowsLoadingSelector); + + const showNoRowsOverlay = !loading && noRows; + const showNoResultsOverlay = !loading && totalRowCount > 0 && visibleRowCount === 0; + + let overlayType: GridOverlayType = null; + let loadingOverlayVariant: GridLoadingOverlayVariant | null = null; + + if (showNoRowsOverlay) { + overlayType = 'noRowsOverlay'; + } + + if (showNoResultsOverlay) { + overlayType = 'noResultsOverlay'; + } + + if (loading) { + overlayType = 'loadingOverlay'; + loadingOverlayVariant = + rootProps.slotProps?.loadingOverlay?.[noRows ? 'noRowsVariant' : 'variant'] || null; + } + + return { overlayType, loadingOverlayVariant }; +}; diff --git a/packages/x-data-grid/src/hooks/features/pagination/index.ts b/packages/x-data-grid/src/hooks/features/pagination/index.ts index f47e042c72ee..4437fa668eb6 100644 --- a/packages/x-data-grid/src/hooks/features/pagination/index.ts +++ b/packages/x-data-grid/src/hooks/features/pagination/index.ts @@ -1,5 +1,7 @@ export * from './gridPaginationSelector'; export type { + GridPaginationModelApi, + GridPaginationRowCountApi, GridPaginationApi, GridPaginationState, GridPaginationInitialState, diff --git a/packages/x-data-grid/src/hooks/features/rows/gridRowsInterfaces.ts b/packages/x-data-grid/src/hooks/features/rows/gridRowsInterfaces.ts index 34562ff2231f..fc999812ee92 100644 --- a/packages/x-data-grid/src/hooks/features/rows/gridRowsInterfaces.ts +++ b/packages/x-data-grid/src/hooks/features/rows/gridRowsInterfaces.ts @@ -50,7 +50,7 @@ export interface GridRowsState { treeDepths: GridTreeDepths; dataRowIds: GridRowId[]; /** - * Matches the value of the `loading` prop. + * The loading status of the rows. */ loading?: boolean; /** @@ -70,6 +70,12 @@ export interface GridRowsState { additionalRowGroups?: { pinnedRows?: GridPinnedRowsState; }; + /** + * Contains some values of type `GridRowId` that have been requested to be fetched + * either by `defaultGroupingExpansionDepth` or `isGroupExpandedByDefault` props. + * Applicable with server-side grouped data and `unstable_dataSource` only. + */ + groupsToFetch?: GridRowId[]; } export interface GridRowTreeCreationParams { @@ -78,6 +84,7 @@ export interface GridRowTreeCreationParams { updates: GridRowsPartialUpdates | GridRowsFullUpdate; dataRowIdToIdLookup: GridRowIdToIdLookup; dataRowIdToModelLookup: GridRowIdToModelLookup; + previousGroupsToFetch?: GridRowId[]; } export type GridRowTreeUpdateGroupAction = 'removeChildren' | 'insertChildren' | 'modifyChildren'; @@ -93,7 +100,7 @@ export type GridRowTreeUpdatedGroupsManager = { export type GridRowTreeCreationValue = Pick< GridRowsState, - 'groupingName' | 'tree' | 'treeDepths' | 'dataRowIds' + 'groupingName' | 'tree' | 'treeDepths' | 'dataRowIds' | 'groupsToFetch' > & { updatedGroupsManager?: GridRowTreeUpdatedGroupsManager; }; @@ -128,6 +135,7 @@ export interface GridRowsPartialUpdates { type: 'partial'; actions: { [action in GridRowsPartialUpdateAction]: GridRowId[] }; idToActionLookup: { [id: GridRowId]: GridRowsPartialUpdateAction | undefined }; + groupKeys?: string[]; } export interface GridPinnedRowsState { diff --git a/packages/x-data-grid/src/hooks/features/rows/gridRowsSelector.ts b/packages/x-data-grid/src/hooks/features/rows/gridRowsSelector.ts index 6dd24b5256bc..c0f3614d0ad3 100644 --- a/packages/x-data-grid/src/hooks/features/rows/gridRowsSelector.ts +++ b/packages/x-data-grid/src/hooks/features/rows/gridRowsSelector.ts @@ -31,6 +31,11 @@ export const gridRowsDataRowIdToIdLookupSelector = createSelector( export const gridRowTreeSelector = createSelector(gridRowsStateSelector, (rows) => rows.tree); +export const gridRowGroupsToFetchSelector = createSelector( + gridRowsStateSelector, + (rows) => rows.groupsToFetch, +); + export const gridRowGroupingNameSelector = createSelector( gridRowsStateSelector, (rows) => rows.groupingName, diff --git a/packages/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts b/packages/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts index a2704b611c8e..83b643c84dd4 100644 --- a/packages/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts +++ b/packages/x-data-grid/src/hooks/features/rows/gridRowsUtils.ts @@ -132,7 +132,11 @@ export const getRowsStateFromCache = ({ loadingProp, previousTree, previousTreeDepths, -}: Pick & { + previousGroupsToFetch, +}: Pick< + GridRowTreeCreationParams, + 'previousTree' | 'previousTreeDepths' | 'previousGroupsToFetch' +> & { apiRef: React.MutableRefObject; rowCountProp: number | undefined; loadingProp: boolean | undefined; @@ -145,12 +149,14 @@ export const getRowsStateFromCache = ({ treeDepths: unProcessedTreeDepths, dataRowIds: unProcessedDataRowIds, groupingName, + groupsToFetch = [], } = apiRef.current.applyStrategyProcessor('rowTreeCreation', { previousTree, previousTreeDepths, updates: cache.updates, dataRowIdToIdLookup: cache.dataRowIdToIdLookup, dataRowIdToModelLookup: cache.dataRowIdToModelLookup, + previousGroupsToFetch, }); // 2. Apply the "hydrateRows" pipe-processing. @@ -182,6 +188,7 @@ export const getRowsStateFromCache = ({ }), groupingName, loading: loadingProp, + groupsToFetch, }; }; @@ -230,10 +237,12 @@ export const updateCacheWithNewRows = ({ previousCache, getRowId, updates, + groupKeys, }: { previousCache: GridRowsInternalCache; getRowId: DataGridProcessedProps['getRowId']; updates: GridRowModelUpdate[]; + groupKeys?: string[]; }): GridRowsInternalCache => { if (previousCache.updates.type === 'full') { throw new Error( @@ -267,6 +276,7 @@ export const updateCacheWithNewRows = ({ remove: [...(previousCache.updates.actions.remove ?? [])], }, idToActionLookup: { ...previousCache.updates.idToActionLookup }, + groupKeys, }; const dataRowIdToModelLookup = { ...previousCache.dataRowIdToModelLookup }; const dataRowIdToIdLookup = { ...previousCache.dataRowIdToIdLookup }; @@ -393,3 +403,35 @@ export function getMinimalContentHeight(apiRef: React.MutableRefObject, + updates: GridRowModelUpdate[], + getRowId: DataGridProcessedProps['getRowId'], +) { + const nonPinnedRowsUpdates: GridRowModelUpdate[] = []; + + updates.forEach((update) => { + const id = getRowIdFromRowModel( + update, + getRowId, + 'A row was provided without id when calling updateRows():', + ); + + const rowNode = apiRef.current.getRowNode(id); + if (rowNode?.type === 'pinnedRow') { + // @ts-ignore because otherwise `release:build` doesn't work + const pinnedRowsCache = apiRef.current.caches.pinnedRows; + const prevModel = pinnedRowsCache.idLookup[id]; + if (prevModel) { + pinnedRowsCache.idLookup[id] = { + ...prevModel, + ...update, + }; + } + } else { + nonPinnedRowsUpdates.push(update); + } + }); + return nonPinnedRowsUpdates; +} diff --git a/packages/x-data-grid/src/hooks/features/rows/useGridRows.ts b/packages/x-data-grid/src/hooks/features/rows/useGridRows.ts index aba863dad31c..2737b07ce94c 100644 --- a/packages/x-data-grid/src/hooks/features/rows/useGridRows.ts +++ b/packages/x-data-grid/src/hooks/features/rows/useGridRows.ts @@ -2,13 +2,8 @@ import * as React from 'react'; import { GridEventListener } from '../../../models/events'; import { DataGridProcessedProps } from '../../../models/props/DataGridProps'; import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity'; -import { GridRowApi, GridRowProApi } from '../../../models/api/gridRowApi'; -import { - GridRowId, - GridGroupNode, - GridLeafNode, - GridRowModelUpdate, -} from '../../../models/gridRows'; +import { GridRowApi, GridRowProApi, GridRowProPrivateApi } from '../../../models/api/gridRowApi'; +import { GridRowId, GridGroupNode, GridLeafNode } from '../../../models/gridRows'; import { useGridApiMethod } from '../../utils/useGridApiMethod'; import { useGridLogger } from '../../utils/useGridLogger'; import { @@ -20,6 +15,7 @@ import { gridDataRowIdsSelector, gridRowsDataRowIdToIdLookupSelector, gridRowMaximumTreeDepthSelector, + gridRowGroupsToFetchSelector, } from './gridRowsSelector'; import { useTimeout } from '../../utils/useTimeout'; import { GridSignature, useGridApiEventHandler } from '../../utils/useGridApiEventHandler'; @@ -38,14 +34,16 @@ import { updateCacheWithNewRows, getTopLevelRowCount, getRowIdFromRowModel, + computeRowsUpdates, } from './gridRowsUtils'; import { useGridRegisterPipeApplier } from '../../core/pipeProcessing'; export const rowsStateInitializer: GridStateInitializer< - Pick + Pick > = (state, props, apiRef) => { + const isDataSourceAvailable = !!props.unstable_dataSource; apiRef.current.caches.rows = createRowsInternalCache({ - rows: props.rows, + rows: isDataSourceAvailable ? [] : props.rows, getRowId: props.getRowId, loading: props.loading, rowCount: props.rowCount, @@ -56,7 +54,7 @@ export const rowsStateInitializer: GridStateInitializer< rows: getRowsStateFromCache({ apiRef, rowCountProp: props.rowCount, - loadingProp: props.loading, + loadingProp: isDataSourceAvailable ? true : props.loading, previousTree: null, previousTreeDepths: null, }), @@ -146,6 +144,7 @@ export const useGridRows = ( loadingProp: props.loading, previousTree: gridRowTreeSelector(apiRef), previousTreeDepths: gridRowTreeDepthsSelector(apiRef), + previousGroupsToFetch: gridRowGroupsToFetchSelector(apiRef), }), })); apiRef.current.publishEvent('rowsSet'); @@ -203,30 +202,7 @@ export const useGridRows = ( ); } - const nonPinnedRowsUpdates: GridRowModelUpdate[] = []; - - updates.forEach((update) => { - const id = getRowIdFromRowModel( - update, - props.getRowId, - 'A row was provided without id when calling updateRows():', - ); - - const rowNode = apiRef.current.getRowNode(id); - if (rowNode?.type === 'pinnedRow') { - // @ts-ignore because otherwise `release:build` doesn't work - const pinnedRowsCache = apiRef.current.caches.pinnedRows; - const prevModel = pinnedRowsCache.idLookup[id]; - if (prevModel) { - pinnedRowsCache.idLookup[id] = { - ...prevModel, - ...update, - }; - } - } else { - nonPinnedRowsUpdates.push(update); - } - }); + const nonPinnedRowsUpdates = computeRowsUpdates(apiRef, updates, props.getRowId); const cache = updateCacheWithNewRows({ updates: nonPinnedRowsUpdates, @@ -239,6 +215,37 @@ export const useGridRows = ( [props.signature, props.getRowId, throttledRowsChange, apiRef], ); + const updateServerRows = React.useCallback( + (updates, groupKeys) => { + const nonPinnedRowsUpdates = computeRowsUpdates(apiRef, updates, props.getRowId); + + const cache = updateCacheWithNewRows({ + updates: nonPinnedRowsUpdates, + getRowId: props.getRowId, + previousCache: apiRef.current.caches.rows, + groupKeys: groupKeys ?? [], + }); + + throttledRowsChange({ cache, throttle: false }); + }, + [props.getRowId, throttledRowsChange, apiRef], + ); + + const setLoading = React.useCallback( + (loading) => { + if (loading === props.loading) { + return; + } + logger.debug(`Setting loading to ${loading}`); + apiRef.current.setState((state) => ({ + ...state, + rows: { ...state.rows, loading }, + })); + apiRef.current.caches.rows.loadingPropBeforePartialUpdates = loading; + }, + [props.loading, apiRef, logger], + ); + const getRowModels = React.useCallback(() => { const dataRows = gridDataRowIdsSelector(apiRef); const idRowsLookup = gridRowsLookupSelector(apiRef); @@ -468,6 +475,7 @@ export const useGridRows = ( const rowApi: GridRowApi = { getRow, + setLoading, getRowId, getRowModels, getRowsCount, @@ -485,6 +493,10 @@ export const useGridRows = ( getRowGroupChildren, }; + const rowProPrivateApi: GridRowProPrivateApi = { + updateServerRows, + }; + /** * EVENTS */ @@ -585,6 +597,7 @@ export const useGridRows = ( rowProApi, props.signature === GridSignature.DataGrid ? 'private' : 'public', ); + useGridApiMethod(apiRef, rowProPrivateApi, 'private'); // The effect do not track any value defined synchronously during the 1st render by hooks called after `useGridRows` // As a consequence, the state generated by the 1st run of this useEffect will always be equal to the initialization one @@ -637,7 +650,7 @@ export const useGridRows = ( } } - logger.debug(`Updating all rows, new length ${props.rows.length}`); + logger.debug(`Updating all rows, new length ${props.rows?.length}`); throttledRowsChange({ cache: createRowsInternalCache({ rows: props.rows, diff --git a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx index a68ba9bae8e1..334d65759aac 100644 --- a/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx +++ b/packages/x-data-grid/src/hooks/features/virtualization/useGridVirtualScroller.tsx @@ -6,12 +6,12 @@ import { } from '@mui/utils'; import useLazyRef from '@mui/utils/useLazyRef'; import useTimeout from '@mui/utils/useTimeout'; +import { useResizeObserver } from '@mui/x-internals/useResizeObserver'; import { useTheme, Theme } from '@mui/material/styles'; import type { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity'; import { useGridPrivateApiContext } from '../../utils/useGridPrivateApiContext'; import { useGridRootProps } from '../../utils/useGridRootProps'; import { useGridSelector } from '../../utils/useGridSelector'; -import { useResizeObserver } from '../../utils/useResizeObserver'; import { useRunOnce } from '../../utils/useRunOnce'; import { gridVisibleColumnDefinitionsSelector, @@ -517,22 +517,13 @@ export const useGridVirtualScroller = () => { ); const contentSize = React.useMemo(() => { - // In cases where the columns exceed the available width, - // the horizontal scrollbar should be shown even when there're no rows. - // Keeping 1px as minimum height ensures that the scrollbar will visible if necessary. - const height = Math.max(contentHeight, 1); - const size: React.CSSProperties = { width: needsHorizontalScrollbar ? columnsTotalWidth : 'auto', - height, + height: contentHeight, }; - if (rootProps.autoHeight) { - if (currentPage.rows.length === 0) { - size.height = getMinimalContentHeight(apiRef); // Give room to show the overlay when there no rows. - } else { - size.height = contentHeight; - } + if (rootProps.autoHeight && currentPage.rows.length === 0) { + size.height = getMinimalContentHeight(apiRef); // Give room to show the overlay when there no rows. } return size; diff --git a/packages/x-data-grid/src/hooks/utils/index.ts b/packages/x-data-grid/src/hooks/utils/index.ts index e609ea5fb0fd..642c9db07366 100644 --- a/packages/x-data-grid/src/hooks/utils/index.ts +++ b/packages/x-data-grid/src/hooks/utils/index.ts @@ -5,5 +5,4 @@ export { useGridSelector } from './useGridSelector'; export * from './useGridNativeEventListener'; export * from './useFirstRender'; export * from './useOnMount'; -export * from './useResizeObserver'; export * from './useRunOnce'; diff --git a/packages/x-data-grid/src/internals/index.ts b/packages/x-data-grid/src/internals/index.ts index 88b4d71bf80f..1387f50016d3 100644 --- a/packages/x-data-grid/src/internals/index.ts +++ b/packages/x-data-grid/src/internals/index.ts @@ -130,10 +130,11 @@ export { useGridInitializeState } from '../hooks/utils/useGridInitializeState'; export type { GridStateInitializer } from '../hooks/utils/useGridInitializeState'; export type * from '../models/props/DataGridProps'; - +export type * from '../models/gridDataSource'; export { getColumnsToExport, defaultGetRowsToExport } from '../hooks/features/export/utils'; export * from '../utils/createControllablePromise'; export { createSelector, createSelectorMemoized } from '../utils/createSelector'; +export { gridRowGroupsToFetchSelector } from '../hooks/features/rows/gridRowsSelector'; export { findParentElementFromClassName, getActiveElement, diff --git a/packages/x-data-grid/src/internals/utils/propValidation.ts b/packages/x-data-grid/src/internals/utils/propValidation.ts index 6fa67ab6cc15..825db3991f71 100644 --- a/packages/x-data-grid/src/internals/utils/propValidation.ts +++ b/packages/x-data-grid/src/internals/utils/propValidation.ts @@ -35,6 +35,7 @@ export const propValidatorsDataGrid: PropValidator[] = [ (props) => (props.paginationMode === 'server' && props.rowCount == null && + !props.unstable_dataSource && [ "MUI X: The `rowCount` prop must be passed using `paginationMode='server'`", 'For more detail, see http://mui.com/components/data-grid/pagination/#index-based-pagination', diff --git a/packages/x-data-grid/src/models/api/gridApiCommon.ts b/packages/x-data-grid/src/models/api/gridApiCommon.ts index 1e59d123c8a5..f5ba4a40faf7 100644 --- a/packages/x-data-grid/src/models/api/gridApiCommon.ts +++ b/packages/x-data-grid/src/models/api/gridApiCommon.ts @@ -10,7 +10,7 @@ import type { GridLocaleTextApi } from './gridLocaleTextApi'; import type { GridParamsApi } from './gridParamsApi'; import { GridPreferencesPanelApi } from './gridPreferencesPanelApi'; import { GridPrintExportApi } from './gridPrintExportApi'; -import { GridRowApi } from './gridRowApi'; +import { GridRowApi, GridRowProPrivateApi } from './gridRowApi'; import { GridRowsMetaApi, GridRowsMetaPrivateApi } from './gridRowsMetaApi'; import { GridRowSelectionApi } from './gridRowSelectionApi'; import { GridSortApi } from './gridSortApi'; @@ -82,7 +82,8 @@ export interface GridPrivateOnlyApiCommon< GridLoggerApi, GridFocusPrivateApi, GridHeaderFilteringPrivateApi, - GridVirtualizationPrivateApi {} + GridVirtualizationPrivateApi, + GridRowProPrivateApi {} export interface GridPrivateApiCommon extends GridApiCommon, diff --git a/packages/x-data-grid/src/models/api/gridRowApi.ts b/packages/x-data-grid/src/models/api/gridRowApi.ts index 35382e3067dc..b54617e856a4 100644 --- a/packages/x-data-grid/src/models/api/gridRowApi.ts +++ b/packages/x-data-grid/src/models/api/gridRowApi.ts @@ -48,6 +48,11 @@ export interface GridRowApi { * @returns {GridRowId[]} A list of ids. */ getAllRowIds: () => GridRowId[]; + /** + * Sets the internal loading state. + * @param {boolean} loading If `true` the loading indicator will be shown over the Data Grid. + */ + setLoading: (loading: boolean) => void; /** * Sets a new set of rows. * @param {GridRowModel[]} rows The new rows. @@ -112,3 +117,13 @@ export interface GridRowProApi { */ setRowChildrenExpansion: (id: GridRowId, isExpanded: boolean) => void; } + +export interface GridRowProPrivateApi { + /** + * Allows to update, insert and delete rows at a specific nested level. + * @param {GridRowModelUpdate[]} updates An array of rows with an `action` specifying what to do. + * @param {string[]} groupKeys The group keys of the rows to update. + * @param {boolean} throttle Whether to throttle the updates or not. (default: `true`) + */ + updateServerRows: (updates: GridRowModelUpdate[], groupKeys?: string[]) => void; +} diff --git a/packages/x-data-grid/src/models/api/gridRowSelectionApi.ts b/packages/x-data-grid/src/models/api/gridRowSelectionApi.ts index ccbd3b1aebd2..ed8f6b228c9f 100644 --- a/packages/x-data-grid/src/models/api/gridRowSelectionApi.ts +++ b/packages/x-data-grid/src/models/api/gridRowSelectionApi.ts @@ -31,9 +31,9 @@ export interface GridRowSelectionApi { /** * Updates the selected rows to be those passed to the `rowIds` argument. * Any row already selected will be unselected. - * @param {GridRowId[]} rowIds The row ids to select. + * @param {readonly GridRowId[]} rowIds The row ids to select. */ - setRowSelectionModel: (rowIds: GridRowId[]) => void; + setRowSelectionModel: (rowIds: readonly GridRowId[]) => void; } export interface GridRowMultiSelectionApi { diff --git a/packages/x-data-grid/src/models/colDef/gridColDef.ts b/packages/x-data-grid/src/models/colDef/gridColDef.ts index 36d7619a5941..4030443ff315 100644 --- a/packages/x-data-grid/src/models/colDef/gridColDef.ts +++ b/packages/x-data-grid/src/models/colDef/gridColDef.ts @@ -134,7 +134,7 @@ export interface GridBaseColDef[]; + filterOperators?: readonly GridFilterOperator[]; /** * The callback that generates a filtering function for a given quick filter value. * This function can return `null` to skip filtering for this value and column. @@ -306,9 +306,9 @@ export interface GridActionsColDef[]} An array of [[GridActionsCell]] elements. + * @returns {readonly React.ReactElement[]} An array of [[GridActionsCell]] elements. */ - getActions: (params: GridRowParams) => React.ReactElement[]; + getActions: (params: GridRowParams) => readonly React.ReactElement[]; } /** diff --git a/packages/x-data-grid/src/models/gridDataSource.ts b/packages/x-data-grid/src/models/gridDataSource.ts new file mode 100644 index 000000000000..58038fe0e290 --- /dev/null +++ b/packages/x-data-grid/src/models/gridDataSource.ts @@ -0,0 +1,97 @@ +import type { + GridSortModel, + GridFilterModel, + GridColDef, + GridRowModel, + GridPaginationModel, +} from '.'; + +export interface GridGetRowsParams { + sortModel: GridSortModel; + filterModel: GridFilterModel; + /** + * Alternate to `start` and `end`, maps to `GridPaginationModel` interface. + */ + paginationModel: GridPaginationModel; + /** + * First row index to fetch (number) or cursor information (number | string). + */ + start: number | string; + /** + * Last row index to fetch. + */ + end: number; // last row index to fetch + /** + * List of grouped columns (only applicable with `rowGrouping`). + */ + groupFields?: GridColDef['field'][]; + /** + * Array of keys returned by `getGroupKey` of all the parent rows until the row for which the data is requested + * `getGroupKey` prop must be implemented to use this. + * Useful for `treeData` and `rowGrouping` only. + */ + groupKeys?: string[]; +} + +export interface GridGetRowsResponse { + rows: GridRowModel[]; + /** + * To reflect updates in total `rowCount` (optional). + * Useful when the `rowCount` is inaccurate (for example when filtering) or not available upfront. + */ + rowCount?: number; + /** + * Additional `pageInfo` for advanced use-cases. + * `hasNextPage`: When row count is unknown/estimated, `hasNextPage` will be used to check if more records are available on server + */ + pageInfo?: { + hasNextPage?: boolean; + nextCursor?: string; + }; +} + +export interface GridDataSource { + /** + * This method will be called when the grid needs to fetch some rows + * @param {GridGetRowsParams} params The parameters required to fetch the rows + * @returns {Promise} A promise that resolves to the data of type [GridGetRowsResponse] + */ + getRows(params: GridGetRowsParams): Promise; + /** + * This method will be called when the user updates a row [Not yet implemented] + * @param {GridRowModel} updatedRow The updated row + * @returns {Promise} If resolved (synced on the backend), the grid will update the row and mutate the cache + */ + updateRow?(updatedRow: GridRowModel): Promise; + /** + * Used to group rows by their parent group. Replaces `getTreeDataPath` used in client side tree-data . + * @param {GridRowModel} row The row to get the group key of + * @returns {string} The group key for the row + */ + getGroupKey?: (row: GridRowModel) => string; + /** + * Used to determine the number of children a row has on server. + * @param {GridRowModel} row The row to check the number of children + * @returns {number} The number of children the row has + */ + getChildrenCount?: (row: GridRowModel) => number; +} + +export interface GridDataSourceCache { + /** + * Set the cache entry for the given key + * @param {GridGetRowsParams} key The key of type `GridGetRowsParams` + * @param {GridGetRowsResponse} value The value to be stored in the cache + */ + set: (key: GridGetRowsParams, value: GridGetRowsResponse) => void; + /** + * Get the cache entry for the given key + * @param {GridGetRowsParams} key The key of type `GridGetRowsParams` + * @returns {GridGetRowsResponse} The value stored in the cache + */ + get: (key: GridGetRowsParams) => GridGetRowsResponse | undefined; + /** + * Clear the cache + */ + clear: () => void; +} diff --git a/packages/x-data-grid/src/models/gridRowSelectionModel.ts b/packages/x-data-grid/src/models/gridRowSelectionModel.ts index 19b3bee14dfb..599d21df8b8f 100644 --- a/packages/x-data-grid/src/models/gridRowSelectionModel.ts +++ b/packages/x-data-grid/src/models/gridRowSelectionModel.ts @@ -1,5 +1,5 @@ import { GridRowId } from './gridRows'; -export type GridInputRowSelectionModel = GridRowId[] | GridRowId; +export type GridInputRowSelectionModel = readonly GridRowId[] | GridRowId; -export type GridRowSelectionModel = GridRowId[]; +export type GridRowSelectionModel = readonly GridRowId[]; diff --git a/packages/x-data-grid/src/models/gridRows.ts b/packages/x-data-grid/src/models/gridRows.ts index 1519fd1bddba..703433dc873c 100644 --- a/packages/x-data-grid/src/models/gridRows.ts +++ b/packages/x-data-grid/src/models/gridRows.ts @@ -114,6 +114,17 @@ export interface GridDataGroupNode extends GridBasicGroupNode { isAutoGenerated: false; } +export interface GridDataSourceGroupNode extends GridDataGroupNode { + /** + * If true, this node has children on server. + */ + hasServerChildren: boolean; + /** + * The cached path to be passed on as `groupKey` to the server. + */ + path: string[]; +} + export type GridGroupNode = GridDataGroupNode | GridAutoGeneratedGroupNode; export type GridChildrenFromPathLookup = { diff --git a/packages/x-data-grid/src/models/gridSlotsComponent.ts b/packages/x-data-grid/src/models/gridSlotsComponent.ts index f08dc9dde12f..4fe7ea508c74 100644 --- a/packages/x-data-grid/src/models/gridSlotsComponent.ts +++ b/packages/x-data-grid/src/models/gridSlotsComponent.ts @@ -93,6 +93,11 @@ export interface GridSlotsComponent extends GridBaseSlots, GridIconSlotsComponen columnHeaderFilterIconButton: React.JSXElementConstructor< GridSlotProps['columnHeaderFilterIconButton'] >; + /** + * Sort icon component rendered in each column header. + * @default GridColumnHeaderSortIcon + */ + columnHeaderSortIcon: React.JSXElementConstructor; /** * Column menu component rendered by clicking on the 3 dots "kebab" icon in column headers. * @default GridColumnMenu diff --git a/packages/x-data-grid/src/models/gridSlotsComponentsProps.ts b/packages/x-data-grid/src/models/gridSlotsComponentsProps.ts index 6623ae5d4483..6ea9c9f27613 100644 --- a/packages/x-data-grid/src/models/gridSlotsComponentsProps.ts +++ b/packages/x-data-grid/src/models/gridSlotsComponentsProps.ts @@ -27,7 +27,9 @@ import type { GridColumnHeadersProps } from '../components/GridColumnHeaders'; import type { GridDetailPanelsProps } from '../components/GridDetailPanels'; import type { GridPinnedRowsProps } from '../components/GridPinnedRows'; import type { GridColumnsManagementProps } from '../components/columnsManagement/GridColumnsManagement'; -import type { GridRowCountProps } from '../components'; +import type { GridLoadingOverlayProps } from '../components/GridLoadingOverlay'; +import type { GridRowCountProps } from '../components/GridRowCount'; +import type { GridColumnHeaderSortIconProps } from '../components/columnHeaders/GridColumnHeaderSortIcon'; // Overrides for module augmentation export interface BaseCheckboxPropsOverrides {} @@ -46,6 +48,7 @@ export interface BaseChipPropsOverrides {} export interface CellPropsOverrides {} export interface ToolbarPropsOverrides {} export interface ColumnHeaderFilterIconButtonPropsOverrides {} +export interface ColumnHeaderSortIconPropsOverrides {} export interface ColumnMenuPropsOverrides {} export interface ColumnsPanelPropsOverrides {} export interface DetailPanelsPropsOverrides {} @@ -84,6 +87,7 @@ export interface GridSlotProps { columnHeaders: GridColumnHeadersProps; columnHeaderFilterIconButton: ColumnHeaderFilterIconButtonProps & ColumnHeaderFilterIconButtonPropsOverrides; + columnHeaderSortIcon: GridColumnHeaderSortIconProps & ColumnHeaderSortIconPropsOverrides; columnMenu: GridColumnMenuProps & ColumnMenuPropsOverrides; columnsPanel: GridColumnsPanelProps & ColumnsPanelPropsOverrides; columnsManagement: GridColumnsManagementProps & ColumnsManagementPropsOverrides; @@ -91,7 +95,7 @@ export interface GridSlotProps { filterPanel: GridFilterPanelProps & FilterPanelPropsOverrides; footer: GridFooterContainerProps & FooterPropsOverrides; footerRowCount: GridRowCountProps & FooterRowCountOverrides; - loadingOverlay: GridOverlayProps & LoadingOverlayPropsOverrides; + loadingOverlay: GridLoadingOverlayProps & LoadingOverlayPropsOverrides; noResultsOverlay: GridOverlayProps & NoResultsOverlayPropsOverrides; noRowsOverlay: GridOverlayProps & NoRowsOverlayPropsOverrides; pagination: Partial & PaginationPropsOverrides; diff --git a/packages/x-data-grid/src/models/props/DataGridProps.ts b/packages/x-data-grid/src/models/props/DataGridProps.ts index 21e6a750d0a3..47a56c9a742a 100644 --- a/packages/x-data-grid/src/models/props/DataGridProps.ts +++ b/packages/x-data-grid/src/models/props/DataGridProps.ts @@ -32,6 +32,7 @@ import { GridCellModesModel, GridRowModesModel } from '../api/gridEditingApi'; import { GridColumnGroupingModel } from '../gridColumnGrouping'; import { GridPaginationMeta, GridPaginationModel } from '../gridPaginationProps'; import type { GridAutosizeOptions } from '../../hooks/features/columnResize'; +import type { GridDataSource } from '../gridDataSource'; export interface GridExperimentalFeatures { /** @@ -814,6 +815,7 @@ export interface DataGridProSharedPropsWithoutDefaultValue { * Override the height of the header filters. */ headerFilterHeight?: number; + unstable_dataSource?: GridDataSource; } export interface DataGridPremiumSharedPropsWithDefaultValue { diff --git a/packages/x-data-grid/src/tests/DataGrid.test.tsx b/packages/x-data-grid/src/tests/DataGrid.test.tsx index 17011096eb2d..cef9fe12cf3a 100644 --- a/packages/x-data-grid/src/tests/DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/DataGrid.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { createRenderer } from '@mui/internal-test-utils'; import { expect } from 'chai'; -import { DataGrid } from '@mui/x-data-grid'; +import { DataGrid, DATA_GRID_PROPS_DEFAULT_VALUES } from '@mui/x-data-grid'; const isJSDOM = /jsdom/.test(window.navigator.userAgent); @@ -62,4 +62,36 @@ describe('', () => {
, ); }); + + it('should not cause unexpected behavior when props are explictly set to undefined', () => { + const rows = [ + { id: 'a', col1: 'Hello', col2: 'World' }, + { id: 'constructor', col1: 'DataGridPro', col2: 'is Awesome' }, + { id: 'hasOwnProperty', col1: 'MUI', col2: 'is Amazing' }, + ]; + + const columns = [ + { field: 'col1', headerName: 'Column 1', width: 150 }, + { field: 'col2', headerName: 'Column 2', width: 150 }, + ]; + expect(() => { + render( +
+ + ).reduce((acc, key) => { + // @ts-ignore + acc[key] = undefined; + return acc; + }, {})} + rows={rows} + columns={columns} + /> +
, + ); + }).not.toErrorDev(); + }); }); diff --git a/packages/x-data-grid/src/tests/cells.DataGrid.test.tsx b/packages/x-data-grid/src/tests/cells.DataGrid.test.tsx index 14c0f51e40e8..91eec8720b13 100644 --- a/packages/x-data-grid/src/tests/cells.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/cells.DataGrid.test.tsx @@ -60,7 +60,7 @@ describe(' - Cells', () => { expect(width).to.equal('1px'); // should not be transparent - expect(color).to.not.equal('rgba(0, 0, 0, 0)'); + expect(color).not.to.equal('rgba(0, 0, 0, 0)'); } it('should add right border to cells', function test() { diff --git a/packages/x-data-grid/src/tests/columnHeaders.DataGrid.test.tsx b/packages/x-data-grid/src/tests/columnHeaders.DataGrid.test.tsx index 817d96a118a9..47e091416795 100644 --- a/packages/x-data-grid/src/tests/columnHeaders.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/columnHeaders.DataGrid.test.tsx @@ -125,7 +125,7 @@ describe(' - Column headers', () => { userEvent.mousePress(within(getColumnHeaderCell(0)).getByLabelText('Menu')); clock.runToLast(); - expect(screen.queryByRole('menu')).to.not.equal(null); + expect(screen.queryByRole('menu')).not.to.equal(null); userEvent.mousePress(within(getColumnHeaderCell(0)).getByLabelText('Menu')); clock.runToLast(); diff --git a/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx b/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx index 28a32fe53aa0..4f003a354866 100644 --- a/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/layout.DataGrid.test.tsx @@ -1174,7 +1174,7 @@ describe(' - Layout & warnings', () => { } render( -
+
, ); @@ -1213,7 +1213,7 @@ describe(' - Layout & warnings', () => { } render( -
+
- Pagination', () => { expect(getColumnValues(0)).to.have.length(20); setProps({ paginationModel: { pageSize: 10, page: 0 } }); expect(getColumnValues(0)).to.have.length(10); - expect(getCell(0, 0)).to.not.equal(null); + expect(getCell(0, 0)).not.to.equal(null); fireEvent.click(screen.getByRole('button', { name: /next page/i })); expect(getColumnValues(0)).to.have.length(10); }); @@ -597,30 +597,30 @@ describe(' - Pagination', () => { it('should support server side pagination with unknown row count', () => { const { setProps } = render(); expect(getColumnValues(0)).to.deep.equal(['0']); - expect(screen.getByText('1–1 of more than 1')).to.not.equal(null); + expect(screen.getByText('1–1 of more than 1')).not.to.equal(null); fireEvent.click(screen.getByRole('button', { name: /next page/i })); expect(getColumnValues(0)).to.deep.equal(['1']); - expect(screen.getByText('2–2 of more than 2')).to.not.equal(null); + expect(screen.getByText('2–2 of more than 2')).not.to.equal(null); fireEvent.click(screen.getByRole('button', { name: /next page/i })); setProps({ rowCount: 3 }); expect(getColumnValues(0)).to.deep.equal(['2']); - expect(screen.getByText('3–3 of 3')).to.not.equal(null); + expect(screen.getByText('3–3 of 3')).not.to.equal(null); }); it('should support server side pagination with estimated row count', () => { const { setProps } = render(); expect(getColumnValues(0)).to.deep.equal(['0']); - expect(screen.getByText('1–1 of more than 2')).to.not.equal(null); + expect(screen.getByText('1–1 of more than 2')).not.to.equal(null); fireEvent.click(screen.getByRole('button', { name: /next page/i })); expect(getColumnValues(0)).to.deep.equal(['1']); - expect(screen.getByText('2–2 of more than 2')).to.not.equal(null); + expect(screen.getByText('2–2 of more than 2')).not.to.equal(null); fireEvent.click(screen.getByRole('button', { name: /next page/i })); expect(getColumnValues(0)).to.deep.equal(['2']); - expect(screen.getByText('3–3 of more than 3')).to.not.equal(null); + expect(screen.getByText('3–3 of more than 3')).not.to.equal(null); fireEvent.click(screen.getByRole('button', { name: /next page/i })); setProps({ rowCount: 4 }); expect(getColumnValues(0)).to.deep.equal(['3']); - expect(screen.getByText('4–4 of 4')).to.not.equal(null); + expect(screen.getByText('4–4 of 4')).not.to.equal(null); }); }); @@ -730,12 +730,14 @@ describe(' - Pagination', () => { ]; expect(() => { const { setProps } = render( - , +
+ +
, ); setProps({ rows: rows.slice(0, 2) }); }).not.to.throw(); diff --git a/packages/x-data-grid/src/utils/utils.ts b/packages/x-data-grid/src/utils/utils.ts index cc682162e59f..097ed683d9b2 100644 --- a/packages/x-data-grid/src/utils/utils.ts +++ b/packages/x-data-grid/src/utils/utils.ts @@ -190,9 +190,16 @@ function mulberry32(a: number): () => number { }; } -export function randomNumberBetween(seed: number, min: number, max: number): () => number { +/** + * Create a random number generator from a seed. The seed + * ensures that the random number generator produces the + * same sequence of 'random' numbers on every render. It + * returns a function that generates a random number between + * a specified min and max. + */ +export function createRandomNumberGenerator(seed: number): (min: number, max: number) => number { const random = mulberry32(seed); - return () => min + (max - min) * random(); + return (min: number, max: number) => min + (max - min) * random(); } export function deepClone(obj: Record) { diff --git a/packages/x-data-grid/tsconfig.build.json b/packages/x-data-grid/tsconfig.build.json index a287257ec3c0..be862bc37b1b 100644 --- a/packages/x-data-grid/tsconfig.build.json +++ b/packages/x-data-grid/tsconfig.build.json @@ -11,6 +11,7 @@ "rootDir": "./src", "types": ["node", "@mui/material/themeCssVarsAugmentation", "@emotion/styled", "@mui/types"] }, + "references": [{ "path": "../x-internals/tsconfig.build.json" }], "include": ["src/**/*.ts*"], "exclude": ["src/**/*.spec.ts*", "src/**/*.test.ts*"] } diff --git a/packages/x-data-grid/tsconfig.json b/packages/x-data-grid/tsconfig.json index aba8438e2441..a95beb1e8020 100644 --- a/packages/x-data-grid/tsconfig.json +++ b/packages/x-data-grid/tsconfig.json @@ -5,7 +5,8 @@ "@mui/internal-test-utils/initMatchers", "@mui/material/themeCssVarsAugmentation", "chai-dom", - "mocha" + "mocha", + "node" ] }, "include": ["src/**/*"] diff --git a/packages/x-date-pickers-pro/package.json b/packages/x-date-pickers-pro/package.json index da78cb86f3b3..e852566d858b 100644 --- a/packages/x-date-pickers-pro/package.json +++ b/packages/x-date-pickers-pro/package.json @@ -1,6 +1,6 @@ { "name": "@mui/x-date-pickers-pro", - "version": "7.7.1", + "version": "7.9.0", "description": "The Pro plan edition of the Date and Time Picker components (MUI X).", "author": "MUI Team", "main": "src/index.ts", @@ -44,8 +44,8 @@ "dependencies": { "@babel/runtime": "^7.24.7", "@mui/base": "^5.0.0-beta.40", - "@mui/system": "^5.15.20", - "@mui/utils": "^5.15.20", + "@mui/system": "^5.16.0", + "@mui/utils": "^5.16.0", "@mui/x-date-pickers": "workspace:*", "@mui/x-license": "workspace:*", "clsx": "^2.1.1", @@ -96,7 +96,7 @@ } }, "devDependencies": { - "@mui/internal-test-utils": "^1.0.1", + "@mui/internal-test-utils": "^1.0.4", "@types/luxon": "^3.4.2", "@types/prop-types": "^15.7.12", "date-fns": "^2.30.0", @@ -104,7 +104,7 @@ "dayjs": "^1.11.11", "luxon": "^3.4.4", "moment": "^2.30.1", - "rimraf": "^5.0.7" + "rimraf": "^5.0.8" }, "engines": { "node": ">=14.0.0" diff --git a/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.test.tsx b/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.test.tsx index ffa81a05f51b..129d6c7ba2f2 100644 --- a/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.test.tsx +++ b/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.test.tsx @@ -14,7 +14,6 @@ import { MockedDataTransfer, rangeCalendarDayTouches, createPickerRenderer, - wrapPickerMount, } from 'test/utils/pickers'; import { DateRangeCalendar, @@ -45,9 +44,8 @@ describe('', () => { inheritComponent: 'div', render, muiName: 'MuiDateRangeCalendar', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, - skip: ['componentProp', 'componentsProp', 'reactTestRenderer', 'themeVariants'], + skip: ['componentProp', 'componentsProp', 'themeVariants'], })); describe('Selection', () => { diff --git a/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePickerToolbar.tsx b/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePickerToolbar.tsx index b14f206755ee..da4b3debfa1d 100644 --- a/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePickerToolbar.tsx +++ b/packages/x-date-pickers-pro/src/DateRangePicker/DateRangePickerToolbar.tsx @@ -9,9 +9,9 @@ import { PickersToolbarButton, useUtils, BaseToolbarProps, - useLocaleText, ExportedBaseToolbarProps, } from '@mui/x-date-pickers/internals'; +import { usePickersTranslations } from '@mui/x-date-pickers/hooks'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import { DateRange } from '../models'; import { UseRangePositionResponse } from '../internals/hooks/useRangePosition'; @@ -86,15 +86,15 @@ const DateRangePickerToolbar = React.forwardRef(function DateRangePickerToolbar< ...other } = props; - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const startDateValue = start ? utils.formatByString(start, toolbarFormat || utils.formats.shortDate) - : localeText.start; + : translations.start; const endDateValue = end ? utils.formatByString(end, toolbarFormat || utils.formats.shortDate) - : localeText.end; + : translations.end; const ownerState = props; const classes = useUtilityClasses(ownerState); @@ -102,7 +102,7 @@ const DateRangePickerToolbar = React.forwardRef(function DateRangePickerToolbar< return ( - Describes', () => { @@ -10,7 +10,6 @@ describe(' - Describes', () => { classes: {} as any, render, muiName: 'MuiDateRangePicker', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, skip: [ 'componentProp', @@ -21,7 +20,6 @@ describe(' - Describes', () => { 'mergeClassName', 'propsSpread', 'rootClass', - 'reactTestRenderer', ], })); }); diff --git a/packages/x-date-pickers-pro/src/DateRangePickerDay/DateRangePickerDay.test.tsx b/packages/x-date-pickers-pro/src/DateRangePickerDay/DateRangePickerDay.test.tsx index 03294c00ca36..6b1ef20fb85b 100644 --- a/packages/x-date-pickers-pro/src/DateRangePickerDay/DateRangePickerDay.test.tsx +++ b/packages/x-date-pickers-pro/src/DateRangePickerDay/DateRangePickerDay.test.tsx @@ -3,7 +3,7 @@ import { DateRangePickerDay, dateRangePickerDayClasses as classes, } from '@mui/x-date-pickers-pro/DateRangePickerDay'; -import { wrapPickerMount, createPickerRenderer, adapterToUse } from 'test/utils/pickers'; +import { createPickerRenderer, adapterToUse } from 'test/utils/pickers'; import { describeConformance } from 'test/utils/describeConformance'; describe('', () => { @@ -29,14 +29,13 @@ describe('', () => { inheritComponent: 'button', muiName: 'MuiDateRangePickerDay', render, - wrapMount: wrapPickerMount, refInstanceof: window.HTMLButtonElement, // cannot test reactTestRenderer because of required context skip: [ 'componentProp', 'rootClass', // forwards classes to DateRangePickerDayDay, but applies root class on DateRangePickerDayRoot + 'mergeClassName', // forwards other props (i.e. data-test-id) to the DateRangePickerDayDay, but `className` is applied on the root 'componentsProp', - 'reactTestRenderer', 'propsSpread', 'refForwarding', // TODO: Fix DateRangePickerDays is not spreading props on root diff --git a/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePickerTabs.tsx b/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePickerTabs.tsx index d71f3a04fce2..a5b56f8eaeac 100644 --- a/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePickerTabs.tsx +++ b/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePickerTabs.tsx @@ -5,13 +5,14 @@ import { styled, useThemeProps } from '@mui/material/styles'; import composeClasses from '@mui/utils/composeClasses'; import useEventCallback from '@mui/utils/useEventCallback'; import { TimeIcon, DateRangeIcon, ArrowLeftIcon, ArrowRightIcon } from '@mui/x-date-pickers/icons'; +import { PickerValidDate } from '@mui/x-date-pickers/models'; import { DateOrTimeViewWithMeridiem, - useLocaleText, BaseTabsProps, ExportedBaseTabsProps, isDatePickerView, } from '@mui/x-date-pickers/internals'; +import { usePickersTranslations } from '@mui/x-date-pickers/hooks'; import IconButton from '@mui/material/IconButton'; import Button from '@mui/material/Button'; import { @@ -106,7 +107,7 @@ const DateTimeRangePickerTabFiller = styled('div', { const tabOptions: TabValue[] = ['start-date', 'start-time', 'end-date', 'end-time']; -const DateTimeRangePickerTabs = function DateTimeRangePickerTabs( +const DateTimeRangePickerTabs = function DateTimeRangePickerTabs( inProps: DateTimeRangePickerTabsProps, ) { const props = useThemeProps({ props: inProps, name: 'MuiDateTimeRangePickerTabs' }); @@ -122,7 +123,7 @@ const DateTimeRangePickerTabs = function DateTimeRangePickerTabs( sx, } = props; - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const classes = useUtilityClasses(props); const value = React.useMemo(() => viewToTab(view, rangePosition), [view, rangePosition]); const isPreviousHidden = value === 'start-date'; @@ -130,17 +131,23 @@ const DateTimeRangePickerTabs = function DateTimeRangePickerTabs( const tabLabel = React.useMemo(() => { switch (value) { case 'start-date': - return localeText.startDate; + return translations.startDate; case 'start-time': - return localeText.startTime; + return translations.startTime; case 'end-date': - return localeText.endDate; + return translations.endDate; case 'end-time': - return localeText.endTime; + return translations.endTime; default: return ''; } - }, [localeText.endDate, localeText.endTime, localeText.startDate, localeText.startTime, value]); + }, [ + translations.endDate, + translations.endTime, + translations.startDate, + translations.startTime, + value, + ]); const handleRangePositionChange = useEventCallback((newTab: TabValue) => { if (newTab.includes('start')) { @@ -176,7 +183,7 @@ const DateTimeRangePickerTabs = function DateTimeRangePickerTabs( @@ -195,7 +202,7 @@ const DateTimeRangePickerTabs = function DateTimeRangePickerTabs( diff --git a/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePickerToolbar.tsx b/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePickerToolbar.tsx index f2ff988c224c..26816d573602 100644 --- a/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePickerToolbar.tsx +++ b/packages/x-date-pickers-pro/src/DateTimeRangePicker/DateTimeRangePickerToolbar.tsx @@ -5,12 +5,12 @@ import { styled, useThemeProps } from '@mui/material/styles'; import { unstable_composeClasses as composeClasses } from '@mui/utils'; import { BaseToolbarProps, - useLocaleText, ExportedBaseToolbarProps, useUtils, DateOrTimeViewWithMeridiem, WrapperVariant, } from '@mui/x-date-pickers/internals'; +import { usePickersTranslations } from '@mui/x-date-pickers/hooks'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import { DateTimePickerToolbarProps, @@ -151,7 +151,7 @@ const DateTimeRangePickerToolbar = React.forwardRef(function DateTimeRangePicker toolbarPlaceholder, }; - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const ownerState = props; const classes = useUtilityClasses(ownerState); @@ -212,7 +212,7 @@ const DateTimeRangePickerToolbar = React.forwardRef(function DateTimeRangePicker value={start} onViewChange={handleStartRangeViewChange} - toolbarTitle={localeText.start} + toolbarTitle={translations.start} ownerState={ownerState} toolbarVariant="desktop" view={rangePosition === 'start' ? view : undefined} @@ -224,7 +224,7 @@ const DateTimeRangePickerToolbar = React.forwardRef(function DateTimeRangePicker value={end} onViewChange={handleEndRangeViewChange} - toolbarTitle={localeText.end} + toolbarTitle={translations.end} ownerState={ownerState} toolbarVariant="desktop" view={rangePosition === 'end' ? view : undefined} diff --git a/packages/x-date-pickers-pro/src/DateTimeRangePicker/tests/describes.DateTimeRangePicker.test.tsx b/packages/x-date-pickers-pro/src/DateTimeRangePicker/tests/describes.DateTimeRangePicker.test.tsx index 4778e65099b2..264143b0f016 100644 --- a/packages/x-date-pickers-pro/src/DateTimeRangePicker/tests/describes.DateTimeRangePicker.test.tsx +++ b/packages/x-date-pickers-pro/src/DateTimeRangePicker/tests/describes.DateTimeRangePicker.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { createPickerRenderer, wrapPickerMount } from 'test/utils/pickers'; +import { createPickerRenderer } from 'test/utils/pickers'; import { describeConformance } from 'test/utils/describeConformance'; import { DateTimeRangePicker } from '../DateTimeRangePicker'; @@ -10,7 +10,6 @@ describe(' - Describes', () => { classes: {} as any, render, muiName: 'MuiDateTimeRangePicker', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, skip: [ 'componentProp', @@ -21,7 +20,6 @@ describe(' - Describes', () => { 'mergeClassName', 'propsSpread', 'rootClass', - 'reactTestRenderer', ], })); }); diff --git a/packages/x-date-pickers-pro/src/DesktopDateRangePicker/tests/describes.DesktopDateRangePicker.test.tsx b/packages/x-date-pickers-pro/src/DesktopDateRangePicker/tests/describes.DesktopDateRangePicker.test.tsx index a4498dca0101..8272c9b05382 100644 --- a/packages/x-date-pickers-pro/src/DesktopDateRangePicker/tests/describes.DesktopDateRangePicker.test.tsx +++ b/packages/x-date-pickers-pro/src/DesktopDateRangePicker/tests/describes.DesktopDateRangePicker.test.tsx @@ -3,7 +3,6 @@ import { screen, userEvent } from '@mui/internal-test-utils'; import { adapterToUse, createPickerRenderer, - wrapPickerMount, expectFieldValueV7, describePicker, describeValue, @@ -34,7 +33,6 @@ describe(' - Describes', () => { classes: {} as any, render, muiName: 'MuiDesktopDateRangePicker', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, skip: [ 'componentProp', @@ -45,7 +43,6 @@ describe(' - Describes', () => { 'mergeClassName', 'propsSpread', 'rootClass', - 'reactTestRenderer', ], })); diff --git a/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/DesktopDateTimeRangePicker.tsx b/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/DesktopDateTimeRangePicker.tsx index 431bed8573b8..d90ff4da876f 100644 --- a/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/DesktopDateTimeRangePicker.tsx +++ b/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/DesktopDateTimeRangePicker.tsx @@ -7,6 +7,8 @@ import { isInternalTimeView, PickerViewRenderer, PickerViewsRendererProps, + resolveDateTimeFormat, + useUtils, } from '@mui/x-date-pickers/internals'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import { resolveComponentProps } from '@mui/base/utils'; @@ -138,6 +140,7 @@ const DesktopDateTimeRangePicker = React.forwardRef(function DesktopDateTimeRang inProps: DesktopDateTimeRangePickerProps, ref: React.Ref, ) { + const utils = useUtils(); // Props with the default values common to all date time range pickers const defaultizedProps = useDateTimeRangePickerDefaultizedProps< TDate, @@ -170,6 +173,7 @@ const DesktopDateTimeRangePicker = React.forwardRef(function DesktopDateTimeRang ...defaultizedProps, views, viewRenderers, + format: resolveDateTimeFormat(utils, defaultizedProps), // force true to correctly handle `renderTimeViewClock` as a renderer ampmInClock: true, calendars: defaultizedProps.calendars ?? 1, diff --git a/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/describes.DesktopDateTimeRangePicker.test.tsx b/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/describes.DesktopDateTimeRangePicker.test.tsx index 1045076de111..09e6d97de385 100644 --- a/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/describes.DesktopDateTimeRangePicker.test.tsx +++ b/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/describes.DesktopDateTimeRangePicker.test.tsx @@ -7,7 +7,6 @@ import { describeValue, describePicker, describeRangeValidation, - wrapPickerMount, getFieldSectionsContainer, } from 'test/utils/pickers'; import { DesktopDateTimeRangePicker } from '../DesktopDateTimeRangePicker'; @@ -35,7 +34,6 @@ describe(' - Describes', () => { classes: {} as any, render, muiName: 'MuiDesktopDateTimeRangePicker', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, skip: [ 'componentProp', @@ -46,7 +44,6 @@ describe(' - Describes', () => { 'mergeClassName', 'propsSpread', 'rootClass', - 'reactTestRenderer', ], })); diff --git a/packages/x-date-pickers-pro/src/MobileDateRangePicker/tests/describes.MobileDateRangePicker.test.tsx b/packages/x-date-pickers-pro/src/MobileDateRangePicker/tests/describes.MobileDateRangePicker.test.tsx index 7b2bcf1dc888..22aace0cc29c 100644 --- a/packages/x-date-pickers-pro/src/MobileDateRangePicker/tests/describes.MobileDateRangePicker.test.tsx +++ b/packages/x-date-pickers-pro/src/MobileDateRangePicker/tests/describes.MobileDateRangePicker.test.tsx @@ -4,7 +4,6 @@ import { MobileDateRangePicker } from '@mui/x-date-pickers-pro/MobileDateRangePi import { adapterToUse, createPickerRenderer, - wrapPickerMount, openPicker, expectFieldValueV7, describeRangeValidation, @@ -34,7 +33,6 @@ describe(' - Describes', () => { classes: {} as any, render, muiName: 'MuiMobileDateRangePicker', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, skip: [ 'componentProp', @@ -45,7 +43,6 @@ describe(' - Describes', () => { 'mergeClassName', 'propsSpread', 'rootClass', - 'reactTestRenderer', ], })); diff --git a/packages/x-date-pickers-pro/src/MobileDateTimeRangePicker/MobileDateTimeRangePicker.tsx b/packages/x-date-pickers-pro/src/MobileDateTimeRangePicker/MobileDateTimeRangePicker.tsx index 7ba1632219fb..8586aa9e32cf 100644 --- a/packages/x-date-pickers-pro/src/MobileDateTimeRangePicker/MobileDateTimeRangePicker.tsx +++ b/packages/x-date-pickers-pro/src/MobileDateTimeRangePicker/MobileDateTimeRangePicker.tsx @@ -11,6 +11,8 @@ import { DefaultizedProps, PickerViewsRendererProps, TimeViewWithMeridiem, + resolveDateTimeFormat, + useUtils, } from '@mui/x-date-pickers/internals'; import { PickerValidDate } from '@mui/x-date-pickers/models'; import { resolveComponentProps } from '@mui/base/utils'; @@ -147,6 +149,7 @@ const MobileDateTimeRangePicker = React.forwardRef(function MobileDateTimeRangeP inProps: MobileDateTimeRangePickerProps, ref: React.Ref, ) { + const utils = useUtils(); // Props with the default values common to all date time range pickers const defaultizedProps = useDateTimeRangePickerDefaultizedProps< TDate, @@ -169,6 +172,7 @@ const MobileDateTimeRangePicker = React.forwardRef(function MobileDateTimeRangeP const props = { ...defaultizedProps, viewRenderers, + format: resolveDateTimeFormat(utils, defaultizedProps), // Force one calendar on mobile to avoid layout issues calendars: 1, // force true to correctly handle `renderTimeViewClock` as a renderer diff --git a/packages/x-date-pickers-pro/src/MobileDateTimeRangePicker/tests/describes.MobileDateTimeRangePicker.test.tsx b/packages/x-date-pickers-pro/src/MobileDateTimeRangePicker/tests/describes.MobileDateTimeRangePicker.test.tsx index 16358cdc5592..3f10b2f0b4ff 100644 --- a/packages/x-date-pickers-pro/src/MobileDateTimeRangePicker/tests/describes.MobileDateTimeRangePicker.test.tsx +++ b/packages/x-date-pickers-pro/src/MobileDateTimeRangePicker/tests/describes.MobileDateTimeRangePicker.test.tsx @@ -7,7 +7,6 @@ import { describeValue, describePicker, describeRangeValidation, - wrapPickerMount, getFieldSectionsContainer, openPicker, } from 'test/utils/pickers'; @@ -36,7 +35,6 @@ describe(' - Describes', () => { classes: {} as any, render, muiName: 'MuiMobileDateTimeRangePicker', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, skip: [ 'componentProp', @@ -47,7 +45,6 @@ describe(' - Describes', () => { 'mergeClassName', 'propsSpread', 'rootClass', - 'reactTestRenderer', ], })); diff --git a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/tests/MultiInputDateRangeField.conformance.test.tsx b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/tests/MultiInputDateRangeField.conformance.test.tsx index d0a04e59dd14..6ba21a354f09 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/tests/MultiInputDateRangeField.conformance.test.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/tests/MultiInputDateRangeField.conformance.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { MultiInputDateRangeField } from '@mui/x-date-pickers-pro/MultiInputDateRangeField'; -import { createPickerRenderer, wrapPickerMount } from 'test/utils/pickers'; +import { createPickerRenderer } from 'test/utils/pickers'; import { describeConformance } from 'test/utils/describeConformance'; describe('', () => { @@ -11,9 +11,7 @@ describe('', () => { inheritComponent: 'div', render, muiName: 'MuiMultiInputDateRangeField', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, - // cannot test reactTestRenderer because of required context - skip: ['reactTestRenderer', 'themeVariants', 'componentProp', 'componentsProp'], + skip: ['themeVariants', 'componentProp', 'componentsProp'], })); }); diff --git a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/tests/MultiInputDateTimeRangeField.conformance.test.tsx b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/tests/MultiInputDateTimeRangeField.conformance.test.tsx index a0ebd8203fc1..7bb1d6cc437b 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/tests/MultiInputDateTimeRangeField.conformance.test.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/tests/MultiInputDateTimeRangeField.conformance.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { MultiInputDateTimeRangeField } from '@mui/x-date-pickers-pro/MultiInputDateTimeRangeField'; -import { createPickerRenderer, wrapPickerMount } from 'test/utils/pickers'; +import { createPickerRenderer } from 'test/utils/pickers'; import { describeConformance } from 'test/utils/describeConformance'; describe('', () => { @@ -11,9 +11,7 @@ describe('', () => { inheritComponent: 'div', render, muiName: 'MuiMultiInputDateTimeRangeField', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, - // cannot test reactTestRenderer because of required context - skip: ['componentProp', 'componentsProp', 'reactTestRenderer', 'themeVariants'], + skip: ['componentProp', 'componentsProp', 'themeVariants'], })); }); diff --git a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/tests/MultiInputTimeRangeField.conformance.test.tsx b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/tests/MultiInputTimeRangeField.conformance.test.tsx index e5efca7026ec..47047c3007d4 100644 --- a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/tests/MultiInputTimeRangeField.conformance.test.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/tests/MultiInputTimeRangeField.conformance.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { MultiInputTimeRangeField } from '@mui/x-date-pickers-pro/MultiInputTimeRangeField'; -import { createPickerRenderer, wrapPickerMount } from 'test/utils/pickers'; +import { createPickerRenderer } from 'test/utils/pickers'; import { describeConformance } from 'test/utils/describeConformance'; describe('', () => { @@ -11,9 +11,7 @@ describe('', () => { inheritComponent: 'div', render, muiName: 'MuiMultiInputTimeRangeField', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, - // cannot test reactTestRenderer because of required context - skip: ['reactTestRenderer', 'themeVariants', 'componentProp', 'componentsProp'], + skip: ['themeVariants', 'componentProp', 'componentsProp'], })); }); diff --git a/packages/x-date-pickers-pro/src/PickersRangeCalendarHeader/PickersRangeCalendarHeader.tsx b/packages/x-date-pickers-pro/src/PickersRangeCalendarHeader/PickersRangeCalendarHeader.tsx index 6657941e84d6..467081a8dfc3 100644 --- a/packages/x-date-pickers-pro/src/PickersRangeCalendarHeader/PickersRangeCalendarHeader.tsx +++ b/packages/x-date-pickers-pro/src/PickersRangeCalendarHeader/PickersRangeCalendarHeader.tsx @@ -5,11 +5,11 @@ import { PickersCalendarHeader } from '@mui/x-date-pickers/PickersCalendarHeader import { PickerValidDate } from '@mui/x-date-pickers/models'; import { PickersArrowSwitcher, - useLocaleText, useNextMonthDisabled, usePreviousMonthDisabled, useUtils, } from '@mui/x-date-pickers/internals'; +import { usePickersTranslations } from '@mui/x-date-pickers/hooks'; import { PickersRangeCalendarHeaderProps } from './PickersRangeCalendarHeader.types'; type PickersRangeCalendarHeaderComponent = (( @@ -27,7 +27,7 @@ const PickersRangeCalendarHeader = React.forwardRef(function PickersRangeCalenda TDate extends PickerValidDate, >(props: PickersRangeCalendarHeaderProps, ref: React.Ref) { const utils = useUtils(); - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const { calendars, month, monthIndex, labelId, ...other } = props; const { @@ -70,10 +70,10 @@ const PickersRangeCalendarHeader = React.forwardRef(function PickersRangeCalenda onGoToNext={selectNextMonth} isPreviousHidden={monthIndex !== 0} isPreviousDisabled={isPreviousMonthDisabled} - previousLabel={localeText.previousMonth} + previousLabel={translations.previousMonth} isNextHidden={monthIndex !== calendars - 1} isNextDisabled={isNextMonthDisabled} - nextLabel={localeText.nextMonth} + nextLabel={translations.nextMonth} slots={slots} slotProps={slotProps} labelId={labelId} diff --git a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/tests/describes.SingleInputDateRangeField.test.tsx b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/tests/describes.SingleInputDateRangeField.test.tsx index 57704368d4a3..673212f9f185 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateRangeField/tests/describes.SingleInputDateRangeField.test.tsx +++ b/packages/x-date-pickers-pro/src/SingleInputDateRangeField/tests/describes.SingleInputDateRangeField.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; import { SingleInputDateRangeField } from '@mui/x-date-pickers-pro/SingleInputDateRangeField'; -import { createPickerRenderer, wrapPickerMount, describeRangeValidation } from 'test/utils/pickers'; +import { createPickerRenderer, describeRangeValidation } from 'test/utils/pickers'; import { describeConformance } from 'test/utils/describeConformance'; describe(' - Describes', () => { @@ -12,11 +12,8 @@ describe(' - Describes', () => { inheritComponent: PickersTextField, render, muiName: 'MuiSingleInputDateRangeField', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, - // cannot test reactTestRenderer because of required context skip: [ - 'reactTestRenderer', 'componentProp', 'componentsProp', 'themeDefaultProps', diff --git a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/tests/describes.SingleInputDateTimeRangeField.test.tsx b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/tests/describes.SingleInputDateTimeRangeField.test.tsx index 219e51370d93..28385f501b68 100644 --- a/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/tests/describes.SingleInputDateTimeRangeField.test.tsx +++ b/packages/x-date-pickers-pro/src/SingleInputDateTimeRangeField/tests/describes.SingleInputDateTimeRangeField.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { SingleInputDateTimeRangeField } from '@mui/x-date-pickers-pro/SingleInputDateTimeRangeField'; -import { createPickerRenderer, wrapPickerMount, describeRangeValidation } from 'test/utils/pickers'; +import { createPickerRenderer, describeRangeValidation } from 'test/utils/pickers'; import { describeConformance } from 'test/utils/describeConformance'; describe(' - Describes', () => { @@ -11,11 +11,8 @@ describe(' - Describes', () => { inheritComponent: 'div', render, muiName: 'MuiSingleInputDateTimeRangeField', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, - // cannot test reactTestRenderer because of required context skip: [ - 'reactTestRenderer', 'componentProp', 'componentsProp', 'themeDefaultProps', diff --git a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/tests/describes.SingleInputTimeRangeField.test.tsx b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/tests/describes.SingleInputTimeRangeField.test.tsx index 684786c4d54d..afab8beb758b 100644 --- a/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/tests/describes.SingleInputTimeRangeField.test.tsx +++ b/packages/x-date-pickers-pro/src/SingleInputTimeRangeField/tests/describes.SingleInputTimeRangeField.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { SingleInputTimeRangeField } from '@mui/x-date-pickers-pro/SingleInputTimeRangeField'; -import { createPickerRenderer, wrapPickerMount, describeRangeValidation } from 'test/utils/pickers'; +import { createPickerRenderer, describeRangeValidation } from 'test/utils/pickers'; import { describeConformance } from 'test/utils/describeConformance'; describe(' - Describes', () => { @@ -11,11 +11,8 @@ describe(' - Describes', () => { inheritComponent: 'div', render, muiName: 'MuiSingleInputTimeRangeField', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, - // cannot test reactTestRenderer because of required context skip: [ - 'reactTestRenderer', 'componentProp', 'componentsProp', 'themeDefaultProps', diff --git a/packages/x-date-pickers-pro/src/StaticDateRangePicker/StaticDateRangePicker.test.tsx b/packages/x-date-pickers-pro/src/StaticDateRangePicker/StaticDateRangePicker.test.tsx index b47653c3e28d..2804871d2440 100644 --- a/packages/x-date-pickers-pro/src/StaticDateRangePicker/StaticDateRangePicker.test.tsx +++ b/packages/x-date-pickers-pro/src/StaticDateRangePicker/StaticDateRangePicker.test.tsx @@ -3,12 +3,7 @@ import { expect } from 'chai'; import { isWeekend } from 'date-fns'; import { StaticDateRangePicker } from '@mui/x-date-pickers-pro/StaticDateRangePicker'; import { screen } from '@mui/internal-test-utils'; -import { - wrapPickerMount, - createPickerRenderer, - adapterToUse, - describeRangeValidation, -} from 'test/utils/pickers'; +import { createPickerRenderer, adapterToUse, describeRangeValidation } from 'test/utils/pickers'; import { describeConformance } from 'test/utils/describeConformance'; describe('', () => { @@ -21,7 +16,6 @@ describe('', () => { classes: {} as any, render, muiName: 'MuiStaticDateRangePicker', - wrapMount: wrapPickerMount, refInstanceof: undefined, skip: [ 'componentProp', @@ -33,7 +27,6 @@ describe('', () => { 'propsSpread', 'refForwarding', 'rootClass', - 'reactTestRenderer', ], })); diff --git a/packages/x-date-pickers-pro/src/internals/hooks/useEnrichedRangePickerFieldProps.ts b/packages/x-date-pickers-pro/src/internals/hooks/useEnrichedRangePickerFieldProps.ts index a0b3a6b24f39..dab1f11a3451 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useEnrichedRangePickerFieldProps.ts +++ b/packages/x-date-pickers-pro/src/internals/hooks/useEnrichedRangePickerFieldProps.ts @@ -11,12 +11,15 @@ import { FieldRef, PickerValidDate, } from '@mui/x-date-pickers/models'; -import { UseClearableFieldSlots, UseClearableFieldSlotProps } from '@mui/x-date-pickers/hooks'; +import { + UseClearableFieldSlots, + UseClearableFieldSlotProps, + usePickersTranslations, +} from '@mui/x-date-pickers/hooks'; import { PickersInputLocaleText } from '@mui/x-date-pickers/locales'; import { BaseFieldProps, onSpaceOrEnter, - useLocaleText, UsePickerResponse, WrapperVariant, UsePickerProps, @@ -167,7 +170,7 @@ const useMultiInputFieldSlotProps = < TError >; - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const handleStartFieldRef = useForkRef(fieldProps.unstableStartFieldRef, startFieldRef); const handleEndFieldRef = useForkRef(fieldProps.unstableEndFieldRef, endFieldRef); @@ -245,7 +248,7 @@ const useMultiInputFieldSlotProps = < let InputProps: MultiInputFieldSlotTextFieldProps['InputProps']; if (ownerState.position === 'start') { textFieldProps = { - label: inLocaleText?.start ?? localeText.start, + label: inLocaleText?.start ?? translations.start, onKeyDown: onSpaceOrEnter(openRangeStartSelection), onFocus: handleFocusStart, focused: open ? rangePosition === 'start' : undefined, @@ -262,7 +265,7 @@ const useMultiInputFieldSlotProps = < } } else { textFieldProps = { - label: inLocaleText?.end ?? localeText.end, + label: inLocaleText?.end ?? translations.end, onKeyDown: onSpaceOrEnter(openRangeEndSelection), onFocus: handleFocusEnd, focused: open ? rangePosition === 'end' : undefined, diff --git a/packages/x-date-pickers-pro/src/internals/hooks/useMobileRangePicker/useMobileRangePicker.tsx b/packages/x-date-pickers-pro/src/internals/hooks/useMobileRangePicker/useMobileRangePicker.tsx index e0016ea48423..ecb9797f7500 100644 --- a/packages/x-date-pickers-pro/src/internals/hooks/useMobileRangePicker/useMobileRangePicker.tsx +++ b/packages/x-date-pickers-pro/src/internals/hooks/useMobileRangePicker/useMobileRangePicker.tsx @@ -8,10 +8,10 @@ import { PickersModalDialog, InferError, ExportedBaseToolbarProps, - useLocaleText, DateOrTimeViewWithMeridiem, ExportedBaseTabsProps, } from '@mui/x-date-pickers/internals'; +import { usePickersTranslations } from '@mui/x-date-pickers/hooks'; import { PickerValidDate, FieldRef, BaseSingleInputFieldProps } from '@mui/x-date-pickers/models'; import useId from '@mui/utils/useId'; import { @@ -78,7 +78,7 @@ export const useMobileRangePicker = < fieldType === 'single-input' ? startFieldRef : undefined, ); const labelId = useId(); - const contextLocaleText = useLocaleText(); + const contextTranslations = usePickersTranslations(); const { open, @@ -193,7 +193,7 @@ export const useMobileRangePicker = < const Layout = slots?.layout ?? PickersLayout; const finalLocaleText = { - ...contextLocaleText, + ...contextTranslations, ...localeText, }; let labelledById = diff --git a/packages/x-date-pickers-pro/tsconfig.json b/packages/x-date-pickers-pro/tsconfig.json index b6443628f807..82f2e7898632 100644 --- a/packages/x-date-pickers-pro/tsconfig.json +++ b/packages/x-date-pickers-pro/tsconfig.json @@ -7,7 +7,8 @@ "chai-dom", "dayjs/plugin/timezone.d.ts", "dayjs/plugin/utc.d.ts", - "mocha" + "mocha", + "node" ], "noImplicitAny": false }, diff --git a/packages/x-date-pickers/package.json b/packages/x-date-pickers/package.json index 72705696804c..c1992bda0d5f 100644 --- a/packages/x-date-pickers/package.json +++ b/packages/x-date-pickers/package.json @@ -1,6 +1,6 @@ { "name": "@mui/x-date-pickers", - "version": "7.7.1", + "version": "7.9.0", "description": "The community edition of the Date and Time Picker components (MUI X).", "author": "MUI Team", "main": "src/index.ts", @@ -47,8 +47,8 @@ "dependencies": { "@babel/runtime": "^7.24.7", "@mui/base": "^5.0.0-beta.40", - "@mui/system": "^5.15.20", - "@mui/utils": "^5.15.20", + "@mui/system": "^5.16.0", + "@mui/utils": "^5.16.0", "@types/react-transition-group": "^4.4.10", "clsx": "^2.1.1", "prop-types": "^15.8.1", @@ -98,7 +98,7 @@ } }, "devDependencies": { - "@mui/internal-test-utils": "^1.0.1", + "@mui/internal-test-utils": "^1.0.4", "@types/luxon": "^3.4.2", "@types/moment-hijri": "^2.1.4", "@types/moment-jalaali": "^0.7.9", @@ -109,9 +109,9 @@ "luxon": "^3.4.4", "moment": "^2.30.1", "moment-hijri": "^2.1.2", - "moment-jalaali": "^0.10.0", + "moment-jalaali": "^0.10.1", "moment-timezone": "^0.5.45", - "rimraf": "^5.0.7" + "rimraf": "^5.0.8" }, "engines": { "node": ">=14.0.0" diff --git a/packages/x-date-pickers/src/DateCalendar/DayCalendar.tsx b/packages/x-date-pickers/src/DateCalendar/DayCalendar.tsx index 00382e513bbd..5c06161d17c1 100644 --- a/packages/x-date-pickers/src/DateCalendar/DayCalendar.tsx +++ b/packages/x-date-pickers/src/DateCalendar/DayCalendar.tsx @@ -10,7 +10,8 @@ import { } from '@mui/utils'; import clsx from 'clsx'; import { PickersDay, PickersDayProps, ExportedPickersDayProps } from '../PickersDay/PickersDay'; -import { useUtils, useNow, useLocaleText } from '../internals/hooks/useUtils'; +import { usePickersTranslations } from '../hooks/usePickersTranslations'; +import { useUtils, useNow } from '../internals/hooks/useUtils'; import { PickerOnChangeFn } from '../internals/hooks/useViews'; import { DAY_SIZE, DAY_MARGIN } from '../internals/constants/dimensions'; import { @@ -385,7 +386,7 @@ export function DayCalendar(inProps: DayCalendarP timezone, }); - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const [internalHasFocus, setInternalHasFocus] = useControlled({ name: 'DayCalendar', @@ -562,10 +563,10 @@ export function DayCalendar(inProps: DayCalendarP - {localeText.calendarWeekNumberHeaderText} + {translations.calendarWeekNumberHeaderText} )} {getWeekdays(utils, now).map((weekday, i) => ( @@ -614,11 +615,11 @@ export function DayCalendar(inProps: DayCalendarP - {localeText.calendarWeekNumberText(utils.getWeekNumber(week[0]))} + {translations.calendarWeekNumberText(utils.getWeekNumber(week[0]))} )} {week.map((day, dayIndex) => ( diff --git a/packages/x-date-pickers/src/DateCalendar/tests/describes.DateCalendar.test.tsx b/packages/x-date-pickers/src/DateCalendar/tests/describes.DateCalendar.test.tsx index 4d03f1df80d0..7a807f651b17 100644 --- a/packages/x-date-pickers/src/DateCalendar/tests/describes.DateCalendar.test.tsx +++ b/packages/x-date-pickers/src/DateCalendar/tests/describes.DateCalendar.test.tsx @@ -5,7 +5,6 @@ import { DateCalendar, dateCalendarClasses as classes } from '@mui/x-date-picker import { pickersDayClasses } from '@mui/x-date-pickers/PickersDay'; import { adapterToUse, - wrapPickerMount, createPickerRenderer, describeValidation, describeValue, @@ -27,10 +26,8 @@ describe(' - Describes', () => { inheritComponent: 'div', render, muiName: 'MuiDateCalendar', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, - // cannot test reactTestRenderer because of required context - skip: ['componentProp', 'componentsProp', 'reactTestRenderer', 'themeVariants'], + skip: ['componentProp', 'componentsProp', 'themeVariants'], })); describeValue(DateCalendar, () => ({ diff --git a/packages/x-date-pickers/src/DateField/tests/describes.DateField.test.tsx b/packages/x-date-pickers/src/DateField/tests/describes.DateField.test.tsx index 1c26eeda56fb..a88c0d4e46c1 100644 --- a/packages/x-date-pickers/src/DateField/tests/describes.DateField.test.tsx +++ b/packages/x-date-pickers/src/DateField/tests/describes.DateField.test.tsx @@ -3,7 +3,6 @@ import { PickersTextField } from '@mui/x-date-pickers/PickersTextField'; import { DateField } from '@mui/x-date-pickers/DateField'; import { createPickerRenderer, - wrapPickerMount, expectFieldValueV7, adapterToUse, describeValidation, @@ -27,11 +26,8 @@ describe(' - Describes', () => { inheritComponent: PickersTextField, render, muiName: 'MuiDateField', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, - // cannot test reactTestRenderer because of required context skip: [ - 'reactTestRenderer', 'componentProp', 'componentsProp', 'themeDefaultProps', diff --git a/packages/x-date-pickers/src/DateField/tests/editing.DateField.test.tsx b/packages/x-date-pickers/src/DateField/tests/editing.DateField.test.tsx index 3d419cdc9240..d68fab6c666c 100644 --- a/packages/x-date-pickers/src/DateField/tests/editing.DateField.test.tsx +++ b/packages/x-date-pickers/src/DateField/tests/editing.DateField.test.tsx @@ -2030,13 +2030,13 @@ describe(' - Editing', () => { fireEvent.change(input, { target: { value: initialValueStr.replace('23', '1') } }); }); - expectFieldValueV6(input, '11/21/2022'); + expectFieldValueV6(input, '11/01/2022'); }); it('should support letter editing', () => { // Test with v6 input const v6Response = renderWithProps({ - defaultValue: adapter.date('2022-05-16'), + defaultValue: adapter.date('2022-01-16'), format: `${adapter.formats.month} ${adapter.formats.year}`, enableAccessibleFieldDOMStructure: false, }); @@ -2057,10 +2057,10 @@ describe(' - Editing', () => { fireEvent.change(input, { target: { value: ' 2022' } }); // Set the key pressed in the selected section - fireEvent.change(input, { target: { value: 'u 2022' } }); + fireEvent.change(input, { target: { value: 'a 2022' } }); }); - expectFieldValueV6(input, 'June 2022'); + expectFieldValueV6(input, 'April 2022'); }); }, ); diff --git a/packages/x-date-pickers/src/DatePicker/DatePickerToolbar.tsx b/packages/x-date-pickers/src/DatePicker/DatePickerToolbar.tsx index 366996ed1a65..46c31a964c5d 100644 --- a/packages/x-date-pickers/src/DatePicker/DatePickerToolbar.tsx +++ b/packages/x-date-pickers/src/DatePicker/DatePickerToolbar.tsx @@ -5,7 +5,8 @@ import Typography from '@mui/material/Typography'; import { styled, useThemeProps } from '@mui/material/styles'; import { unstable_composeClasses as composeClasses } from '@mui/utils'; import { PickersToolbar } from '../internals/components/PickersToolbar'; -import { useLocaleText, useUtils } from '../internals/hooks/useUtils'; +import { usePickersTranslations } from '../hooks/usePickersTranslations'; +import { useUtils } from '../internals/hooks/useUtils'; import { BaseToolbarProps, ExportedBaseToolbarProps } from '../internals/models/props/toolbar'; import { DateView, PickerValidDate } from '../models'; import { @@ -87,7 +88,7 @@ export const DatePickerToolbar = React.forwardRef(function DatePickerToolbar< ...other } = props; const utils = useUtils(); - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const classes = useUtilityClasses(props); const dateText = React.useMemo(() => { @@ -105,7 +106,7 @@ export const DatePickerToolbar = React.forwardRef(function DatePickerToolbar< return ( - Describes', () => { inheritComponent: PickersTextField, render, muiName: 'MuiDateTimeField', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, - // cannot test reactTestRenderer because of required context skip: [ - 'reactTestRenderer', 'componentProp', 'componentsProp', 'themeDefaultProps', diff --git a/packages/x-date-pickers/src/DateTimePicker/DateTimePickerTabs.tsx b/packages/x-date-pickers/src/DateTimePicker/DateTimePickerTabs.tsx index 72b58d1c4f94..4e04145fcf47 100644 --- a/packages/x-date-pickers/src/DateTimePicker/DateTimePickerTabs.tsx +++ b/packages/x-date-pickers/src/DateTimePicker/DateTimePickerTabs.tsx @@ -7,13 +7,14 @@ import { styled, useThemeProps } from '@mui/material/styles'; import composeClasses from '@mui/utils/composeClasses'; import { TimeIcon, DateRangeIcon } from '../icons'; import { DateOrTimeViewWithMeridiem } from '../internals/models'; -import { useLocaleText } from '../internals/hooks/useUtils'; +import { usePickersTranslations } from '../hooks/usePickersTranslations'; import { DateTimePickerTabsClasses, getDateTimePickerTabsUtilityClass, } from './dateTimePickerTabsClasses'; import { BaseTabsProps, ExportedBaseTabsProps } from '../internals/models/props/tabs'; import { isDatePickerView } from '../internals/utils/date-utils'; +import { PickerValidDate } from '../models'; type TabValue = 'date' | 'time'; @@ -93,7 +94,9 @@ const DateTimePickerTabsRoot = styled(Tabs, { * * - [DateTimePickerTabs API](https://mui.com/x/api/date-pickers/date-time-picker-tabs/) */ -const DateTimePickerTabs = function DateTimePickerTabs(inProps: DateTimePickerTabsProps) { +const DateTimePickerTabs = function DateTimePickerTabs( + inProps: DateTimePickerTabsProps, +) { const props = useThemeProps({ props: inProps, name: 'MuiDateTimePickerTabs' }); const { dateIcon = , @@ -105,7 +108,7 @@ const DateTimePickerTabs = function DateTimePickerTabs(inProps: DateTimePickerTa sx, } = props; - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const classes = useUtilityClasses(props); const handleChange = (event: React.SyntheticEvent, value: TabValue) => { @@ -127,12 +130,12 @@ const DateTimePickerTabs = function DateTimePickerTabs(inProps: DateTimePickerTa > {dateIcon}} /> {timeIcon}} /> diff --git a/packages/x-date-pickers/src/DateTimePicker/DateTimePickerToolbar.tsx b/packages/x-date-pickers/src/DateTimePicker/DateTimePickerToolbar.tsx index c8df143a0131..fc46e8bf0083 100644 --- a/packages/x-date-pickers/src/DateTimePicker/DateTimePickerToolbar.tsx +++ b/packages/x-date-pickers/src/DateTimePicker/DateTimePickerToolbar.tsx @@ -7,7 +7,8 @@ import clsx from 'clsx'; import { PickersToolbarText } from '../internals/components/PickersToolbarText'; import { PickersToolbar } from '../internals/components/PickersToolbar'; import { PickersToolbarButton } from '../internals/components/PickersToolbarButton'; -import { useLocaleText, useUtils } from '../internals/hooks/useUtils'; +import { usePickersTranslations } from '../hooks/usePickersTranslations'; +import { useUtils } from '../internals/hooks/useUtils'; import { BaseToolbarProps, ExportedBaseToolbarProps } from '../internals/models/props/toolbar'; import { dateTimePickerToolbarClasses, @@ -20,7 +21,7 @@ import { MULTI_SECTION_CLOCK_SECTION_WIDTH } from '../internals/constants/dimens import { formatMeridiem } from '../internals/utils/date-utils'; import { MakeOptional } from '../internals/models/helpers'; import { pickersToolbarTextClasses } from '../internals/components/pickersToolbarTextClasses'; -import { pickersToolbarClasses } from '../internals'; +import { pickersToolbarClasses } from '../internals/components/pickersToolbarClasses'; import { PickerValidDate } from '../models'; export interface ExportedDateTimePickerToolbarProps extends ExportedBaseToolbarProps { @@ -260,9 +261,9 @@ function DateTimePickerToolbar( const showAmPmControl = Boolean(ampm && !ampmInClock); const isDesktop = toolbarVariant === 'desktop'; - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const classes = useUtilityClasses(ownerState); - const toolbarTitle = inToolbarTitle ?? localeText.dateTimePickerToolbarTitle; + const toolbarTitle = inToolbarTitle ?? translations.dateTimePickerToolbarTitle; const formatHours = (time: TDate) => ampm ? utils.format(time, 'hours12h') : utils.format(time, 'hours24h'); diff --git a/packages/x-date-pickers/src/DesktopDatePicker/DesktopDatePicker.tsx b/packages/x-date-pickers/src/DesktopDatePicker/DesktopDatePicker.tsx index 5a1043e6d2d6..ef7bc618e178 100644 --- a/packages/x-date-pickers/src/DesktopDatePicker/DesktopDatePicker.tsx +++ b/packages/x-date-pickers/src/DesktopDatePicker/DesktopDatePicker.tsx @@ -5,7 +5,8 @@ import { refType } from '@mui/utils'; import { singleItemValueManager } from '../internals/utils/valueManagers'; import { DesktopDatePickerProps } from './DesktopDatePicker.types'; import { DatePickerViewRenderers, useDatePickerDefaultizedProps } from '../DatePicker/shared'; -import { useLocaleText, useUtils } from '../internals/hooks/useUtils'; +import { usePickersTranslations } from '../hooks/usePickersTranslations'; +import { useUtils } from '../internals/hooks/useUtils'; import { validateDate } from '../internals/utils/validation/validateDate'; import { DateView, PickerValidDate } from '../models'; import { useDesktopPicker } from '../internals/hooks/useDesktopPicker'; @@ -40,7 +41,7 @@ const DesktopDatePicker = React.forwardRef(function DesktopDatePicker< inProps: DesktopDatePickerProps, ref: React.Ref, ) { - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const utils = useUtils(); // Props with the default values common to all date pickers @@ -91,7 +92,7 @@ const DesktopDatePicker = React.forwardRef(function DesktopDatePicker< valueManager: singleItemValueManager, valueType: 'date', getOpenDialogAriaText: - props.localeText?.openDatePickerDialogue ?? localeText.openDatePickerDialogue, + props.localeText?.openDatePickerDialogue ?? translations.openDatePickerDialogue, validator: validateDate, }); diff --git a/packages/x-date-pickers/src/DesktopDatePicker/tests/DesktopDatePicker.test.tsx b/packages/x-date-pickers/src/DesktopDatePicker/tests/DesktopDatePicker.test.tsx index 3d615adc120f..b3ed68ab6851 100644 --- a/packages/x-date-pickers/src/DesktopDatePicker/tests/DesktopDatePicker.test.tsx +++ b/packages/x-date-pickers/src/DesktopDatePicker/tests/DesktopDatePicker.test.tsx @@ -85,7 +85,7 @@ describe('', () => { openPicker({ type: 'date', variant: 'desktop' }); - expect(screen.getByRole('radio', { checked: true, name: '2018' })).to.not.equal(null); + expect(screen.getByRole('radio', { checked: true, name: '2018' })).not.to.equal(null); // Dismiss the picker userEvent.keyPress(document.activeElement!, { key: 'Escape' }); @@ -95,7 +95,7 @@ describe('', () => { clock.runToLast(); // should have changed the open view - expect(screen.getByRole('radio', { checked: true, name: 'January' })).to.not.equal(null); + expect(screen.getByRole('radio', { checked: true, name: 'January' })).not.to.equal(null); }); it('should move the focus to the newly opened views', function test() { @@ -122,7 +122,7 @@ describe('', () => { openPicker({ type: 'date', variant: 'desktop' }); - expect(screen.getByRole('radio', { checked: true, name: 'January' })).to.not.equal(null); + expect(screen.getByRole('radio', { checked: true, name: 'January' })).not.to.equal(null); // Dismiss the picker userEvent.keyPress(document.activeElement!, { key: 'Escape' }); @@ -132,7 +132,7 @@ describe('', () => { clock.runToLast(); // should have changed the open view - expect(screen.getByRole('radio', { checked: true, name: '2018' })).to.not.equal(null); + expect(screen.getByRole('radio', { checked: true, name: '2018' })).not.to.equal(null); }); }); @@ -322,7 +322,7 @@ describe('', () => { />, ); - expect(document.querySelector(`.${inputBaseClasses.error}`)).to.not.equal(null); + expect(document.querySelector(`.${inputBaseClasses.error}`)).not.to.equal(null); }); it('should enable the input error state when the current date has an invalid month', () => { @@ -333,7 +333,7 @@ describe('', () => { />, ); - expect(document.querySelector(`.${inputBaseClasses.error}`)).to.not.equal(null); + expect(document.querySelector(`.${inputBaseClasses.error}`)).not.to.equal(null); }); it('should enable the input error state when the current date has an invalid year', () => { @@ -344,7 +344,7 @@ describe('', () => { />, ); - expect(document.querySelector(`.${inputBaseClasses.error}`)).to.not.equal(null); + expect(document.querySelector(`.${inputBaseClasses.error}`)).not.to.equal(null); }); }); diff --git a/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePicker.tsx b/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePicker.tsx index be5eb451549d..42695c7bb8e0 100644 --- a/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePicker.tsx +++ b/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePicker.tsx @@ -11,7 +11,8 @@ import { DateTimePickerViewRenderers, } from '../DateTimePicker/shared'; import { renderDateViewCalendar } from '../dateViewRenderers/dateViewRenderers'; -import { useLocaleText, useUtils } from '../internals/hooks/useUtils'; +import { usePickersTranslations } from '../hooks/usePickersTranslations'; +import { useUtils } from '../internals/hooks/useUtils'; import { validateDateTime } from '../internals/utils/validation/validateDateTime'; import { DateOrTimeViewWithMeridiem } from '../internals/models'; import { CalendarIcon } from '../icons'; @@ -28,19 +29,18 @@ import { renderDigitalClockTimeView, renderMultiSectionDigitalClockTimeView, } from '../timeViewRenderers'; -import { - DefaultizedProps, - UsePickerViewsProps, - VIEW_HEIGHT, - isDatePickerView, - isInternalTimeView, -} from '../internals'; + import { multiSectionDigitalClockClasses, multiSectionDigitalClockSectionClasses, } from '../MultiSectionDigitalClock'; import { digitalClockClasses } from '../DigitalClock'; import { DesktopDateTimePickerLayout } from './DesktopDateTimePickerLayout'; +import { VIEW_HEIGHT } from '../internals/constants/dimensions'; +import { DefaultizedProps } from '../internals/models/helpers'; +import { UsePickerViewsProps } from '../internals/hooks/usePicker/usePickerViews'; +import { isInternalTimeView } from '../internals/utils/time-utils'; +import { isDatePickerView } from '../internals/utils/date-utils'; const rendererInterceptor = function rendererInterceptor< TDate extends PickerValidDate, @@ -134,7 +134,7 @@ const DesktopDateTimePicker = React.forwardRef(function DesktopDateTimePicker< inProps: DesktopDateTimePickerProps, ref: React.Ref, ) { - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const utils = useUtils(); // Props with the default values common to all date time pickers @@ -227,7 +227,7 @@ const DesktopDateTimePicker = React.forwardRef(function DesktopDateTimePicker< valueManager: singleItemValueManager, valueType: 'date-time', getOpenDialogAriaText: - props.localeText?.openDatePickerDialogue ?? localeText.openDatePickerDialogue, + props.localeText?.openDatePickerDialogue ?? translations.openDatePickerDialogue, validator: validateDateTime, rendererInterceptor, }); diff --git a/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePickerLayout.tsx b/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePickerLayout.tsx index fca2a0f44898..85b531fef636 100644 --- a/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePickerLayout.tsx +++ b/packages/x-date-pickers/src/DesktopDateTimePicker/DesktopDateTimePickerLayout.tsx @@ -11,7 +11,7 @@ import { usePickerLayout, } from '../PickersLayout'; import { PickerValidDate } from '../models'; -import { DateOrTimeViewWithMeridiem } from '../internals'; +import { DateOrTimeViewWithMeridiem } from '../internals/models/common'; /** * @ignore - internal component. diff --git a/packages/x-date-pickers/src/DesktopTimePicker/DesktopTimePicker.tsx b/packages/x-date-pickers/src/DesktopTimePicker/DesktopTimePicker.tsx index d0a2d8b38c20..63a21269ac3b 100644 --- a/packages/x-date-pickers/src/DesktopTimePicker/DesktopTimePicker.tsx +++ b/packages/x-date-pickers/src/DesktopTimePicker/DesktopTimePicker.tsx @@ -6,7 +6,8 @@ import { singleItemValueManager } from '../internals/utils/valueManagers'; import { TimeField } from '../TimeField'; import { DesktopTimePickerProps } from './DesktopTimePicker.types'; import { TimePickerViewRenderers, useTimePickerDefaultizedProps } from '../TimePicker/shared'; -import { useLocaleText, useUtils } from '../internals/hooks/useUtils'; +import { usePickersTranslations } from '../hooks/usePickersTranslations'; +import { useUtils } from '../internals/hooks/useUtils'; import { validateTime } from '../internals/utils/validation/validateTime'; import { ClockIcon } from '../icons'; import { useDesktopPicker } from '../internals/hooks/useDesktopPicker'; @@ -46,7 +47,7 @@ const DesktopTimePicker = React.forwardRef(function DesktopTimePicker< inProps: DesktopTimePickerProps, ref: React.Ref, ) { - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const utils = useUtils(); // Props with the default values common to all time pickers @@ -129,7 +130,7 @@ const DesktopTimePicker = React.forwardRef(function DesktopTimePicker< valueManager: singleItemValueManager, valueType: 'time', getOpenDialogAriaText: - props.localeText?.openTimePickerDialogue ?? localeText.openTimePickerDialogue, + props.localeText?.openTimePickerDialogue ?? translations.openTimePickerDialogue, validator: validateTime, }); diff --git a/packages/x-date-pickers/src/DesktopTimePicker/tests/describes.DesktopTimePicker.test.tsx b/packages/x-date-pickers/src/DesktopTimePicker/tests/describes.DesktopTimePicker.test.tsx index 38219d321165..36a9cc7288aa 100644 --- a/packages/x-date-pickers/src/DesktopTimePicker/tests/describes.DesktopTimePicker.test.tsx +++ b/packages/x-date-pickers/src/DesktopTimePicker/tests/describes.DesktopTimePicker.test.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { screen, userEvent } from '@mui/internal-test-utils'; import { createPickerRenderer, - wrapPickerMount, adapterToUse, expectFieldValueV7, describeValidation, @@ -35,7 +34,6 @@ describe(' - Describes', () => { classes: {} as any, render, muiName: 'MuiDesktopTimePicker', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, skip: [ 'componentProp', @@ -46,7 +44,6 @@ describe(' - Describes', () => { 'mergeClassName', 'propsSpread', 'rootClass', - 'reactTestRenderer', ], })); diff --git a/packages/x-date-pickers/src/DigitalClock/DigitalClock.tsx b/packages/x-date-pickers/src/DigitalClock/DigitalClock.tsx index bfd5ae2efc29..81d214a13049 100644 --- a/packages/x-date-pickers/src/DigitalClock/DigitalClock.tsx +++ b/packages/x-date-pickers/src/DigitalClock/DigitalClock.tsx @@ -8,7 +8,8 @@ import composeClasses from '@mui/utils/composeClasses'; import MenuItem from '@mui/material/MenuItem'; import MenuList from '@mui/material/MenuList'; import useForkRef from '@mui/utils/useForkRef'; -import { useUtils, useNow, useLocaleText } from '../internals/hooks/useUtils'; +import { usePickersTranslations } from '../hooks/usePickersTranslations'; +import { useUtils, useNow } from '../internals/hooks/useUtils'; import { createIsAfterIgnoreDatePart } from '../internals/utils/time-utils'; import { PickerViewRoot } from '../internals/components/PickerViewRoot'; import { getDigitalClockUtilityClass } from './digitalClockClasses'; @@ -163,7 +164,7 @@ export const DigitalClock = React.forwardRef(function DigitalClock(); + const translations = usePickersTranslations(); const now = useNow(timezone); const ownerState = React.useMemo( @@ -301,7 +302,7 @@ export const DigitalClock = React.forwardRef(function DigitalClock {timeOptions.map((option, index) => { diff --git a/packages/x-date-pickers/src/DigitalClock/tests/describes.DigitalClock.test.tsx b/packages/x-date-pickers/src/DigitalClock/tests/describes.DigitalClock.test.tsx index c4eb1f60a69c..380c056fa557 100644 --- a/packages/x-date-pickers/src/DigitalClock/tests/describes.DigitalClock.test.tsx +++ b/packages/x-date-pickers/src/DigitalClock/tests/describes.DigitalClock.test.tsx @@ -3,7 +3,6 @@ import { expect } from 'chai'; import { screen } from '@mui/internal-test-utils'; import { createPickerRenderer, - wrapPickerMount, adapterToUse, digitalClockHandler, describeValidation, @@ -28,7 +27,6 @@ describe(' - Describes', () => { classes: {} as any, render, muiName: 'MuiDigitalClock', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, skip: [ 'componentProp', @@ -39,7 +37,6 @@ describe(' - Describes', () => { 'mergeClassName', 'propsSpread', 'rootClass', - 'reactTestRenderer', ], })); diff --git a/packages/x-date-pickers/src/MobileDatePicker/MobileDatePicker.tsx b/packages/x-date-pickers/src/MobileDatePicker/MobileDatePicker.tsx index 23fe6ab1943e..870bee0911cf 100644 --- a/packages/x-date-pickers/src/MobileDatePicker/MobileDatePicker.tsx +++ b/packages/x-date-pickers/src/MobileDatePicker/MobileDatePicker.tsx @@ -5,7 +5,8 @@ import { refType } from '@mui/utils'; import { useMobilePicker } from '../internals/hooks/useMobilePicker'; import { MobileDatePickerProps } from './MobileDatePicker.types'; import { DatePickerViewRenderers, useDatePickerDefaultizedProps } from '../DatePicker/shared'; -import { useUtils, useLocaleText } from '../internals/hooks/useUtils'; +import { usePickersTranslations } from '../hooks/usePickersTranslations'; +import { useUtils } from '../internals/hooks/useUtils'; import { validateDate } from '../internals/utils/validation/validateDate'; import { DateView, PickerValidDate } from '../models'; import { DateField } from '../DateField'; @@ -39,7 +40,7 @@ const MobileDatePicker = React.forwardRef(function MobileDatePicker< inProps: MobileDatePickerProps, ref: React.Ref, ) { - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const utils = useUtils(); // Props with the default values common to all date pickers @@ -88,7 +89,7 @@ const MobileDatePicker = React.forwardRef(function MobileDatePicker< valueManager: singleItemValueManager, valueType: 'date', getOpenDialogAriaText: - props.localeText?.openDatePickerDialogue ?? localeText.openDatePickerDialogue, + props.localeText?.openDatePickerDialogue ?? translations.openDatePickerDialogue, validator: validateDate, }); diff --git a/packages/x-date-pickers/src/MobileDateTimePicker/MobileDateTimePicker.tsx b/packages/x-date-pickers/src/MobileDateTimePicker/MobileDateTimePicker.tsx index 9964c55a3948..8c4aa9ac36e2 100644 --- a/packages/x-date-pickers/src/MobileDateTimePicker/MobileDateTimePicker.tsx +++ b/packages/x-date-pickers/src/MobileDateTimePicker/MobileDateTimePicker.tsx @@ -9,7 +9,8 @@ import { DateTimePickerViewRenderers, useDateTimePickerDefaultizedProps, } from '../DateTimePicker/shared'; -import { useLocaleText, useUtils } from '../internals/hooks/useUtils'; +import { usePickersTranslations } from '../hooks/usePickersTranslations'; +import { useUtils } from '../internals/hooks/useUtils'; import { validateDateTime } from '../internals/utils/validation/validateDateTime'; import { DateOrTimeView, PickerValidDate } from '../models'; import { useMobilePicker } from '../internals/hooks/useMobilePicker'; @@ -43,7 +44,7 @@ const MobileDateTimePicker = React.forwardRef(function MobileDateTimePicker< inProps: MobileDateTimePickerProps, ref: React.Ref, ) { - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const utils = useUtils(); // Props with the default values common to all date time pickers @@ -103,7 +104,7 @@ const MobileDateTimePicker = React.forwardRef(function MobileDateTimePicker< valueManager: singleItemValueManager, valueType: 'date-time', getOpenDialogAriaText: - props.localeText?.openDatePickerDialogue ?? localeText.openDatePickerDialogue, + props.localeText?.openDatePickerDialogue ?? translations.openDatePickerDialogue, validator: validateDateTime, }); diff --git a/packages/x-date-pickers/src/MobileTimePicker/MobileTimePicker.tsx b/packages/x-date-pickers/src/MobileTimePicker/MobileTimePicker.tsx index 49e09712163b..159260767130 100644 --- a/packages/x-date-pickers/src/MobileTimePicker/MobileTimePicker.tsx +++ b/packages/x-date-pickers/src/MobileTimePicker/MobileTimePicker.tsx @@ -6,7 +6,8 @@ import { singleItemValueManager } from '../internals/utils/valueManagers'; import { TimeField } from '../TimeField'; import { MobileTimePickerProps } from './MobileTimePicker.types'; import { TimePickerViewRenderers, useTimePickerDefaultizedProps } from '../TimePicker/shared'; -import { useLocaleText, useUtils } from '../internals/hooks/useUtils'; +import { usePickersTranslations } from '../hooks/usePickersTranslations'; +import { useUtils } from '../internals/hooks/useUtils'; import { validateTime } from '../internals/utils/validation/validateTime'; import { PickerValidDate, TimeView } from '../models'; import { useMobilePicker } from '../internals/hooks/useMobilePicker'; @@ -39,7 +40,7 @@ const MobileTimePicker = React.forwardRef(function MobileTimePicker< inProps: MobileTimePickerProps, ref: React.Ref, ) { - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const utils = useUtils(); // Props with the default values common to all time pickers @@ -92,7 +93,7 @@ const MobileTimePicker = React.forwardRef(function MobileTimePicker< valueManager: singleItemValueManager, valueType: 'time', getOpenDialogAriaText: - props.localeText?.openTimePickerDialogue ?? localeText.openTimePickerDialogue, + props.localeText?.openTimePickerDialogue ?? translations.openTimePickerDialogue, validator: validateTime, }); diff --git a/packages/x-date-pickers/src/MobileTimePicker/tests/describes.MobileTimePicker.test.tsx b/packages/x-date-pickers/src/MobileTimePicker/tests/describes.MobileTimePicker.test.tsx index 39db06fea3e0..ec8a060c935f 100644 --- a/packages/x-date-pickers/src/MobileTimePicker/tests/describes.MobileTimePicker.test.tsx +++ b/packages/x-date-pickers/src/MobileTimePicker/tests/describes.MobileTimePicker.test.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { screen, fireEvent, userEvent, fireTouchChangedEvent } from '@mui/internal-test-utils'; import { createPickerRenderer, - wrapPickerMount, adapterToUse, expectFieldValueV7, openPicker, @@ -36,7 +35,6 @@ describe(' - Describes', () => { classes: {} as any, render, muiName: 'MuiMobileTimePicker', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, skip: [ 'componentProp', @@ -47,7 +45,6 @@ describe(' - Describes', () => { 'mergeClassName', 'propsSpread', 'rootClass', - 'reactTestRenderer', ], })); diff --git a/packages/x-date-pickers/src/MonthCalendar/tests/MonthCalendar.test.tsx b/packages/x-date-pickers/src/MonthCalendar/tests/MonthCalendar.test.tsx index 98cb6e98686e..72037d514c1c 100644 --- a/packages/x-date-pickers/src/MonthCalendar/tests/MonthCalendar.test.tsx +++ b/packages/x-date-pickers/src/MonthCalendar/tests/MonthCalendar.test.tsx @@ -165,7 +165,7 @@ describe('', () => { it('should not mark the `referenceDate` month as selected', () => { render(); - expect(screen.getByRole('radio', { name: 'February', checked: false })).to.not.equal(null); + expect(screen.getByRole('radio', { name: 'February', checked: false })).not.to.equal(null); }); }); }); diff --git a/packages/x-date-pickers/src/MonthCalendar/tests/describes.MonthCalendar.test.tsx b/packages/x-date-pickers/src/MonthCalendar/tests/describes.MonthCalendar.test.tsx index e34093f7fb33..f439b851f2c3 100644 --- a/packages/x-date-pickers/src/MonthCalendar/tests/describes.MonthCalendar.test.tsx +++ b/packages/x-date-pickers/src/MonthCalendar/tests/describes.MonthCalendar.test.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { expect } from 'chai'; import { userEvent, screen } from '@mui/internal-test-utils'; import { - wrapPickerMount, createPickerRenderer, adapterToUse, describeValidation, @@ -25,11 +24,9 @@ describe(' - Describes', () => { classes, inheritComponent: 'div', render, - wrapMount: wrapPickerMount, muiName: 'MuiMonthCalendar', refInstanceof: window.HTMLDivElement, - // cannot test reactTestRenderer because of required context - skip: ['componentProp', 'componentsProp', 'reactTestRenderer', 'themeVariants'], + skip: ['componentProp', 'componentsProp', 'themeVariants'], })); describeValue(MonthCalendar, () => ({ diff --git a/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClock.tsx b/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClock.tsx index c4fcc16f1a83..bf30b978c580 100644 --- a/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClock.tsx +++ b/packages/x-date-pickers/src/MultiSectionDigitalClock/MultiSectionDigitalClock.tsx @@ -5,7 +5,8 @@ import { useRtl } from '@mui/system/RtlProvider'; import { styled, useThemeProps } from '@mui/material/styles'; import useEventCallback from '@mui/utils/useEventCallback'; import composeClasses from '@mui/utils/composeClasses'; -import { useUtils, useNow, useLocaleText } from '../internals/hooks/useUtils'; +import { usePickersTranslations } from '../hooks/usePickersTranslations'; +import { useUtils, useNow } from '../internals/hooks/useUtils'; import { convertValueToMeridiem, createIsAfterIgnoreDatePart } from '../internals/utils/time-utils'; import { useViews } from '../internals/hooks/useViews'; import type { PickerSelectionState } from '../internals/hooks/usePicker'; @@ -114,7 +115,7 @@ export const MultiSectionDigitalClock = React.forwardRef(function MultiSectionDi valueManager: singleItemValueManager, }); - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const now = useNow(timezone); const timeSteps = React.useMemo>( @@ -296,7 +297,7 @@ export const MultiSectionDigitalClock = React.forwardRef(function MultiSectionDi utils, isDisabled: (hours) => isTimeDisabled(hours, 'hours'), timeStep: timeSteps.hours, - resolveAriaLabel: localeText.hoursClockNumberText, + resolveAriaLabel: translations.hoursClockNumberText, valueOrReferenceDate, }), }; @@ -318,7 +319,7 @@ export const MultiSectionDigitalClock = React.forwardRef(function MultiSectionDi resolveLabel: (minutes) => utils.format(utils.setMinutes(now, minutes), 'minutes'), timeStep: timeSteps.minutes, hasValue: !!value, - resolveAriaLabel: localeText.minutesClockNumberText, + resolveAriaLabel: translations.minutesClockNumberText, }), }; } @@ -339,7 +340,7 @@ export const MultiSectionDigitalClock = React.forwardRef(function MultiSectionDi resolveLabel: (seconds) => utils.format(utils.setSeconds(now, seconds), 'seconds'), timeStep: timeSteps.seconds, hasValue: !!value, - resolveAriaLabel: localeText.secondsClockNumberText, + resolveAriaLabel: translations.secondsClockNumberText, }), }; } @@ -380,9 +381,9 @@ export const MultiSectionDigitalClock = React.forwardRef(function MultiSectionDi timeSteps.hours, timeSteps.minutes, timeSteps.seconds, - localeText.hoursClockNumberText, - localeText.minutesClockNumberText, - localeText.secondsClockNumberText, + translations.hoursClockNumberText, + translations.minutesClockNumberText, + translations.secondsClockNumberText, meridiemMode, setValueAndGoToNextView, valueOrReferenceDate, @@ -396,7 +397,7 @@ export const MultiSectionDigitalClock = React.forwardRef(function MultiSectionDi return views; } const digitViews = views.filter((v) => v !== 'meridiem'); - const result = digitViews.toReversed(); + const result: TimeViewWithMeridiem[] = digitViews.toReversed(); if (views.includes('meridiem')) { result.push('meridiem'); } @@ -435,7 +436,7 @@ export const MultiSectionDigitalClock = React.forwardRef(function MultiSectionDi slots={slots} slotProps={slotProps} skipDisabled={skipDisabled} - aria-label={localeText.selectViewText(timeView)} + aria-label={translations.selectViewText(timeView)} /> ))} diff --git a/packages/x-date-pickers/src/MultiSectionDigitalClock/tests/describes.MultiSectionDigitalClock.test.tsx b/packages/x-date-pickers/src/MultiSectionDigitalClock/tests/describes.MultiSectionDigitalClock.test.tsx index ed61d90f3988..87b19d1f7fc5 100644 --- a/packages/x-date-pickers/src/MultiSectionDigitalClock/tests/describes.MultiSectionDigitalClock.test.tsx +++ b/packages/x-date-pickers/src/MultiSectionDigitalClock/tests/describes.MultiSectionDigitalClock.test.tsx @@ -3,7 +3,6 @@ import { expect } from 'chai'; import { screen } from '@mui/internal-test-utils'; import { createPickerRenderer, - wrapPickerMount, adapterToUse, multiSectionDigitalClockHandler, describeValidation, @@ -28,7 +27,6 @@ describe(' - Describes', () => { classes: {} as any, render, muiName: 'MuiMultiSectionDigitalClock', - wrapMount: wrapPickerMount, refInstanceof: window.HTMLDivElement, skip: [ 'componentProp', @@ -39,7 +37,6 @@ describe(' - Describes', () => { 'mergeClassName', 'propsSpread', 'rootClass', - 'reactTestRenderer', ], })); diff --git a/packages/x-date-pickers/src/PickersActionBar/PickersActionBar.tsx b/packages/x-date-pickers/src/PickersActionBar/PickersActionBar.tsx index f2f5f05ffe38..3b12b4353d02 100644 --- a/packages/x-date-pickers/src/PickersActionBar/PickersActionBar.tsx +++ b/packages/x-date-pickers/src/PickersActionBar/PickersActionBar.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import Button from '@mui/material/Button'; import DialogActions, { DialogActionsProps } from '@mui/material/DialogActions'; -import { useLocaleText } from '../internals/hooks/useUtils'; +import { usePickersTranslations } from '../hooks/usePickersTranslations'; export type PickersActionBarAction = 'clear' | 'cancel' | 'accept' | 'today'; @@ -32,7 +32,7 @@ export interface PickersActionBarProps extends DialogActionsProps { function PickersActionBar(props: PickersActionBarProps) { const { onAccept, onClear, onCancel, onSetToday, actions, ...other } = props; - const localeText = useLocaleText(); + const translations = usePickersTranslations(); if (actions == null || actions.length === 0) { return null; @@ -43,28 +43,28 @@ function PickersActionBar(props: PickersActionBarProps) { case 'clear': return ( ); case 'cancel': return ( ); case 'accept': return ( ); case 'today': return ( ); diff --git a/packages/x-date-pickers/src/PickersCalendarHeader/PickersCalendarHeader.tsx b/packages/x-date-pickers/src/PickersCalendarHeader/PickersCalendarHeader.tsx index d49252d9c441..8412b01d8848 100644 --- a/packages/x-date-pickers/src/PickersCalendarHeader/PickersCalendarHeader.tsx +++ b/packages/x-date-pickers/src/PickersCalendarHeader/PickersCalendarHeader.tsx @@ -6,7 +6,8 @@ import { styled, useThemeProps } from '@mui/material/styles'; import { useSlotProps } from '@mui/base/utils'; import { unstable_composeClasses as composeClasses } from '@mui/utils'; import IconButton from '@mui/material/IconButton'; -import { useLocaleText, useUtils } from '../internals/hooks/useUtils'; +import { usePickersTranslations } from '../hooks/usePickersTranslations'; +import { useUtils } from '../internals/hooks/useUtils'; import { PickersFadeTransitionGroup } from '../DateCalendar/PickersFadeTransitionGroup'; import { ArrowDropDownIcon } from '../icons'; import { PickersArrowSwitcher } from '../internals/components/PickersArrowSwitcher'; @@ -129,7 +130,7 @@ type PickersCalendarHeaderComponent = (( const PickersCalendarHeader = React.forwardRef(function PickersCalendarHeader< TDate extends PickerValidDate, >(inProps: PickersCalendarHeaderProps, ref: React.Ref) { - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const utils = useUtils(); const props = useThemeProps({ props: inProps, name: 'MuiPickersCalendarHeader' }); @@ -165,7 +166,7 @@ const PickersCalendarHeader = React.forwardRef(function PickersCalendarHeader< externalSlotProps: slotProps?.switchViewButton, additionalProps: { size: 'small', - 'aria-label': localeText.calendarViewSwitchingButtonAriaLabel(view), + 'aria-label': translations.calendarViewSwitchingButtonAriaLabel(view), }, ownerState, className: classes.switchViewButton, @@ -252,10 +253,10 @@ const PickersCalendarHeader = React.forwardRef(function PickersCalendarHeader< slotProps={slotProps} onGoToPrevious={selectPreviousMonth} isPreviousDisabled={isPreviousMonthDisabled} - previousLabel={localeText.previousMonth} + previousLabel={translations.previousMonth} onGoToNext={selectNextMonth} isNextDisabled={isNextMonthDisabled} - nextLabel={localeText.nextMonth} + nextLabel={translations.nextMonth} /> diff --git a/packages/x-date-pickers/src/PickersDay/PickersDay.test.tsx b/packages/x-date-pickers/src/PickersDay/PickersDay.test.tsx index 361f7d7ae798..5afe172c0b1f 100644 --- a/packages/x-date-pickers/src/PickersDay/PickersDay.test.tsx +++ b/packages/x-date-pickers/src/PickersDay/PickersDay.test.tsx @@ -4,7 +4,7 @@ import { spy } from 'sinon'; import { fireEvent, screen } from '@mui/internal-test-utils'; import ButtonBase from '@mui/material/ButtonBase'; import { PickersDay, pickersDayClasses as classes } from '@mui/x-date-pickers/PickersDay'; -import { adapterToUse, wrapPickerMount, createPickerRenderer } from 'test/utils/pickers'; +import { adapterToUse, createPickerRenderer } from 'test/utils/pickers'; import { describeConformance } from 'test/utils/describeConformance'; describe('', () => { @@ -23,12 +23,10 @@ describe('', () => { classes, inheritComponent: ButtonBase, render, - wrapMount: wrapPickerMount, muiName: 'MuiPickersDay', refInstanceof: window.HTMLButtonElement, testVariantProps: { variant: 'disableMargin' }, - // cannot test reactTestRenderer because of required context - skip: ['componentProp', 'componentsProp', 'reactTestRenderer'], + skip: ['componentProp', 'componentsProp'], }), ); diff --git a/packages/x-date-pickers/src/StaticTimePicker/StaticTimePicker.test.tsx b/packages/x-date-pickers/src/StaticTimePicker/StaticTimePicker.test.tsx index 7cb2ef91eaae..3eafe702915b 100644 --- a/packages/x-date-pickers/src/StaticTimePicker/StaticTimePicker.test.tsx +++ b/packages/x-date-pickers/src/StaticTimePicker/StaticTimePicker.test.tsx @@ -2,12 +2,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { spy } from 'sinon'; import { fireTouchChangedEvent, screen, getAllByRole, fireEvent } from '@mui/internal-test-utils'; -import { - adapterToUse, - wrapPickerMount, - createPickerRenderer, - describeValidation, -} from 'test/utils/pickers'; +import { adapterToUse, createPickerRenderer, describeValidation } from 'test/utils/pickers'; import { StaticTimePicker } from '@mui/x-date-pickers/StaticTimePicker'; import { describeConformance } from 'test/utils/describeConformance'; @@ -28,7 +23,6 @@ describe('', () => { classes: {} as any, render, muiName: 'MuiStaticTimePicker', - wrapMount: wrapPickerMount, refInstanceof: undefined, skip: [ 'componentProp', @@ -41,7 +35,6 @@ describe('', () => { // TODO: `ref` is typed but has no effect 'refForwarding', 'rootClass', - 'reactTestRenderer', ], })); diff --git a/packages/x-date-pickers/src/TimeClock/Clock.tsx b/packages/x-date-pickers/src/TimeClock/Clock.tsx index 23a583f9dd71..26d69784720d 100644 --- a/packages/x-date-pickers/src/TimeClock/Clock.tsx +++ b/packages/x-date-pickers/src/TimeClock/Clock.tsx @@ -8,7 +8,8 @@ import { unstable_composeClasses as composeClasses, } from '@mui/utils'; import { ClockPointer } from './ClockPointer'; -import { useLocaleText, useUtils } from '../internals/hooks/useUtils'; +import { usePickersTranslations } from '../hooks/usePickersTranslations'; +import { useUtils } from '../internals/hooks/useUtils'; import type { PickerSelectionState } from '../internals/hooks/usePicker'; import { useMeridiemMode } from '../internals/hooks/date-helpers-hooks'; import { CLOCK_HOUR_WIDTH, getHours, getMinutes } from './shared'; @@ -233,7 +234,7 @@ export function Clock(inProps: ClockProps) const ownerState = props; const utils = useUtils(); - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const isMoving = React.useRef(false); const classes = useUtilityClasses(ownerState); @@ -372,7 +373,7 @@ export function Clock(inProps: ClockProps) )} (); + const translations = usePickersTranslations(); const now = useNow(timezone); const { view, setView, previousView, nextView, setValueAndGoToNextView } = useViews({ @@ -269,7 +270,7 @@ export const TimeClock = React.forwardRef(function TimeClock disabled || isTimeDisabled(hourValue, 'hours'), selectedId, }), @@ -293,7 +294,7 @@ export const TimeClock = React.forwardRef(function TimeClock disabled || isTimeDisabled(minuteValue, 'minutes'), selectedId, }), @@ -317,7 +318,7 @@ export const TimeClock = React.forwardRef(function TimeClock disabled || isTimeDisabled(secondValue, 'seconds'), selectedId, }), @@ -332,9 +333,9 @@ export const TimeClock = React.forwardRef(function TimeClock setView(previousView!)} isPreviousDisabled={!previousView} - previousLabel={localeText.openPreviousView} + previousLabel={translations.openPreviousView} onGoToNext={() => setView(nextView!)} isNextDisabled={!nextView} - nextLabel={localeText.openNextView} + nextLabel={translations.openNextView} ownerState={ownerState} /> )} diff --git a/packages/x-date-pickers/src/TimeClock/tests/describes.TimeClock.test.tsx b/packages/x-date-pickers/src/TimeClock/tests/describes.TimeClock.test.tsx index f2b06f645f4c..dc295643b47c 100644 --- a/packages/x-date-pickers/src/TimeClock/tests/describes.TimeClock.test.tsx +++ b/packages/x-date-pickers/src/TimeClock/tests/describes.TimeClock.test.tsx @@ -7,7 +7,6 @@ import { timeClockClasses as classes, } from '@mui/x-date-pickers/TimeClock'; import { - wrapPickerMount, createPickerRenderer, adapterToUse, timeClockHandler, @@ -21,11 +20,10 @@ describe(' - Describes', () => { describeConformance(, () => ({ classes, inheritComponent: 'div', - wrapMount: wrapPickerMount, render, refInstanceof: window.HTMLDivElement, muiName: 'MuiTimeClock', - skip: ['componentProp', 'componentsProp', 'reactTestRenderer', 'themeVariants'], + skip: ['componentProp', 'componentsProp', 'themeVariants'], })); describeValue(TimeClock, () => ({ diff --git a/packages/x-date-pickers/src/TimePicker/TimePickerToolbar.tsx b/packages/x-date-pickers/src/TimePicker/TimePickerToolbar.tsx index a24f68cf5711..ef2d545cfad0 100644 --- a/packages/x-date-pickers/src/TimePicker/TimePickerToolbar.tsx +++ b/packages/x-date-pickers/src/TimePicker/TimePickerToolbar.tsx @@ -8,7 +8,8 @@ import { PickersToolbarText } from '../internals/components/PickersToolbarText'; import { PickersToolbarButton } from '../internals/components/PickersToolbarButton'; import { PickersToolbar } from '../internals/components/PickersToolbar'; import { arrayIncludes } from '../internals/utils/utils'; -import { useLocaleText, useUtils } from '../internals/hooks/useUtils'; +import { usePickersTranslations } from '../hooks/usePickersTranslations'; +import { useUtils } from '../internals/hooks/useUtils'; import { useMeridiemMode } from '../internals/hooks/date-helpers-hooks'; import { BaseToolbarProps, ExportedBaseToolbarProps } from '../internals/models/props/toolbar'; import { @@ -165,7 +166,7 @@ function TimePickerToolbar(inProps: TimePickerToo ...other } = props; const utils = useUtils(); - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const isRtl = useRtl(); const showAmPmControl = Boolean(ampm && !ampmInClock && views.includes('hours')); @@ -190,7 +191,7 @@ function TimePickerToolbar(inProps: TimePickerToo return ( ', () => { it('should not mark the `referenceDate` year as selected', () => { render(); - expect(screen.getByRole('radio', { name: '2018', checked: false })).to.not.equal(null); + expect(screen.getByRole('radio', { name: '2018', checked: false })).not.to.equal(null); }); }); diff --git a/packages/x-date-pickers/src/YearCalendar/tests/describes.YearCalendar.test.tsx b/packages/x-date-pickers/src/YearCalendar/tests/describes.YearCalendar.test.tsx index c93548b4ec59..e2b1c722d71a 100644 --- a/packages/x-date-pickers/src/YearCalendar/tests/describes.YearCalendar.test.tsx +++ b/packages/x-date-pickers/src/YearCalendar/tests/describes.YearCalendar.test.tsx @@ -3,7 +3,6 @@ import { expect } from 'chai'; import { userEvent, screen } from '@mui/internal-test-utils'; import { YearCalendar, yearCalendarClasses as classes } from '@mui/x-date-pickers/YearCalendar'; import { - wrapPickerMount, createPickerRenderer, adapterToUse, describeValidation, @@ -26,12 +25,10 @@ describe(' - Describes', () => { describeConformance(, () => ({ classes, inheritComponent: 'div', - wrapMount: wrapPickerMount, render, muiName: 'MuiYearCalendar', refInstanceof: window.HTMLDivElement, - // cannot test reactTestRenderer because of required context - skip: ['componentProp', 'componentsProp', 'reactTestRenderer', 'themeVariants'], + skip: ['componentProp', 'componentsProp', 'themeVariants'], })); describeValue(YearCalendar, () => ({ diff --git a/packages/x-date-pickers/src/hooks/index.tsx b/packages/x-date-pickers/src/hooks/index.tsx index 40f52b8c93d7..99cde931f0f5 100644 --- a/packages/x-date-pickers/src/hooks/index.tsx +++ b/packages/x-date-pickers/src/hooks/index.tsx @@ -5,3 +5,5 @@ export type { UseClearableFieldSlotProps, UseClearableFieldResponse, } from './useClearableField'; + +export { usePickersTranslations } from './usePickersTranslations'; diff --git a/packages/x-date-pickers/src/hooks/useClearableField.tsx b/packages/x-date-pickers/src/hooks/useClearableField.tsx index 27815914b83c..fb06acdfbd90 100644 --- a/packages/x-date-pickers/src/hooks/useClearableField.tsx +++ b/packages/x-date-pickers/src/hooks/useClearableField.tsx @@ -4,7 +4,7 @@ import MuiIconButton from '@mui/material/IconButton'; import InputAdornment from '@mui/material/InputAdornment'; import { SxProps } from '@mui/system'; import { ClearIcon } from '../icons'; -import { useLocaleText } from '../internals/hooks/useUtils'; +import { usePickersTranslations } from './usePickersTranslations'; export interface ExportedUseClearableFieldProps { /** @@ -51,7 +51,7 @@ export type UseClearableFieldResponse( props: TFieldProps, ): UseClearableFieldResponse => { - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const { clearable, onClear, InputProps, sx, slots, slotProps, ...other } = props; @@ -63,7 +63,7 @@ export const useClearableField = ( ownerState: {}, className: 'clearButton', additionalProps: { - title: localeText.fieldClearLabel, + title: translations.fieldClearLabel, }, }); const EndClearIcon = slots?.clearIcon ?? ClearIcon; diff --git a/packages/x-date-pickers/src/hooks/usePickersTranslations.ts b/packages/x-date-pickers/src/hooks/usePickersTranslations.ts new file mode 100644 index 000000000000..6ad1a7d4bcc2 --- /dev/null +++ b/packages/x-date-pickers/src/hooks/usePickersTranslations.ts @@ -0,0 +1,5 @@ +import { PickerValidDate } from '../models'; +import { useLocalizationContext } from '../internals/hooks/useUtils'; + +export const usePickersTranslations = () => + useLocalizationContext().localeText; diff --git a/packages/x-date-pickers/src/internals/hooks/useField/useFieldState.ts b/packages/x-date-pickers/src/internals/hooks/useField/useFieldState.ts index c6fadb4b23d2..23e6bbc66900 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useFieldState.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useFieldState.ts @@ -1,7 +1,8 @@ import * as React from 'react'; import useControlled from '@mui/utils/useControlled'; import { useRtl } from '@mui/system/RtlProvider'; -import { useUtils, useLocaleText, useLocalizationContext } from '../useUtils'; +import { usePickersTranslations } from '../../../hooks/usePickersTranslations'; +import { useUtils, useLocalizationContext } from '../useUtils'; import { UseFieldInternalProps, UseFieldParams, @@ -86,7 +87,7 @@ export const useFieldState = < >, ): UseFieldStateResponse => { const utils = useUtils(); - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const adapter = useLocalizationContext(); const isRtl = useRtl(); @@ -136,7 +137,7 @@ export const useFieldState = < buildSectionsFromFormat({ utils, timezone, - localeText, + localeText: translations, localizedDigits, format, date, @@ -149,7 +150,7 @@ export const useFieldState = < [ fieldValueManager, format, - localeText, + translations, localizedDigits, isRtl, shouldRespectLeadingZeros, @@ -285,7 +286,7 @@ export const useFieldState = < const sections = buildSectionsFromFormat({ utils, timezone, - localeText, + localeText: translations, localizedDigits, format, date, diff --git a/packages/x-date-pickers/src/internals/hooks/useField/useFieldV6TextField.ts b/packages/x-date-pickers/src/internals/hooks/useField/useFieldV6TextField.ts index f382ec975758..9dd3d684e0d6 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useFieldV6TextField.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useFieldV6TextField.ts @@ -162,6 +162,18 @@ export const useFieldV6TextField: UseFieldTextField = (params) => { inputRef.current.setSelectionRange(selectionStart, selectionEnd); } } + setTimeout(() => { + // handle case when the selection is not updated correctly + // could happen on Android + if ( + inputRef.current && + inputRef.current === getActiveElement(document) && + (inputRef.current.selectionStart !== selectionStart || + inputRef.current.selectionEnd !== selectionEnd) + ) { + interactions.syncSelectionToDOM(); + } + }); } // Even reading this variable seems to do the trick, but also setting it just to make use of it @@ -377,10 +389,9 @@ export const useFieldV6TextField: UseFieldTextField = (params) => { if (keyPressed.length === 0) { if (isAndroid()) { setTempAndroidValueStr(valueStr); - } else { - resetCharacterQuery(); - clearActiveSection(); } + resetCharacterQuery(); + clearActiveSection(); return; } diff --git a/packages/x-date-pickers/src/internals/hooks/useField/useFieldV7TextField.ts b/packages/x-date-pickers/src/internals/hooks/useField/useFieldV7TextField.ts index 741323d69b4c..e198a6b999cb 100644 --- a/packages/x-date-pickers/src/internals/hooks/useField/useFieldV7TextField.ts +++ b/packages/x-date-pickers/src/internals/hooks/useField/useFieldV7TextField.ts @@ -11,7 +11,8 @@ import { } from './useField.types'; import { getActiveElement } from '../../utils/utils'; import { PickersSectionElement, PickersSectionListRef } from '../../../PickersSectionList'; -import { useLocaleText, useUtils } from '../useUtils'; +import { usePickersTranslations } from '../../../hooks/usePickersTranslations'; +import { useUtils } from '../useUtils'; export const useFieldV7TextField: UseFieldTextField = (params) => { const { @@ -43,7 +44,7 @@ export const useFieldV7TextField: UseFieldTextField = (params) => { const sectionListRef = React.useRef(null); const handleSectionListRef = useForkRef(inSectionListRef, sectionListRef); - const localeText = useLocaleText(); + const translations = usePickersTranslations(); const utils = useUtils(); const id = useId(); @@ -435,8 +436,10 @@ export const useFieldV7TextField: UseFieldTextField = (params) => { 'aria-valuenow': getSectionValueNow(section, utils), 'aria-valuemin': sectionBoundaries[section.type].minimum, 'aria-valuemax': sectionBoundaries[section.type].maximum, - 'aria-valuetext': section.value ? getSectionValueText(section, utils) : localeText.empty, - 'aria-label': localeText[section.type], + 'aria-valuetext': section.value + ? getSectionValueText(section, utils) + : translations.empty, + 'aria-label': translations[section.type], 'aria-disabled': disabled, spellCheck: isEditable ? false : undefined, autoCapitalize: isEditable ? 'off' : undefined, @@ -471,7 +474,7 @@ export const useFieldV7TextField: UseFieldTextField = (params) => { disabled, readOnly, isContainerEditable, - localeText, + translations, utils, sectionBoundaries, id, diff --git a/packages/x-date-pickers/src/internals/hooks/useUtils.ts b/packages/x-date-pickers/src/internals/hooks/useUtils.ts index 2759b1b05078..a7c2e1d54130 100644 --- a/packages/x-date-pickers/src/internals/hooks/useUtils.ts +++ b/packages/x-date-pickers/src/internals/hooks/useUtils.ts @@ -50,9 +50,6 @@ export const useUtils = () => useLocalizationCont export const useDefaultDates = () => useLocalizationContext().defaultDates; -export const useLocaleText = () => - useLocalizationContext().localeText; - export const useNow = (timezone: PickersTimezone): TDate => { const utils = useUtils(); diff --git a/packages/x-date-pickers/src/internals/index.ts b/packages/x-date-pickers/src/internals/index.ts index 5eafbf5d1962..d336ee07f1e0 100644 --- a/packages/x-date-pickers/src/internals/index.ts +++ b/packages/x-date-pickers/src/internals/index.ts @@ -89,13 +89,7 @@ export type { UseStaticPickerSlots, UseStaticPickerSlotProps, } from './hooks/useStaticPicker'; -export { - useLocalizationContext, - useDefaultDates, - useUtils, - useLocaleText, - useNow, -} from './hooks/useUtils'; +export { useLocalizationContext, useDefaultDates, useUtils, useNow } from './hooks/useUtils'; export type { ExportedUseViewsOptions, UseViewsOptions } from './hooks/useViews'; export { useViews } from './hooks/useViews'; export { useValidation } from './hooks/useValidation'; @@ -137,7 +131,7 @@ export { mergeDateAndTime, formatMeridiem, } from './utils/date-utils'; -export { resolveTimeViewsResponse } from './utils/date-time-utils'; +export { resolveTimeViewsResponse, resolveDateTimeFormat } from './utils/date-time-utils'; export { splitFieldInternalAndForwardedProps } from './utils/fields'; export { getDefaultReferenceDate } from './utils/getDefaultReferenceDate'; export { diff --git a/packages/x-date-pickers/src/internals/utils/date-time-utils.ts b/packages/x-date-pickers/src/internals/utils/date-time-utils.ts index 0be0869483c4..47688559cf1b 100644 --- a/packages/x-date-pickers/src/internals/utils/date-time-utils.ts +++ b/packages/x-date-pickers/src/internals/utils/date-time-utils.ts @@ -14,7 +14,11 @@ import { DefaultizedProps } from '../models/helpers'; export const resolveDateTimeFormat = ( utils: MuiPickersAdapter, - { views, format, ...other }: { format?: string; views: readonly DateOrTimeView[]; ampm: boolean }, + { + views, + format, + ...other + }: { format?: string; views: readonly DateOrTimeViewWithMeridiem[]; ampm: boolean }, ) => { if (format) { return format; diff --git a/packages/x-date-pickers/tsconfig.json b/packages/x-date-pickers/tsconfig.json index 679bf256599a..5f862d31ec2b 100644 --- a/packages/x-date-pickers/tsconfig.json +++ b/packages/x-date-pickers/tsconfig.json @@ -5,7 +5,8 @@ "@mui/internal-test-utils/initMatchers", "@mui/material/themeCssVarsAugmentation", "chai-dom", - "mocha" + "mocha", + "node" ], "noImplicitAny": false }, diff --git a/packages/x-internals/LICENSE b/packages/x-internals/LICENSE new file mode 100644 index 000000000000..126bc57eaa23 --- /dev/null +++ b/packages/x-internals/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Material-UI SAS + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/x-internals/README.md b/packages/x-internals/README.md new file mode 100644 index 000000000000..e4389f60af4d --- /dev/null +++ b/packages/x-internals/README.md @@ -0,0 +1,4 @@ +# @mui/x-internals + +Shared utilities used by MUI X packages. +This package should never be installed or used directly. diff --git a/packages/x-internals/package.json b/packages/x-internals/package.json new file mode 100644 index 000000000000..4bb12cb51783 --- /dev/null +++ b/packages/x-internals/package.json @@ -0,0 +1,57 @@ +{ + "name": "@mui/x-internals", + "version": "7.9.0", + "description": "Utility functions for the MUI X packages (internal use only).", + "author": "MUI Team", + "license": "MIT", + "bugs": { + "url": "https://github.com/mui/mui-x/issues" + }, + "homepage": "https://mui.com/x/", + "sideEffects": false, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "publishConfig": { + "access": "public", + "directory": "build" + }, + "keywords": [ + "react", + "react-component", + "material-ui", + "mui", + "mui-x", + "utils" + ], + "scripts": { + "typescript": "tsc -p tsconfig.json", + "build": "pnpm build:modern && pnpm build:node && pnpm build:stable && pnpm build:types && pnpm build:copy-files ", + "build:modern": "node ../../scripts/build.mjs modern", + "build:node": "node ../../scripts/build.mjs node", + "build:stable": "node ../../scripts/build.mjs stable", + "build:copy-files": "node ../../scripts/copyFiles.mjs", + "build:types": "node ../../scripts/buildTypes.mjs", + "prebuild": "rimraf build tsconfig.build.tsbuildinfo" + }, + "repository": { + "type": "git", + "url": "https://github.com/mui/mui-x.git", + "directory": "packages/x-internals" + }, + "dependencies": { + "@babel/runtime": "^7.24.7", + "@mui/utils": "^5.16.0" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0" + }, + "devDependencies": { + "@mui/internal-test-utils": "^1.0.4", + "rimraf": "^5.0.8" + }, + "engines": { + "node": ">=14.0.0" + } +} diff --git a/packages/x-internals/src/useResizeObserver/index.ts b/packages/x-internals/src/useResizeObserver/index.ts new file mode 100644 index 000000000000..327eacb9a95d --- /dev/null +++ b/packages/x-internals/src/useResizeObserver/index.ts @@ -0,0 +1 @@ +export { useResizeObserver } from './useResizeObserver'; diff --git a/packages/x-data-grid/src/hooks/utils/useResizeObserver.ts b/packages/x-internals/src/useResizeObserver/useResizeObserver.ts similarity index 100% rename from packages/x-data-grid/src/hooks/utils/useResizeObserver.ts rename to packages/x-internals/src/useResizeObserver/useResizeObserver.ts diff --git a/packages/x-internals/tsconfig.build.json b/packages/x-internals/tsconfig.build.json new file mode 100644 index 000000000000..1bd81f499e5c --- /dev/null +++ b/packages/x-internals/tsconfig.build.json @@ -0,0 +1,16 @@ +{ + // This config is for emitting declarations (.d.ts) only + // Actual .ts source files are transpiled via babel + "extends": "./tsconfig.json", + "compilerOptions": { + "composite": true, + "declaration": true, + "noEmit": false, + "emitDeclarationOnly": true, + "outDir": "build", + "rootDir": "./src", + "types": ["node"] + }, + "include": ["src/**/*.ts*"], + "exclude": ["src/**/*.spec.ts*", "src/**/*.test.ts*"] +} diff --git a/packages/x-internals/tsconfig.json b/packages/x-internals/tsconfig.json new file mode 100644 index 000000000000..359e742ef933 --- /dev/null +++ b/packages/x-internals/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "types": ["node", "@mui/internal-test-utils/initMatchers", "chai-dom", "mocha"] + }, + "include": ["src/**/*"] +} diff --git a/packages/x-license/package.json b/packages/x-license/package.json index 5889ec606ab7..01e1a1931055 100644 --- a/packages/x-license/package.json +++ b/packages/x-license/package.json @@ -1,6 +1,6 @@ { "name": "@mui/x-license", - "version": "7.7.1", + "version": "7.9.0", "description": "MUI X License verification", "author": "MUI Team", "main": "src/index.ts", @@ -35,14 +35,14 @@ }, "dependencies": { "@babel/runtime": "^7.24.7", - "@mui/utils": "^5.15.20" + "@mui/utils": "^5.16.0" }, "peerDependencies": { "react": "^17.0.0 || ^18.0.0" }, "devDependencies": { - "@mui/internal-test-utils": "^1.0.1", - "rimraf": "^5.0.7" + "@mui/internal-test-utils": "^1.0.4", + "rimraf": "^5.0.8" }, "engines": { "node": ">=14.0.0" diff --git a/packages/x-license/src/Watermark/Watermark.tsx b/packages/x-license/src/Watermark/Watermark.tsx index b970d5a12fc4..ff1eafba9298 100644 --- a/packages/x-license/src/Watermark/Watermark.tsx +++ b/packages/x-license/src/Watermark/Watermark.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; -import { MuiCommercialPackageName, useLicenseVerifier } from '../useLicenseVerifier'; +import { useLicenseVerifier } from '../useLicenseVerifier'; import { LICENSE_STATUS, LicenseStatus } from '../utils/licenseStatus'; +import { MuiCommercialPackageName } from '../utils/commercialPackages'; function getLicenseErrorMessage(licenseStatus: LicenseStatus) { switch (licenseStatus) { diff --git a/packages/x-license/src/useLicenseVerifier/index.ts b/packages/x-license/src/useLicenseVerifier/index.ts index e8e4693717d8..ef9135804f69 100644 --- a/packages/x-license/src/useLicenseVerifier/index.ts +++ b/packages/x-license/src/useLicenseVerifier/index.ts @@ -1,2 +1 @@ export { useLicenseVerifier } from './useLicenseVerifier'; -export type { MuiCommercialPackageName } from './useLicenseVerifier'; diff --git a/packages/x-license/src/useLicenseVerifier/useLicenseVerifier.ts b/packages/x-license/src/useLicenseVerifier/useLicenseVerifier.ts index d85e4477ef61..72fb2bf48f10 100644 --- a/packages/x-license/src/useLicenseVerifier/useLicenseVerifier.ts +++ b/packages/x-license/src/useLicenseVerifier/useLicenseVerifier.ts @@ -11,15 +11,8 @@ import { showNotAvailableInInitialProPlanError, } from '../utils/licenseErrorMessageUtils'; import { LICENSE_STATUS, LicenseStatus } from '../utils/licenseStatus'; -import { extractAcceptedScopes, extractProductScope } from '../utils/licenseScope'; import MuiLicenseInfoContext from '../Unstable_LicenseInfoProvider/MuiLicenseInfoContext'; - -export type MuiCommercialPackageName = - | 'x-data-grid-pro' - | 'x-data-grid-premium' - | 'x-date-pickers-pro' - | 'x-tree-view-pro' - | 'x-charts-pro'; +import { MuiCommercialPackageName } from '../utils/commercialPackages'; export const sharedLicenseStatuses: { [packageName in MuiCommercialPackageName]?: { @@ -48,15 +41,11 @@ export function useLicenseVerifier( return sharedLicenseStatuses[packageName]!.licenseVerifier; } - const acceptedScopes = extractAcceptedScopes(packageName); - const productScope = extractProductScope(packageName); - const plan = packageName.includes('premium') ? 'Premium' : 'Pro'; const licenseStatus = verifyLicense({ releaseInfo, licenseKey, - acceptedScopes, - productScope, + packageName, }); const fullPackageName = `@mui/${packageName}`; diff --git a/packages/x-license/src/utils/commercialPackages.ts b/packages/x-license/src/utils/commercialPackages.ts new file mode 100644 index 000000000000..ae4e676b5732 --- /dev/null +++ b/packages/x-license/src/utils/commercialPackages.ts @@ -0,0 +1,6 @@ +export type MuiCommercialPackageName = + | 'x-data-grid-pro' + | 'x-data-grid-premium' + | 'x-date-pickers-pro' + | 'x-tree-view-pro' + | 'x-charts-pro'; diff --git a/packages/x-license/src/utils/index.ts b/packages/x-license/src/utils/index.ts index 20a11f9c8cd8..7197239c1e95 100644 --- a/packages/x-license/src/utils/index.ts +++ b/packages/x-license/src/utils/index.ts @@ -3,3 +3,4 @@ export * from './licenseInfo'; export * from './licenseStatus'; export type { LicenseScope } from './licenseScope'; export type { LicensingModel } from './licensingModel'; +export type { MuiCommercialPackageName } from './commercialPackages'; diff --git a/packages/x-license/src/utils/licenseScope.ts b/packages/x-license/src/utils/licenseScope.ts index d75a3b56607a..f998b354f7b0 100644 --- a/packages/x-license/src/utils/licenseScope.ts +++ b/packages/x-license/src/utils/licenseScope.ts @@ -1,20 +1,5 @@ export const LICENSE_SCOPES = ['pro', 'premium'] as const; -export const PRODUCT_SCOPES = ['data-grid', 'date-pickers', 'charts', 'tree-view'] as const; export const PLAN_VERSIONS = ['initial', 'Q3-2024'] as const; export type LicenseScope = (typeof LICENSE_SCOPES)[number]; -export type ProductScope = (typeof PRODUCT_SCOPES)[number]; export type PlanVersion = (typeof PLAN_VERSIONS)[number]; - -export const extractProductScope = (packageName: string): ProductScope => { - // extract the part between "x-" and "-pro"/"-premium" - const regex = /x-(.*?)(-pro|-premium)?$/; - const match = packageName.match(regex); - return match![1] as ProductScope; -}; - -export const extractAcceptedScopes = (packageName: string): readonly LicenseScope[] => { - return packageName.includes('premium') - ? LICENSE_SCOPES.filter((scope) => scope.includes('premium')) - : LICENSE_SCOPES; -}; diff --git a/packages/x-license/src/verifyLicense/verifyLicense.test.ts b/packages/x-license/src/verifyLicense/verifyLicense.test.ts index 3e040c782a17..3b096e31abae 100644 --- a/packages/x-license/src/verifyLicense/verifyLicense.test.ts +++ b/packages/x-license/src/verifyLicense/verifyLicense.test.ts @@ -30,8 +30,7 @@ describe('License: verifyLicense', () => { verifyLicense({ releaseInfo: '__RELEASE_INFO__', licenseKey, - acceptedScopes: ['pro', 'premium'], - productScope: 'data-grid', + packageName: 'x-data-grid-pro', }).status, ).to.throw('MUI X: The release information is invalid. Not able to validate license.'); }); @@ -42,8 +41,7 @@ describe('License: verifyLicense', () => { verifyLicense({ releaseInfo: RELEASE_INFO, licenseKey, - acceptedScopes: ['pro', 'premium'], - productScope: 'data-grid', + packageName: 'x-data-grid-pro', }).status, ).to.equal(LICENSE_STATUS.Valid); }); @@ -62,8 +60,7 @@ describe('License: verifyLicense', () => { verifyLicense({ releaseInfo: RELEASE_INFO, licenseKey: expiredLicenseKey, - acceptedScopes: ['pro', 'premium'], - productScope: 'data-grid', + packageName: 'x-data-grid-pro', }).status, ).to.equal(LICENSE_STATUS.ExpiredVersion); }); @@ -75,8 +72,7 @@ describe('License: verifyLicense', () => { releaseInfo: RELEASE_INFO, licenseKey: 'b43ff5f9ac93f021855ff59ff0ba5220TkFNRTpNYC1VSSBTQVMsREVWRUxPUEVSX0NPVU5UPTEwLEVYUElSWT0xNTkxNzIzMDY3MDQyLFZFUlNJT049MS4yLjM', - acceptedScopes: ['pro', 'premium'], - productScope: 'data-grid', + packageName: 'x-data-grid-pro', }).status, ).to.equal(LICENSE_STATUS.Invalid); }); @@ -106,8 +102,7 @@ describe('License: verifyLicense', () => { verifyLicense({ releaseInfo: '__RELEASE_INFO__', licenseKey: licenseKeyPro, - acceptedScopes: ['pro', 'premium'], - productScope: 'data-grid', + packageName: 'x-data-grid-pro', }).status, ).to.throw('MUI X: The release information is invalid. Not able to validate license.'); }); @@ -119,8 +114,7 @@ describe('License: verifyLicense', () => { verifyLicense({ releaseInfo: RELEASE_INFO, licenseKey: licenseKeyPro, - acceptedScopes: ['pro', 'premium'], - productScope: 'data-grid', + packageName: 'x-data-grid-pro', }).status, ).to.equal(LICENSE_STATUS.Valid); }); @@ -131,8 +125,7 @@ describe('License: verifyLicense', () => { verifyLicense({ releaseInfo: RELEASE_INFO, licenseKey: licenseKeyPremium, - acceptedScopes: ['premium'], - productScope: 'data-grid', + packageName: 'x-data-grid-premium', }).status, ).to.equal(LICENSE_STATUS.Valid); }); @@ -143,8 +136,7 @@ describe('License: verifyLicense', () => { verifyLicense({ releaseInfo: RELEASE_INFO, licenseKey: licenseKeyPro, - acceptedScopes: ['premium'], - productScope: 'data-grid', + packageName: 'x-data-grid-premium', }).status, ).to.equal(LICENSE_STATUS.OutOfScope); }); @@ -165,8 +157,7 @@ describe('License: verifyLicense', () => { verifyLicense({ releaseInfo: RELEASE_INFO, licenseKey: expiredLicenseKey, - acceptedScopes: ['pro', 'premium'], - productScope: 'data-grid', + packageName: 'x-data-grid-pro', }).status, ).to.equal(LICENSE_STATUS.Valid); }); @@ -184,8 +175,7 @@ describe('License: verifyLicense', () => { verifyLicense({ releaseInfo: RELEASE_INFO, licenseKey: expiredLicenseKey, - acceptedScopes: ['pro', 'premium'], - productScope: 'data-grid', + packageName: 'x-data-grid-pro', }).status, ).to.equal(LICENSE_STATUS.ExpiredAnnualGrace); }); @@ -204,8 +194,7 @@ describe('License: verifyLicense', () => { verifyLicense({ releaseInfo: RELEASE_INFO, licenseKey: expiredLicenseKey, - acceptedScopes: ['pro', 'premium'], - productScope: 'data-grid', + packageName: 'x-data-grid-pro', }).status, ).to.equal(LICENSE_STATUS.ExpiredAnnual); }); @@ -223,8 +212,7 @@ describe('License: verifyLicense', () => { verifyLicense({ releaseInfo: RELEASE_INFO, licenseKey: expiredLicenseKey, - acceptedScopes: ['pro', 'premium'], - productScope: 'data-grid', + packageName: 'x-data-grid-pro', }).status, ).to.equal(LICENSE_STATUS.Valid); }); @@ -237,8 +225,7 @@ describe('License: verifyLicense', () => { releaseInfo: RELEASE_INFO, licenseKey: 'b43ff5f9ac93f021855ff59ff0ba5220TkFNRTpNYC1VSSBTQVMsREVWRUxPUEVSX0NPVU5UPTEwLEVYUElSWT0xNTkxNzIzMDY3MDQyLFZFUlNJT049MS4yLjM', - acceptedScopes: ['pro', 'premium'], - productScope: 'data-grid', + packageName: 'x-data-grid-pro', }).status, ).to.equal(LICENSE_STATUS.Invalid); }); @@ -259,15 +246,14 @@ describe('License: verifyLicense', () => { verifyLicense({ releaseInfo: RELEASE_INFO, licenseKey: licenseKeyPro, - acceptedScopes: ['pro', 'premium'], - productScope: 'data-grid', + packageName: 'x-data-grid-pro', }).status, ).to.equal(LICENSE_STATUS.Valid); }); }); describe('key version: 2.2', () => { - const licenseKeyInitial = generateLicense({ + const proLicenseKeyInitial = generateLicense({ expiryDate: new Date(releaseDate.getTime() + oneDayInMS), orderNumber: 'MUI-123', scope: 'pro', @@ -275,7 +261,15 @@ describe('License: verifyLicense', () => { planVersion: 'initial', }); - const licenseKey2 = generateLicense({ + const premiumLicenseKeyInitial = generateLicense({ + expiryDate: new Date(releaseDate.getTime() + oneDayInMS), + orderNumber: 'MUI-123', + scope: 'premium', + licensingModel: 'annual', + planVersion: 'initial', + }); + + const proLicenseKeyQ32024 = generateLicense({ expiryDate: new Date(releaseDate.getTime() + oneDayInMS), orderNumber: 'MUI-123', scope: 'pro', @@ -283,50 +277,68 @@ describe('License: verifyLicense', () => { planVersion: 'Q3-2024', }); - it('PlanVersion "initial" should not accept charts', () => { + it('PlanVersion "initial" should not accept x-charts-pro', () => { process.env.NODE_ENV = 'production'; expect( verifyLicense({ releaseInfo: RELEASE_INFO, - licenseKey: licenseKeyInitial, - acceptedScopes: ['pro', 'premium'], - productScope: 'charts', + licenseKey: proLicenseKeyInitial, + packageName: 'x-charts-pro', }).status, ).to.equal(LICENSE_STATUS.NotAvailableInInitialProPlan); }); - it('PlanVersion "initial" should not accept tree-view', () => { + it('PlanVersion "initial" should not accept x-tree-view-pro', () => { process.env.NODE_ENV = 'production'; expect( verifyLicense({ releaseInfo: RELEASE_INFO, - licenseKey: licenseKeyInitial, - acceptedScopes: ['pro', 'premium'], - productScope: 'tree-view', + licenseKey: proLicenseKeyInitial, + packageName: 'x-tree-view-pro', }).status, ).to.equal(LICENSE_STATUS.NotAvailableInInitialProPlan); }); - it('PlanVersion "Q3-2024" should accept charts', () => { + it('PlanVersion "Q3-2024" should accept x-charts-pro', () => { + process.env.NODE_ENV = 'production'; + expect( + verifyLicense({ + releaseInfo: RELEASE_INFO, + licenseKey: proLicenseKeyQ32024, + packageName: 'x-charts-pro', + }).status, + ).to.equal(LICENSE_STATUS.Valid); + }); + + it('PlanVersion "Q3-2024" should accept x-tree-view-pro', () => { + process.env.NODE_ENV = 'production'; + expect( + verifyLicense({ + releaseInfo: RELEASE_INFO, + licenseKey: proLicenseKeyQ32024, + packageName: 'x-tree-view-pro', + }).status, + ).to.equal(LICENSE_STATUS.Valid); + }); + + it('Premium with planVersion "initial" should accept x-tree-view-pro', () => { process.env.NODE_ENV = 'production'; expect( verifyLicense({ releaseInfo: RELEASE_INFO, - licenseKey: licenseKey2, - acceptedScopes: ['pro', 'premium'], - productScope: 'charts', + licenseKey: premiumLicenseKeyInitial, + packageName: 'x-tree-view-pro', }).status, ).to.equal(LICENSE_STATUS.Valid); }); - it('PlanVersion "Q3-2024" should accept tree-view', () => { + it('Premium with planVersion "initial" should accept x-charts-pro', () => { process.env.NODE_ENV = 'production'; expect( verifyLicense({ releaseInfo: RELEASE_INFO, - licenseKey: licenseKey2, - acceptedScopes: ['pro', 'premium'], - productScope: 'tree-view', + licenseKey: premiumLicenseKeyInitial, + packageName: 'x-charts-pro', }).status, ).to.equal(LICENSE_STATUS.Valid); }); diff --git a/packages/x-license/src/verifyLicense/verifyLicense.ts b/packages/x-license/src/verifyLicense/verifyLicense.ts index ed9b936357cb..8aa5d8915d5a 100644 --- a/packages/x-license/src/verifyLicense/verifyLicense.ts +++ b/packages/x-license/src/verifyLicense/verifyLicense.ts @@ -1,8 +1,9 @@ import { base64Decode, base64Encode } from '../encoding/base64'; import { md5 } from '../encoding/md5'; import { LICENSE_STATUS, LicenseStatus } from '../utils/licenseStatus'; -import { LicenseScope, LICENSE_SCOPES, ProductScope, PlanVersion } from '../utils/licenseScope'; +import { LicenseScope, LICENSE_SCOPES, PlanVersion } from '../utils/licenseScope'; import { LicensingModel, LICENSING_MODELS } from '../utils/licensingModel'; +import { MuiCommercialPackageName } from '../utils/commercialPackages'; const getDefaultReleaseDate = () => { const today = new Date(); @@ -15,6 +16,22 @@ export function generateReleaseInfo(releaseDate = getDefaultReleaseDate()) { return base64Encode(releaseDate.getTime().toString()); } +function isLicenseScopeSufficient( + packageName: MuiCommercialPackageName, + licenseScope: LicenseScope, +) { + let acceptedScopes: LicenseScope[]; + if (packageName.includes('-pro')) { + acceptedScopes = ['pro', 'premium']; + } else if (packageName.includes('-premium')) { + acceptedScopes = ['premium']; + } else { + acceptedScopes = []; + } + + return acceptedScopes.includes(licenseScope); +} + const expiryReg = /^.*EXPIRY=([0-9]+),.*$/; interface MuiLicense { @@ -24,6 +41,11 @@ interface MuiLicense { planVersion: PlanVersion; } +const PRO_PACKAGES_AVAILABLE_IN_INITIAL_PRO_PLAN: MuiCommercialPackageName[] = [ + 'x-data-grid-pro', + 'x-date-pickers-pro', +]; + /** * Format: ORDER:${orderNumber},EXPIRY=${expiryTimestamp},KEYVERSION=1 */ @@ -105,13 +127,11 @@ const decodeLicense = (encodedLicense: string): MuiLicense | null => { export function verifyLicense({ releaseInfo, licenseKey, - acceptedScopes, - productScope, + packageName, }: { releaseInfo: string; licenseKey?: string; - acceptedScopes: readonly LicenseScope[]; - productScope: ProductScope; + packageName: MuiCommercialPackageName; }): { status: LicenseStatus; meta?: any } { if (!releaseInfo) { throw new Error('MUI X: The release information is missing. Not able to validate license.'); @@ -178,15 +198,17 @@ export function verifyLicense({ return { status: LICENSE_STATUS.Invalid }; } - if (license.planVersion === 'initial') { - // 'charts-pro' or 'tree-view-pro' can only be used with a newer license - if (productScope === 'charts' || productScope === 'tree-view') { - return { status: LICENSE_STATUS.NotAvailableInInitialProPlan }; - } + if (!isLicenseScopeSufficient(packageName, license.scope)) { + return { status: LICENSE_STATUS.OutOfScope }; } - if (!acceptedScopes.includes(license.scope)) { - return { status: LICENSE_STATUS.OutOfScope }; + // 'charts-pro' or 'tree-view-pro' can only be used with a newer Pro license + if ( + license.planVersion === 'initial' && + license.scope === 'pro' && + !PRO_PACKAGES_AVAILABLE_IN_INITIAL_PRO_PLAN.includes(packageName) + ) { + return { status: LICENSE_STATUS.NotAvailableInInitialProPlan }; } return { status: LICENSE_STATUS.Valid }; diff --git a/packages/x-tree-view-pro/package.json b/packages/x-tree-view-pro/package.json index bb4eca31328e..f3f15b83c205 100644 --- a/packages/x-tree-view-pro/package.json +++ b/packages/x-tree-view-pro/package.json @@ -45,8 +45,8 @@ "dependencies": { "@babel/runtime": "^7.24.7", "@mui/base": "^5.0.0-beta.40", - "@mui/system": "^5.15.20", - "@mui/utils": "^5.15.20", + "@mui/system": "^5.16.0", + "@mui/utils": "^5.16.0", "@mui/x-license": "workspace:*", "@mui/x-tree-view": "workspace:*", "@types/react-transition-group": "^4.4.10", @@ -62,8 +62,8 @@ "react-dom": "^17.0.0 || ^18.0.0" }, "devDependencies": { - "@mui/internal-test-utils": "^1.0.1", - "rimraf": "^5.0.7" + "@mui/internal-test-utils": "^1.0.4", + "rimraf": "^5.0.8" }, "engines": { "node": ">=14.0.0" diff --git a/packages/x-tree-view-pro/tsconfig.json b/packages/x-tree-view-pro/tsconfig.json index 8f928a498c68..8abd09069709 100644 --- a/packages/x-tree-view-pro/tsconfig.json +++ b/packages/x-tree-view-pro/tsconfig.json @@ -5,7 +5,8 @@ "@mui/internal-test-utils/initMatchers", "@mui/material/themeCssVarsAugmentation", "chai-dom", - "mocha" + "mocha", + "node" ], "noImplicitAny": false }, diff --git a/packages/x-tree-view/package.json b/packages/x-tree-view/package.json index 8e56eb3fd087..adef657c5f6d 100644 --- a/packages/x-tree-view/package.json +++ b/packages/x-tree-view/package.json @@ -1,6 +1,6 @@ { "name": "@mui/x-tree-view", - "version": "7.7.1", + "version": "7.9.0", "description": "The community edition of the Tree View components (MUI X).", "author": "MUI Team", "main": "src/index.ts", @@ -45,8 +45,8 @@ "dependencies": { "@babel/runtime": "^7.24.7", "@mui/base": "^5.0.0-beta.40", - "@mui/system": "^5.15.20", - "@mui/utils": "^5.15.20", + "@mui/system": "^5.16.0", + "@mui/utils": "^5.16.0", "@types/react-transition-group": "^4.4.10", "clsx": "^2.1.1", "prop-types": "^15.8.1", @@ -60,9 +60,9 @@ "react-dom": "^17.0.0 || ^18.0.0" }, "devDependencies": { - "@mui/internal-test-utils": "^1.0.1", + "@mui/internal-test-utils": "^1.0.4", "@types/prop-types": "^15.7.12", - "rimraf": "^5.0.7" + "rimraf": "^5.0.8" }, "engines": { "node": ">=14.0.0" diff --git a/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx b/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx index 5f94c0db2be7..bef997346ee0 100644 --- a/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx +++ b/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx @@ -151,6 +151,8 @@ RichTreeView.propTypes = { current: PropTypes.shape({ focusItem: PropTypes.func.isRequired, getItem: PropTypes.func.isRequired, + getItemDOMElement: PropTypes.func.isRequired, + selectItem: PropTypes.func.isRequired, setItemExpansion: PropTypes.func.isRequired, }), }), @@ -191,6 +193,11 @@ RichTreeView.propTypes = { * Used when the item's expansion is controlled. */ expandedItems: PropTypes.arrayOf(PropTypes.string), + /** + * The slot that triggers the item's expansion when clicked. + * @default 'content' + */ + expansionTrigger: PropTypes.oneOf(['content', 'iconContainer']), /** * Unstable features, breaking changes might be introduced. * For each feature, if the flag is not explicitly set to `true`, @@ -243,34 +250,34 @@ RichTreeView.propTypes = { multiSelect: PropTypes.bool, /** * Callback fired when tree items are expanded/collapsed. - * @param {React.SyntheticEvent} event The event source of the callback. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {array} itemIds The ids of the expanded items. */ onExpandedItemsChange: PropTypes.func, /** * Callback fired when a tree item is expanded or collapsed. - * @param {React.SyntheticEvent} event The event source of the callback. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {array} itemId The itemId of the modified item. * @param {array} isExpanded `true` if the item has just been expanded, `false` if it has just been collapsed. */ onItemExpansionToggle: PropTypes.func, /** * Callback fired when tree items are focused. - * @param {React.SyntheticEvent} event The event source of the callback **Warning**: This is a generic event not a focus event. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. **Warning**: This is a generic event not a focus event. * @param {string} itemId The id of the focused item. * @param {string} value of the focused item. */ onItemFocus: PropTypes.func, /** * Callback fired when a tree item is selected or deselected. - * @param {React.SyntheticEvent} event The event source of the callback. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {array} itemId The itemId of the modified item. * @param {array} isSelected `true` if the item has just been selected, `false` if it has just been deselected. */ onItemSelectionToggle: PropTypes.func, /** * Callback fired when tree items are selected/deselected. - * @param {React.SyntheticEvent} event The event source of the callback + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {string[] | string} itemIds The ids of the selected items. * When `multiSelect` is `true`, this is an array of strings; when false (default) a string. */ diff --git a/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx b/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx index 472bf6208f58..6ae14a68284e 100644 --- a/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx +++ b/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx @@ -110,6 +110,8 @@ SimpleTreeView.propTypes = { current: PropTypes.shape({ focusItem: PropTypes.func.isRequired, getItem: PropTypes.func.isRequired, + getItemDOMElement: PropTypes.func.isRequired, + selectItem: PropTypes.func.isRequired, setItemExpansion: PropTypes.func.isRequired, }), }), @@ -154,6 +156,11 @@ SimpleTreeView.propTypes = { * Used when the item's expansion is controlled. */ expandedItems: PropTypes.arrayOf(PropTypes.string), + /** + * The slot that triggers the item's expansion when clicked. + * @default 'content' + */ + expansionTrigger: PropTypes.oneOf(['content', 'iconContainer']), /** * Unstable features, breaking changes might be introduced. * For each feature, if the flag is not explicitly set to `true`, @@ -180,34 +187,34 @@ SimpleTreeView.propTypes = { multiSelect: PropTypes.bool, /** * Callback fired when tree items are expanded/collapsed. - * @param {React.SyntheticEvent} event The event source of the callback. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {array} itemIds The ids of the expanded items. */ onExpandedItemsChange: PropTypes.func, /** * Callback fired when a tree item is expanded or collapsed. - * @param {React.SyntheticEvent} event The event source of the callback. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {array} itemId The itemId of the modified item. * @param {array} isExpanded `true` if the item has just been expanded, `false` if it has just been collapsed. */ onItemExpansionToggle: PropTypes.func, /** * Callback fired when tree items are focused. - * @param {React.SyntheticEvent} event The event source of the callback **Warning**: This is a generic event not a focus event. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. **Warning**: This is a generic event not a focus event. * @param {string} itemId The id of the focused item. * @param {string} value of the focused item. */ onItemFocus: PropTypes.func, /** * Callback fired when a tree item is selected or deselected. - * @param {React.SyntheticEvent} event The event source of the callback. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {array} itemId The itemId of the modified item. * @param {array} isSelected `true` if the item has just been selected, `false` if it has just been deselected. */ onItemSelectionToggle: PropTypes.func, /** * Callback fired when tree items are selected/deselected. - * @param {React.SyntheticEvent} event The event source of the callback + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {string[] | string} itemIds The ids of the selected items. * When `multiSelect` is `true`, this is an array of strings; when false (default) a string. */ diff --git a/packages/x-tree-view/src/TreeItem/TreeItem.test.tsx b/packages/x-tree-view/src/TreeItem/TreeItem.test.tsx index 86f502bb6119..d85f3e7aa395 100644 --- a/packages/x-tree-view/src/TreeItem/TreeItem.test.tsx +++ b/packages/x-tree-view/src/TreeItem/TreeItem.test.tsx @@ -68,12 +68,6 @@ describe('', () => { describeConformance(, () => ({ classes, inheritComponent: 'li', - wrapMount: (mount) => (item: React.ReactNode) => { - const wrapper = mount( - {item}, - ); - return wrapper.childAt(0); - }, render: (item) => { return render( {item}, @@ -81,7 +75,7 @@ describe('', () => { }, muiName: 'MuiTreeItem', refInstanceof: window.HTMLLIElement, - skip: ['reactTestRenderer', 'componentProp', 'componentsProp', 'themeVariants'], + skip: ['componentProp', 'componentsProp', 'themeVariants'], })); describe('PropTypes warnings', () => { diff --git a/packages/x-tree-view/src/TreeItem/TreeItem.tsx b/packages/x-tree-view/src/TreeItem/TreeItem.tsx index 2f35d8974905..b048be14f8dc 100644 --- a/packages/x-tree-view/src/TreeItem/TreeItem.tsx +++ b/packages/x-tree-view/src/TreeItem/TreeItem.tsx @@ -23,6 +23,7 @@ import { useTreeViewContext } from '../internals/TreeViewProvider/useTreeViewCon import { TreeViewCollapseIcon, TreeViewExpandIcon } from '../icons'; import { TreeItem2Provider } from '../TreeItem2Provider'; import { TreeViewItemDepthContext } from '../internals/TreeViewItemDepthContext'; +import { useTreeItemState } from './useTreeItemState'; const useThemeProps = createUseThemeProps('MuiTreeItem'); @@ -187,6 +188,7 @@ export const TreeItem = React.forwardRef(function TreeItem( icons: contextIcons, runItemPlugins, selection: { multiSelect }, + expansion: { expansionTrigger }, disabledItemsFocusable, indentationAtItemLevel, instance, @@ -213,6 +215,8 @@ export const TreeItem = React.forwardRef(function TreeItem( ...other } = props; + const { expanded, focused, selected, disabled, handleExpansion } = useTreeItemState(itemId); + const { contentRef, rootRef } = runItemPlugins(props); const handleRootRef = useForkRef(inRef, rootRef); const handleContentRef = useForkRef(ContentProps?.ref, contentRef); @@ -232,10 +236,6 @@ export const TreeItem = React.forwardRef(function TreeItem( return Boolean(reactChildren); }; const expandable = isExpandable(children); - const expanded = instance.isItemExpanded(itemId); - const focused = instance.isItemFocused(itemId); - const selected = instance.isItemSelected(itemId); - const disabled = instance.isItemDisabled(itemId); const ownerState: TreeItemOwnerState = { ...props, @@ -263,6 +263,11 @@ export const TreeItem = React.forwardRef(function TreeItem( className: classes.groupTransition, }); + const handleIconContainerClick = (event: React.MouseEvent) => { + if (expansionTrigger === 'iconContainer') { + handleExpansion(event); + } + }; const ExpansionIcon = expanded ? slots.collapseIcon : slots.expandIcon; const { ownerState: expansionIconOwnerState, ...expansionIconProps } = useSlotProps({ elementType: ExpansionIcon, @@ -280,6 +285,9 @@ export const TreeItem = React.forwardRef(function TreeItem( ...resolveComponentProps(inSlotProps?.expandIcon, tempOwnerState), }; }, + additionalProps: { + onClick: handleIconContainerClick, + }, }); const expansionIcon = expandable && !!ExpansionIcon ? : null; diff --git a/packages/x-tree-view/src/TreeItem/TreeItemContent.tsx b/packages/x-tree-view/src/TreeItem/TreeItemContent.tsx index 11c31e401cee..c04b65ed08ea 100644 --- a/packages/x-tree-view/src/TreeItem/TreeItemContent.tsx +++ b/packages/x-tree-view/src/TreeItem/TreeItemContent.tsx @@ -82,6 +82,7 @@ const TreeItemContent = React.forwardRef(function TreeItemContent( handleSelection, handleCheckboxSelection, preventSelection, + expansionTrigger, } = useTreeItemState(itemId); const icon = iconProp || expansionIcon || displayIcon; @@ -100,7 +101,9 @@ const TreeItemContent = React.forwardRef(function TreeItemContent( return; } - handleExpansion(event); + if (expansionTrigger === 'content') { + handleExpansion(event); + } if (!checkboxSelection) { handleSelection(event); diff --git a/packages/x-tree-view/src/TreeItem/useTreeItemState.ts b/packages/x-tree-view/src/TreeItem/useTreeItemState.ts index 09f9ce6f88c2..531f340b62c2 100644 --- a/packages/x-tree-view/src/TreeItem/useTreeItemState.ts +++ b/packages/x-tree-view/src/TreeItem/useTreeItemState.ts @@ -18,6 +18,7 @@ export function useTreeItemState(itemId: string) { const { instance, selection: { multiSelect, checkboxSelection, disableSelection }, + expansion: { expansionTrigger }, } = useTreeViewContext(); const expandable = instance.isItemExpandable(itemId); @@ -48,15 +49,14 @@ export function useTreeItemState(itemId: string) { } const multiple = multiSelect && (event.shiftKey || event.ctrlKey || event.metaKey); - if (multiple) { if (event.shiftKey) { instance.expandSelectionRange(event, itemId); } else { - instance.selectItem(event, itemId, true); + instance.selectItem({ event, itemId, keepExistingSelection: true }); } } else { - instance.selectItem(event, itemId, false); + instance.selectItem({ event, itemId, shouldBeSelected: true }); } } }; @@ -70,7 +70,12 @@ export function useTreeItemState(itemId: string) { if (multiSelect && hasShift) { instance.expandSelectionRange(event, itemId); } else { - instance.selectItem(event, itemId, multiSelect, event.target.checked); + instance.selectItem({ + event, + itemId, + keepExistingSelection: multiSelect, + shouldBeSelected: event.target.checked, + }); } }; @@ -92,5 +97,6 @@ export function useTreeItemState(itemId: string) { handleSelection, handleCheckboxSelection, preventSelection, + expansionTrigger, }; } diff --git a/packages/x-tree-view/src/TreeItem2/TreeItem2.test.tsx b/packages/x-tree-view/src/TreeItem2/TreeItem2.test.tsx index 6476ec7eb8a9..524b3aca824f 100644 --- a/packages/x-tree-view/src/TreeItem2/TreeItem2.test.tsx +++ b/packages/x-tree-view/src/TreeItem2/TreeItem2.test.tsx @@ -13,12 +13,6 @@ describe('', () => { describeConformance(, () => ({ classes, inheritComponent: 'li', - wrapMount: (mount) => (item: React.ReactNode) => { - const wrapper = mount( - {item}, - ); - return wrapper.childAt(0); - }, render: (item) => { return render( {item}, @@ -26,7 +20,7 @@ describe('', () => { }, muiName: 'MuiTreeItem2', refInstanceof: window.HTMLLIElement, - skip: ['reactTestRenderer', 'componentProp', 'componentsProp', 'themeVariants'], + skip: ['componentProp', 'componentsProp', 'themeVariants'], })); describeSlotsConformance({ diff --git a/packages/x-tree-view/src/TreeView/TreeView.tsx b/packages/x-tree-view/src/TreeView/TreeView.tsx index 2149524f39fd..18cfb0c1f8e0 100644 --- a/packages/x-tree-view/src/TreeView/TreeView.tsx +++ b/packages/x-tree-view/src/TreeView/TreeView.tsx @@ -95,6 +95,8 @@ TreeView.propTypes = { current: PropTypes.shape({ focusItem: PropTypes.func.isRequired, getItem: PropTypes.func.isRequired, + getItemDOMElement: PropTypes.func.isRequired, + selectItem: PropTypes.func.isRequired, setItemExpansion: PropTypes.func.isRequired, }), }), @@ -139,6 +141,11 @@ TreeView.propTypes = { * Used when the item's expansion is controlled. */ expandedItems: PropTypes.arrayOf(PropTypes.string), + /** + * The slot that triggers the item's expansion when clicked. + * @default 'content' + */ + expansionTrigger: PropTypes.oneOf(['content', 'iconContainer']), /** * Unstable features, breaking changes might be introduced. * For each feature, if the flag is not explicitly set to `true`, @@ -165,34 +172,34 @@ TreeView.propTypes = { multiSelect: PropTypes.bool, /** * Callback fired when tree items are expanded/collapsed. - * @param {React.SyntheticEvent} event The event source of the callback. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {array} itemIds The ids of the expanded items. */ onExpandedItemsChange: PropTypes.func, /** * Callback fired when a tree item is expanded or collapsed. - * @param {React.SyntheticEvent} event The event source of the callback. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {array} itemId The itemId of the modified item. * @param {array} isExpanded `true` if the item has just been expanded, `false` if it has just been collapsed. */ onItemExpansionToggle: PropTypes.func, /** * Callback fired when tree items are focused. - * @param {React.SyntheticEvent} event The event source of the callback **Warning**: This is a generic event not a focus event. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. **Warning**: This is a generic event not a focus event. * @param {string} itemId The id of the focused item. * @param {string} value of the focused item. */ onItemFocus: PropTypes.func, /** * Callback fired when a tree item is selected or deselected. - * @param {React.SyntheticEvent} event The event source of the callback. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {array} itemId The itemId of the modified item. * @param {array} isSelected `true` if the item has just been selected, `false` if it has just been deselected. */ onItemSelectionToggle: PropTypes.func, /** * Callback fired when tree items are selected/deselected. - * @param {React.SyntheticEvent} event The event source of the callback + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {string[] | string} itemIds The ids of the selected items. * When `multiSelect` is `true`, this is an array of strings; when false (default) a string. */ diff --git a/packages/x-tree-view/src/hooks/useTreeItem2Utils/useTreeItem2Utils.tsx b/packages/x-tree-view/src/hooks/useTreeItem2Utils/useTreeItem2Utils.tsx index 81e0f169559c..ab33dc1eb1a8 100644 --- a/packages/x-tree-view/src/hooks/useTreeItem2Utils/useTreeItem2Utils.tsx +++ b/packages/x-tree-view/src/hooks/useTreeItem2Utils/useTreeItem2Utils.tsx @@ -91,10 +91,10 @@ export const useTreeItem2Utils = ({ if (event.shiftKey) { instance.expandSelectionRange(event, itemId); } else { - instance.selectItem(event, itemId, true); + instance.selectItem({ event, itemId, keepExistingSelection: true }); } } else { - instance.selectItem(event, itemId, false); + instance.selectItem({ event, itemId, shouldBeSelected: true }); } }; @@ -103,7 +103,12 @@ export const useTreeItem2Utils = ({ if (multiSelect && hasShift) { instance.expandSelectionRange(event, itemId); } else { - instance.selectItem(event, itemId, multiSelect, event.target.checked); + instance.selectItem({ + event, + itemId, + keepExistingSelection: multiSelect, + shouldBeSelected: event.target.checked, + }); } }; diff --git a/packages/x-tree-view/src/internals/models/plugin.ts b/packages/x-tree-view/src/internals/models/plugin.ts index b9459acecf93..5cbe4e634f60 100644 --- a/packages/x-tree-view/src/internals/models/plugin.ts +++ b/packages/x-tree-view/src/internals/models/plugin.ts @@ -67,7 +67,9 @@ export type TreeViewPluginSignature< >; } : {}; - experimentalFeatures: T['experimentalFeatures']; + experimentalFeatures: T extends { experimentalFeatures: string } + ? { [key in T['experimentalFeatures']]?: boolean } + : {}; dependencies: T extends { dependencies: Array } ? T['dependencies'] : []; optionalDependencies: T extends { optionalDependencies: Array } ? T['optionalDependencies'] diff --git a/packages/x-tree-view/src/internals/models/treeView.ts b/packages/x-tree-view/src/internals/models/treeView.ts index a9b5e2452203..ad86ffeb39ac 100644 --- a/packages/x-tree-view/src/internals/models/treeView.ts +++ b/packages/x-tree-view/src/internals/models/treeView.ts @@ -38,4 +38,5 @@ export type TreeViewPublicAPI< export type TreeViewExperimentalFeatures< TSignatures extends readonly TreeViewAnyPluginSignature[], -> = { [key in MergeSignaturesProperty]?: boolean }; + TOptionalSignatures extends readonly TreeViewAnyPluginSignature[] = [], +> = MergeSignaturesProperty<[...TSignatures, ...TOptionalSignatures], 'experimentalFeatures'>; diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts index d463f24e85bb..3fd669acf55f 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts @@ -83,6 +83,14 @@ export const useTreeViewExpansion: TreeViewPlugin } }; + const expansionTrigger = React.useMemo(() => { + if (params.expansionTrigger) { + return params.expansionTrigger; + } + + return 'content'; + }, [params.expansionTrigger]); + return { publicAPI: { setItemExpansion, @@ -94,6 +102,11 @@ export const useTreeViewExpansion: TreeViewPlugin toggleItemExpansion, expandAllSiblings, }, + contextValue: { + expansion: { + expansionTrigger, + }, + }, }; }; @@ -115,4 +128,5 @@ useTreeViewExpansion.params = { defaultExpandedItems: true, onExpandedItemsChange: true, onItemExpansionToggle: true, + expansionTrigger: true, }; diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts index f3e93a059afd..d471bcb19606 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts @@ -6,9 +6,9 @@ import { TreeViewItemId } from '../../../models'; export interface UseTreeViewExpansionPublicAPI { /** * Change the expansion status of a given item. - * @param {React.SyntheticEvent} event The UI event that triggered the change. - * @param {string} itemId The id of the item to modify. - * @param {boolean} isExpanded The new expansion status of the given item. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. + * @param {string} itemId The id of the item to expand of collapse. + * @param {boolean} isExpanded If `true` the item will be expanded. If `false` the item will be collapsed. */ setItemExpansion: (event: React.SyntheticEvent, itemId: string, isExpanded: boolean) => void; } @@ -31,13 +31,13 @@ export interface UseTreeViewExpansionInstance extends UseTreeViewExpansionPublic /** * Toggle the current expansion of an item. * If it is expanded, it will be collapsed, and vice versa. - * @param {React.SyntheticEvent} event The UI event that triggered the change. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {TreeViewItemId} itemId The id of the item to toggle. */ toggleItemExpansion: (event: React.SyntheticEvent, itemId: TreeViewItemId) => void; /** * Expand all the siblings (i.e.: the items that have the same parent) of a given item. - * @param {React.SyntheticEvent} event The UI event that triggered the change. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {TreeViewItemId} itemId The id of the item whose siblings will be expanded. */ expandAllSiblings: (event: React.KeyboardEvent, itemId: TreeViewItemId) => void; @@ -57,13 +57,13 @@ export interface UseTreeViewExpansionParameters { defaultExpandedItems?: string[]; /** * Callback fired when tree items are expanded/collapsed. - * @param {React.SyntheticEvent} event The event source of the callback. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {array} itemIds The ids of the expanded items. */ onExpandedItemsChange?: (event: React.SyntheticEvent, itemIds: string[]) => void; /** * Callback fired when a tree item is expanded or collapsed. - * @param {React.SyntheticEvent} event The event source of the callback. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {array} itemId The itemId of the modified item. * @param {array} isExpanded `true` if the item has just been expanded, `false` if it has just been collapsed. */ @@ -72,6 +72,11 @@ export interface UseTreeViewExpansionParameters { itemId: string, isExpanded: boolean, ) => void; + /** + * The slot that triggers the item's expansion when clicked. + * @default 'content' + */ + expansionTrigger?: 'content' | 'iconContainer'; } export type UseTreeViewExpansionDefaultizedParameters = DefaultizedProps< @@ -79,11 +84,16 @@ export type UseTreeViewExpansionDefaultizedParameters = DefaultizedProps< 'defaultExpandedItems' >; +interface UseTreeViewExpansionContextValue { + expansion: Pick; +} + export type UseTreeViewExpansionSignature = TreeViewPluginSignature<{ params: UseTreeViewExpansionParameters; defaultizedParams: UseTreeViewExpansionDefaultizedParameters; instance: UseTreeViewExpansionInstance; publicAPI: UseTreeViewExpansionPublicAPI; modelNames: 'expandedItems'; + contextValue: UseTreeViewExpansionContextValue; dependencies: [UseTreeViewItemsSignature]; }>; diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewFocus/useTreeViewFocus.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewFocus/useTreeViewFocus.ts index 2bec87a29de3..d2128d3c91b8 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewFocus/useTreeViewFocus.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewFocus/useTreeViewFocus.ts @@ -65,10 +65,7 @@ export const useTreeViewFocus: TreeViewPlugin = ({ }; const innerFocusItem = (event: React.SyntheticEvent | null, itemId: string) => { - const itemMeta = instance.getItemMeta(itemId); - const itemElement = document.getElementById( - instance.getTreeItemIdAttribute(itemId, itemMeta.idAttribute), - ); + const itemElement = instance.getItemDOMElement(itemId); if (itemElement) { itemElement.focus(); } diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.ts index 3d28f2f3e223..ec7c9d9958a5 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.ts @@ -11,7 +11,7 @@ export interface UseTreeViewFocusPublicAPI { * * If the item is the child of a collapsed item, then this method will do nothing. * Make sure to expand the ancestors of the item before calling this method if needed. - * @param {React.SyntheticEvent} event The event source of the action. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {TreeViewItemId} itemId The id of the item to focus. */ focusItem: (event: React.SyntheticEvent, itemId: string) => void; @@ -41,7 +41,7 @@ export interface UseTreeViewFocusInstance extends UseTreeViewFocusPublicAPI { export interface UseTreeViewFocusParameters { /** * Callback fired when tree items are focused. - * @param {React.SyntheticEvent} event The event source of the callback **Warning**: This is a generic event not a focus event. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. **Warning**: This is a generic event not a focus event. * @param {string} itemId The id of the focused item. * @param {string} value of the focused item. */ diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.test.tsx b/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.test.tsx index cc112b345834..efe95a709268 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.test.tsx +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.test.tsx @@ -182,5 +182,23 @@ describeTreeView< expect(response.getItemRoot('1.1.1')).to.have.attribute('aria-disabled', 'true'); }); }); + + describe('getItemDOMElement api method', () => { + it('should return the DOM element of the item', () => { + const response = render({ + items: [{ id: '1' }], + }); + + expect(response.apiRef.current.getItemDOMElement('1')).to.equal(response.getItemRoot('1')); + }); + + it("should return the null when the item doesn't exist", () => { + const response = render({ + items: [{ id: '1' }], + }); + + expect(response.apiRef.current.getItemDOMElement('2')).to.equal(null); + }); + }); }, ); diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.tsx b/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.tsx index c2a77e35bd97..eb439b0b0e88 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.tsx +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.tsx @@ -161,6 +161,15 @@ export const useTreeViewItems: TreeViewPlugin = ({ [state.items.itemOrderedChildrenIds], ); + const getItemDOMElement = (itemId: string) => { + const itemMeta = instance.getItemMeta(itemId); + if (itemMeta == null) { + return null; + } + + return document.getElementById(instance.getTreeItemIdAttribute(itemId, itemMeta.idAttribute)); + }; + const isItemNavigable = (itemId: string) => { if (params.disabledItemsFocusable) { return true; @@ -232,12 +241,14 @@ export const useTreeViewItems: TreeViewPlugin = ({ }), publicAPI: { getItem, + getItemDOMElement, }, instance: { getItemMeta, getItem, getItemsToRender, getItemIndex, + getItemDOMElement, getItemOrderedChildrenIds, isItemDisabled, isItemNavigable, diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.types.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.types.ts index dc234010c855..9e22e97ea665 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.types.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewItems/useTreeViewItems.types.ts @@ -12,10 +12,16 @@ export interface UseTreeViewItemsPublicAPI { /** * Get the item with the given id. * When used in the `SimpleTreeView`, it returns an object with the `id` and `label` properties. - * @param {string} itemId The id of the item to return. + * @param {string} itemId The id of the item to retrieve. * @returns {R} The item with the given id. */ getItem: (itemId: TreeViewItemId) => R; + /** + * Get the DOM element of the item with the given id. + * @param {TreeViewItemId} itemId The id of the item to get the DOM element of. + * @returns {HTMLElement | null} The DOM element of the item with the given id. + */ + getItemDOMElement: (itemId: TreeViewItemId) => HTMLElement | null; } export interface UseTreeViewItemsInstance extends UseTreeViewItemsPublicAPI { diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.ts index 40d6dd3ce6d2..2a414205c2e9 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.ts @@ -107,10 +107,13 @@ export const useTreeViewKeyboardNavigation: TreeViewPlugin< event.preventDefault(); if (params.multiSelect && event.shiftKey) { instance.expandSelectionRange(event, itemId); - } else if (params.multiSelect) { - instance.selectItem(event, itemId, true); } else { - instance.selectItem(event, itemId, false); + instance.selectItem({ + event, + itemId, + keepExistingSelection: params.multiSelect, + shouldBeSelected: params.multiSelect ? undefined : true, + }); } break; } @@ -124,9 +127,9 @@ export const useTreeViewKeyboardNavigation: TreeViewPlugin< } else if (canToggleItemSelection(itemId)) { if (params.multiSelect) { event.preventDefault(); - instance.selectItem(event, itemId, true); + instance.selectItem({ event, itemId, keepExistingSelection: true }); } else if (!instance.isItemSelected(itemId)) { - instance.selectItem(event, itemId, false); + instance.selectItem({ event, itemId }); event.preventDefault(); } } diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.test.tsx b/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.test.tsx index 6bd4595d4c06..3664db627d13 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.test.tsx +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.test.tsx @@ -1,6 +1,6 @@ import { expect } from 'chai'; import { spy } from 'sinon'; -import { fireEvent } from '@mui/internal-test-utils'; +import { fireEvent, act } from '@mui/internal-test-utils'; import { describeTreeView } from 'test/utils/tree-view/describeTreeView'; import { UseTreeViewExpansionSignature, @@ -794,5 +794,136 @@ describeTreeView<[UseTreeViewSelectionSignature, UseTreeViewExpansionSignature]> expect(onItemSelectionToggle.lastCall.args[2]).to.equal(false); }); }); + + describe('selectItem api method', () => { + describe('single selection', () => { + it('should select un-selected item when shouldBeSelected is not defined', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + }); + + act(() => { + response.apiRef.current.selectItem({ itemId: '1', event: {} as any }); + }); + + expect(response.isItemSelected('1')).to.equal(true); + }); + + it('should un-select selected item when shouldBeSelected is not defined', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + defaultSelectedItems: ['1'], + }); + + act(() => { + response.apiRef.current.selectItem({ itemId: '1', event: {} as any }); + }); + + expect(response.isItemSelected('1')).to.equal(false); + }); + + it('should not select an item when disableSelection is true', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + disableSelection: true, + }); + + act(() => { + response.apiRef.current.selectItem({ itemId: '1', event: {} as any }); + }); + + expect(response.isItemSelected('1')).to.equal(false); + }); + + it('should not un-select an item when disableSelection is true', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + defaultSelectedItems: ['1'], + disableSelection: true, + }); + + act(() => { + response.apiRef.current.selectItem({ itemId: '1', event: {} as any }); + }); + + expect(response.isItemSelected('1')).to.equal(true); + }); + }); + + describe('multi selection', () => { + it('should select un-selected item and remove other selected items when shouldBeSelected is not defined', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + defaultSelectedItems: ['2'], + multiSelect: true, + }); + + act(() => { + response.apiRef.current.selectItem({ itemId: '1', event: {} as any }); + }); + + expect(response.getSelectedTreeItems()).to.deep.equal(['1']); + }); + + it('should select un-selected item and keep other selected items when shouldBeSelected is not defined and keepExistingSelection is true', () => { + const response = render({ + items: [{ id: '1' }, { id: '2' }], + defaultSelectedItems: ['2'], + multiSelect: true, + }); + + act(() => { + response.apiRef.current.selectItem({ + itemId: '1', + event: {} as any, + keepExistingSelection: true, + }); + }); + + expect(response.getSelectedTreeItems()).to.deep.equal(['1', '2']); + }); + }); + + describe('onItemSelectionToggle prop', () => { + it('should call call onItemSelectionToggle callback when selecting an item', () => { + const event = {} as any; + const onItemSelectionToggle = spy(); + + const response = render({ + items: [{ id: '1' }, { id: '2' }], + onItemSelectionToggle, + }); + + act(() => { + response.apiRef.current.selectItem({ itemId: '1', event }); + }); + + expect(onItemSelectionToggle.callCount).to.equal(1); + expect(onItemSelectionToggle.lastCall.args[0]).to.equal(event); + expect(onItemSelectionToggle.lastCall.args[1]).to.equal('1'); + expect(onItemSelectionToggle.lastCall.args[2]).to.equal(true); + }); + + it('should call call onItemSelectionToggle callback when un-selecting an item', () => { + const event = {} as any; + const onItemSelectionToggle = spy(); + + const response = render({ + items: [{ id: '1' }, { id: '2' }], + onItemSelectionToggle, + defaultSelectedItems: '1', + }); + + act(() => { + response.apiRef.current.selectItem({ itemId: '1', event }); + }); + + expect(onItemSelectionToggle.callCount).to.equal(1); + expect(onItemSelectionToggle.lastCall.args[0]).to.equal(event); + expect(onItemSelectionToggle.lastCall.args[1]).to.equal('1'); + expect(onItemSelectionToggle.lastCall.args[2]).to.equal(false); + }); + }); + }); }, ); diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.ts index 1de3cebb122d..048f429a4fe0 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.ts @@ -74,12 +74,12 @@ export const useTreeViewSelection: TreeViewPlugin const isItemSelected = (itemId: string) => selectedItemsMap.has(itemId); - const selectItem: UseTreeViewSelectionInstance['selectItem'] = ( + const selectItem: UseTreeViewSelectionInstance['selectItem'] = ({ event, itemId, - keepExistingSelection, - newValue, - ) => { + keepExistingSelection = false, + shouldBeSelected, + }) => { if (params.disableSelection) { return; } @@ -88,16 +88,19 @@ export const useTreeViewSelection: TreeViewPlugin if (keepExistingSelection) { const cleanSelectedItems = convertSelectedItemsToArray(models.selectedItems.value); const isSelectedBefore = instance.isItemSelected(itemId); - if (isSelectedBefore && (newValue === false || newValue == null)) { + if (isSelectedBefore && (shouldBeSelected === false || shouldBeSelected == null)) { newSelected = cleanSelectedItems.filter((id) => id !== itemId); - } else if (!isSelectedBefore && (newValue === true || newValue == null)) { + } else if (!isSelectedBefore && (shouldBeSelected === true || shouldBeSelected == null)) { newSelected = [itemId].concat(cleanSelectedItems); } else { newSelected = cleanSelectedItems; } } else { // eslint-disable-next-line no-lonely-if - if (newValue === false) { + if ( + shouldBeSelected === false || + (shouldBeSelected == null && instance.isItemSelected(itemId)) + ) { newSelected = params.multiSelect ? [] : null; } else { newSelected = params.multiSelect ? [itemId] : itemId; @@ -193,6 +196,9 @@ export const useTreeViewSelection: TreeViewPlugin getRootProps: () => ({ 'aria-multiselectable': params.multiSelect, }), + publicAPI: { + selectItem, + }, instance: { isItemSelected, selectItem, diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.ts index c6fc7cedf450..aa115aed1549 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.ts @@ -3,52 +3,56 @@ import type { DefaultizedProps, TreeViewPluginSignature } from '../../models'; import { UseTreeViewItemsSignature } from '../useTreeViewItems'; import { UseTreeViewExpansionSignature } from '../useTreeViewExpansion'; -export interface UseTreeViewSelectionInstance { +export interface UseTreeViewSelectionPublicAPI { + /** + * Select or deselect an item. + * @param {object} params The params of the method. + * @param {React.SyntheticEvent} params.event The DOM event that triggered the change. + * @param {string} params.itemId The id of the item to select or deselect. + * @param {boolean} params.keepExistingSelection If `true`, the other already selected items will remain selected, otherwise, they will be deselected. This parameter is only relevant when `multiSelect` is `true` + * @param {boolean | undefined} params.shouldBeSelected If `true` the item will be selected. If `false` the item will be deselected. If not defined, the item's new selection status will be the opposite of its current one. + */ + selectItem: (params: { + event: React.SyntheticEvent; + itemId: string; + keepExistingSelection?: boolean; + shouldBeSelected?: boolean; + }) => void; +} + +export interface UseTreeViewSelectionInstance extends UseTreeViewSelectionPublicAPI { /** * Check if an item is selected. * @param {TreeViewItemId} itemId The id of the item to check. * @returns {boolean} `true` if the item is selected, `false` otherwise. */ isItemSelected: (itemId: string) => boolean; - /** - * Select or deselect an item. - * @param {React.SyntheticEvent} event The event source of the callback. - * @param {string} itemId The id of the item to select or deselect. - * @param {boolean} keepExistingSelection If `true`, don't remove the other selected items. - * @param {boolean | undefined} newValue The new selection status of the item. If not defined, the new state will be the opposite of the current state. - */ - selectItem: ( - event: React.SyntheticEvent, - itemId: string, - keepExistingSelection: boolean, - newValue?: boolean, - ) => void; /** * Select all the navigable items in the tree. - * @param {React.SyntheticEvent} event The event source of the callback. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. */ selectAllNavigableItems: (event: React.SyntheticEvent) => void; /** * Expand the current selection range up to the given item. - * @param {React.SyntheticEvent} event The event source of the callback. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {string} itemId The id of the item to expand the selection to. */ expandSelectionRange: (event: React.SyntheticEvent, itemId: string) => void; /** * Expand the current selection range from the first navigable item to the given item. - * @param {React.SyntheticEvent} event The event source of the callback. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {string} itemId The id of the item up to which the selection range should be expanded. */ selectRangeFromStartToItem: (event: React.SyntheticEvent, itemId: string) => void; /** * Expand the current selection range from the given item to the last navigable item. - * @param {React.SyntheticEvent} event The event source of the callback. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {string} itemId The id of the item from which the selection range should be expanded. */ selectRangeFromItemToEnd: (event: React.SyntheticEvent, itemId: string) => void; /** * Update the selection when navigating with ArrowUp / ArrowDown keys. - * @param {React.SyntheticEvent} event The event source of the callback. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {string} currentItemId The id of the active item before the keyboard navigation. * @param {string} nextItemId The id of the active item after the keyboard navigation. */ @@ -92,7 +96,7 @@ export interface UseTreeViewSelectionParameters void; /** * Callback fired when a tree item is selected or deselected. - * @param {React.SyntheticEvent} event The event source of the callback. + * @param {React.SyntheticEvent} event The DOM event that triggered the change. * @param {array} itemId The itemId of the modified item. * @param {array} isSelected `true` if the item has just been selected, `false` if it has just been deselected. */ @@ -129,6 +133,7 @@ export type UseTreeViewSelectionSignature = TreeViewPluginSignature<{ params: UseTreeViewSelectionParameters; defaultizedParams: UseTreeViewSelectionDefaultizedParameters; instance: UseTreeViewSelectionInstance; + publicAPI: UseTreeViewSelectionPublicAPI; contextValue: UseTreeViewSelectionContextValue; modelNames: 'selectedItems'; dependencies: [ diff --git a/packages/x-tree-view/src/internals/useTreeView/extractPluginParamsFromProps.ts b/packages/x-tree-view/src/internals/useTreeView/extractPluginParamsFromProps.ts index d91f18fe1b4d..cc81cb92400e 100644 --- a/packages/x-tree-view/src/internals/useTreeView/extractPluginParamsFromProps.ts +++ b/packages/x-tree-view/src/internals/useTreeView/extractPluginParamsFromProps.ts @@ -71,6 +71,6 @@ export const extractPluginParamsFromProps = < pluginParams: defaultizedPluginParams, slots: slots ?? ({} as any), slotProps: slotProps ?? ({} as any), - experimentalFeatures: experimentalFeatures ?? {}, + experimentalFeatures: experimentalFeatures ?? ({} as any), }; }; diff --git a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts index 54c6e3dc7435..904a6706dcc5 100644 --- a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts +++ b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts @@ -27,6 +27,7 @@ export const useTreeItem2 = < const { runItemPlugins, selection: { multiSelect, disableSelection, checkboxSelection }, + expansion: { expansionTrigger }, disabledItemsFocusable, indentationAtItemLevel, instance, @@ -85,7 +86,9 @@ export const useTreeItem2 = < return; } - interactions.handleExpansion(event); + if (expansionTrigger === 'content') { + interactions.handleExpansion(event); + } if (!checkboxSelection) { interactions.handleSelection(event); @@ -120,6 +123,17 @@ export const useTreeItem2 = < interactions.handleCheckboxSelection(event); }; + const createIconContainerHandleClick = + (otherHandlers: EventHandlers) => (event: React.MouseEvent & MuiCancellableEvent) => { + otherHandlers.onClick?.(event); + if (event.defaultMuiPrevented) { + return; + } + if (expansionTrigger === 'iconContainer') { + interactions.handleExpansion(event); + } + }; + const getRootProps = = {}>( externalProps: ExternalProps = {} as ExternalProps, ): UseTreeItem2RootSlotProps => { @@ -227,6 +241,7 @@ export const useTreeItem2 = < return { ...externalEventHandlers, ...externalProps, + onClick: createIconContainerHandleClick(externalEventHandlers), }; }; diff --git a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts index 6aff48add0b1..8d29f86796e3 100644 --- a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts +++ b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts @@ -6,6 +6,7 @@ import { UseTreeViewSelectionSignature } from '../internals/plugins/useTreeViewS import { UseTreeViewItemsSignature } from '../internals/plugins/useTreeViewItems'; import { UseTreeViewFocusSignature } from '../internals/plugins/useTreeViewFocus'; import { UseTreeViewKeyboardNavigationSignature } from '../internals/plugins/useTreeViewKeyboardNavigation'; +import { UseTreeViewExpansionSignature } from '../internals/plugins/useTreeViewExpansion'; export interface UseTreeItem2Parameters { /** @@ -67,7 +68,9 @@ export interface UseTreeItem2ContentSlotOwnProps { export type UseTreeItem2ContentSlotProps = ExternalProps & UseTreeItem2ContentSlotOwnProps; -export interface UseTreeItem2IconContainerSlotOwnProps {} +export interface UseTreeItem2IconContainerSlotOwnProps { + onClick: MuiCancellableEventHandler; +} export type UseTreeItemIconContainerSlotProps = ExternalProps & UseTreeItem2IconContainerSlotOwnProps; @@ -185,6 +188,7 @@ export interface UseTreeItem2ReturnValue< */ export type UseTreeItem2MinimalPlugins = readonly [ UseTreeViewSelectionSignature, + UseTreeViewExpansionSignature, UseTreeViewItemsSignature, UseTreeViewFocusSignature, UseTreeViewKeyboardNavigationSignature, diff --git a/packages/x-tree-view/tsconfig.json b/packages/x-tree-view/tsconfig.json index 8f928a498c68..8abd09069709 100644 --- a/packages/x-tree-view/tsconfig.json +++ b/packages/x-tree-view/tsconfig.json @@ -5,7 +5,8 @@ "@mui/internal-test-utils/initMatchers", "@mui/material/themeCssVarsAugmentation", "chai-dom", - "mocha" + "mocha", + "node" ], "noImplicitAny": false }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d9f3ea9d6402..ecc587b26896 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,8 +5,8 @@ settings: excludeLinksFromLockfile: false overrides: - react-is: ^18.2.0 - '@types/node': ^18.19.34 + react-is: ^18.3.1 + '@types/node': ^18.19.39 patchedDependencies: babel-plugin-replace-imports@1.0.2: @@ -21,8 +21,8 @@ importers: .: devDependencies: '@argos-ci/core': - specifier: ^2.2.0 - version: 2.2.0 + specifier: ^2.3.0 + version: 2.3.0 '@babel/cli': specifier: ^7.24.7 version: 7.24.7(@babel/core@7.24.7) @@ -73,40 +73,37 @@ importers: version: 11.11.0 '@emotion/react': specifier: ^11.11.4 - version: 11.11.4(@types/react@18.2.60)(react@18.2.0) + version: 11.11.4(@types/react@18.3.3)(react@18.3.1) '@emotion/styled': specifier: ^11.11.5 - version: 11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) - '@mnajdova/enzyme-adapter-react-18': - specifier: ^0.2.0 - version: 0.2.0(enzyme@3.11.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/icons-material': - specifier: ^5.15.20 - version: 5.15.20(@mui/material@5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/internal-markdown': - specifier: ^1.0.5 - version: 1.0.5 + specifier: ^1.0.7 + version: 1.0.7 '@mui/internal-test-utils': - specifier: ^1.0.1 - version: 1.0.1(@babel/core@7.24.7)(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^1.0.4 + version: 1.0.4(@babel/core@7.24.7)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/material': - specifier: ^5.15.20 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/monorepo': - specifier: github:mui/material-ui#22c5206a9e8191b2f81131d6978a0958e55b7032 - version: https://codeload.github.com/mui/material-ui/tar.gz/22c5206a9e8191b2f81131d6978a0958e55b7032(@opentelemetry/api@1.8.0)(encoding@0.1.13) + specifier: github:mui/material-ui#43cb32700af699cd48baaf6922fbe21343f30e2f + version: https://codeload.github.com/mui/material-ui/tar.gz/43cb32700af699cd48baaf6922fbe21343f30e2f(encoding@0.1.13) '@mui/utils': - specifier: ^5.15.20 - version: 5.15.20(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@types/react@18.3.3)(react@18.3.1) '@next/eslint-plugin-next': specifier: 14.2.4 version: 14.2.4 '@octokit/plugin-retry': - specifier: ^6.0.1 - version: 6.0.1(@octokit/core@4.2.4(encoding@0.1.13)) + specifier: ^7.1.1 + version: 7.1.1(@octokit/core@4.2.4(encoding@0.1.13)) '@octokit/rest': - specifier: ^20.1.1 - version: 20.1.1 + specifier: ^21.0.0 + version: 21.0.0 '@playwright/test': specifier: ^1.44.1 version: 1.44.1 @@ -122,9 +119,6 @@ importers: '@types/chai-dom': specifier: ^1.11.3 version: 1.11.3 - '@types/enzyme': - specifier: 3.10.12 - version: 3.10.12 '@types/fs-extra': specifier: ^11.0.4 version: 11.0.4 @@ -132,20 +126,20 @@ importers: specifier: ^6.3.8 version: 6.3.8 '@types/lodash': - specifier: ^4.17.5 - version: 4.17.5 + specifier: ^4.17.6 + version: 4.17.6 '@types/mocha': - specifier: ^10.0.6 - version: 10.0.6 + specifier: ^10.0.7 + version: 10.0.7 '@types/node': - specifier: ^18.19.34 - version: 18.19.34 + specifier: ^18.19.39 + version: 18.19.39 '@types/react': - specifier: ^18.2.60 - version: 18.2.60 + specifier: ^18.3.3 + version: 18.3.3 '@types/react-dom': - specifier: ^18.2.25 - version: 18.2.25 + specifier: ^18.3.0 + version: 18.3.0 '@types/react-test-renderer': specifier: ^18.3.0 version: 18.3.0 @@ -159,23 +153,23 @@ importers: specifier: ^17.0.32 version: 17.0.32 '@typescript-eslint/eslint-plugin': - specifier: ^7.13.1 - version: 7.13.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) + specifier: ^7.15.0 + version: 7.15.0(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3) '@typescript-eslint/parser': - specifier: ^7.13.1 - version: 7.13.1(eslint@8.57.0)(typescript@5.4.5) + specifier: ^7.15.0 + version: 7.15.0(eslint@8.57.0)(typescript@5.5.3) autoprefixer: specifier: ^10.4.19 - version: 10.4.19(postcss@8.4.38) + version: 10.4.19(postcss@8.4.39) axe-core: specifier: 4.9.1 version: 4.9.1 babel-loader: specifier: ^9.1.3 - version: 9.1.3(@babel/core@7.24.7)(webpack@5.92.0(webpack-cli@5.1.4)) + version: 9.1.3(@babel/core@7.24.7)(webpack@5.92.1(webpack-cli@5.1.4)) babel-plugin-istanbul: - specifier: ^6.1.1 - version: 6.1.1 + specifier: ^7.0.0 + version: 7.0.0 babel-plugin-module-resolver: specifier: ^5.0.2 version: 5.0.2 @@ -202,7 +196,7 @@ importers: version: 1.12.0(chai@4.4.1) compression-webpack-plugin: specifier: ^11.1.0 - version: 11.1.0(webpack@5.92.0(webpack-cli@5.1.4)) + version: 11.1.0(webpack@5.92.1(webpack-cli@5.1.4)) concurrently: specifier: ^8.2.2 version: 8.2.2 @@ -213,44 +207,41 @@ importers: specifier: ^7.0.3 version: 7.0.3 danger: - specifier: ^12.3.1 - version: 12.3.1(encoding@0.1.13) + specifier: ^12.3.3 + version: 12.3.3(encoding@0.1.13) date-fns-jalali-v3: - specifier: npm:date-fns-jalali@3.6.0-0 - version: date-fns-jalali@3.6.0-0 + specifier: npm:date-fns-jalali@3.6.0-1 + version: date-fns-jalali@3.6.0-1 date-fns-v3: specifier: npm:date-fns@3.6.0 version: date-fns@3.6.0 - enzyme: - specifier: ^3.11.0 - version: 3.11.0 eslint: specifier: ^8.57.0 version: 8.57.0 eslint-config-airbnb: specifier: ^19.0.4 - version: 19.0.4(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0))(eslint-plugin-jsx-a11y@6.8.0(eslint@8.57.0))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.0))(eslint-plugin-react@7.34.2(eslint@8.57.0))(eslint@8.57.0) + version: 19.0.4(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0))(eslint-plugin-jsx-a11y@6.9.0(eslint@8.57.0))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.0))(eslint-plugin-react@7.34.3(eslint@8.57.0))(eslint@8.57.0) eslint-config-airbnb-typescript: specifier: ^18.0.0 - version: 18.0.0(@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0))(eslint@8.57.0) + version: 18.0.0(@typescript-eslint/eslint-plugin@7.15.0(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0))(eslint@8.57.0) eslint-config-prettier: specifier: ^9.1.0 version: 9.1.0(eslint@8.57.0) eslint-import-resolver-webpack: specifier: ^0.13.8 - version: 0.13.8(eslint-plugin-import@2.29.1)(webpack@5.92.0(webpack-cli@5.1.4)) + version: 0.13.8(eslint-plugin-import@2.29.1)(webpack@5.92.1(webpack-cli@5.1.4)) eslint-plugin-filenames: specifier: ^1.3.2 version: 1.3.2(eslint@8.57.0) eslint-plugin-import: specifier: ^2.29.1 - version: 2.29.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0) + version: 2.29.1(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0) eslint-plugin-jsdoc: - specifier: ^48.2.12 - version: 48.2.12(eslint@8.57.0) + specifier: ^48.5.2 + version: 48.5.2(eslint@8.57.0) eslint-plugin-jsx-a11y: - specifier: ^6.8.0 - version: 6.8.0(eslint@8.57.0) + specifier: ^6.9.0 + version: 6.9.0(eslint@8.57.0) eslint-plugin-material-ui: specifier: workspace:^ version: link:packages/eslint-plugin-material-ui @@ -261,8 +252,8 @@ importers: specifier: ^5.1.3 version: 5.1.3(@types/eslint@8.56.10)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.2) eslint-plugin-react: - specifier: ^7.34.2 - version: 7.34.2(eslint@8.57.0) + specifier: ^7.34.3 + version: 7.34.3(eslint@8.57.0) eslint-plugin-react-compiler: specifier: 0.0.0-experimental-51a85ea-20240601 version: 0.0.0-experimental-51a85ea-20240601(eslint@8.57.0) @@ -286,7 +277,7 @@ importers: version: 14.0.1 html-webpack-plugin: specifier: ^5.6.0 - version: 5.6.0(webpack@5.92.0(webpack-cli@5.1.4)) + version: 5.6.0(webpack@5.92.1(webpack-cli@5.1.4)) jsdom: specifier: 24.1.0 version: 24.1.0 @@ -316,10 +307,10 @@ importers: version: 0.4.0 karma-webpack: specifier: ^5.0.1 - version: 5.0.1(webpack@5.92.0(webpack-cli@5.1.4)) + version: 5.0.1(webpack@5.92.1(webpack-cli@5.1.4)) lerna: - specifier: ^8.1.3 - version: 8.1.3(encoding@0.1.13) + specifier: ^8.1.6 + version: 8.1.6(babel-plugin-macros@3.1.0)(encoding@0.1.13) lodash: specifier: ^4.17.21 version: 4.17.21 @@ -327,8 +318,8 @@ importers: specifier: ^0.13.0 version: 0.13.0 mocha: - specifier: ^10.4.0 - version: 10.4.0 + specifier: ^10.6.0 + version: 10.6.0 moment: specifier: ^2.30.1 version: 2.30.1 @@ -348,17 +339,17 @@ importers: specifier: ^0.11.10 version: 0.11.10 react: - specifier: ^18.2.0 - version: 18.2.0 + specifier: ^18.3.1 + version: 18.3.1 react-dom: - specifier: ^18.2.0 - version: 18.2.0(react@18.2.0) + specifier: ^18.3.1 + version: 18.3.1(react@18.3.1) remark: specifier: ^13.0.0 version: 13.0.0 rimraf: - specifier: ^5.0.7 - version: 5.0.7 + specifier: ^5.0.8 + version: 5.0.8 serve: specifier: ^14.2.3 version: 14.2.3 @@ -370,16 +361,16 @@ importers: version: 3.0.0 string-replace-loader: specifier: ^3.1.0 - version: 3.1.0(webpack@5.92.0(webpack-cli@5.1.4)) + version: 3.1.0(webpack@5.92.1(webpack-cli@5.1.4)) terser-webpack-plugin: specifier: ^5.3.10 - version: 5.3.10(webpack@5.92.0(webpack-cli@5.1.4)) + version: 5.3.10(webpack@5.92.1(webpack-cli@5.1.4)) tsx: - specifier: ^4.15.5 - version: 4.15.5 + specifier: ^4.16.2 + version: 4.16.2 typescript: - specifier: ^5.4.5 - version: 5.4.5 + specifier: ^5.5.3 + version: 5.5.3 unist-util-visit: specifier: ^2.0.3 version: 2.0.3 @@ -387,14 +378,14 @@ importers: specifier: ^0.12.5 version: 0.12.5 webpack: - specifier: ^5.92.0 - version: 5.92.0(webpack-cli@5.1.4) + specifier: ^5.92.1 + version: 5.92.1(webpack-cli@5.1.4) webpack-bundle-analyzer: specifier: ^4.10.2 version: 4.10.2 webpack-cli: specifier: ^5.1.4 - version: 5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0) + version: 5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1) yargs: specifier: ^17.7.2 version: 17.7.2 @@ -412,46 +403,49 @@ importers: version: 7.24.7 '@docsearch/react': specifier: ^3.6.0 - version: 3.6.0(@algolia/client-search@4.22.1)(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(search-insights@2.13.0) + version: 3.6.0(@algolia/client-search@4.22.1)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.13.0) '@emotion/cache': specifier: ^11.11.0 version: 11.11.0 '@emotion/react': specifier: ^11.11.4 - version: 11.11.4(@types/react@18.2.60)(react@18.2.0) + version: 11.11.4(@types/react@18.3.3)(react@18.3.1) '@emotion/server': specifier: ^11.11.0 version: 11.11.0 '@emotion/styled': specifier: ^11.11.5 - version: 11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + version: 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/base': specifier: ^5.0.0-beta.40 - version: 5.0.0-beta.40(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@mui/docs': + specifier: ^6.0.0-alpha.14 + version: 6.0.0-dev.240424162023-9968b4889d(7g77v67zn53nen4txxrs63agbq) '@mui/icons-material': - specifier: ^5.15.20 - version: 5.15.20(@mui/material@5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/joy': - specifier: 5.0.0-beta.32 - version: 5.0.0-beta.32(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^5.0.0-beta.47 + version: 5.0.0-beta.47(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/lab': - specifier: ^5.0.0-alpha.170 - version: 5.0.0-alpha.170(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@mui/material@5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^5.0.0-alpha.171 + version: 5.0.0-alpha.171(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/material': - specifier: ^5.15.20 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/material-nextjs': specifier: ^5.15.11 - version: 5.15.11(@emotion/cache@11.11.0)(@emotion/server@11.11.0)(@mui/material@5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@types/react@18.2.60)(next@14.2.4(@babel/core@7.24.7)(@opentelemetry/api@1.8.0)(@playwright/test@1.44.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0) + version: 5.15.11(@emotion/cache@11.11.0)(@emotion/server@11.11.0)(@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(next@14.2.4(@babel/core@7.24.7)(@opentelemetry/api@1.8.0)(@playwright/test@1.44.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) '@mui/styles': - specifier: ^5.15.20 - version: 5.15.20(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@types/react@18.3.3)(react@18.3.1) '@mui/system': - specifier: ^5.15.20 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/utils': - specifier: ^5.15.20 - version: 5.15.20(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@types/react@18.3.3)(react@18.3.1) '@mui/x-charts': specifier: workspace:* version: link:../packages/x-charts/build @@ -478,13 +472,16 @@ importers: version: link:../packages/x-tree-view/build '@react-spring/web': specifier: ^9.7.3 - version: 9.7.3(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 9.7.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@tanstack/query-core': + specifier: ^5.50.1 + version: 5.50.1 ast-types: specifier: ^0.14.2 version: 0.14.2 autoprefixer: specifier: ^10.4.19 - version: 10.4.19(postcss@8.4.38) + version: 10.4.19(postcss@8.4.39) babel-plugin-module-resolver: specifier: ^5.0.2 version: 5.0.2 @@ -518,6 +515,9 @@ importers: cross-env: specifier: ^7.0.3 version: 7.0.3 + d3-scale-chromatic: + specifier: ^3.1.0 + version: 3.1.0 date-fns: specifier: ^2.30.0 version: 2.30.0 @@ -537,8 +537,8 @@ importers: specifier: ^3.1.0 version: 3.1.0 jscodeshift: - specifier: 0.13.1 - version: 0.13.1(@babel/preset-env@7.24.7(@babel/core@7.24.7)) + specifier: 0.16.1 + version: 0.16.1(@babel/preset-env@7.24.7(@babel/core@7.24.7)) lodash: specifier: ^4.17.21 version: 4.17.21 @@ -550,7 +550,7 @@ importers: version: 1.5.0 markdown-to-jsx: specifier: ^7.4.7 - version: 7.4.7(react@18.2.0) + version: 7.4.7(react@18.3.1) moment: specifier: ^2.30.1 version: 2.30.1 @@ -558,20 +558,20 @@ importers: specifier: ^2.1.2 version: 2.1.2 moment-jalaali: - specifier: ^0.10.0 - version: 0.10.0 + specifier: ^0.10.1 + version: 0.10.1 moment-timezone: specifier: ^0.5.45 version: 0.5.45 next: specifier: ^14.2.4 - version: 14.2.4(@babel/core@7.24.7)(@opentelemetry/api@1.8.0)(@playwright/test@1.44.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 14.2.4(@babel/core@7.24.7)(@opentelemetry/api@1.8.0)(@playwright/test@1.44.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) nprogress: specifier: ^0.2.0 version: 0.2.0 postcss: - specifier: ^8.4.38 - version: 8.4.38 + specifier: ^8.4.39 + version: 8.4.39 prismjs: specifier: ^1.29.0 version: 1.29.0 @@ -579,44 +579,44 @@ importers: specifier: ^15.8.1 version: 15.8.1 react: - specifier: ^18.2.0 - version: 18.2.0 + specifier: ^18.3.1 + version: 18.3.1 react-docgen: specifier: ^5.4.3 version: 5.4.3 react-dom: - specifier: ^18.2.0 - version: 18.2.0(react@18.2.0) + specifier: ^18.3.1 + version: 18.3.1(react@18.3.1) react-hook-form: - specifier: ^7.52.0 - version: 7.52.0(react@18.2.0) + specifier: ^7.52.1 + version: 7.52.1(react@18.3.1) react-is: - specifier: ^18.2.0 - version: 18.2.0 + specifier: ^18.3.1 + version: 18.3.1 react-router: - specifier: ^6.23.1 - version: 6.23.1(react@18.2.0) + specifier: ^6.24.1 + version: 6.24.1(react@18.3.1) react-router-dom: - specifier: ^6.23.1 - version: 6.23.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^6.24.1 + version: 6.24.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-runner: specifier: ^1.0.5 - version: 1.0.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 1.0.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-simple-code-editor: - specifier: ^0.13.1 - version: 0.13.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^0.14.1 + version: 0.14.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) recast: specifier: ^0.23.9 version: 0.23.9 rimraf: - specifier: ^5.0.7 - version: 5.0.7 + specifier: ^5.0.8 + version: 5.0.8 rxjs: specifier: ^7.8.1 version: 7.8.1 styled-components: specifier: ^6.1.11 - version: 6.1.11(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 6.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) stylis: specifier: ^4.3.2 version: 4.3.2 @@ -637,20 +637,23 @@ importers: specifier: ^1.0.7 version: 1.0.7 '@mui/internal-scripts': - specifier: ^1.0.10 - version: 1.0.10 + specifier: ^1.0.12 + version: 1.0.12 '@types/chance': specifier: ^1.1.6 version: 1.1.6 '@types/d3-scale': specifier: ^4.0.8 version: 4.0.8 + '@types/d3-scale-chromatic': + specifier: ^3.0.3 + version: 3.0.3 '@types/doctrine': specifier: ^0.0.9 version: 0.0.9 '@types/lodash': - specifier: ^4.17.5 - version: 4.17.5 + specifier: ^4.17.6 + version: 4.17.6 '@types/luxon': specifier: ^3.4.2 version: 3.4.2 @@ -661,8 +664,8 @@ importers: specifier: ^0.7.9 version: 0.7.9 '@types/react-dom': - specifier: 18.2.25 - version: 18.2.25 + specifier: ^18.3.0 + version: 18.3.0 '@types/react-router-dom': specifier: ^5.3.3 version: 5.3.3 @@ -671,7 +674,7 @@ importers: version: 4.2.6 '@types/webpack-bundle-analyzer': specifier: ^4.7.0 - version: 4.7.0(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0)) + version: 4.7.0(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1)) gm: specifier: ^1.25.0 version: 1.25.0 @@ -685,11 +688,11 @@ importers: specifier: ^8.56.10 version: 8.56.10 '@typescript-eslint/parser': - specifier: ^7.13.1 - version: 7.13.1(eslint@8.57.0)(typescript@5.4.5) + specifier: ^7.15.0 + version: 7.15.0(eslint@8.57.0)(typescript@5.5.3) '@typescript-eslint/utils': - specifier: ^7.13.1 - version: 7.13.1(eslint@8.57.0)(typescript@5.4.5) + specifier: ^7.15.0 + version: 7.15.0(eslint@8.57.0)(typescript@5.5.3) packages/x-charts: dependencies: @@ -698,28 +701,28 @@ importers: version: 7.24.7 '@emotion/react': specifier: ^11.9.0 - version: 11.11.4(@types/react@18.2.60)(react@18.2.0) + version: 11.11.4(@types/react@18.3.3)(react@18.3.1) '@emotion/styled': specifier: ^11.8.1 - version: 11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + version: 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/base': specifier: ^5.0.0-beta.40 - version: 5.0.0-beta.40(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/material': specifier: ^5.15.14 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/system': - specifier: ^5.15.20 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/utils': - specifier: ^5.15.20 - version: 5.15.20(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@types/react@18.3.3)(react@18.3.1) '@react-spring/rafz': specifier: ^9.7.3 version: 9.7.3 '@react-spring/web': specifier: ^9.7.3 - version: 9.7.3(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 9.7.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) clsx: specifier: ^2.1.1 version: 2.1.1 @@ -743,20 +746,20 @@ importers: version: 15.8.1 react: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0 + version: 18.3.1 react-dom: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0(react@18.2.0) + version: 18.3.1(react@18.3.1) devDependencies: '@mui/internal-test-utils': - specifier: ^1.0.1 - version: 1.0.1(@babel/core@7.24.7)(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^1.0.4 + version: 1.0.4(@babel/core@7.24.7)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spring/core': specifier: ^9.7.3 - version: 9.7.3(react@18.2.0) + version: 9.7.3(react@18.3.1) '@react-spring/shared': specifier: ^9.7.3 - version: 9.7.3(react@18.2.0) + version: 9.7.3(react@18.3.1) '@types/d3-color': specifier: ^3.1.3 version: 3.1.3 @@ -779,8 +782,8 @@ importers: specifier: ^3.1.3 version: 3.1.3 rimraf: - specifier: ^5.0.7 - version: 5.0.7 + specifier: ^5.0.8 + version: 5.0.8 publishDirectory: build packages/x-charts-pro: @@ -790,22 +793,22 @@ importers: version: 7.24.7 '@emotion/react': specifier: ^11.9.0 - version: 11.11.4(@types/react@18.2.60)(react@18.2.0) + version: 11.11.4(@types/react@18.3.3)(react@18.3.1) '@emotion/styled': specifier: ^11.8.1 - version: 11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + version: 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/base': specifier: ^5.0.0-beta.40 - version: 5.0.0-beta.40(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/material': specifier: ^5.15.14 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/system': - specifier: ^5.15.20 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/utils': - specifier: ^5.15.20 - version: 5.15.20(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@types/react@18.3.3)(react@18.3.1) '@mui/x-charts': specifier: workspace:* version: link:../x-charts/build @@ -817,7 +820,7 @@ importers: version: 9.7.3 '@react-spring/web': specifier: ^9.7.3 - version: 9.7.3(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 9.7.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) clsx: specifier: ^2.1.1 version: 2.1.1 @@ -841,17 +844,17 @@ importers: version: 15.8.1 react: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0 + version: 18.3.1 react-dom: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0(react@18.2.0) + version: 18.3.1(react@18.3.1) devDependencies: '@react-spring/core': specifier: ^9.7.3 - version: 9.7.3(react@18.2.0) + version: 9.7.3(react@18.3.1) '@react-spring/shared': specifier: ^9.7.3 - version: 9.7.3(react@18.2.0) + version: 9.7.3(react@18.3.1) '@types/d3-color': specifier: ^3.1.3 version: 3.1.3 @@ -874,8 +877,8 @@ importers: specifier: ^3.1.3 version: 3.1.3 rimraf: - specifier: ^5.0.7 - version: 5.0.7 + specifier: ^5.0.8 + version: 5.0.8 publishDirectory: build packages/x-codemod: @@ -890,17 +893,14 @@ importers: specifier: ^7.24.7 version: 7.24.7 jscodeshift: - specifier: 0.13.1 - version: 0.13.1(@babel/preset-env@7.24.7(@babel/core@7.24.7)) - jscodeshift-add-imports: - specifier: ^1.0.10 - version: 1.0.10(jscodeshift@0.13.1(@babel/preset-env@7.24.7(@babel/core@7.24.7))) + specifier: 0.16.1 + version: 0.16.1(@babel/preset-env@7.24.7(@babel/core@7.24.7)) yargs: specifier: ^17.7.2 version: 17.7.2 devDependencies: '@types/jscodeshift': - specifier: ^0.11.5 + specifier: ^0.11.11 version: 0.11.11 dayjs: specifier: ^1.11.11 @@ -909,8 +909,8 @@ importers: specifier: ^0.5.45 version: 0.5.45 rimraf: - specifier: ^5.0.7 - version: 5.0.7 + specifier: ^5.0.8 + version: 5.0.8 publishDirectory: build packages/x-data-grid: @@ -920,13 +920,16 @@ importers: version: 7.24.7 '@mui/material': specifier: ^5.15.14 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/system': - specifier: ^5.15.20 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/utils': - specifier: ^5.15.20 - version: 5.15.20(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@types/react@18.3.3)(react@18.3.1) + '@mui/x-internals': + specifier: workspace:* + version: link:../x-internals/build clsx: specifier: ^2.1.1 version: 2.1.1 @@ -935,29 +938,29 @@ importers: version: 15.8.1 react: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0 + version: 18.3.1 react-dom: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0(react@18.2.0) + version: 18.3.1(react@18.3.1) reselect: specifier: ^4.1.8 version: 4.1.8 devDependencies: '@mui/internal-test-utils': - specifier: ^1.0.1 - version: 1.0.1(@babel/core@7.24.7)(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^1.0.4 + version: 1.0.4(@babel/core@7.24.7)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/joy': - specifier: 5.0.0-beta.32 - version: 5.0.0-beta.32(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^5.0.0-beta.47 + version: 5.0.0-beta.47(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/types': specifier: ^7.2.14 - version: 7.2.14(@types/react@18.2.60) + version: 7.2.14(@types/react@18.3.3) '@types/prop-types': specifier: ^15.7.12 version: 15.7.12 rimraf: - specifier: ^5.0.7 - version: 5.0.7 + specifier: ^5.0.8 + version: 5.0.8 publishDirectory: build packages/x-data-grid-generator: @@ -967,13 +970,13 @@ importers: version: 7.24.7 '@mui/base': specifier: ^5.0.0-beta.40 - version: 5.0.0-beta.40(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/icons-material': specifier: ^5.4.1 - version: 5.15.20(@mui/material@5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + version: 5.16.0(@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/material': specifier: ^5.15.14 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/x-data-grid-premium': specifier: workspace:* version: link:../x-data-grid-premium/build @@ -984,21 +987,18 @@ importers: specifier: ^2.1.1 version: 2.1.1 lru-cache: - specifier: ^7.18.3 - version: 7.18.3 + specifier: ^10.3.0 + version: 10.3.0 react: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0 + version: 18.3.1 devDependencies: '@types/chance': specifier: ^1.1.6 version: 1.1.6 - '@types/lru-cache': - specifier: ^7.10.10 - version: 7.10.10 rimraf: - specifier: ^5.0.7 - version: 5.0.7 + specifier: ^5.0.8 + version: 5.0.8 publishDirectory: build packages/x-data-grid-premium: @@ -1008,19 +1008,22 @@ importers: version: 7.24.7 '@mui/material': specifier: ^5.15.14 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/system': - specifier: ^5.15.20 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/utils': - specifier: ^5.15.20 - version: 5.15.20(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@types/react@18.3.3)(react@18.3.1) '@mui/x-data-grid': specifier: workspace:* version: link:../x-data-grid/build '@mui/x-data-grid-pro': specifier: workspace:* version: link:../x-data-grid-pro/build + '@mui/x-internals': + specifier: workspace:* + version: link:../x-internals/build '@mui/x-license': specifier: workspace:* version: link:../x-license/build @@ -1038,17 +1041,17 @@ importers: version: 15.8.1 react: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0 + version: 18.3.1 react-dom: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0(react@18.2.0) + version: 18.3.1(react@18.3.1) reselect: specifier: ^4.1.8 version: 4.1.8 devDependencies: '@mui/internal-test-utils': - specifier: ^1.0.1 - version: 1.0.1(@babel/core@7.24.7)(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^1.0.4 + version: 1.0.4(@babel/core@7.24.7)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/prop-types': specifier: ^15.7.12 version: 15.7.12 @@ -1056,8 +1059,8 @@ importers: specifier: ^2.30.0 version: 2.30.0 rimraf: - specifier: ^5.0.7 - version: 5.0.7 + specifier: ^5.0.8 + version: 5.0.8 publishDirectory: build packages/x-data-grid-pro: @@ -1067,16 +1070,19 @@ importers: version: 7.24.7 '@mui/material': specifier: ^5.15.14 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/system': - specifier: ^5.15.20 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/utils': - specifier: ^5.15.20 - version: 5.15.20(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@types/react@18.3.3)(react@18.3.1) '@mui/x-data-grid': specifier: workspace:* version: link:../x-data-grid/build + '@mui/x-internals': + specifier: workspace:* + version: link:../x-internals/build '@mui/x-license': specifier: workspace:* version: link:../x-license/build @@ -1091,23 +1097,23 @@ importers: version: 15.8.1 react: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0 + version: 18.3.1 react-dom: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0(react@18.2.0) + version: 18.3.1(react@18.3.1) reselect: specifier: ^4.1.8 version: 4.1.8 devDependencies: '@mui/internal-test-utils': - specifier: ^1.0.1 - version: 1.0.1(@babel/core@7.24.7)(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^1.0.4 + version: 1.0.4(@babel/core@7.24.7)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/prop-types': specifier: ^15.7.12 version: 15.7.12 rimraf: - specifier: ^5.0.7 - version: 5.0.7 + specifier: ^5.0.8 + version: 5.0.8 publishDirectory: build packages/x-date-pickers: @@ -1117,22 +1123,22 @@ importers: version: 7.24.7 '@emotion/react': specifier: ^11.9.0 - version: 11.11.4(@types/react@18.2.60)(react@18.2.0) + version: 11.11.4(@types/react@18.3.3)(react@18.3.1) '@emotion/styled': specifier: ^11.8.1 - version: 11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + version: 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/base': specifier: ^5.0.0-beta.40 - version: 5.0.0-beta.40(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/material': specifier: ^5.15.14 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/system': - specifier: ^5.15.20 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/utils': - specifier: ^5.15.20 - version: 5.15.20(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@types/react@18.3.3)(react@18.3.1) '@types/react-transition-group': specifier: ^4.4.10 version: 4.4.10 @@ -1144,17 +1150,17 @@ importers: version: 15.8.1 react: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0 + version: 18.3.1 react-dom: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0(react@18.2.0) + version: 18.3.1(react@18.3.1) react-transition-group: specifier: ^4.4.5 - version: 4.4.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@mui/internal-test-utils': - specifier: ^1.0.1 - version: 1.0.1(@babel/core@7.24.7)(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^1.0.4 + version: 1.0.4(@babel/core@7.24.7)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/luxon': specifier: ^3.4.2 version: 3.4.2 @@ -1186,14 +1192,14 @@ importers: specifier: ^2.1.2 version: 2.1.2 moment-jalaali: - specifier: ^0.10.0 - version: 0.10.0 + specifier: ^0.10.1 + version: 0.10.1 moment-timezone: specifier: ^0.5.45 version: 0.5.45 rimraf: - specifier: ^5.0.7 - version: 5.0.7 + specifier: ^5.0.8 + version: 5.0.8 publishDirectory: build packages/x-date-pickers-pro: @@ -1203,22 +1209,22 @@ importers: version: 7.24.7 '@emotion/react': specifier: ^11.9.0 - version: 11.11.4(@types/react@18.2.60)(react@18.2.0) + version: 11.11.4(@types/react@18.3.3)(react@18.3.1) '@emotion/styled': specifier: ^11.8.1 - version: 11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + version: 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/base': specifier: ^5.0.0-beta.40 - version: 5.0.0-beta.40(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/material': specifier: ^5.15.14 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/system': - specifier: ^5.15.20 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/utils': - specifier: ^5.15.20 - version: 5.15.20(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@types/react@18.3.3)(react@18.3.1) '@mui/x-date-pickers': specifier: workspace:* version: link:../x-date-pickers/build @@ -1233,23 +1239,23 @@ importers: version: 2.1.2 moment-jalaali: specifier: ^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0 - version: 0.10.0 + version: 0.10.1 prop-types: specifier: ^15.8.1 version: 15.8.1 react: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0 + version: 18.3.1 react-dom: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0(react@18.2.0) + version: 18.3.1(react@18.3.1) react-transition-group: specifier: ^4.4.5 - version: 4.4.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@mui/internal-test-utils': - specifier: ^1.0.1 - version: 1.0.1(@babel/core@7.24.7)(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^1.0.4 + version: 1.0.4(@babel/core@7.24.7)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/luxon': specifier: ^3.4.2 version: 3.4.2 @@ -1272,8 +1278,28 @@ importers: specifier: ^2.30.1 version: 2.30.1 rimraf: - specifier: ^5.0.7 - version: 5.0.7 + specifier: ^5.0.8 + version: 5.0.8 + publishDirectory: build + + packages/x-internals: + dependencies: + '@babel/runtime': + specifier: ^7.24.7 + version: 7.24.7 + '@mui/utils': + specifier: ^5.16.0 + version: 5.16.0(@types/react@18.3.3)(react@18.3.1) + react: + specifier: ^17.0.0 || ^18.0.0 + version: 18.3.1 + devDependencies: + '@mui/internal-test-utils': + specifier: ^1.0.4 + version: 1.0.4(@babel/core@7.24.7)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rimraf: + specifier: ^5.0.8 + version: 5.0.8 publishDirectory: build packages/x-license: @@ -1282,18 +1308,18 @@ importers: specifier: ^7.24.7 version: 7.24.7 '@mui/utils': - specifier: ^5.15.20 - version: 5.15.20(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@types/react@18.3.3)(react@18.3.1) react: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0 + version: 18.3.1 devDependencies: '@mui/internal-test-utils': - specifier: ^1.0.1 - version: 1.0.1(@babel/core@7.24.7)(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^1.0.4 + version: 1.0.4(@babel/core@7.24.7)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rimraf: - specifier: ^5.0.7 - version: 5.0.7 + specifier: ^5.0.8 + version: 5.0.8 publishDirectory: build packages/x-tree-view: @@ -1303,22 +1329,22 @@ importers: version: 7.24.7 '@emotion/react': specifier: ^11.9.0 - version: 11.11.4(@types/react@18.2.60)(react@18.2.0) + version: 11.11.4(@types/react@18.3.3)(react@18.3.1) '@emotion/styled': specifier: ^11.8.1 - version: 11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + version: 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/base': specifier: ^5.0.0-beta.40 - version: 5.0.0-beta.40(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/material': specifier: ^5.15.14 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/system': - specifier: ^5.15.20 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/utils': - specifier: ^5.15.20 - version: 5.15.20(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@types/react@18.3.3)(react@18.3.1) '@types/react-transition-group': specifier: ^4.4.10 version: 4.4.10 @@ -1330,23 +1356,23 @@ importers: version: 15.8.1 react: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0 + version: 18.3.1 react-dom: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0(react@18.2.0) + version: 18.3.1(react@18.3.1) react-transition-group: specifier: ^4.4.5 - version: 4.4.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@mui/internal-test-utils': - specifier: ^1.0.1 - version: 1.0.1(@babel/core@7.24.7)(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^1.0.4 + version: 1.0.4(@babel/core@7.24.7)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/prop-types': specifier: ^15.7.12 version: 15.7.12 rimraf: - specifier: ^5.0.7 - version: 5.0.7 + specifier: ^5.0.8 + version: 5.0.8 publishDirectory: build packages/x-tree-view-pro: @@ -1356,22 +1382,22 @@ importers: version: 7.24.7 '@emotion/react': specifier: ^11.9.0 - version: 11.11.4(@types/react@18.2.60)(react@18.2.0) + version: 11.11.4(@types/react@18.3.3)(react@18.3.1) '@emotion/styled': specifier: ^11.8.1 - version: 11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + version: 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/base': specifier: ^5.0.0-beta.40 - version: 5.0.0-beta.40(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/material': specifier: ^5.15.14 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/system': - specifier: ^5.15.20 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) '@mui/utils': - specifier: ^5.15.20 - version: 5.15.20(@types/react@18.2.60)(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@types/react@18.3.3)(react@18.3.1) '@mui/x-license': specifier: workspace:* version: link:../x-license/build @@ -1389,20 +1415,20 @@ importers: version: 15.8.1 react: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0 + version: 18.3.1 react-dom: specifier: ^17.0.0 || ^18.0.0 - version: 18.2.0(react@18.2.0) + version: 18.3.1(react@18.3.1) react-transition-group: specifier: ^4.4.5 - version: 4.4.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@mui/internal-test-utils': - specifier: ^1.0.1 - version: 1.0.1(@babel/core@7.24.7)(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^1.0.4 + version: 1.0.4(@babel/core@7.24.7)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rimraf: - specifier: ^5.0.7 - version: 5.0.7 + specifier: ^5.0.8 + version: 5.0.8 test: devDependencies: @@ -1414,10 +1440,10 @@ importers: version: 11.11.0 '@emotion/react': specifier: ^11.11.4 - version: 11.11.4(@types/react@18.2.60)(react@18.2.0) + version: 11.11.4(@types/react@18.3.3)(react@18.3.1) '@mui/material': - specifier: ^5.15.20 - version: 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^5.16.0 + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/x-data-grid': specifier: workspace:* version: link:../packages/x-data-grid/build @@ -1438,7 +1464,7 @@ importers: version: 1.44.1 '@react-spring/web': specifier: ^9.7.3 - version: 9.7.3(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 9.7.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/chai': specifier: ^4.3.16 version: 4.3.16 @@ -1452,8 +1478,8 @@ importers: specifier: ^15.7.12 version: 15.7.12 '@types/react': - specifier: ^18.2.60 - version: 18.2.60 + specifier: ^18.3.3 + version: 18.3.3 chai: specifier: ^4.4.1 version: 4.4.1 @@ -1464,20 +1490,20 @@ importers: specifier: ^2.30.1 version: 2.30.1 moment-jalaali: - specifier: ^0.10.0 - version: 0.10.0 + specifier: ^0.10.1 + version: 0.10.1 prop-types: specifier: ^15.8.1 version: 15.8.1 react: - specifier: ^18.2.0 - version: 18.2.0 + specifier: ^18.3.1 + version: 18.3.1 react-dom: - specifier: ^18.2.0 - version: 18.2.0(react@18.2.0) + specifier: ^18.3.1 + version: 18.3.1(react@18.3.1) react-router-dom: - specifier: ^6.23.1 - version: 6.23.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^6.24.1 + version: 6.24.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) stylis: specifier: ^4.3.2 version: 4.3.2 @@ -1557,8 +1583,8 @@ packages: resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} engines: {node: '>=6.0.0'} - '@argos-ci/core@2.2.0': - resolution: {integrity: sha512-T5W37CZ6HZjRcVAXuPj0wUB/Fm4VdwLvKpQL9yqSwiJganeNz7u8AFYJ30ujSUJS1jdUViW5TNnmsgDjuvGyTQ==} + '@argos-ci/core@2.3.0': + resolution: {integrity: sha512-0mHncBeOD7GFYfGZYUEcDgLyzsvPyxK/L1MROfAurFeWcw89ODG24JEdPsECtZBSCZMmMcK8XqeJIJkZsnDGZA==} engines: {node: '>=18.0.0'} '@argos-ci/util@2.0.0': @@ -1735,27 +1761,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-proposal-class-properties@7.18.6': - resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} - engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead. - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-proposal-nullish-coalescing-operator@7.18.6': - resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} - engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead. - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-proposal-optional-chaining@7.21.0': - resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==} - engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead. - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-proposal-private-methods@7.18.6': resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} engines: {node: '>=6.9.0'} @@ -1795,8 +1800,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-flow@7.23.3': - resolution: {integrity: sha512-YZiAIpkJAwQXBJLIQbRFayR5c+gJ35Vcz3bg954k7cd73zqjvhacJuL9RbrzPz8qPmZdgqP6EUKwy0PCNhaaPA==} + '@babel/plugin-syntax-flow@7.24.7': + resolution: {integrity: sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1973,8 +1978,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-flow-strip-types@7.23.3': - resolution: {integrity: sha512-26/pQTf9nQSNVJCrLB1IkHUKyPxR+lMrH2QDPG89+Znu9rAMbtrybdbWeE9bb7gzjmE5iXHEY+e0HUwM6Co93Q==} + '@babel/plugin-transform-flow-strip-types@7.24.7': + resolution: {integrity: sha512-cjRKJ7FobOH2eakx7Ja+KpJRj8+y+/SiB3ooYm/n2UJfxu0oEaOoxOinitkJcPqv9KxS0kxTGPUaR7L2XcXDXA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2225,8 +2230,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/preset-flow@7.23.3': - resolution: {integrity: sha512-7yn6hl8RIv+KNk6iIrGZ+D06VhVY35wLVf23Cz/mMu1zOr7u4MMP4j0nZ9tLf8+4ZFpnib8cFYgB/oYg9hfswA==} + '@babel/preset-flow@7.24.7': + resolution: {integrity: sha512-NL3Lo0NorCU607zU3NwRyJbpaB6E3t0xtd3LfAQKDfkeX4/ggcDXvkmkW42QWT5owUeW/jAe4hn+2qvkV1IbfQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2566,8 +2571,8 @@ packages: resolution: {integrity: sha512-9KMSDtJ/sIov+5pcH+CAfiJXSiuYgN0KLKQFg0HHWR2DwcjGYkcbmhoZcWsaOWOqq4kihN1l7wX91UoRxxKKTQ==} engines: {node: '>=18.0.0'} - '@googleapis/sheets@7.0.1': - resolution: {integrity: sha512-n+ctnqtKd24Dd4X6yE2NSq47iodqxvaaRcxNdqLIkV+4GQs0u8UnF7Cj9Bqi8/sd9kdLZV70H5R7q/lzVEhpmw==} + '@googleapis/sheets@8.0.0': + resolution: {integrity: sha512-EwLC+bMLTz3n2EDJMhMdrNR+aTxDBPpcq3k6Ibc4eKrp8UbytNAEB0VgfQFOGJN7+BTCcjiojt08O/cwn+YnHg==} engines: {node: '>=12.0.0'} '@humanwhocodes/config-array@0.11.14': @@ -2704,6 +2709,9 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + '@isaacs/string-locale-compare@1.1.0': + resolution: {integrity: sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==} + '@istanbuljs/load-nyc-config@1.1.0': resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} engines: {node: '>=8'} @@ -2737,17 +2745,10 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - '@lerna/create@8.1.3': - resolution: {integrity: sha512-JFvIYrlvR8Txa8h7VZx8VIQDltukEKOKaZL/muGO7Q/5aE2vjOKHsD/jkWYe/2uFy1xv37ubdx17O1UXQNadPg==} + '@lerna/create@8.1.6': + resolution: {integrity: sha512-z7CjDSWFKS6cqydxP2XDrnmp1MYavSk2sU70ku1uo/38SZvFeUlEAkV6evxc2QJOqWQFsGKOO26zX2DBnQ45YQ==} engines: {node: '>=18.0.0'} - '@mnajdova/enzyme-adapter-react-18@0.2.0': - resolution: {integrity: sha512-BOnjlVa7FHI1YUnYe+FdUtQu6szI1wLJ+C1lHyqmF3T9gu/J/WCYqqcD44dPkrU+8eYvvk/gQducsqna4HFiAg==} - peerDependencies: - enzyme: ^3.0.0 - react: ^18.0.0 - react-dom: ^18.0.0 - '@mui/base@5.0.0-beta.40': resolution: {integrity: sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==} engines: {node: '>=12.0.0'} @@ -2759,11 +2760,26 @@ packages: '@types/react': optional: true - '@mui/core-downloads-tracker@5.15.20': - resolution: {integrity: sha512-DoL2ppgldL16utL8nNyj/P12f8mCNdx/Hb/AJnX9rLY4b52hCMIx1kH83pbXQ6uMy6n54M3StmEbvSGoj2OFuA==} + '@mui/core-downloads-tracker@5.16.0': + resolution: {integrity: sha512-8SLffXYPRVpcZx5QzxNE8fytTqzp+IuU3deZbQWg/vSaTlDpR5YVrQ4qQtXTi5cRdhOufV5INylmwlKK+//nPw==} + + '@mui/docs@6.0.0-dev.240424162023-9968b4889d': + resolution: {integrity: sha512-F1K/DUvuJ5R18eG9K7m9zVfyC4qgujz7FjGyKdo/XGOfFUsKiKcEDg18DUN174mNqwc5MHCzo/sb9reP9V1K7w==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@mui/base': '*' + '@mui/icons-material': ^5.0.0 + '@mui/material': ^5.0.0 + '@mui/system': ^5.0.0 + '@types/react': ^17.0.0 || ^18.0.0 + next: ^13.5.1 || ^14 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true - '@mui/icons-material@5.15.20': - resolution: {integrity: sha512-oGcKmCuHaYbAAoLN67WKSXtHmEgyWcJToT1uRtmPyxMj9N5uqwc/mRtEnst4Wj/eGr+zYH2FiZQ79v9k7kSk1Q==} + '@mui/icons-material@5.16.0': + resolution: {integrity: sha512-6ISoOhkp9w5gD0PEW9JklrcbyARDkFWNTBdwXZ1Oy5IGlyu9B0zG0hnUIe4H17IaF1Vgj6C8VI+v4tkSdK0veg==} engines: {node: '>=12.0.0'} peerDependencies: '@mui/material': ^5.0.0 @@ -2776,20 +2792,20 @@ packages: '@mui/internal-docs-utils@1.0.7': resolution: {integrity: sha512-vHplixLKu17U7Wa3RDbGv9C3FmXniJKywyZEIeJaTG4ikvl+iWI+BuZPCNniJwj0HSxu3thbyPIrBXijh7j+Xg==} - '@mui/internal-markdown@1.0.5': - resolution: {integrity: sha512-5Hv6XypPsVW8PHZiJvGl/KT+BdyyR9o7YGBQCM5KYitHtNSHHpTkfsjimhyKbZHI4jPNzWFzTjibYJRPpW8Jdw==} + '@mui/internal-markdown@1.0.7': + resolution: {integrity: sha512-DpCOZ+TQPx3GXnA7PY8qq7yUsjUpFu3SzYSBMvmwF/KPHj7prvudSFjg+0qjwQOI7l7fapyfkn6+S8QbzxEOrg==} - '@mui/internal-scripts@1.0.10': - resolution: {integrity: sha512-Cj07lzcM2ozjTF7BYIhSaCwy6MYzAUB7HxC3d7lex46dE9N6zsG/48S0Hs5qSMrWOyUnNXI/5Y/SypgL/Ss8ng==} + '@mui/internal-scripts@1.0.12': + resolution: {integrity: sha512-7W2OBXKwtDjxFPxQZK796lDDsRtDA/9xWmpmHJMXSJY+gG+8sH6kwsU7pNdf2uB/uC0uCY9kxfWpr+9+0JI5EA==} - '@mui/internal-test-utils@1.0.1': - resolution: {integrity: sha512-Au9VZoJtlCdw3oSE6YQldS+uCmD5FQWn6hBPq5Vgf04PdndqQyRGKs5YkNZYizG7Nl8JvjNihlDM13vOiltxhQ==} + '@mui/internal-test-utils@1.0.4': + resolution: {integrity: sha512-7scv+UvpqEcFE0vTI6GYXqIQDMbbZKkB0G96gPy5QhMC+zbMHkY5PaOlp+/M1Quu8TW10nmV9gxwiX37o/jg0A==} peerDependencies: react: ^18.2.0 react-dom: ^18.2.0 - '@mui/joy@5.0.0-beta.32': - resolution: {integrity: sha512-QJW5Mu2GTJUX4sXjxt4nQBugpJAiSkUT49S/bwoKCCWx8bCfsEyplTzZPK+FraweiGhGgZWExWOTAPpxH83RUQ==} + '@mui/joy@5.0.0-beta.47': + resolution: {integrity: sha512-iWTuabnVg8XA5oBB5d6inNbCfYBhE0oq0d0+DMs2ndI4Nq459LheJ74P7mTkohg4sFIhTbvr3uXuKk8U9Rw+zg==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -2805,8 +2821,8 @@ packages: '@types/react': optional: true - '@mui/lab@5.0.0-alpha.170': - resolution: {integrity: sha512-0bDVECGmrNjd3+bLdcLiwYZ0O4HP5j5WSQm5DV6iA/Z9kr8O6AnvZ1bv9ImQbbX7Gj3pX4o43EKwCutj3EQxQg==} + '@mui/lab@5.0.0-alpha.171': + resolution: {integrity: sha512-/ZRnx0wB7hWHMsy76AAUJREVHZ7v5kOKwgJKCQrqOcaPNyo3WiwtTqKaM4Pgj+2r7O10IrC6zOniq8kTRqVAlA==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -2841,8 +2857,8 @@ packages: '@types/react': optional: true - '@mui/material@5.15.20': - resolution: {integrity: sha512-tVq3l4qoXx/NxUgIx/x3lZiPn/5xDbdTE8VrLczNpfblLYZzlrbxA7kb9mI8NoBF6+w9WE9IrxWnKK5KlPI2bg==} + '@mui/material@5.16.0': + resolution: {integrity: sha512-DbR1NckTLpjt9Zut9EGQ70th86HfN0BYQgyYro6aXQrNfjzSwe3BJS1AyBQ5mJ7TdL6YVRqohfukxj9JlqZZUg==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -2858,13 +2874,13 @@ packages: '@types/react': optional: true - '@mui/monorepo@https://codeload.github.com/mui/material-ui/tar.gz/22c5206a9e8191b2f81131d6978a0958e55b7032': - resolution: {tarball: https://codeload.github.com/mui/material-ui/tar.gz/22c5206a9e8191b2f81131d6978a0958e55b7032} - version: 6.0.0-alpha.11 - engines: {pnpm: 9.2.0} + '@mui/monorepo@https://codeload.github.com/mui/material-ui/tar.gz/43cb32700af699cd48baaf6922fbe21343f30e2f': + resolution: {tarball: https://codeload.github.com/mui/material-ui/tar.gz/43cb32700af699cd48baaf6922fbe21343f30e2f} + version: 6.0.0-alpha.14 + engines: {pnpm: 9.4.0} - '@mui/private-theming@5.15.20': - resolution: {integrity: sha512-BK8F94AIqSrnaPYXf2KAOjGZJgWfvqAVQ2gVR3EryvQFtuBnG6RwodxrCvd3B48VuMy6Wsk897+lQMUxJyk+6g==} + '@mui/private-theming@5.16.0': + resolution: {integrity: sha512-sYpubkO1MZOnxNyVOClrPNOTs0MfuRVVnAvCeMaOaXt6GimgQbnUcshYv2pSr6PFj+Mqzdff/FYOBceK8u5QgA==} engines: {node: '>=12.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -2886,8 +2902,8 @@ packages: '@emotion/styled': optional: true - '@mui/styles@5.15.20': - resolution: {integrity: sha512-zpXYhNxQ9A4zxF3IRQRZRUg7fXYj6Wfa3nB+7yOLVecokhjCAr1zY2VC5Uznf5qs2cfgBRfmDkBYqvQjHWf2uA==} + '@mui/styles@5.16.0': + resolution: {integrity: sha512-d/Hd1FJuIzAmX89sNazRcnFBGZLb8klPG9E+AshhVpWZcoV/9Ar29On2XS0IxRh7Y5GoA0oTDkU0jivKWjzkiw==} engines: {node: '>=12.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -2896,8 +2912,8 @@ packages: '@types/react': optional: true - '@mui/system@5.15.20': - resolution: {integrity: sha512-LoMq4IlAAhxzL2VNUDBTQxAb4chnBe8JvRINVNDiMtHE2PiPOoHlhOPutSxEbaL5mkECPVWSv6p8JEV+uykwIA==} + '@mui/system@5.16.0': + resolution: {integrity: sha512-9YbkC2m3+pNumAvubYv+ijLtog6puJ0fJ6rYfzfLCM47pWrw3m+30nXNM8zMgDaKL6vpfWJcCXm+LPaWBpy7sw==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -2920,8 +2936,8 @@ packages: '@types/react': optional: true - '@mui/utils@5.15.20': - resolution: {integrity: sha512-mAbYx0sovrnpAu1zHc3MDIhPqL8RPVC5W5xcO1b7PiSCJPtckIZmBkp8hefamAvUiAV8gpfMOM6Zb+eSisbI2A==} + '@mui/utils@5.16.0': + resolution: {integrity: sha512-kLLi5J1xY+mwtUlMb8Ubdxf4qFAA1+U7WPBvjM/qQ4CIwLCohNb0sHo1oYPufjSIH/Z9+dhVxD7dJlfGjd1AVA==} engines: {node: '>=12.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -2930,16 +2946,16 @@ packages: '@types/react': optional: true - '@netlify/functions@2.7.0': - resolution: {integrity: sha512-4pXC/fuj3eGQ86wbgPiM4zY8+AsNrdz6vcv6FEdUJnZW+LqF8IWjQcY3S0d1hLeLKODYOqq4CkrzGyCpce63Nw==} + '@netlify/functions@2.8.1': + resolution: {integrity: sha512-+6wtYdoz0yE06dSa9XkP47tw5zm6g13QMeCwM3MmHx1vn8hzwFa51JtmfraprdkL7amvb7gaNM+OOhQU1h6T8A==} engines: {node: '>=14.0.0'} '@netlify/node-cookies@0.1.0': resolution: {integrity: sha512-OAs1xG+FfLX0LoRASpqzVntVV/RpYkgpI0VrUnw2u0Q1qiZUzcPffxRK8HF3gc4GjuhG5ahOEMJ9bswBiZPq0g==} engines: {node: ^14.16.0 || >=16.0.0} - '@netlify/serverless-functions-api@1.18.1': - resolution: {integrity: sha512-DrSvivchuwsuQW03zbVPT3nxCQa5tn7m4aoPOsQKibuJXIuSbfxzCBxPLz0+LchU5ds7YyOaCc9872Y32ngYzg==} + '@netlify/serverless-functions-api@1.19.1': + resolution: {integrity: sha512-2KYkyluThg1AKfd0JWI7FzpS4A/fzVVGYIf6AM4ydWyNj8eI/86GQVLeRgDoH7CNOxt243R5tutWlmHpVq0/Ew==} engines: {node: '>=18.0.0'} '@next/env@14.2.4': @@ -3021,37 +3037,58 @@ packages: resolution: {integrity: sha512-2yThA1Es98orMkpSLVqlDZAMPK3jHJhifP2gnNUdk1754uZ8yI5c+ulCoVG+WlntQA6MzhrURMXjSd9Z7dJ2/Q==} engines: {node: ^16.14.0 || >=18.0.0} - '@npmcli/fs@3.1.0': - resolution: {integrity: sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==} + '@npmcli/arborist@7.5.3': + resolution: {integrity: sha512-7gbMdDNSYUzi0j2mpb6FoXRg3BxXWplMQZH1MZlvNjSdWFObaUz2Ssvo0Nlh2xmWks1OPo+gpsE6qxpT/5M7lQ==} + engines: {node: ^16.14.0 || >=18.0.0} + hasBin: true + + '@npmcli/fs@3.1.1': + resolution: {integrity: sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} '@npmcli/git@5.0.4': resolution: {integrity: sha512-nr6/WezNzuYUppzXRaYu/W4aT5rLxdXqEFupbh6e/ovlYFQ8hpu1UUPV3Ir/YTl+74iXl2ZOMlGzudh9ZPUchQ==} engines: {node: ^16.14.0 || >=18.0.0} - '@npmcli/installed-package-contents@2.0.2': - resolution: {integrity: sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==} + '@npmcli/installed-package-contents@2.1.0': + resolution: {integrity: sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} hasBin: true + '@npmcli/map-workspaces@3.0.6': + resolution: {integrity: sha512-tkYs0OYnzQm6iIRdfy+LcLBjcKuQCeE5YLb8KnrIlutJfheNaPvPpgoFEyEFgbjzl5PLZ3IA/BWAwRU0eHuQDA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/metavuln-calculator@7.1.1': + resolution: {integrity: sha512-Nkxf96V0lAx3HCpVda7Vw4P23RILgdi/5K1fmj2tZkWIYLpXAN8k2UVVOsW16TsS5F8Ws2I7Cm+PU1/rsVF47g==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@npmcli/name-from-folder@2.0.0': + resolution: {integrity: sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + '@npmcli/node-gyp@3.0.0': resolution: {integrity: sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - '@npmcli/package-json@5.0.0': - resolution: {integrity: sha512-OI2zdYBLhQ7kpNPaJxiflofYIpkNLi+lnGdzqUOfRmCF3r2l1nadcjtCYMJKv/Utm/ZtlffaUuTiAktPHbc17g==} + '@npmcli/package-json@5.2.0': + resolution: {integrity: sha512-qe/kiqqkW0AGtvBjL8TJKZk/eBBSpnJkUWvHdQ9jM2lKHXRYYJuyNpJPlJw3c8QjC2ow6NZYiLExhUaeJelbxQ==} engines: {node: ^16.14.0 || >=18.0.0} '@npmcli/promise-spawn@7.0.1': resolution: {integrity: sha512-P4KkF9jX3y+7yFUxgcUdDtLy+t4OlDGuEBLNs57AZsfSfg+uV6MLndqGpnl4831ggaEdXwR50XFoZP4VFtHolg==} engines: {node: ^16.14.0 || >=18.0.0} - '@npmcli/run-script@7.0.2': - resolution: {integrity: sha512-Omu0rpA8WXvcGeY6DDzyRoY1i5DkCBkzyJ+m2u7PD6quzb0TvSqdIPOkTn8ZBOj7LbbcbMfZ3c5skwSu6m8y2w==} + '@npmcli/query@3.1.0': + resolution: {integrity: sha512-C/iR0tk7KSKGldibYIB9x8GtO/0Bd0I2mhOaDb8ucQL/bQVTmGoeREaFj64Z5+iCBRf3dQfed0CjJL7I8iTkiQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/redact@2.0.1': + resolution: {integrity: sha512-YgsR5jCQZhVmTJvjduTOIHph0L73pK8xwMVaDY0PatySqVM9AZj93jpoXYSJqfHFxFkN9dmqTw6OiqExsS3LPw==} engines: {node: ^16.14.0 || >=18.0.0} - '@npmcli/run-script@7.0.4': - resolution: {integrity: sha512-9ApYM/3+rBt9V80aYg6tZfzj3UWdiYyCt7gJUD1VJKvWF5nwKDSICXbYIQbspFTq6TOpbsEtIC0LArB8d9PFmg==} + '@npmcli/run-script@8.1.0': + resolution: {integrity: sha512-y7efHHwghQfk28G2z3tlZ67pLG0XdfYbcVG26r7YIXALRsrVQcTq4/tdenSmdOrEsNahIYA/eh8aEVROWGFUDg==} engines: {node: ^16.14.0 || >=18.0.0} '@nrwl/devkit@17.3.0': @@ -3133,8 +3170,8 @@ packages: resolution: {integrity: sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==} engines: {node: '>= 14'} - '@octokit/auth-token@4.0.0': - resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} + '@octokit/auth-token@5.1.1': + resolution: {integrity: sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==} engines: {node: '>= 18'} '@octokit/core@3.6.0': @@ -3144,8 +3181,12 @@ packages: resolution: {integrity: sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==} engines: {node: '>= 14'} - '@octokit/core@5.1.0': - resolution: {integrity: sha512-BDa2VAMLSh3otEiaMJ/3Y36GU4qf6GI+VivQ/P41NC6GHcdxpKlqV0ikSZ5gdQsmS3ojXeRx5vasgNTinF0Q4g==} + '@octokit/core@6.1.2': + resolution: {integrity: sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg==} + engines: {node: '>= 18'} + + '@octokit/endpoint@10.1.1': + resolution: {integrity: sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q==} engines: {node: '>= 18'} '@octokit/endpoint@6.0.12': @@ -3155,10 +3196,6 @@ packages: resolution: {integrity: sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==} engines: {node: '>= 14'} - '@octokit/endpoint@9.0.4': - resolution: {integrity: sha512-DWPLtr1Kz3tv8L0UvXTDP1fNwM0S+z6EJpRcvH66orY6Eld4XBMCSYsaWp4xIm61jTWxK68BrR7ibO+vSDnZqw==} - engines: {node: '>= 18'} - '@octokit/graphql@4.8.0': resolution: {integrity: sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==} @@ -3166,8 +3203,8 @@ packages: resolution: {integrity: sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==} engines: {node: '>= 14'} - '@octokit/graphql@7.0.2': - resolution: {integrity: sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==} + '@octokit/graphql@8.1.1': + resolution: {integrity: sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg==} engines: {node: '>= 18'} '@octokit/openapi-types@12.11.0': @@ -3176,9 +3213,6 @@ packages: '@octokit/openapi-types@18.1.1': resolution: {integrity: sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw==} - '@octokit/openapi-types@19.1.0': - resolution: {integrity: sha512-6G+ywGClliGQwRsjvqVYpklIfa7oRPA0vyhPQG/1Feh+B+wU0vGH1JiJ5T25d3g1JZYBHzR2qefLi9x8Gt+cpw==} - '@octokit/openapi-types@22.2.0': resolution: {integrity: sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==} @@ -3207,11 +3241,11 @@ packages: peerDependencies: '@octokit/core': '>=3' - '@octokit/plugin-request-log@4.0.0': - resolution: {integrity: sha512-2uJI1COtYCq8Z4yNSnM231TgH50bRkheQ9+aH8TnZanB6QilOnx8RMD2qsnamSOXtDj0ilxvevf5fGsBhBBzKA==} + '@octokit/plugin-request-log@5.3.0': + resolution: {integrity: sha512-FiGcyjdtYPlr03ExBk/0ysIlEFIFGJQAVoPPMxL19B24bVSEiZQnVGBunNtaAF1YnvE/EFoDpXmITtRnyCiypQ==} engines: {node: '>= 18'} peerDependencies: - '@octokit/core': '>=5' + '@octokit/core': '>=6' '@octokit/plugin-rest-endpoint-methods@13.2.2': resolution: {integrity: sha512-EI7kXWidkt3Xlok5uN43suK99VWqc8OaIMktY9d9+RNKl69juoTyxmLoWPIZgJYzi41qj/9zU7G/ljnNOJ5AFA==} @@ -3230,11 +3264,11 @@ packages: peerDependencies: '@octokit/core': '>=3' - '@octokit/plugin-retry@6.0.1': - resolution: {integrity: sha512-SKs+Tz9oj0g4p28qkZwl/topGcb0k0qPNX/i7vBKmDsjoeqnVfFUquqrE/O9oJY7+oLzdCtkiWSXLpLjvl6uog==} + '@octokit/plugin-retry@7.1.1': + resolution: {integrity: sha512-G9Ue+x2odcb8E1XIPhaFBnTTIrrUDfXN05iFXiqhR+SeeeDMMILcAnysOsxUpEWcQp2e5Ft397FCXTcPkiPkLw==} engines: {node: '>= 18'} peerDependencies: - '@octokit/core': '>=5' + '@octokit/core': '>=6' '@octokit/request-error@2.1.0': resolution: {integrity: sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==} @@ -3243,8 +3277,8 @@ packages: resolution: {integrity: sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==} engines: {node: '>= 14'} - '@octokit/request-error@5.0.1': - resolution: {integrity: sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==} + '@octokit/request-error@6.1.1': + resolution: {integrity: sha512-1mw1gqT3fR/WFvnoVpY/zUM2o/XkMs/2AszUUG9I69xn0JFLv6PGkPhNk5lbfvROs79wiS0bqiJNxfCZcRJJdg==} engines: {node: '>= 18'} '@octokit/request@5.6.3': @@ -3254,8 +3288,8 @@ packages: resolution: {integrity: sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==} engines: {node: '>= 14'} - '@octokit/request@8.1.6': - resolution: {integrity: sha512-YhPaGml3ncZC1NfXpP3WZ7iliL1ap6tLkAp6MvbK2fTTPytzVUyUesBBogcdMm86uRYO5rHaM1xIWxigWZ17MQ==} + '@octokit/request@9.1.1': + resolution: {integrity: sha512-pyAguc0p+f+GbQho0uNetNQMmLG1e80WjkIaqqgUkihqUp0boRU6nKItXO4VWnr+nbZiLGEyy4TeKRwqaLvYgw==} engines: {node: '>= 18'} '@octokit/rest@18.12.0': @@ -3265,8 +3299,8 @@ packages: resolution: {integrity: sha512-m2a9VhaP5/tUw8FwfnW2ICXlXpLPIqxtg3XcAiGMLj/Xhw3RSBfZ8le/466ktO1Gcjr8oXudGnHhxV1TXJgFxw==} engines: {node: '>= 14'} - '@octokit/rest@20.1.1': - resolution: {integrity: sha512-MB4AYDsM5jhIHro/dq4ix1iWTLGToIGk6cWF5L6vanFaMble5jTX/UBQyiv05HsWnwUtY8JrfHy2LWfKwihqMw==} + '@octokit/rest@21.0.0': + resolution: {integrity: sha512-XudXXOmiIjivdjNZ+fN71NLrnDM00sxSZlhqmPR3v0dVoJwyP628tSlc12xqn8nX3N0965583RBw5GPo6r8u4Q==} engines: {node: '>= 18'} '@octokit/tsconfig@1.0.2': @@ -3275,9 +3309,6 @@ packages: '@octokit/types@10.0.0': resolution: {integrity: sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==} - '@octokit/types@12.4.0': - resolution: {integrity: sha512-FLWs/AvZllw/AGVs+nJ+ELCDZZJk+kY0zMen118xhL2zD0s1etIUHm1odgjP7epxYU1ln7SZxEUWYop5bhsdgQ==} - '@octokit/types@13.5.0': resolution: {integrity: sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==} @@ -3287,77 +3318,10 @@ packages: '@octokit/types@9.3.2': resolution: {integrity: sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==} - '@opentelemetry/api-logs@0.50.0': - resolution: {integrity: sha512-JdZuKrhOYggqOpUljAq4WWNi5nB10PmgoF0y2CvedLGXd0kSawb/UBnWT8gg1ND3bHCNHStAIVT0ELlxJJRqrA==} - engines: {node: '>=14'} - '@opentelemetry/api@1.8.0': resolution: {integrity: sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==} engines: {node: '>=8.0.0'} - '@opentelemetry/core@1.23.0': - resolution: {integrity: sha512-hdQ/a9TMzMQF/BO8Cz1juA43/L5YGtCSiKoOHmrTEf7VMDAZgy8ucpWx3eQTnQ3gBloRcWtzvcrMZABC3PTSKQ==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.9.0' - - '@opentelemetry/core@1.24.1': - resolution: {integrity: sha512-wMSGfsdmibI88K9wB498zXY04yThPexo8jvwNNlm542HZB7XrrMRBbAyKJqG8qDRJwIBdBrPMi4V9ZPW/sqrcg==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.9.0' - - '@opentelemetry/otlp-transformer@0.50.0': - resolution: {integrity: sha512-s0sl1Yfqd5q1Kjrf6DqXPWzErL+XHhrXOfejh4Vc/SMTNqC902xDsC8JQxbjuramWt/+hibfguIvi7Ns8VLolA==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.3.0 <1.9.0' - - '@opentelemetry/resources@1.23.0': - resolution: {integrity: sha512-iPRLfVfcEQynYGo7e4Di+ti+YQTAY0h5mQEUJcHlU9JOqpb4x965O6PZ+wMcwYVY63G96KtdS86YCM1BF1vQZg==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.9.0' - - '@opentelemetry/resources@1.24.1': - resolution: {integrity: sha512-cyv0MwAaPF7O86x5hk3NNgenMObeejZFLJJDVuSeSMIsknlsj3oOZzRv3qSzlwYomXsICfBeFFlxwHQte5mGXQ==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.9.0' - - '@opentelemetry/sdk-logs@0.50.0': - resolution: {integrity: sha512-PeUEupBB29p9nlPNqXoa1PUWNLsZnxG0DCDj3sHqzae+8y76B/A5hvZjg03ulWdnvBLYpnJslqzylG9E0IL87g==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.4.0 <1.9.0' - '@opentelemetry/api-logs': '>=0.39.1' - - '@opentelemetry/sdk-metrics@1.23.0': - resolution: {integrity: sha512-4OkvW6+wST4h6LFG23rXSTf6nmTf201h9dzq7bE0z5R9ESEVLERZz6WXwE7PSgg1gdjlaznm1jLJf8GttypFDg==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.3.0 <1.9.0' - - '@opentelemetry/sdk-trace-base@1.23.0': - resolution: {integrity: sha512-PzBmZM8hBomUqvCddF/5Olyyviayka44O5nDWq673np3ctnvwMOvNrsUORZjKja1zJbwEuD9niAGbnVrz3jwRQ==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.9.0' - - '@opentelemetry/sdk-trace-base@1.24.1': - resolution: {integrity: sha512-zz+N423IcySgjihl2NfjBf0qw1RWe11XIAWVrTNOSSI6dtSPJiVom2zipFB2AEEtJWpv0Iz6DY6+TjnyTV5pWg==} - engines: {node: '>=14'} - peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.9.0' - - '@opentelemetry/semantic-conventions@1.23.0': - resolution: {integrity: sha512-MiqFvfOzfR31t8cc74CTP1OZfz7MbqpAnLCra8NqQoaHJX6ncIRTdYOQYBDQ2uFISDq0WY8Y9dDTWvsgzzBYRg==} - engines: {node: '>=14'} - - '@opentelemetry/semantic-conventions@1.24.1': - resolution: {integrity: sha512-VkliWlS4/+GHLLW7J/rVBA00uXus1SWvwFvcUDxDwmFxYfg/2VI6ekwdXS28cjI8Qz2ky2BzG8OUHo+WeYIWqw==} - engines: {node: '>=14'} - '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -3404,17 +3368,13 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - '@remix-run/router@1.16.1': - resolution: {integrity: sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig==} + '@remix-run/router@1.17.1': + resolution: {integrity: sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q==} engines: {node: '>=14.0.0'} '@sec-ant/readable-stream@0.4.1': resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} - '@sigstore/bundle@1.1.0': - resolution: {integrity: sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - '@sigstore/bundle@2.1.1': resolution: {integrity: sha512-v3/iS+1nufZdKQ5iAlQKcCsoh0jffQyABvYIxKsZQFWc4ubuGjwZklFHpDgV6O6T7vvV78SW5NHI91HFKEcxKg==} engines: {node: ^16.14.0 || >=18.0.0} @@ -3427,18 +3387,10 @@ packages: resolution: {integrity: sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - '@sigstore/sign@1.0.0': - resolution: {integrity: sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - '@sigstore/sign@2.2.1': resolution: {integrity: sha512-U5sKQEj+faE1MsnLou1f4DQQHeFZay+V9s9768lw48J4pKykPj34rWyI1lsMOGJ3Mae47Ye6q3HAJvgXO21rkQ==} engines: {node: ^16.14.0 || >=18.0.0} - '@sigstore/tuf@1.0.3': - resolution: {integrity: sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - '@sigstore/tuf@2.3.0': resolution: {integrity: sha512-S98jo9cpJwO1mtQ+2zY7bOdcYyfVYCUaofCG6wWRzk3pxKHVAkSfshkfecto2+LKsx7Ovtqbgb2LS8zTRhxJ9Q==} engines: {node: ^16.14.0 || >=18.0.0} @@ -3476,8 +3428,8 @@ packages: '@sinonjs/text-encoding@0.7.2': resolution: {integrity: sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==} - '@slack/bolt@3.18.0': - resolution: {integrity: sha512-A7bDi5kY50fS6/nsmURkQdO3iMxD8aX/rA+m1UXEM2ue2z4KijeQtx2sOZ4YkJQ/h7BsgTQM0CYh3qqmo+m5sQ==} + '@slack/bolt@3.19.0': + resolution: {integrity: sha512-P5Yup/PbO8sE5xsuqkBkpSPkxEkfWZ6yo5ZlmBGxRhhoU1usUSU2w0bgZoiDX4WFm7ZX+3x2Dyf4VMa9kzfmVQ==} engines: {node: '>=12.13.0', npm: '>=6.12.0'} '@slack/logger@3.0.0': @@ -3513,37 +3465,36 @@ packages: '@swc/helpers@0.5.5': resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} - '@testing-library/dom@10.1.0': - resolution: {integrity: sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==} + '@tanstack/query-core@5.50.1': + resolution: {integrity: sha512-lpfhKPrJlyV2DSVcQb/HuozH3Av3kws4ge22agx+lNGpFkS4vLZ7St0l3GLwlAD+bqB+qXGex3JdRKUNtMviEQ==} + + '@testing-library/dom@10.3.1': + resolution: {integrity: sha512-q/WL+vlXMpC0uXDyfsMtc1rmotzLV8Y0gq6q1gfrrDjQeHoeLrqHbxdPvPNAh1i+xuJl7+BezywcXArz7vLqKQ==} engines: {node: '>=18'} - '@testing-library/react@15.0.7': - resolution: {integrity: sha512-cg0RvEdD1TIhhkm1IeYMQxrzy0MtUNfa3minv4MjbgcYzJAZ7yD0i0lwoPOTPr+INtiXFezt2o8xMSnyHhEn2Q==} + '@testing-library/react@16.0.0': + resolution: {integrity: sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ==} engines: {node: '>=18'} peerDependencies: + '@testing-library/dom': ^10.0.0 '@types/react': ^18.0.0 + '@types/react-dom': ^18.0.0 react: ^18.0.0 react-dom: ^18.0.0 peerDependenciesMeta: '@types/react': optional: true + '@types/react-dom': + optional: true '@tootallnate/once@2.0.0': resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} engines: {node: '>= 10'} - '@tufjs/canonical-json@1.0.0': - resolution: {integrity: sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - '@tufjs/canonical-json@2.0.0': resolution: {integrity: sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==} engines: {node: ^16.14.0 || >=18.0.0} - '@tufjs/models@1.0.4': - resolution: {integrity: sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - '@tufjs/models@2.0.0': resolution: {integrity: sha512-c8nj8BaOExmZKO2DXhDfegyhSGcG9E/mPN3U13L+/PsoWm1uaGiHHjxqSHQiasDBQwDA3aHuw9+9spYAP1qvvg==} engines: {node: ^16.14.0 || >=18.0.0} @@ -3575,9 +3526,6 @@ packages: '@types/chance@1.1.6': resolution: {integrity: sha512-V+pm3stv1Mvz8fSKJJod6CglNGVqEQ6OyuqitoDkWywEODM/eJd1eSuIp9xt6DrX8BWZ2eDSIzbw1tPCUTvGbQ==} - '@types/cheerio@0.22.35': - resolution: {integrity: sha512-yD57BchKRvTV+JD53UZ6PD8KWY5g5rvvMLRnZR3EQBCZXiDT/HR+pKpMzFGlWNhFrXlo7VPZXtKvIEwZkAWOIA==} - '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} @@ -3599,6 +3547,9 @@ packages: '@types/d3-path@3.1.0': resolution: {integrity: sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==} + '@types/d3-scale-chromatic@3.0.3': + resolution: {integrity: sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==} + '@types/d3-scale@4.0.8': resolution: {integrity: sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==} @@ -3611,9 +3562,6 @@ packages: '@types/doctrine@0.0.9': resolution: {integrity: sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==} - '@types/enzyme@3.10.12': - resolution: {integrity: sha512-xryQlOEIe1TduDWAOphR0ihfebKFSWOXpIsk+70JskCfRfW+xALdnJ0r1ZOTo85F9Qsjk6vtlU7edTYHbls9tA==} - '@types/eslint-scope@3.7.7': resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} @@ -3668,12 +3616,8 @@ packages: '@types/karma@6.3.8': resolution: {integrity: sha512-+QGoOPhb1f6Oli8pG+hxdnGDzVhIrpsHaFSJ4UJg15Xj+QBtluKELkJY+L4Li532HmT3l5K5o1FoUZHRQeOOaQ==} - '@types/lodash@4.17.5': - resolution: {integrity: sha512-MBIOHVZqVqgfro1euRDWX7OO0fBVUUMrN6Pwm8LQsz8cWhEpihlvR70ENj3f40j58TNxZaWv2ndSkInykNBBJw==} - - '@types/lru-cache@7.10.10': - resolution: {integrity: sha512-nEpVRPWW9EBmx2SCfNn3ClYxPL7IktPX12HhIoSc/H5mMjdeW3+YsXIpseLQ2xF35+OcpwKQbEUw5VtqE4PDNA==} - deprecated: This is a stub types definition. lru-cache provides its own type definitions, so you do not need this installed. + '@types/lodash@4.17.6': + resolution: {integrity: sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA==} '@types/luxon@3.4.2': resolution: {integrity: sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==} @@ -3693,8 +3637,8 @@ packages: '@types/minimist@1.2.5': resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} - '@types/mocha@10.0.6': - resolution: {integrity: sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==} + '@types/mocha@10.0.7': + resolution: {integrity: sha512-GN8yJ1mNTcFcah/wKEFIJckJx9iJLoMSzWcfRRuxz/Jk+U6KQNnml+etbtxFK8lPjzOw3zp4Ha/kjSst9fsHYw==} '@types/moment-hijri@2.1.4': resolution: {integrity: sha512-pGX1DaSducJDkJAC3q8fCuemow0pzI4oa0iKcspwQNPXuwlI55WRgBVrA6NVi+rf8bZN1qjWVsGdUatrLhZk6Q==} @@ -3702,8 +3646,8 @@ packages: '@types/moment-jalaali@0.7.9': resolution: {integrity: sha512-gsDOoAzRnCfQTbfdlUrCvX6R0wIto6CvwfvV2C3j4qJLK+DEiTK8Rl/xlOCBO9C6qeUfX8oyZ2UfjnXJTOvHSA==} - '@types/node@18.19.34': - resolution: {integrity: sha512-eXF4pfBNV5DAMKGbI02NnDtWrQ40hAN558/2vvS4gMpMIxaf6JmD7YjnZbq0Q9TDSSkKBamime8ewRoomHdt4g==} + '@types/node@18.19.39': + resolution: {integrity: sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -3726,8 +3670,8 @@ packages: '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - '@types/react-dom@18.2.25': - resolution: {integrity: sha512-o/V48vf4MQh7juIKZU2QGDfli6p1+OOi5oXx36Hffpc9adsHeXjVp8rHuPkjd8VT8sOJ2Zp05HR7CdpGTIUFUA==} + '@types/react-dom@18.3.0': + resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==} '@types/react-router-dom@5.3.3': resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==} @@ -3741,8 +3685,8 @@ packages: '@types/react-transition-group@4.4.10': resolution: {integrity: sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==} - '@types/react@18.2.60': - resolution: {integrity: sha512-dfiPj9+k20jJrLGOu9Nf6eqxm2EyJRrq2NvwOFsfbb7sFExZ9WELPs67UImHj3Ayxg8ruTtKtNnbjaF8olPq0A==} + '@types/react@18.3.3': + resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==} '@types/requestidlecallback@0.3.7': resolution: {integrity: sha512-5/EwNH3H/+M2zxATq9UidyD7rCq3WhK5Te/XhdhqP270QoGInVkoNBj6kK2Ah5slkZewkX8XJb7WDaYhmJu+eg==} @@ -3750,9 +3694,6 @@ packages: '@types/retry@0.12.0': resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} - '@types/scheduler@0.16.8': - resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==} - '@types/send@0.17.4': resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} @@ -3789,8 +3730,8 @@ packages: '@types/yargs@17.0.32': resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} - '@typescript-eslint/eslint-plugin@7.13.1': - resolution: {integrity: sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==} + '@typescript-eslint/eslint-plugin@7.15.0': + resolution: {integrity: sha512-uiNHpyjZtFrLwLDpHnzaDlP3Tt6sGMqTCiqmxaN4n4RP0EfYZDODJyddiFDF44Hjwxr5xAcaYxVKm9QKQFJFLA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: '@typescript-eslint/parser': ^7.0.0 @@ -3800,8 +3741,8 @@ packages: typescript: optional: true - '@typescript-eslint/parser@7.13.1': - resolution: {integrity: sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==} + '@typescript-eslint/parser@7.15.0': + resolution: {integrity: sha512-k9fYuQNnypLFcqORNClRykkGOMOj+pV6V91R4GO/l1FDGwpqmSwoOQrOHo3cGaH63e+D3ZiCAOsuS/D2c99j/A==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -3810,12 +3751,12 @@ packages: typescript: optional: true - '@typescript-eslint/scope-manager@7.13.1': - resolution: {integrity: sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==} + '@typescript-eslint/scope-manager@7.15.0': + resolution: {integrity: sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/type-utils@7.13.1': - resolution: {integrity: sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==} + '@typescript-eslint/type-utils@7.15.0': + resolution: {integrity: sha512-SkgriaeV6PDvpA6253PDVep0qCqgbO1IOBiycjnXsszNTVQe5flN5wR5jiczoEoDEnAqYFSFFc9al9BSGVltkg==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -3824,12 +3765,12 @@ packages: typescript: optional: true - '@typescript-eslint/types@7.13.1': - resolution: {integrity: sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==} + '@typescript-eslint/types@7.15.0': + resolution: {integrity: sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/typescript-estree@7.13.1': - resolution: {integrity: sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==} + '@typescript-eslint/typescript-estree@7.15.0': + resolution: {integrity: sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: typescript: '*' @@ -3837,14 +3778,14 @@ packages: typescript: optional: true - '@typescript-eslint/utils@7.13.1': - resolution: {integrity: sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==} + '@typescript-eslint/utils@7.15.0': + resolution: {integrity: sha512-hfDMDqaqOqsUVGiEPSMLR/AjTSCsmJwjpKkYQRo1FNbmW4tBwBspYDwO9eh7sKSTwMQgBw9/T4DHudPaqshRWA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 - '@typescript-eslint/visitor-keys@7.13.1': - resolution: {integrity: sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==} + '@typescript-eslint/visitor-keys@7.15.0': + resolution: {integrity: sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw==} engines: {node: ^18.18.0 || >=20.0.0} '@ungap/structured-clone@1.2.0': @@ -3988,10 +3929,6 @@ packages: resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} engines: {node: '>= 14'} - agentkeepalive@4.5.0: - resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} - engines: {node: '>= 8.0.0'} - aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} @@ -4000,12 +3937,6 @@ packages: resolution: {integrity: sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==} engines: {node: '>=12'} - airbnb-prop-types@2.16.0: - resolution: {integrity: sha512-7WHOFolP/6cS96PhKNrslCLMYAI8yB1Pp6u6XmxozQOiZbsI5ycglZr5cHhBFfuRcQQjzCMith5ZPZdYiJCxUg==} - deprecated: This package has been renamed to 'prop-types-tools' - peerDependencies: - react: ^0.14 || ^15.0.0 || ^16.0.0-alpha - ajv-formats@2.1.1: resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: @@ -4040,10 +3971,6 @@ packages: ansi-align@3.0.1: resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} - ansi-colors@4.1.1: - resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} - engines: {node: '>=6'} - ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} @@ -4112,11 +4039,6 @@ packages: resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} engines: {node: '>=14'} - are-we-there-yet@3.0.1: - resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - deprecated: This package is no longer supported. - arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -4126,21 +4048,12 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + aria-query@5.1.3: + resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} + aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - arr-diff@4.0.0: - resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} - engines: {node: '>=0.10.0'} - - arr-flatten@1.1.0: - resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==} - engines: {node: '>=0.10.0'} - - arr-union@3.1.0: - resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} - engines: {node: '>=0.10.0'} - array-buffer-byte-length@1.0.1: resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} engines: {node: '>= 0.4'} @@ -4169,14 +4082,6 @@ packages: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - array-unique@0.3.2: - resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==} - engines: {node: '>=0.10.0'} - - array.prototype.filter@1.0.3: - resolution: {integrity: sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==} - engines: {node: '>= 0.4'} - array.prototype.find@2.2.2: resolution: {integrity: sha512-DRumkfW97iZGOfn+lIXbkVrXL04sfYKX+EfOodo8XboR5sxPDVvOjZTF/rysusa9lmhmSOeD6Vp6RKQP+eP4Tg==} @@ -4207,8 +4112,9 @@ packages: array.prototype.toreversed@1.1.2: resolution: {integrity: sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==} - array.prototype.tosorted@1.1.3: - resolution: {integrity: sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==} + array.prototype.tosorted@1.1.4: + resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} + engines: {node: '>= 0.4'} arraybuffer.prototype.slice@1.0.3: resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} @@ -4229,10 +4135,6 @@ packages: assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - assign-symbols@1.0.0: - resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} - engines: {node: '>=0.10.0'} - ast-types-flow@0.0.8: resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} @@ -4256,11 +4158,6 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - atob@2.1.2: - resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} - engines: {node: '>= 4.5.0'} - hasBin: true - autoprefixer@10.4.19: resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==} engines: {node: ^10 || ^12 || >=14} @@ -4272,10 +4169,6 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} - axe-core@4.7.0: - resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==} - engines: {node: '>=4'} - axe-core@4.9.1: resolution: {integrity: sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==} engines: {node: '>=4'} @@ -4283,13 +4176,8 @@ packages: axios@1.7.2: resolution: {integrity: sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==} - axobject-query@3.2.1: - resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} - - babel-core@7.0.0-bridge.0: - resolution: {integrity: sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==} - peerDependencies: - '@babel/core': ^7.0.0-0 + axobject-query@3.1.1: + resolution: {integrity: sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==} babel-loader@9.1.3: resolution: {integrity: sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==} @@ -4298,9 +4186,9 @@ packages: '@babel/core': ^7.12.0 webpack: '>=5' - babel-plugin-istanbul@6.1.1: - resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} - engines: {node: '>=8'} + babel-plugin-istanbul@7.0.0: + resolution: {integrity: sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==} + engines: {node: '>=12'} babel-plugin-macros@3.1.0: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} @@ -4356,13 +4244,12 @@ packages: resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} engines: {node: ^4.5.0 || >= 5.9} - base@0.11.2: - resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} - engines: {node: '>=0.10.0'} - before-after-hook@2.2.3: resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} + before-after-hook@3.0.2: + resolution: {integrity: sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==} + big-integer@1.6.52: resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} engines: {node: '>=0.6'} @@ -4373,6 +4260,10 @@ packages: bignumber.js@9.1.2: resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} + bin-links@4.0.4: + resolution: {integrity: sha512-cMtq4W5ZsEwcutJrVId+a/tjt8GSbS+h0oNkdl6+6rBuEv8Ot33Bevj5KPm40t309zuhVic8NjpuL42QCiJWWA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} @@ -4410,12 +4301,8 @@ packages: brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - braces@2.3.2: - resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} - engines: {node: '>=0.10.0'} - - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} browser-stdout@1.3.1: @@ -4449,12 +4336,6 @@ packages: resolution: {integrity: sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==} engines: {node: '>=0.2.0'} - builtins@1.0.3: - resolution: {integrity: sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==} - - builtins@5.0.1: - resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} - busboy@1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} @@ -4476,18 +4357,10 @@ packages: engines: {node: '>=10.12.0'} hasBin: true - cacache@17.1.4: - resolution: {integrity: sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - cacache@18.0.2: - resolution: {integrity: sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==} + cacache@18.0.3: + resolution: {integrity: sha512-qXCd4rh6I07cnDqh8V48/94Tc/WSfj+o3Gn6NZ0aZovS255bUx8O13uKxRFd2eWG0xgsco7+YItQNPaa5E85hg==} engines: {node: ^16.14.0 || >=18.0.0} - cache-base@1.0.1: - resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} - engines: {node: '>=0.10.0'} - caching-transform@4.0.0: resolution: {integrity: sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==} engines: {node: '>=8'} @@ -4580,13 +4453,6 @@ packages: check-error@1.0.3: resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} - cheerio-select@2.1.0: - resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} - - cheerio@1.0.0-rc.12: - resolution: {integrity: sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==} - engines: {node: '>= 6'} - chokidar@3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} @@ -4603,9 +4469,9 @@ packages: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} - class-utils@0.3.6: - resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} - engines: {node: '>=0.10.0'} + ci-info@4.0.0: + resolution: {integrity: sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==} + engines: {node: '>=8'} clean-css@5.3.3: resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} @@ -4671,14 +4537,10 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} - cmd-shim@6.0.1: - resolution: {integrity: sha512-S9iI9y0nKR4hwEQsVWpyxld/6kRfGepGfzff83FcaiEBpmvlbA2nnGe7Cylgrx2f/p1P5S5wpRm9oL8z1PbS3Q==} + cmd-shim@6.0.3: + resolution: {integrity: sha512-FMabTRlc5t5zjdenF6mS0MBeFZm0XqHqeOkcskKFb/LYCcRQ5fVgLOHVc4Lq9CqABd9zhjwPjMBCJvMCziSVtA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - collection-visit@1.0.0: - resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} - engines: {node: '>=0.10.0'} - color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -4745,6 +4607,9 @@ packages: resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} engines: {node: '>= 12.0.0'} + common-ancestor-path@1.0.1: + resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} + common-path-prefix@3.0.0: resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} @@ -4754,9 +4619,6 @@ packages: compare-func@2.0.0: resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} - component-emitter@1.3.1: - resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} - compress-commons@4.1.2: resolution: {integrity: sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==} engines: {node: '>= 10'} @@ -4861,10 +4723,6 @@ packages: resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} engines: {node: '>= 0.6'} - copy-descriptor@0.1.1: - resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} - engines: {node: '>=0.10.0'} - core-js-compat@3.36.1: resolution: {integrity: sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA==} @@ -4936,9 +4794,6 @@ packages: css-select@4.3.0: resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} - css-select@5.1.0: - resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} - css-to-react-native@3.2.0: resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==} @@ -4949,6 +4804,11 @@ packages: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + cssjanus@2.1.0: resolution: {integrity: sha512-kAijbny3GmdOi9k+QT6DGIXqFvL96aksNlGr4Rhk9qXDZYWUojU4bRc3IHWxdaLNOqgEZHuXoe5Wl2l7dxLW5g==} engines: {node: '>=10.0.0'} @@ -4987,6 +4847,10 @@ packages: resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} engines: {node: '>=12'} + d3-scale-chromatic@3.1.0: + resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==} + engines: {node: '>=12'} + d3-scale@4.0.2: resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} engines: {node: '>=12'} @@ -5006,8 +4870,8 @@ packages: damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} - danger@12.3.1: - resolution: {integrity: sha512-K5ydQs6fTl6+iAWZJ5Fk238YmGMGnDx/5ZD7ZBTK4NgztAxXIupWVEYUACFy/lUpvih6EDKocn12OF1MS3UsLQ==} + danger@12.3.3: + resolution: {integrity: sha512-nZKzpgXN21rr4dwa6bFhM7G2JEa79dZRJiT3RVRSyi4yk1/hgZ2f8HDGoa7tMladTmu8WjJFyE3LpBIihh+aDw==} engines: {node: '>=18'} hasBin: true @@ -5035,8 +4899,8 @@ packages: resolution: {integrity: sha512-2wz5AOzd3oQ+PnL3E/iKvJZ14i6oTp15sW047ZFCOgM9OSP8ggbb9jm/4SKI8ejdUGH96Krb5dfEQe8zbkVyZw==} engines: {node: '>=0.11'} - date-fns-jalali@3.6.0-0: - resolution: {integrity: sha512-rcOocwhBFgEN4i+vXPoEp/irCxAmX8yloK/l/oeMOVCLpaFQfkq7jVn0vCWK91P2H9I/doSAPEN4WSWQeqwsug==} + date-fns-jalali@3.6.0-1: + resolution: {integrity: sha512-f4FlXArA3kE0uW27y/2AJjRevb6x7DaLMjJfxw7CEXC+XK/JXbZ/WVHND5l1zq2VZsssRrXRWWS0u9NGwawVsQ==} date-fns@2.30.0: resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} @@ -5074,8 +4938,8 @@ packages: supports-color: optional: true - debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + debug@4.3.5: + resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -5098,17 +4962,22 @@ packages: decimal.js@10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} - decode-uri-component@0.2.2: - resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} - engines: {node: '>=0.10'} - - dedent@0.7.0: - resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} + dedent@1.5.3: + resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true deep-eql@4.1.3: resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} engines: {node: '>=6'} + deep-equal@2.2.3: + resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} + engines: {node: '>= 0.4'} + deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} @@ -5135,18 +5004,6 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} - define-property@0.2.5: - resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} - engines: {node: '>=0.10.0'} - - define-property@1.0.0: - resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==} - engines: {node: '>=0.10.0'} - - define-property@2.0.2: - resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} - engines: {node: '>=0.10.0'} - delaunator@5.0.1: resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} @@ -5154,9 +5011,6 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} - delegates@1.0.0: - resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} @@ -5187,21 +5041,14 @@ packages: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - diff@5.0.0: - resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} - engines: {node: '>=0.3.1'} - - diff@5.1.0: - resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} + diff@5.2.0: + resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} - discontinuous-range@1.0.0: - resolution: {integrity: sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==} - doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} @@ -5228,9 +5075,6 @@ packages: dom-serializer@1.4.1: resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} - dom-serializer@2.0.0: - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} - domelementtype@2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} @@ -5238,16 +5082,9 @@ packages: resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} engines: {node: '>= 4'} - domhandler@5.0.3: - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} - engines: {node: '>= 4'} - domutils@2.8.0: resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} - domutils@3.1.0: - resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} - dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} @@ -5340,27 +5177,11 @@ packages: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} - envinfo@7.11.0: - resolution: {integrity: sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==} - engines: {node: '>=4'} - hasBin: true - - envinfo@7.8.1: - resolution: {integrity: sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==} + envinfo@7.13.0: + resolution: {integrity: sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==} engines: {node: '>=4'} hasBin: true - enzyme-adapter-utils@1.14.1: - resolution: {integrity: sha512-JZgMPF1QOI7IzBj24EZoDpaeG/p8Os7WeBZWTJydpsH7JRStc7jYbHE4CmNQaLqazaGFyLM8ALWA3IIZvxW3PQ==} - peerDependencies: - react: 0.13.x || 0.14.x || ^15.0.0-0 || ^16.0.0-0 - - enzyme-shallow-equal@1.0.5: - resolution: {integrity: sha512-i6cwm7hN630JXenxxJFBKzgLC3hMTafFQXflvzHgPmDhOBhxUWDe8AeRv1qp2/uWJ2Y8z5yLWMzmAfkTOiOCZg==} - - enzyme@3.11.0: - resolution: {integrity: sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==} - err-code@2.0.3: resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} @@ -5389,8 +5210,8 @@ packages: resolution: {integrity: sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==} engines: {node: '>= 0.4'} - es-module-lexer@1.4.1: - resolution: {integrity: sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==} + es-module-lexer@1.5.4: + resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} es-object-atoms@1.0.0: resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} @@ -5515,14 +5336,14 @@ packages: '@typescript-eslint/parser': optional: true - eslint-plugin-jsdoc@48.2.12: - resolution: {integrity: sha512-sO9sKkJx5ovWoRk9hV0YiNzXQ4Z6j27CqE/po2E3wddZVuy9wvKPSTiIhpxMTrP/qURvKayJIDB2+o9kyCW1Fw==} + eslint-plugin-jsdoc@48.5.2: + resolution: {integrity: sha512-VXBJFviQz30rynlOEQ+dNWLmeopjoAgutUVrWOZwm6Ki4EVDm4XkyIqAV/Zhf7FcDr0AG0aGmRn5FxxCtAF0tA==} engines: {node: '>=18'} peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 - eslint-plugin-jsx-a11y@6.8.0: - resolution: {integrity: sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==} + eslint-plugin-jsx-a11y@6.9.0: + resolution: {integrity: sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==} engines: {node: '>=4.0'} peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 @@ -5559,8 +5380,8 @@ packages: peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - eslint-plugin-react@7.34.2: - resolution: {integrity: sha512-2HCmrU+/JNigDN6tg55cRDKCQWicYAPB38JGSFDQt95jDm8rrvSUo7YPkOIm5l6ts1j1zCvysNcasvfTMQzUOw==} + eslint-plugin-react@7.34.3: + resolution: {integrity: sha512-aoW4MV891jkUulwDApQbPYTVZmeuSyFrudpbTAQuj5Fv8VL+o6df2xIGpw8B0hPjAaih1/Fb0om9grCdyFYemA==} engines: {node: '>=4'} peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 @@ -5660,14 +5481,10 @@ packages: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} - execa@9.2.0: - resolution: {integrity: sha512-vpOyYg7UAVKLAWWtRS2gAdgkT7oJbCn0me3gmUmxZih4kd3MF/oo8kNTBTIbkO3yuuF5uB4ZCZfn8BOolITYhg==} + execa@9.3.0: + resolution: {integrity: sha512-l6JFbqnHEadBoVAVpN5dl2yCyfX28WoBAGaoQcNmLLSedOxTxcn2Qa83s8I/PA5i56vWru2OHOtrwF7Om2vqlg==} engines: {node: ^18.19.0 || >=20.5.0} - expand-brackets@2.1.4: - resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} - engines: {node: '>=0.10.0'} - expand-tilde@2.0.2: resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} engines: {node: '>=0.10.0'} @@ -5683,10 +5500,6 @@ packages: resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} engines: {node: '>=0.10.0'} - extend-shallow@3.0.2: - resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} - engines: {node: '>=0.10.0'} - extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -5694,10 +5507,6 @@ packages: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} - extglob@2.0.4: - resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} - engines: {node: '>=0.10.0'} - fast-csv@4.3.6: resolution: {integrity: sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw==} engines: {node: '>=10.0.0'} @@ -5750,12 +5559,8 @@ packages: filelist@1.0.4: resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} - fill-range@4.0.0: - resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} - engines: {node: '>=0.10.0'} - - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} finalhandler@1.1.2: @@ -5834,10 +5639,6 @@ packages: for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - for-in@1.0.2: - resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} - engines: {node: '>=0.10.0'} - foreground-child@2.0.0: resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==} engines: {node: '>=8.0.0'} @@ -5864,10 +5665,6 @@ packages: fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - fragment-cache@0.2.1: - resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} - engines: {node: '>=0.10.0'} - fresh@0.5.2: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} @@ -5929,11 +5726,6 @@ packages: functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - gauge@4.0.4: - resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - deprecated: This package is no longer supported. - gaxios@6.1.1: resolution: {integrity: sha512-bw8smrX+XlAoo9o1JAksBwX+hi/RG15J+NTSxmNPIclKC3ZVK6C2afwY8OSdRvOK0+ZLecUJYtj2MmjOt3Dm0w==} engines: {node: '>=14'} @@ -5993,10 +5785,6 @@ packages: get-tsconfig@4.7.5: resolution: {integrity: sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==} - get-value@2.0.6: - resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} - engines: {node: '>=0.10.0'} - git-config-path@1.0.1: resolution: {integrity: sha512-KcJ2dlrrP5DbBnYIZ2nlikALfRhKzNSX0stvv3ImJ+fvC4hXKoV+U+74SV0upg+jlQZbrtQzc0bu6/Zh+7aQbg==} engines: {node: '>=0.10.0'} @@ -6018,8 +5806,8 @@ packages: git-up@7.0.0: resolution: {integrity: sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==} - git-url-parse@13.1.0: - resolution: {integrity: sha512-5FvPJP/70WkIprlUZ33bm4UAaFdjcLkJLpWft1BeZKqwR0uhhNGoKwlUaPtVb4LxCSQ++erHapRak9kWGj+FCA==} + git-url-parse@14.0.0: + resolution: {integrity: sha512-NnLweV+2A4nCvn4U/m2AoYu0pPKlsmhK9cknG7IMwsjFY1S2jxM+mAhsDxyxfCIGfGaD+dozsyX4b6vkYc83yQ==} gitconfiglocal@1.0.0: resolution: {integrity: sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==} @@ -6089,8 +5877,8 @@ packages: resolution: {integrity: sha512-4kKdWXTtgQ4biIo7hZA396HT062nDVVHPjQcurNZ3o/voYN+o5FUC5kOwuORbpExp3XbTJ3SU7iRipiIhQtovw==} engines: {node: '>=14'} - google-auth-library@9.10.0: - resolution: {integrity: sha512-ol+oSa5NbcGdDqA+gZ3G3mev59OHBZksBTxY/tYwjtcp1H/scAFwJfSQU9/1RALoyZ7FslNbke8j4i3ipwlyuQ==} + google-auth-library@9.11.0: + resolution: {integrity: sha512-epX3ww/mNnhl6tL45EQ/oixsY8JLEgUFoT4A5E/5iAR4esld9Kqv6IJGk7EmGuOgDvaarwF95hU2+v7Irql9lw==} engines: {node: '>=14'} googleapis-common@7.0.1: @@ -6160,26 +5948,6 @@ packages: has-unicode@2.0.1: resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - has-value@0.3.1: - resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} - engines: {node: '>=0.10.0'} - - has-value@1.0.0: - resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==} - engines: {node: '>=0.10.0'} - - has-values@0.1.4: - resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==} - engines: {node: '>=0.10.0'} - - has-values@1.0.0: - resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} - engines: {node: '>=0.10.0'} - - has@1.0.4: - resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==} - engines: {node: '>= 0.4.0'} - hasha@5.2.2: resolution: {integrity: sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==} engines: {node: '>=8'} @@ -6208,25 +5976,14 @@ packages: hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - hosted-git-info@3.0.8: - resolution: {integrity: sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==} - engines: {node: '>=10'} - hosted-git-info@4.1.0: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} - hosted-git-info@6.1.1: - resolution: {integrity: sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - hosted-git-info@7.0.1: - resolution: {integrity: sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==} + hosted-git-info@7.0.2: + resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} engines: {node: ^16.14.0 || >=18.0.0} - html-element-map@1.3.1: - resolution: {integrity: sha512-6XMlxrAFX4UEEGxctfFnmrFaaZFNf9i5fNuV5wZ3WWQ4FVaNP1aX1LkX9j2mfEx1NpjeE/rL3nmgEn23GdFmrg==} - html-encoding-sniffer@4.0.0: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} engines: {node: '>=18'} @@ -6258,9 +6015,6 @@ packages: htmlparser2@6.1.0: resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} - htmlparser2@8.0.2: - resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} - http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} @@ -6296,9 +6050,6 @@ packages: resolution: {integrity: sha512-74kytxOUSvNbjrT9KisAbaTZ/eJwD/LrbM/kh5j0IhPuJzwuA19dWvniFGwBzN9rVjg+O/e+F310PjObDXS+9Q==} engines: {node: '>=18.18.0'} - humanize-ms@1.2.1: - resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} - hyperlinker@1.0.0: resolution: {integrity: sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ==} engines: {node: '>=4'} @@ -6317,10 +6068,6 @@ packages: ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - ignore-walk@5.0.1: - resolution: {integrity: sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - ignore-walk@6.0.4: resolution: {integrity: sha512-t7sv42WkwFkyKbivUCglsQW5YWMskWtbEf4MNKX5u/CCWHKSPzN4FtBQGsQZgCLbxOzpVlcbWVK5KB3auIOjSw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -6363,9 +6110,9 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - init-package-json@5.0.0: - resolution: {integrity: sha512-kBhlSheBfYmq3e0L1ii+VKe3zBTLL5lDCDWR+f9dLmEGSB3MqLlMlsolubSsyI88Bg6EA+BIMlomAnQ1SwgQBw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + init-package-json@6.0.3: + resolution: {integrity: sha512-Zfeb5ol+H+eqJWHTaGca9BovufyGeIfr4zaaBorPmJBMrJ+KBnN+kQx2ZtXdsotUTgldHmHQV44xvUWOUA7E2w==} + engines: {node: ^16.14.0 || >=18.0.0} inquirer@8.2.6: resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==} @@ -6394,10 +6141,6 @@ packages: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} - is-accessor-descriptor@1.0.1: - resolution: {integrity: sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==} - engines: {node: '>= 0.10'} - is-alphabetical@1.0.4: resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} @@ -6433,9 +6176,6 @@ packages: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} engines: {node: '>= 0.4'} - is-buffer@1.1.6: - resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} - is-buffer@2.0.5: resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} engines: {node: '>=4'} @@ -6451,10 +6191,6 @@ packages: is-core-module@2.13.1: resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} - is-data-descriptor@1.0.1: - resolution: {integrity: sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==} - engines: {node: '>= 0.4'} - is-data-view@1.0.1: resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} engines: {node: '>= 0.4'} @@ -6466,14 +6202,6 @@ packages: is-decimal@1.0.4: resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==} - is-descriptor@0.1.7: - resolution: {integrity: sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==} - engines: {node: '>= 0.4'} - - is-descriptor@1.0.3: - resolution: {integrity: sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==} - engines: {node: '>= 0.4'} - is-docker@2.2.1: resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} engines: {node: '>=8'} @@ -6486,10 +6214,6 @@ packages: resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} engines: {node: '>=0.10.0'} - is-extendable@1.0.1: - resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} - engines: {node: '>=0.10.0'} - is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -6533,10 +6257,6 @@ packages: resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} engines: {node: '>= 0.4'} - is-number@3.0.0: - resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} - engines: {node: '>=0.10.0'} - is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -6610,9 +6330,6 @@ packages: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} engines: {node: '>= 0.4'} - is-subset@0.1.1: - resolution: {integrity: sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==} - is-symbol@1.0.4: resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} engines: {node: '>= 0.4'} @@ -6673,10 +6390,6 @@ packages: resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} engines: {node: '>=16'} - isobject@2.1.0: - resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} - engines: {node: '>=0.10.0'} - isobject@3.0.1: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} @@ -6689,10 +6402,6 @@ packages: resolution: {integrity: sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==} engines: {node: '>=8'} - istanbul-lib-instrument@5.2.1: - resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} - engines: {node: '>=8'} - istanbul-lib-instrument@6.0.2: resolution: {integrity: sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==} engines: {node: '>=10'} @@ -6765,21 +6474,14 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true - jscodeshift-add-imports@1.0.10: - resolution: {integrity: sha512-VUe9DJ3zkWIR62zSRQnmsOVeyt77yD8knvYNna/PzRZlF9j799hJw5sqTZu4EX16XLIqS3FxWz3nXuGuiw9iyQ==} - peerDependencies: - jscodeshift: ^0.7.0 || ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 - - jscodeshift-find-imports@2.0.4: - resolution: {integrity: sha512-HxOzjWDOFFSCf8EKSTQGqCxXeRFqZszOywnZ0HuMB9YPDFHVpxftGRsY+QS+Qq8o2qUojlmNU3JEHts5DWYS1A==} - peerDependencies: - jscodeshift: ^0.7.0 || ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 - - jscodeshift@0.13.1: - resolution: {integrity: sha512-lGyiEbGOvmMRKgWk4vf+lUrCWO/8YR8sUR3FKF1Cq5fovjZDlIcw3Hu5ppLHAnEXshVffvaM0eyuY/AbOeYpnQ==} + jscodeshift@0.16.1: + resolution: {integrity: sha512-oMQXySazy63awNBzMpXbbVv73u3irdxTeX2L5ueRyFRxi32qb9uzdZdOY5fTBYADBG19l5M/wnGknZSV1dzCdA==} hasBin: true peerDependencies: '@babel/preset-env': ^7.1.6 + peerDependenciesMeta: + '@babel/preset-env': + optional: true jsdoc-type-pratt-parser@4.0.0: resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==} @@ -6815,8 +6517,8 @@ packages: json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - json-parse-even-better-errors@3.0.1: - resolution: {integrity: sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==} + json-parse-even-better-errors@3.0.2: + resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} json-schema-traverse@0.4.1: @@ -6828,6 +6530,9 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + json-stringify-nice@1.1.4: + resolution: {integrity: sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==} + json-stringify-safe@5.0.1: resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} @@ -6907,6 +6612,12 @@ packages: resolution: {integrity: sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==} engines: {node: '>=12.20'} + just-diff-apply@5.5.0: + resolution: {integrity: sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==} + + just-diff@6.0.2: + resolution: {integrity: sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA==} + just-extend@6.2.0: resolution: {integrity: sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==} @@ -6951,14 +6662,6 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - kind-of@3.2.2: - resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} - engines: {node: '>=0.10.0'} - - kind-of@4.0.0: - resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} - engines: {node: '>=0.10.0'} - kind-of@6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} @@ -6974,8 +6677,8 @@ packages: resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} engines: {node: '>= 0.6.3'} - lerna@8.1.3: - resolution: {integrity: sha512-Dg/r1dGnRCXKsOUC3lol7o6ggYTA6WWiPQzZJNKqyygn4fzYGuA3Dro2d5677pajaqFnFA72mdCjzSyF16Vi2Q==} + lerna@8.1.6: + resolution: {integrity: sha512-O3zSX/dmchMVy9m37DD1BCx7X68nS5lZFECjqG7Siiv3+KgqKXHnF4JQPJUDD/vG2qBQv5StpXCyqGxR0XJVAQ==} engines: {node: '>=18.0.0'} hasBin: true @@ -6987,13 +6690,13 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - libnpmaccess@7.0.2: - resolution: {integrity: sha512-vHBVMw1JFMTgEk15zRsJuSAg7QtGGHpUSEfnbcRL1/gTBag9iEfJbyjpDmdJmwMhvpoLoNBtdAUCdGnaP32hhw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + libnpmaccess@8.0.6: + resolution: {integrity: sha512-uM8DHDEfYG6G5gVivVl+yQd4pH3uRclHC59lzIbSvy7b5FEwR+mU49Zq1jEyRtRFv7+M99mUW9S0wL/4laT4lw==} + engines: {node: ^16.14.0 || >=18.0.0} - libnpmpublish@7.3.0: - resolution: {integrity: sha512-fHUxw5VJhZCNSls0KLNEG0mCD2PN1i14gH5elGOgiVnU3VgTcRahagYP2LKI1m0tFCJ+XrAm0zVYyF5RCbXzcg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + libnpmpublish@9.0.9: + resolution: {integrity: sha512-26zzwoBNAvX9AWOPiqqF6FG4HrSCPsHFkQm7nT+xU1ggAujL/eae81RnCv4CJ2In9q9fh10B88sYSzKCUh/Ghg==} + engines: {node: ^16.14.0 || >=18.0.0} lie@3.3.0: resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} @@ -7062,9 +6765,6 @@ packages: lodash.difference@4.5.0: resolution: {integrity: sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==} - lodash.escape@4.0.1: - resolution: {integrity: sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==} - lodash.escaperegexp@4.1.2: resolution: {integrity: sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==} @@ -7179,8 +6879,8 @@ packages: lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} - lru-cache@10.2.0: - resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} + lru-cache@10.3.0: + resolution: {integrity: sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==} engines: {node: 14 || >=16.14} lru-cache@4.1.5: @@ -7193,10 +6893,6 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} - lru-cache@7.18.3: - resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} - engines: {node: '>=12'} - luxon@3.4.4: resolution: {integrity: sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==} engines: {node: '>=12'} @@ -7221,18 +6917,10 @@ packages: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} - make-fetch-happen@11.1.1: - resolution: {integrity: sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - make-fetch-happen@13.0.0: resolution: {integrity: sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==} engines: {node: ^16.14.0 || >=18.0.0} - map-cache@0.2.2: - resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} - engines: {node: '>=0.10.0'} - map-obj@1.0.1: resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} engines: {node: '>=0.10.0'} @@ -7241,10 +6929,6 @@ packages: resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} engines: {node: '>=8'} - map-visit@1.0.0: - resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} - engines: {node: '>=0.10.0'} - markdown-it@14.1.0: resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} hasBin: true @@ -7273,9 +6957,9 @@ packages: resolution: {integrity: sha512-qwGyuyKwjkEMOJ10XN6OTKNOVYvOIi35RNvDLNxTof5s8UmyGHlCdpngRHoRGNvQVGuxO3BJ7uNSgdeX166WXw==} engines: {node: '>=18'} - marked@5.1.2: - resolution: {integrity: sha512-ahRPGXJpjMjwSOlBoTMZAK7ATXkli5qCPxZ21TG44rx1KEo44bii4ekgTDQPNRQ4Kh7JMb9Ub1PVk1NxRSsorg==} - engines: {node: '>= 16'} + marked@13.0.1: + resolution: {integrity: sha512-7kBohS6GrZKvCsNXZyVVXSW7/hGBHe49ng99YPkDCckSUrrG7MSFLCexsRxptzOmyW2eT5dySh4Md1V6my52fA==} + engines: {node: '>= 18'} hasBin: true mdast-util-from-markdown@0.8.5: @@ -7325,14 +7009,14 @@ packages: micromark@2.11.4: resolution: {integrity: sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==} - micromatch@3.1.10: - resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} - engines: {node: '>=0.10.0'} - micromatch@4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} + engines: {node: '>=8.6'} + mime-db@1.33.0: resolution: {integrity: sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==} engines: {node: '>= 0.6'} @@ -7373,10 +7057,6 @@ packages: minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - minimatch@5.0.1: - resolution: {integrity: sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==} - engines: {node: '>=10'} - minimatch@5.1.6: resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} engines: {node: '>=10'} @@ -7400,10 +7080,6 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass-collect@1.0.2: - resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} - engines: {node: '>= 8'} - minipass-collect@2.0.1: resolution: {integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==} engines: {node: '>=16 || 14 >=14.17'} @@ -7416,9 +7092,6 @@ packages: resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} engines: {node: '>= 8'} - minipass-json-stream@1.0.1: - resolution: {integrity: sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==} - minipass-pipeline@1.2.4: resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} engines: {node: '>=8'} @@ -7447,10 +7120,6 @@ packages: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} engines: {node: '>= 8'} - mixin-deep@1.3.2: - resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} - engines: {node: '>=0.10.0'} - mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true @@ -7460,8 +7129,8 @@ packages: engines: {node: '>=10'} hasBin: true - mocha@10.4.0: - resolution: {integrity: sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==} + mocha@10.6.0: + resolution: {integrity: sha512-hxjt4+EEB0SA0ZDygSS015t65lJw/I2yRCS3Ae+SJ5FrbzrXgfYwJr96f0OvIXdj7h4lv/vLCrH3rkiuizFSvw==} engines: {node: '>= 14.0.0'} hasBin: true @@ -7472,8 +7141,8 @@ packages: moment-hijri@2.1.2: resolution: {integrity: sha512-p5ZOA1UzBHAAXiePh37XRjjwuyH78+1ShYZ7R6jogxketewG7kTCUjUmcP9c4Qsx8D8cqxwUWrESjtgdT6tNoA==} - moment-jalaali@0.10.0: - resolution: {integrity: sha512-XICH1+UHd3zyaE1bXWQBlhoXBqbzEyFfT0TrifNobHxLALRuTSwXn376bX8FmkYg9mZimevwwdd6EB57s5wuFA==} + moment-jalaali@0.10.1: + resolution: {integrity: sha512-/iwLtt3onvI6wFydUSTj10nFeNkD9sZ0fSY1gmqC2dwt1yGYJun6agI7E7SiBYi8uzGlt3P4KuPYCMLiv43E+g==} moment-timezone@0.5.45: resolution: {integrity: sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==} @@ -7481,9 +7150,6 @@ packages: moment@2.30.1: resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} - moo@0.5.2: - resolution: {integrity: sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==} - mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -7523,17 +7189,9 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - nanomatch@1.2.13: - resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} - engines: {node: '>=0.10.0'} - natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - nearley@2.20.1: - resolution: {integrity: sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==} - hasBin: true - negotiator@0.6.3: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} @@ -7615,8 +7273,8 @@ packages: resolution: {integrity: sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==} hasBin: true - nopt@7.2.0: - resolution: {integrity: sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==} + nopt@7.2.1: + resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} hasBin: true @@ -7627,12 +7285,8 @@ packages: resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} engines: {node: '>=10'} - normalize-package-data@5.0.0: - resolution: {integrity: sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - normalize-package-data@6.0.0: - resolution: {integrity: sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==} + normalize-package-data@6.0.2: + resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==} engines: {node: ^16.14.0 || >=18.0.0} normalize-path@3.0.0: @@ -7643,9 +7297,6 @@ packages: resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} engines: {node: '>=0.10.0'} - npm-bundled@1.1.2: - resolution: {integrity: sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==} - npm-bundled@3.0.0: resolution: {integrity: sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -7654,44 +7305,24 @@ packages: resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - npm-normalize-package-bin@1.0.1: - resolution: {integrity: sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==} - npm-normalize-package-bin@3.0.1: resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - npm-package-arg@10.1.0: - resolution: {integrity: sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - npm-package-arg@11.0.1: - resolution: {integrity: sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==} + npm-package-arg@11.0.2: + resolution: {integrity: sha512-IGN0IAwmhDJwy13Wc8k+4PEbTPhpJnMtfR53ZbOyjkvmEcLS4nCwp6mvMWjS5sUjeiW3mpx6cHmuhKEu9XmcQw==} engines: {node: ^16.14.0 || >=18.0.0} - npm-package-arg@8.1.1: - resolution: {integrity: sha512-CsP95FhWQDwNqiYS+Q0mZ7FAEDytDZAkNxQqea6IaAFJTAY9Lhhqyl0irU/6PMc7BGfUmnsbHcqxJD7XuVM/rg==} - engines: {node: '>=10'} - - npm-packlist@5.1.1: - resolution: {integrity: sha512-UfpSvQ5YKwctmodvPPkK6Fwk603aoVsf8AEbmVKAEECrfvL8SSe1A2YIwrJ6xmTHAITKPwwZsWo7WwEbNk0kxw==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - hasBin: true - npm-packlist@8.0.2: resolution: {integrity: sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - npm-pick-manifest@9.0.0: - resolution: {integrity: sha512-VfvRSs/b6n9ol4Qb+bDwNGUXutpy76x6MARw/XssevE0TnctIKcmklJZM5Z7nqs5z5aW+0S63pgCNbpkUNNXBg==} + npm-pick-manifest@9.0.1: + resolution: {integrity: sha512-Udm1f0l2nXb3wxDpKjfohwgdFUSV50UVwzEIpDXVsbDMXVIEF81a/i0UhuQbhrPMMmdiq3+YMFLFIRVLs3hxQw==} engines: {node: ^16.14.0 || >=18.0.0} - npm-registry-fetch@14.0.5: - resolution: {integrity: sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - npm-registry-fetch@16.1.0: - resolution: {integrity: sha512-PQCELXKt8Azvxnt5Y85GseQDJJlglTFM9L9U9gkv2y4e9s0k3GVDdOx3YoB6gm2Do0hlkzC39iCGXby+Wve1Bw==} + npm-registry-fetch@17.1.0: + resolution: {integrity: sha512-5+bKQRH0J1xG1uZ1zMNvxW0VEyoNWgJpY9UDuluPFLKDfJ9u2JmmjmTJV1srBGQOROfdBMiVvnH2Zvpbm+xkVA==} engines: {node: ^16.14.0 || >=18.0.0} npm-run-path@4.0.1: @@ -7702,11 +7333,6 @@ packages: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - npmlog@6.0.2: - resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - deprecated: This package is no longer supported. - nprogress@0.2.0: resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==} @@ -7737,10 +7363,6 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - object-copy@0.1.0: - resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==} - engines: {node: '>=0.10.0'} - object-hash@2.2.0: resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==} engines: {node: '>= 6'} @@ -7759,10 +7381,6 @@ packages: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} - object-visit@1.0.1: - resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==} - engines: {node: '>=0.10.0'} - object.assign@4.1.5: resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} engines: {node: '>= 0.4'} @@ -7786,10 +7404,6 @@ packages: resolution: {integrity: sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==} engines: {node: '>= 0.4'} - object.pick@1.3.0: - resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} - engines: {node: '>=0.10.0'} - object.values@1.2.0: resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} engines: {node: '>= 0.4'} @@ -7960,8 +7574,8 @@ packages: resolution: {integrity: sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==} engines: {node: '>=8'} - pacote@17.0.6: - resolution: {integrity: sha512-cJKrW21VRE8vVTRskJo78c/RCvwJCn1f4qgfxL4w77SOWrTCRcmfkYHlHtS0gqpgjv3zhXflRtgsrUCX5xwNnQ==} + pacote@18.0.6: + resolution: {integrity: sha512-+eK3G27SMwsB8kLIuj4h1FUhHtwiEUo21Tw8wNjmvdlpOEr613edv+8FUsTj/4F/VN5ywGE19X18N7CC2EJk6A==} engines: {node: ^16.14.0 || >=18.0.0} hasBin: true @@ -7975,6 +7589,10 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} + parse-conflict-json@3.0.1: + resolution: {integrity: sha512-01TvEktc68vwbJOtWZluyWeVGWjP+bZwXtPDMQVbBKzbJ/vZBif0L69KH1+cHv1SZ6e0FKLvjyHe8mqsIqYOmw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + parse-diff@0.7.1: resolution: {integrity: sha512-1j3l8IKcy4yRK2W4o9EYvJLSzpAVwz4DXqCewYyx2vEwk2gcf3DBPqc8Fj4XV3K33OYJ08A8fWwyu/ykD/HUSg==} @@ -7990,6 +7608,10 @@ packages: engines: {node: '>=0.10.0'} hasBin: true + parse-imports@2.1.0: + resolution: {integrity: sha512-JQWgmK2o4w8leUkZeZPatWdAny6vXGU/3siIUvMF6J2rDCud9aTt8h/px9oZJ6U3EcfhngBJ635uPFI0q0VAeA==} + engines: {node: '>= 18'} + parse-json@4.0.0: resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} engines: {node: '>=4'} @@ -8015,9 +7637,6 @@ packages: parse-url@8.1.0: resolution: {integrity: sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==} - parse5-htmlparser2-tree-adapter@7.0.0: - resolution: {integrity: sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==} - parse5@7.1.2: resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} @@ -8028,10 +7647,6 @@ packages: pascal-case@3.1.2: resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} - pascalcase@0.1.1: - resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} - engines: {node: '>=0.10.0'} - path-exists@3.0.0: resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} engines: {node: '>=4'} @@ -8090,11 +7705,8 @@ packages: pathval@1.1.1: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - performance-now@2.1.0: - resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} - - picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -8148,22 +7760,32 @@ packages: engines: {node: '>=16'} hasBin: true + playwright-core@1.45.1: + resolution: {integrity: sha512-LF4CUUtrUu2TCpDw4mcrAIuYrEjVDfT1cHbJMfwnE2+1b8PZcFzPNgvZCvq2JfQ4aTjRCCHw5EJ2tmr2NSzdPg==} + engines: {node: '>=18'} + hasBin: true + playwright@1.44.1: resolution: {integrity: sha512-qr/0UJ5CFAtloI3avF95Y0L1xQo6r3LQArLIg/z/PoGJ6xa+EwzrwO5lpNr/09STxdHuUoP2mvuELJS+hLdtgg==} engines: {node: '>=16'} hasBin: true + playwright@1.45.1: + resolution: {integrity: sha512-Hjrgae4kpSQBr98nhCj3IScxVeVUixqj+5oyif8TdIn2opTCPEzqAqNMeK42i3cWDCVu9MI+ZsGWw+gVR4ISBg==} + engines: {node: '>=18'} + hasBin: true + please-upgrade-node@3.2.0: resolution: {integrity: sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==} - posix-character-classes@0.1.1: - resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==} - engines: {node: '>=0.10.0'} - possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} + postcss-selector-parser@6.1.0: + resolution: {integrity: sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==} + engines: {node: '>=4'} + postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} @@ -8175,6 +7797,10 @@ packages: resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} engines: {node: ^10 || ^12 || >=14} + postcss@8.4.39: + resolution: {integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==} + engines: {node: ^10 || ^12 || >=14} + prelude-ls@1.1.2: resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} engines: {node: '>= 0.8.0'} @@ -8226,6 +7852,10 @@ packages: resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + proc-log@4.2.0: + resolution: {integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} @@ -8237,6 +7867,16 @@ packages: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} + proggy@2.0.0: + resolution: {integrity: sha512-69agxLtnI8xBs9gUGqEnK26UfiexpHy+KUpBQWabiytQjnn5wFY8rklAi7GRfABIuPNnQ/ik48+LGLkYYJcy4A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + promise-all-reject-late@1.0.1: + resolution: {integrity: sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==} + + promise-call-limit@3.0.1: + resolution: {integrity: sha512-utl+0x8gIDasV5X+PI5qWEPqH6fJS0pFtQ/4gZ95xfEFb/89dmh+/b895TbFDBLiafBvxD/PGTKfvxl4kH/pQg==} + promise-inflight@1.0.1: resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} peerDependencies: @@ -8257,9 +7897,6 @@ packages: resolution: {integrity: sha512-KQVDEubSUHGSt5xLakaToDFrSoZhStB8dXLzk2xvwR67gJktrHFvpR63oZgHyK19WKbHFLXJqCPXdVR3aBP8Ig==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - prop-types-exact@1.2.0: - resolution: {integrity: sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==} - prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} @@ -8312,19 +7949,9 @@ packages: resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} engines: {node: '>=8'} - raf@3.4.1: - resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==} - - railroad-diagrams@1.0.0: - resolution: {integrity: sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==} - rambda@7.5.0: resolution: {integrity: sha512-y/M9weqWAH4iopRd7EHDEQQvpFPHj1AA3oHozE9tfITHUtTR7Z9PSlIRRG2l1GuW7sefC1cXFfIcF+cgnShdBA==} - randexp@0.4.6: - resolution: {integrity: sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==} - engines: {node: '>=0.12'} - randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} @@ -8353,35 +7980,29 @@ packages: engines: {node: '>=8.10.0'} hasBin: true - react-dom@18.2.0: - resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} + react-dom@18.3.1: + resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} peerDependencies: - react: ^18.2.0 + react: ^18.3.1 - react-hook-form@7.52.0: - resolution: {integrity: sha512-mJX506Xc6mirzLsmXUJyqlAI3Kj9Ph2RhplYhUVffeOQSnubK2uVqBFOBJmvKikvbFV91pxVXmDiR+QMF19x6A==} + react-hook-form@7.52.1: + resolution: {integrity: sha512-uNKIhaoICJ5KQALYZ4TOaOLElyM+xipord+Ha3crEFhTntdLvWZqVY49Wqd/0GiVCA/f9NjemLeiNPjG7Hpurg==} engines: {node: '>=12.22.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 - react-is@18.2.0: - resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} - - react-reconciler@0.29.0: - resolution: {integrity: sha512-wa0fGj7Zht1EYMRhKWwoo1H9GApxYLBuhoAuXN0TlltESAjDssB+Apf0T/DngVqaMyPypDmabL37vw/2aRM98Q==} - engines: {node: '>=0.10.0'} - peerDependencies: - react: ^18.2.0 + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - react-router-dom@6.23.1: - resolution: {integrity: sha512-utP+K+aSTtEdbWpC+4gxhdlPFwuEfDKq8ZrPFU65bbRJY+l706qjR7yaidBpo3MSeA/fzwbXWbKBI6ftOnP3OQ==} + react-router-dom@6.24.1: + resolution: {integrity: sha512-U19KtXqooqw967Vw0Qcn5cOvrX5Ejo9ORmOtJMzYWtCT4/WOfFLIZGGsVLxcd9UkBO0mSTZtXqhZBsWlHr7+Sg==} engines: {node: '>=14.0.0'} peerDependencies: react: '>=16.8' react-dom: '>=16.8' - react-router@6.23.1: - resolution: {integrity: sha512-fzcOaRF69uvqbbM7OhvQyBTFDVrrGlsFdS3AL+1KfIBtGETibHzi3FkoTRyiDJnWNc2VxrfvR+657ROHjaNjqQ==} + react-router@6.24.1: + resolution: {integrity: sha512-PTXFXGK2pyXpHzVo3rR9H7ip4lSPZZc0bHG5CARmj65fTT6qG7sTngmb6lcYu1gf3y/8KxORoy9yn59pGpCnpg==} engines: {node: '>=14.0.0'} peerDependencies: react: '>=16.8' @@ -8392,21 +8013,11 @@ packages: react: ^16.0.0 || ^17 || ^18 react-dom: ^16.0.0 || ^17 || ^18 - react-shallow-renderer@16.15.0: - resolution: {integrity: sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==} + react-simple-code-editor@0.14.1: + resolution: {integrity: sha512-BR5DtNRy+AswWJECyA17qhUDvrrCZ6zXOCfkQY5zSmb96BVUbpVAv03WpcjcwtCwiLbIANx3gebHOcXYn1EHow==} peerDependencies: - react: ^16.0.0 || ^17.0.0 || ^18.0.0 - - react-simple-code-editor@0.13.1: - resolution: {integrity: sha512-XYeVwRZwgyKtjNIYcAEgg2FaQcCZwhbarnkJIV20U2wkCU9q/CPFBo8nRXrK4GXUz3AvbqZFsZRrpUTkqqEYyQ==} - peerDependencies: - react: '*' - react-dom: '*' - - react-test-renderer@18.2.0: - resolution: {integrity: sha512-JWD+aQ0lh2gvh4NM3bBM42Kx+XybOxCpgYK7F8ugAlpaTSnWsX+39Z4XkOykGZAHrjwwTZT3x3KxswVWxHPUqA==} - peerDependencies: - react: ^18.2.0 + react: '>=16.8.0' + react-dom: '>=16.8.0' react-transition-group@4.4.5: resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} @@ -8414,8 +8025,8 @@ packages: react: '>=16.6.0' react-dom: '>=16.6.0' - react@18.2.0: - resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} read-cmd-shim@4.0.0: @@ -8426,16 +8037,6 @@ packages: resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - read-package-json@6.0.4: - resolution: {integrity: sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - deprecated: This package is no longer supported. Please use @npmcli/package-json instead. - - read-package-json@7.0.0: - resolution: {integrity: sha512-uL4Z10OKV4p6vbdvIXB+OzhInYtIozl/VxUBPgNkBuUi2DeRonnuspmaVAMcrkmfjKGNmRndyQAbE7/AmzGwFg==} - engines: {node: ^16.14.0 || >=18.0.0} - deprecated: This package is no longer supported. Please use @npmcli/package-json instead. - read-pkg-up@3.0.0: resolution: {integrity: sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==} engines: {node: '>=4'} @@ -8456,6 +8057,10 @@ packages: resolution: {integrity: sha512-bvxi1QLJHcaywCAEsAk4DG3nVoqiY2Csps3qzWalhj5hFqRn1d/OixkFXtLO1PrgHUcAP0FNaSY/5GYNfENFFQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + read@3.0.1: + resolution: {integrity: sha512-SLBrDU/Srs/9EoWhU5GdbAoxG1GzpQHo/6qiGItaoLJ1thmYpcNIM1qISEUvyHBzfGlWIyd6p2DNi1oV1VmAuw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + readable-stream@1.0.34: resolution: {integrity: sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==} @@ -8497,9 +8102,6 @@ packages: resolution: {integrity: sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==} engines: {node: '>= 0.4'} - reflect.ownkeys@0.2.0: - resolution: {integrity: sha512-qOLsBKHCpSOFKK1NUOCGC5VyeufB6lEsFe92AL2bhIJsacZS1qdoOZSbPk3MYKuT2cFlRDnulKXuuElIrMjGUg==} - regenerate-unicode-properties@10.1.1: resolution: {integrity: sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==} engines: {node: '>=4'} @@ -8516,10 +8118,6 @@ packages: regenerator-transform@0.15.2: resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} - regex-not@1.0.2: - resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} - engines: {node: '>=0.10.0'} - regexp.prototype.flags@1.5.2: resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} engines: {node: '>= 0.4'} @@ -8559,10 +8157,6 @@ packages: renderkid@3.0.0: resolution: {integrity: sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==} - repeat-element@1.1.4: - resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==} - engines: {node: '>=0.10.0'} - repeat-string@1.6.1: resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} engines: {node: '>=0.10'} @@ -8599,10 +8193,6 @@ packages: resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - resolve-url@0.2.1: - resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} - deprecated: https://github.com/lydell/resolve-url#deprecated - resolve@1.1.7: resolution: {integrity: sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==} @@ -8618,10 +8208,6 @@ packages: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} - ret@0.1.15: - resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} - engines: {node: '>=0.12'} - retry@0.12.0: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} @@ -8657,9 +8243,9 @@ packages: engines: {node: '>=14'} hasBin: true - rimraf@5.0.7: - resolution: {integrity: sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==} - engines: {node: '>=14.18'} + rimraf@5.0.8: + resolution: {integrity: sha512-XSh0V2/yNhDEi8HwdIefD8MLgs4LQXPag/nEJWs3YUc3Upn+UHa1GyIkEg9xSSNt7HnkO5FjTvmcRzgf+8UZuw==} + engines: {node: '>=18'} hasBin: true robust-predicates@3.0.2: @@ -8671,9 +8257,6 @@ packages: rrweb-cssom@0.7.0: resolution: {integrity: sha512-KlSv0pm9kgQSRxXEMgtivPJ4h826YHsuob8pSHcfSZsSXGtvpEAie8S0AnXuObEJ7nhikOb4ahwxDm0H2yW17g==} - rst-selector-parser@2.2.3: - resolution: {integrity: sha512-nDG1rZeP6oFTLN6yNDV/uiAvs1+FS/KlrEwh7+y7dpuApDBy6bI2HTBcc0/V8lv9OTqfyD34eF7au2pm8aBbhA==} - rtl-css-js@1.16.1: resolution: {integrity: sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==} @@ -8701,9 +8284,6 @@ packages: resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} engines: {node: '>= 0.4'} - safe-regex@1.1.0: - resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} - safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -8715,8 +8295,8 @@ packages: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} - scheduler@0.23.0: - resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} + scheduler@0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} schema-utils@3.3.0: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} @@ -8754,9 +8334,6 @@ packages: resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} engines: {node: '>= 0.8.0'} - serialize-javascript@6.0.0: - resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} - serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} @@ -8783,10 +8360,6 @@ packages: resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} engines: {node: '>= 0.4'} - set-value@2.0.1: - resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} - engines: {node: '>=0.10.0'} - setimmediate@1.0.5: resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} @@ -8826,11 +8399,6 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - sigstore@1.9.0: - resolution: {integrity: sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - sigstore@2.2.0: resolution: {integrity: sha512-fcU9clHwEss2/M/11FFM8Jwc4PjBgbhXoNskoK5guoK0qGQBSeUbQZRJ+B2fDFIvhyf0gqCaPrel9mszbhAxug==} engines: {node: ^16.14.0 || >=18.0.0} @@ -8861,22 +8429,13 @@ packages: resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} engines: {node: '>=14.16'} + slashes@3.0.12: + resolution: {integrity: sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==} + smart-buffer@4.2.0: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - snapdragon-node@2.1.1: - resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} - engines: {node: '>=0.10.0'} - - snapdragon-util@3.0.1: - resolution: {integrity: sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==} - engines: {node: '>=0.10.0'} - - snapdragon@0.8.2: - resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} - engines: {node: '>=0.10.0'} - socket.io-adapter@2.5.2: resolution: {integrity: sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==} @@ -8888,10 +8447,6 @@ packages: resolution: {integrity: sha512-DcotgfP1Zg9iP/dH9zvAQcWrE0TtbMVwXmlV4T4mqsvY+gw+LqUGPfx2AoVyRk0FLME+GQhufDMyacFmw7ksqw==} engines: {node: '>=10.2.0'} - socks-proxy-agent@7.0.0: - resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} - engines: {node: '>= 10'} - socks-proxy-agent@8.0.2: resolution: {integrity: sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==} engines: {node: '>= 14'} @@ -8908,17 +8463,9 @@ packages: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} - source-map-resolve@0.5.3: - resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} - deprecated: See https://github.com/lydell/source-map-resolve#deprecated - source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - source-map-url@0.4.1: - resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} - deprecated: See https://github.com/lydell/source-map-url#deprecated - source-map@0.2.0: resolution: {integrity: sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==} engines: {node: '>=0.8.0'} @@ -8953,10 +8500,6 @@ packages: spdx-license-ids@3.0.16: resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==} - split-string@3.1.0: - resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} - engines: {node: '>=0.10.0'} - split2@3.2.2: resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} @@ -8966,18 +8509,10 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - ssri@10.0.5: - resolution: {integrity: sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==} + ssri@10.0.6: + resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - ssri@9.0.1: - resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - static-extend@0.1.2: - resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} - engines: {node: '>=0.10.0'} - statuses@1.5.0: resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} engines: {node: '>= 0.6'} @@ -9014,6 +8549,9 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} + string.prototype.includes@2.0.0: + resolution: {integrity: sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==} + string.prototype.matchall@4.0.11: resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} engines: {node: '>= 0.4'} @@ -9146,6 +8684,10 @@ packages: resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} engines: {node: ^14.18.0 || >=16.0.0} + synckit@0.9.0: + resolution: {integrity: sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==} + engines: {node: ^14.18.0 || >=16.0.0} + tapable@0.1.10: resolution: {integrity: sha512-jX8Et4hHg57mug1/079yitEKWGB3LCwoxByLsNim89LABq8NqgiX+6iYVOsq0vX8uJHkU+DZ5fnq95f800bEsQ==} engines: {node: '>=0.6'} @@ -9166,8 +8708,8 @@ packages: resolution: {integrity: sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==} engines: {node: '>=4'} - temp@0.8.4: - resolution: {integrity: sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==} + temp@0.9.4: + resolution: {integrity: sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==} engines: {node: '>=6.0.0'} terser-webpack-plugin@5.3.10: @@ -9236,22 +8778,10 @@ packages: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} - to-object-path@0.3.0: - resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} - engines: {node: '>=0.10.0'} - - to-regex-range@2.1.1: - resolution: {integrity: sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==} - engines: {node: '>=0.10.0'} - to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - to-regex@3.0.2: - resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} - engines: {node: '>=0.10.0'} - toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} @@ -9278,6 +8808,10 @@ packages: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true + treeverse@3.0.0: + resolution: {integrity: sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + trim-newlines@3.0.1: resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} engines: {node: '>=8'} @@ -9308,15 +8842,11 @@ packages: resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==} engines: {node: '>=0.6.x'} - tsx@4.15.5: - resolution: {integrity: sha512-iKi8jQ2VBmZ2kU/FkGkL2OSHBHsazsUzsdC/W/RwhKIEsIoZ1alCclZHP5jGfNHEaEWUJFM1GquzCf+4db3b0w==} + tsx@4.16.2: + resolution: {integrity: sha512-C1uWweJDgdtX2x600HjaFaucXTilT7tgUZHbOE4+ypskZ1OP8CRCSDkCxG6Vya9EwaFIVagWwpaVAn5wzypaqQ==} engines: {node: '>=18.0.0'} hasBin: true - tuf-js@1.1.7: - resolution: {integrity: sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - tuf-js@2.2.0: resolution: {integrity: sha512-ZSDngmP1z6zw+FIkIBjvOp/II/mIub/O7Pp12j1WNsiCpg5R5wAc//i555bBQsE44O94btLt0xM/Zr2LQjwdCg==} engines: {node: ^16.14.0 || >=18.0.0} @@ -9387,8 +8917,8 @@ packages: typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - typescript@5.4.5: - resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + typescript@5.5.3: + resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==} engines: {node: '>=14.17'} hasBin: true @@ -9432,10 +8962,6 @@ packages: unified@9.2.2: resolution: {integrity: sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ==} - union-value@1.0.1: - resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} - engines: {node: '>=0.10.0'} - unique-filename@3.0.0: resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -9459,6 +8985,9 @@ packages: universal-user-agent@6.0.1: resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==} + universal-user-agent@7.0.2: + resolution: {integrity: sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==} + universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -9475,10 +9004,6 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - unset-value@1.0.0: - resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==} - engines: {node: '>=0.10.0'} - unzipper@0.10.14: resolution: {integrity: sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==} @@ -9498,10 +9023,6 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - urix@0.1.0: - resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==} - deprecated: Please see https://github.com/lydell/urix#deprecated - url-parse@1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} @@ -9511,10 +9032,6 @@ packages: urlpattern-polyfill@8.0.2: resolution: {integrity: sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==} - use@3.1.1: - resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} - engines: {node: '>=0.10.0'} - util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -9532,6 +9049,10 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} + uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + hasBin: true + uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true @@ -9551,11 +9072,8 @@ packages: validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - validate-npm-package-name@3.0.0: - resolution: {integrity: sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==} - - validate-npm-package-name@5.0.0: - resolution: {integrity: sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==} + validate-npm-package-name@5.0.1: + resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} vary@1.1.2: @@ -9576,6 +9094,9 @@ packages: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} + walk-up-path@3.0.1: + resolution: {integrity: sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==} + watchpack@2.4.1: resolution: {integrity: sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==} engines: {node: '>=10.13.0'} @@ -9623,8 +9144,8 @@ packages: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} - webpack@5.92.0: - resolution: {integrity: sha512-Bsw2X39MYIgxouNATyVpCNVWBCuUwDgWtN78g6lSdPJRLaQ/PUVm/oXcaRAyY/sMFoKFQrsPeqvTizWtq7QPCA==} + webpack@5.92.1: + resolution: {integrity: sha512-JECQ7IwJb+7fgUFBlrJzbyu3GEuNBcdqr1LD7IbSzwkSmIevTm8PF+wej3Oxuz/JFBUZ6O1o43zsPkwm1C4TmA==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -9696,8 +9217,8 @@ packages: wordwrap@1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - workerpool@6.2.1: - resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==} + workerpool@6.5.1: + resolution: {integrity: sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==} wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} @@ -9810,10 +9331,6 @@ packages: resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} engines: {node: '>=6'} - yargs-parser@20.2.4: - resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} - engines: {node: '>=10'} - yargs-parser@20.2.9: resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} engines: {node: '>=10'} @@ -9965,12 +9482,12 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - '@argos-ci/core@2.2.0': + '@argos-ci/core@2.3.0': dependencies: '@argos-ci/util': 2.0.0 - axios: 1.7.2(debug@4.3.4) + axios: 1.7.2(debug@4.3.5) convict: 6.2.4 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) fast-glob: 3.3.2 sharp: 0.33.4 tmp: 0.2.3 @@ -9996,7 +9513,7 @@ snapshots: '@babel/code-frame@7.24.7': dependencies: '@babel/highlight': 7.24.7 - picocolors: 1.0.0 + picocolors: 1.0.1 '@babel/compat-data@7.24.7': {} @@ -10013,7 +9530,7 @@ snapshots: '@babel/traverse': 7.24.7 '@babel/types': 7.24.7 convert-source-map: 2.0.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -10073,7 +9590,7 @@ snapshots: '@babel/core': 7.24.7 '@babel/helper-compilation-targets': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -10184,7 +9701,7 @@ snapshots: '@babel/helper-validator-identifier': 7.24.7 chalk: 2.4.2 js-tokens: 4.0.0 - picocolors: 1.0.0 + picocolors: 1.0.1 '@babel/node@7.24.7(@babel/core@7.24.7)': dependencies: @@ -10226,29 +9743,6 @@ snapshots: '@babel/helper-environment-visitor': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.24.7)': - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.24.7) - '@babel/helper-plugin-utils': 7.24.7 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.24.7)': - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.7) - - '@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.24.7)': - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.7) - transitivePeerDependencies: - - supports-color - '@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.24.7)': dependencies: '@babel/core': 7.24.7 @@ -10286,7 +9780,7 @@ snapshots: '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-flow@7.23.3(@babel/core@7.24.7)': + '@babel/plugin-syntax-flow@7.24.7(@babel/core@7.24.7)': dependencies: '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 @@ -10474,11 +9968,11 @@ snapshots: '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.7) - '@babel/plugin-transform-flow-strip-types@7.23.3(@babel/core@7.24.7)': + '@babel/plugin-transform-flow-strip-types@7.24.7(@babel/core@7.24.7)': dependencies: '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-flow': 7.23.3(@babel/core@7.24.7) + '@babel/plugin-syntax-flow': 7.24.7(@babel/core@7.24.7) '@babel/plugin-transform-for-of@7.24.7(@babel/core@7.24.7)': dependencies: @@ -10839,12 +10333,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/preset-flow@7.23.3(@babel/core@7.24.7)': + '@babel/preset-flow@7.24.7(@babel/core@7.24.7)': dependencies: '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 '@babel/helper-validator-option': 7.24.7 - '@babel/plugin-transform-flow-strip-types': 7.23.3(@babel/core@7.24.7) + '@babel/plugin-transform-flow-strip-types': 7.24.7(@babel/core@7.24.7) '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.24.7)': dependencies: @@ -10912,7 +10406,7 @@ snapshots: '@babel/helper-split-export-declaration': 7.24.7 '@babel/parser': 7.24.7 '@babel/types': 7.24.7 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -10931,16 +10425,16 @@ snapshots: '@docsearch/css@3.6.0': {} - '@docsearch/react@3.6.0(@algolia/client-search@4.22.1)(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(search-insights@2.13.0)': + '@docsearch/react@3.6.0(@algolia/client-search@4.22.1)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.13.0)': dependencies: '@algolia/autocomplete-core': 1.9.3(@algolia/client-search@4.22.1)(algoliasearch@4.22.1)(search-insights@2.13.0) '@algolia/autocomplete-preset-algolia': 1.9.3(@algolia/client-search@4.22.1)(algoliasearch@4.22.1) '@docsearch/css': 3.6.0 algoliasearch: 4.22.1 optionalDependencies: - '@types/react': 18.2.60 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@types/react': 18.3.3 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) search-insights: 2.13.0 transitivePeerDependencies: - '@algolia/client-search' @@ -10982,19 +10476,19 @@ snapshots: '@emotion/memoize@0.8.1': {} - '@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0)': + '@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.7 '@emotion/babel-plugin': 11.11.0 '@emotion/cache': 11.11.0 '@emotion/serialize': 1.1.4 - '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.2.0) + '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.3.1) '@emotion/utils': 1.2.1 '@emotion/weak-memoize': 0.3.1 hoist-non-react-statics: 3.3.2 - react: 18.2.0 + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.60 + '@types/react': 18.3.3 transitivePeerDependencies: - supports-color @@ -11015,26 +10509,26 @@ snapshots: '@emotion/sheet@1.2.2': {} - '@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0)': + '@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.7 '@emotion/babel-plugin': 11.11.0 '@emotion/is-prop-valid': 1.2.2 - '@emotion/react': 11.11.4(@types/react@18.2.60)(react@18.2.0) + '@emotion/react': 11.11.4(@types/react@18.3.3)(react@18.3.1) '@emotion/serialize': 1.1.4 - '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.2.0) + '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.3.1) '@emotion/utils': 1.2.1 - react: 18.2.0 + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.60 + '@types/react': 18.3.3 transitivePeerDependencies: - supports-color '@emotion/unitless@0.8.1': {} - '@emotion/use-insertion-effect-with-fallbacks@1.0.1(react@18.2.0)': + '@emotion/use-insertion-effect-with-fallbacks@1.0.1(react@18.3.1)': dependencies: - react: 18.2.0 + react: 18.3.1 '@emotion/utils@1.2.1': {} @@ -11044,7 +10538,7 @@ snapshots: dependencies: '@types/eslint': 8.56.10 '@types/estree': 1.0.5 - '@typescript-eslint/types': 7.13.1 + '@typescript-eslint/types': 7.15.0 comment-parser: 1.4.1 esquery: 1.5.0 jsdoc-type-pratt-parser: 4.0.0 @@ -11128,7 +10622,7 @@ snapshots: '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) espree: 9.6.1 globals: 13.24.0 ignore: 5.3.1 @@ -11143,7 +10637,7 @@ snapshots: '@fast-csv/format@4.3.5': dependencies: - '@types/node': 18.19.34 + '@types/node': 18.19.39 lodash.escaperegexp: 4.1.2 lodash.isboolean: 3.0.3 lodash.isequal: 4.5.0 @@ -11152,7 +10646,7 @@ snapshots: '@fast-csv/parse@4.3.6': dependencies: - '@types/node': 18.19.34 + '@types/node': 18.19.39 lodash.escaperegexp: 4.1.2 lodash.groupby: 4.6.0 lodash.isfunction: 3.0.9 @@ -11169,11 +10663,11 @@ snapshots: '@floating-ui/core': 1.6.0 '@floating-ui/utils': 0.2.1 - '@floating-ui/react-dom@2.0.8(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@floating-ui/react-dom@2.0.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@floating-ui/dom': 1.6.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) '@floating-ui/utils@0.2.1': {} @@ -11193,7 +10687,7 @@ snapshots: '@gitbeaker/core': 38.12.1 '@gitbeaker/requester-utils': 38.12.1 - '@googleapis/sheets@7.0.1(encoding@0.1.13)': + '@googleapis/sheets@8.0.0(encoding@0.1.13)': dependencies: googleapis-common: 7.0.1(encoding@0.1.13) transitivePeerDependencies: @@ -11203,7 +10697,7 @@ snapshots: '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.2 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -11298,6 +10792,8 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + '@isaacs/string-locale-compare@1.1.0': {} + '@istanbuljs/load-nyc-config@1.1.0': dependencies: camelcase: 5.3.1 @@ -11334,68 +10830,74 @@ snapshots: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 - '@lerna/create@8.1.3(encoding@0.1.13)(typescript@5.4.5)': + '@lerna/create@8.1.6(babel-plugin-macros@3.1.0)(encoding@0.1.13)(typescript@5.5.3)': dependencies: - '@npmcli/run-script': 7.0.2 + '@npmcli/arborist': 7.5.3 + '@npmcli/package-json': 5.2.0 + '@npmcli/run-script': 8.1.0 '@nx/devkit': 17.3.0(nx@17.3.0) '@octokit/plugin-enterprise-rest': 6.0.1 '@octokit/rest': 19.0.11(encoding@0.1.13) + aproba: 2.0.0 byte-size: 8.1.1 chalk: 4.1.0 clone-deep: 4.0.1 - cmd-shim: 6.0.1 + cmd-shim: 6.0.3 + color-support: 1.1.3 columnify: 1.6.0 + console-control-strings: 1.1.0 conventional-changelog-core: 5.0.1 conventional-recommended-bump: 7.0.1 - cosmiconfig: 8.3.6(typescript@5.4.5) - dedent: 0.7.0 + cosmiconfig: 8.3.6(typescript@5.5.3) + dedent: 1.5.3(babel-plugin-macros@3.1.0) execa: 5.0.0 fs-extra: 11.2.0 get-stream: 6.0.0 - git-url-parse: 13.1.0 - glob-parent: 5.1.2 + git-url-parse: 14.0.0 + glob-parent: 6.0.2 globby: 11.1.0 graceful-fs: 4.2.11 has-unicode: 2.0.1 ini: 1.3.8 - init-package-json: 5.0.0 + init-package-json: 6.0.3 inquirer: 8.2.6 is-ci: 3.0.1 is-stream: 2.0.0 js-yaml: 4.1.0 - libnpmpublish: 7.3.0 + libnpmpublish: 9.0.9 load-json-file: 6.2.0 lodash: 4.17.21 make-dir: 4.0.0 minimatch: 3.0.5 multimatch: 5.0.0 node-fetch: 2.6.7(encoding@0.1.13) - npm-package-arg: 8.1.1 - npm-packlist: 5.1.1 - npm-registry-fetch: 14.0.5 - npmlog: 6.0.2 + npm-package-arg: 11.0.2 + npm-packlist: 8.0.2 + npm-registry-fetch: 17.1.0 nx: 17.3.0 p-map: 4.0.0 p-map-series: 2.1.0 p-queue: 6.6.2 p-reduce: 2.1.0 - pacote: 17.0.6 + pacote: 18.0.6 pify: 5.0.0 read-cmd-shim: 4.0.0 - read-package-json: 6.0.4 resolve-from: 5.0.0 rimraf: 4.4.1 semver: 7.6.2 + set-blocking: 2.0.0 signal-exit: 3.0.7 slash: 3.0.0 - ssri: 9.0.1 + ssri: 10.0.6 + string-width: 4.2.3 strong-log-transformer: 2.1.0 tar: 6.2.1 temp-dir: 1.0.0 upath: 2.0.1 - uuid: 9.0.1 + uuid: 10.0.0 validate-npm-package-license: 3.0.4 - validate-npm-package-name: 5.0.0 + validate-npm-package-name: 5.0.1 + wide-align: 1.1.5 write-file-atomic: 5.0.1 write-pkg: 4.0.0 yargs: 17.7.2 @@ -11403,65 +10905,67 @@ snapshots: transitivePeerDependencies: - '@swc-node/register' - '@swc/core' + - babel-plugin-macros - bluebird - debug - encoding - supports-color - typescript - '@mnajdova/enzyme-adapter-react-18@0.2.0(enzyme@3.11.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@mui/base@5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - enzyme: 3.11.0 - enzyme-adapter-utils: 1.14.1(react@18.2.0) - enzyme-shallow-equal: 1.0.5 - has: 1.0.4 - object.assign: 4.1.5 - object.values: 1.2.0 + '@babel/runtime': 7.24.7 + '@floating-ui/react-dom': 2.0.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@mui/types': 7.2.14(@types/react@18.3.3) + '@mui/utils': 5.16.0(@types/react@18.3.3)(react@18.3.1) + '@popperjs/core': 2.11.8 + clsx: 2.1.1 prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-is: 18.2.0 - react-reconciler: 0.29.0(react@18.2.0) - react-test-renderer: 18.2.0(react@18.2.0) - semver: 5.7.2 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.3 - '@mui/base@5.0.0-beta.40(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@mui/core-downloads-tracker@5.16.0': {} + + '@mui/docs@6.0.0-dev.240424162023-9968b4889d(7g77v67zn53nen4txxrs63agbq)': dependencies: '@babel/runtime': 7.24.7 - '@floating-ui/react-dom': 2.0.8(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@mui/types': 7.2.14(@types/react@18.2.60) - '@mui/utils': 5.15.20(@types/react@18.2.60)(react@18.2.0) - '@popperjs/core': 2.11.8 + '@mui/base': 5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@mui/icons-material': 5.16.0(@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) + '@mui/internal-markdown': 1.0.7 + '@mui/material': 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@mui/system': 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) + clipboard-copy: 4.0.1 clsx: 2.1.1 + next: 14.2.4(@babel/core@7.24.7)(@opentelemetry/api@1.8.0)(@playwright/test@1.44.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + nprogress: 0.2.0 prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.60 + '@types/react': 18.3.3 - '@mui/core-downloads-tracker@5.15.20': {} - - '@mui/icons-material@5.15.20(@mui/material@5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@types/react@18.2.60)(react@18.2.0)': + '@mui/icons-material@5.16.0(@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.7 - '@mui/material': 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - react: 18.2.0 + '@mui/material': 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.60 + '@types/react': 18.3.3 '@mui/internal-docs-utils@1.0.7': dependencies: - rimraf: 5.0.7 - typescript: 5.4.5 + rimraf: 5.0.8 + typescript: 5.5.3 - '@mui/internal-markdown@1.0.5': + '@mui/internal-markdown@1.0.7': dependencies: '@babel/runtime': 7.24.7 lodash: 4.17.21 - marked: 5.1.2 + marked: 13.0.1 prismjs: 1.29.0 - '@mui/internal-scripts@1.0.10': + '@mui/internal-scripts@1.0.12': dependencies: '@babel/core': 7.24.7 '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.7) @@ -11471,153 +10975,150 @@ snapshots: '@mui/internal-docs-utils': 1.0.7 doctrine: 3.0.0 lodash: 4.17.21 - typescript: 5.4.5 + typescript: 5.5.3 uuid: 9.0.1 transitivePeerDependencies: - supports-color - '@mui/internal-test-utils@1.0.1(@babel/core@7.24.7)(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@mui/internal-test-utils@1.0.4(@babel/core@7.24.7)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/plugin-transform-modules-commonjs': 7.24.7(@babel/core@7.24.7) '@babel/preset-typescript': 7.24.7(@babel/core@7.24.7) '@babel/register': 7.24.6(@babel/core@7.24.7) '@babel/runtime': 7.24.7 '@emotion/cache': 11.11.0 - '@emotion/react': 11.11.4(@types/react@18.2.60)(react@18.2.0) - '@mnajdova/enzyme-adapter-react-18': 0.2.0(enzyme@3.11.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@testing-library/dom': 10.1.0 - '@testing-library/react': 15.0.7(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@emotion/react': 11.11.4(@types/react@18.3.3)(react@18.3.1) + '@testing-library/dom': 10.3.1 + '@testing-library/react': 16.0.0(@testing-library/dom@10.3.1)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) chai: 4.4.1 chai-dom: 1.12.0(chai@4.4.1) dom-accessibility-api: 0.6.3 - enzyme: 3.11.0 format-util: 1.0.5 fs-extra: 11.2.0 jsdom: 24.1.0 lodash: 4.17.21 - mocha: 10.4.0 - playwright: 1.44.1 + mocha: 10.6.0 + playwright: 1.45.1 prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-test-renderer: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) sinon: 16.1.3 transitivePeerDependencies: - '@babel/core' - '@types/react' + - '@types/react-dom' - bufferutil - canvas - supports-color - utf-8-validate - '@mui/joy@5.0.0-beta.32(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@mui/joy@5.0.0-beta.47(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.7 - '@mui/base': 5.0.0-beta.40(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@mui/core-downloads-tracker': 5.15.20 - '@mui/system': 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) - '@mui/types': 7.2.14(@types/react@18.2.60) - '@mui/utils': 5.15.20(@types/react@18.2.60)(react@18.2.0) + '@mui/base': 5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@mui/core-downloads-tracker': 5.16.0 + '@mui/system': 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) + '@mui/types': 7.2.14(@types/react@18.3.3) + '@mui/utils': 5.16.0(@types/react@18.3.3)(react@18.3.1) clsx: 2.1.1 prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@emotion/react': 11.11.4(@types/react@18.2.60)(react@18.2.0) - '@emotion/styled': 11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) - '@types/react': 18.2.60 + '@emotion/react': 11.11.4(@types/react@18.3.3)(react@18.3.1) + '@emotion/styled': 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) + '@types/react': 18.3.3 - '@mui/lab@5.0.0-alpha.170(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@mui/material@5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@mui/lab@5.0.0-alpha.171(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.7 - '@mui/base': 5.0.0-beta.40(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@mui/material': 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@mui/system': 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) - '@mui/types': 7.2.14(@types/react@18.2.60) - '@mui/utils': 5.15.20(@types/react@18.2.60)(react@18.2.0) + '@mui/base': 5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@mui/material': 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@mui/system': 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) + '@mui/types': 7.2.14(@types/react@18.3.3) + '@mui/utils': 5.16.0(@types/react@18.3.3)(react@18.3.1) clsx: 2.1.1 prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@emotion/react': 11.11.4(@types/react@18.2.60)(react@18.2.0) - '@emotion/styled': 11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) - '@types/react': 18.2.60 + '@emotion/react': 11.11.4(@types/react@18.3.3)(react@18.3.1) + '@emotion/styled': 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) + '@types/react': 18.3.3 - '@mui/material-nextjs@5.15.11(@emotion/cache@11.11.0)(@emotion/server@11.11.0)(@mui/material@5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@types/react@18.2.60)(next@14.2.4(@babel/core@7.24.7)(@opentelemetry/api@1.8.0)(@playwright/test@1.44.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0)': + '@mui/material-nextjs@5.15.11(@emotion/cache@11.11.0)(@emotion/server@11.11.0)(@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(next@14.2.4(@babel/core@7.24.7)(@opentelemetry/api@1.8.0)(@playwright/test@1.44.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.7 - '@mui/material': 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - next: 14.2.4(@babel/core@7.24.7)(@opentelemetry/api@1.8.0)(@playwright/test@1.44.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - react: 18.2.0 + '@mui/material': 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.4(@babel/core@7.24.7)(@opentelemetry/api@1.8.0)(@playwright/test@1.44.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 optionalDependencies: '@emotion/cache': 11.11.0 '@emotion/server': 11.11.0 - '@types/react': 18.2.60 + '@types/react': 18.3.3 - '@mui/material@5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.7 - '@mui/base': 5.0.0-beta.40(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@mui/core-downloads-tracker': 5.15.20 - '@mui/system': 5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) - '@mui/types': 7.2.14(@types/react@18.2.60) - '@mui/utils': 5.15.20(@types/react@18.2.60)(react@18.2.0) + '@mui/base': 5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@mui/core-downloads-tracker': 5.16.0 + '@mui/system': 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) + '@mui/types': 7.2.14(@types/react@18.3.3) + '@mui/utils': 5.16.0(@types/react@18.3.3)(react@18.3.1) '@types/react-transition-group': 4.4.10 clsx: 2.1.1 csstype: 3.1.3 prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-is: 18.2.0 - react-transition-group: 4.4.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-is: 18.3.1 + react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) optionalDependencies: - '@emotion/react': 11.11.4(@types/react@18.2.60)(react@18.2.0) - '@emotion/styled': 11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) - '@types/react': 18.2.60 + '@emotion/react': 11.11.4(@types/react@18.3.3)(react@18.3.1) + '@emotion/styled': 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) + '@types/react': 18.3.3 - '@mui/monorepo@https://codeload.github.com/mui/material-ui/tar.gz/22c5206a9e8191b2f81131d6978a0958e55b7032(@opentelemetry/api@1.8.0)(encoding@0.1.13)': + '@mui/monorepo@https://codeload.github.com/mui/material-ui/tar.gz/43cb32700af699cd48baaf6922fbe21343f30e2f(encoding@0.1.13)': dependencies: - '@googleapis/sheets': 7.0.1(encoding@0.1.13) - '@netlify/functions': 2.7.0(@opentelemetry/api@1.8.0) - '@slack/bolt': 3.18.0 - execa: 9.2.0 - google-auth-library: 9.10.0(encoding@0.1.13) + '@googleapis/sheets': 8.0.0(encoding@0.1.13) + '@netlify/functions': 2.8.1 + '@slack/bolt': 3.19.0 + execa: 9.3.0 + google-auth-library: 9.11.0(encoding@0.1.13) transitivePeerDependencies: - - '@opentelemetry/api' - bufferutil - debug - encoding - supports-color - utf-8-validate - '@mui/private-theming@5.15.20(@types/react@18.2.60)(react@18.2.0)': + '@mui/private-theming@5.16.0(@types/react@18.3.3)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.7 - '@mui/utils': 5.15.20(@types/react@18.2.60)(react@18.2.0) + '@mui/utils': 5.16.0(@types/react@18.3.3)(react@18.3.1) prop-types: 15.8.1 - react: 18.2.0 + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.60 + '@types/react': 18.3.3 - '@mui/styled-engine@5.15.14(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(react@18.2.0)': + '@mui/styled-engine@5.15.14(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.7 '@emotion/cache': 11.11.0 csstype: 3.1.3 prop-types: 15.8.1 - react: 18.2.0 + react: 18.3.1 optionalDependencies: - '@emotion/react': 11.11.4(@types/react@18.2.60)(react@18.2.0) - '@emotion/styled': 11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) + '@emotion/react': 11.11.4(@types/react@18.3.3)(react@18.3.1) + '@emotion/styled': 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) - '@mui/styles@5.15.20(@types/react@18.2.60)(react@18.2.0)': + '@mui/styles@5.16.0(@types/react@18.3.3)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.7 '@emotion/hash': 0.9.1 - '@mui/private-theming': 5.15.20(@types/react@18.2.60)(react@18.2.0) - '@mui/types': 7.2.14(@types/react@18.2.60) - '@mui/utils': 5.15.20(@types/react@18.2.60)(react@18.2.0) + '@mui/private-theming': 5.16.0(@types/react@18.3.3)(react@18.3.1) + '@mui/types': 7.2.14(@types/react@18.3.3) + '@mui/utils': 5.16.0(@types/react@18.3.3)(react@18.3.1) clsx: 2.1.1 csstype: 3.1.3 hoist-non-react-statics: 3.3.2 @@ -11630,59 +11131,50 @@ snapshots: jss-plugin-rule-value-function: 10.10.0 jss-plugin-vendor-prefixer: 10.10.0 prop-types: 15.8.1 - react: 18.2.0 + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.60 + '@types/react': 18.3.3 - '@mui/system@5.15.20(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0)': + '@mui/system@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.7 - '@mui/private-theming': 5.15.20(@types/react@18.2.60)(react@18.2.0) - '@mui/styled-engine': 5.15.14(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0))(react@18.2.0) - '@mui/types': 7.2.14(@types/react@18.2.60) - '@mui/utils': 5.15.20(@types/react@18.2.60)(react@18.2.0) + '@mui/private-theming': 5.16.0(@types/react@18.3.3)(react@18.3.1) + '@mui/styled-engine': 5.15.14(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(react@18.3.1) + '@mui/types': 7.2.14(@types/react@18.3.3) + '@mui/utils': 5.16.0(@types/react@18.3.3)(react@18.3.1) clsx: 2.1.1 csstype: 3.1.3 prop-types: 15.8.1 - react: 18.2.0 + react: 18.3.1 optionalDependencies: - '@emotion/react': 11.11.4(@types/react@18.2.60)(react@18.2.0) - '@emotion/styled': 11.11.5(@emotion/react@11.11.4(@types/react@18.2.60)(react@18.2.0))(@types/react@18.2.60)(react@18.2.0) - '@types/react': 18.2.60 + '@emotion/react': 11.11.4(@types/react@18.3.3)(react@18.3.1) + '@emotion/styled': 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) + '@types/react': 18.3.3 - '@mui/types@7.2.14(@types/react@18.2.60)': + '@mui/types@7.2.14(@types/react@18.3.3)': optionalDependencies: - '@types/react': 18.2.60 + '@types/react': 18.3.3 - '@mui/utils@5.15.20(@types/react@18.2.60)(react@18.2.0)': + '@mui/utils@5.16.0(@types/react@18.3.3)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.7 '@types/prop-types': 15.7.12 prop-types: 15.8.1 - react: 18.2.0 - react-is: 18.2.0 + react: 18.3.1 + react-is: 18.3.1 optionalDependencies: - '@types/react': 18.2.60 + '@types/react': 18.3.3 - '@netlify/functions@2.7.0(@opentelemetry/api@1.8.0)': + '@netlify/functions@2.8.1': dependencies: - '@netlify/serverless-functions-api': 1.18.1(@opentelemetry/api@1.8.0) - transitivePeerDependencies: - - '@opentelemetry/api' + '@netlify/serverless-functions-api': 1.19.1 '@netlify/node-cookies@0.1.0': {} - '@netlify/serverless-functions-api@1.18.1(@opentelemetry/api@1.8.0)': + '@netlify/serverless-functions-api@1.19.1': dependencies: '@netlify/node-cookies': 0.1.0 - '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/otlp-transformer': 0.50.0(@opentelemetry/api@1.8.0) - '@opentelemetry/resources': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/sdk-trace-base': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 urlpattern-polyfill: 8.0.2 - transitivePeerDependencies: - - '@opentelemetry/api' '@next/env@14.2.4': {} @@ -11737,20 +11229,61 @@ snapshots: agent-base: 7.1.0 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.4 - lru-cache: 10.2.0 + lru-cache: 10.3.0 socks-proxy-agent: 8.0.2 transitivePeerDependencies: - supports-color - '@npmcli/fs@3.1.0': + '@npmcli/arborist@7.5.3': + dependencies: + '@isaacs/string-locale-compare': 1.1.0 + '@npmcli/fs': 3.1.1 + '@npmcli/installed-package-contents': 2.1.0 + '@npmcli/map-workspaces': 3.0.6 + '@npmcli/metavuln-calculator': 7.1.1 + '@npmcli/name-from-folder': 2.0.0 + '@npmcli/node-gyp': 3.0.0 + '@npmcli/package-json': 5.2.0 + '@npmcli/query': 3.1.0 + '@npmcli/redact': 2.0.1 + '@npmcli/run-script': 8.1.0 + bin-links: 4.0.4 + cacache: 18.0.3 + common-ancestor-path: 1.0.1 + hosted-git-info: 7.0.2 + json-parse-even-better-errors: 3.0.2 + json-stringify-nice: 1.1.4 + lru-cache: 10.3.0 + minimatch: 9.0.4 + nopt: 7.2.1 + npm-install-checks: 6.3.0 + npm-package-arg: 11.0.2 + npm-pick-manifest: 9.0.1 + npm-registry-fetch: 17.1.0 + pacote: 18.0.6 + parse-conflict-json: 3.0.1 + proc-log: 4.2.0 + proggy: 2.0.0 + promise-all-reject-late: 1.0.1 + promise-call-limit: 3.0.1 + read-package-json-fast: 3.0.2 + semver: 7.6.2 + ssri: 10.0.6 + treeverse: 3.0.0 + walk-up-path: 3.0.1 + transitivePeerDependencies: + - bluebird + - supports-color + + '@npmcli/fs@3.1.1': dependencies: semver: 7.6.2 '@npmcli/git@5.0.4': dependencies: '@npmcli/promise-spawn': 7.0.1 - lru-cache: 10.2.0 - npm-pick-manifest: 9.0.0 + lru-cache: 10.3.0 + npm-pick-manifest: 9.0.1 proc-log: 3.0.0 promise-inflight: 1.0.1 promise-retry: 2.0.1 @@ -11759,21 +11292,41 @@ snapshots: transitivePeerDependencies: - bluebird - '@npmcli/installed-package-contents@2.0.2': + '@npmcli/installed-package-contents@2.1.0': dependencies: npm-bundled: 3.0.0 npm-normalize-package-bin: 3.0.1 - '@npmcli/node-gyp@3.0.0': {} - - '@npmcli/package-json@5.0.0': + '@npmcli/map-workspaces@3.0.6': dependencies: - '@npmcli/git': 5.0.4 + '@npmcli/name-from-folder': 2.0.0 glob: 10.3.10 - hosted-git-info: 7.0.1 - json-parse-even-better-errors: 3.0.1 - normalize-package-data: 6.0.0 - proc-log: 3.0.0 + minimatch: 9.0.4 + read-package-json-fast: 3.0.2 + + '@npmcli/metavuln-calculator@7.1.1': + dependencies: + cacache: 18.0.3 + json-parse-even-better-errors: 3.0.2 + pacote: 18.0.6 + proc-log: 4.2.0 + semver: 7.6.2 + transitivePeerDependencies: + - bluebird + - supports-color + + '@npmcli/name-from-folder@2.0.0': {} + + '@npmcli/node-gyp@3.0.0': {} + + '@npmcli/package-json@5.2.0': + dependencies: + '@npmcli/git': 5.0.4 + glob: 10.3.10 + hosted-git-info: 7.0.2 + json-parse-even-better-errors: 3.0.2 + normalize-package-data: 6.0.2 + proc-log: 4.2.0 semver: 7.6.2 transitivePeerDependencies: - bluebird @@ -11782,22 +11335,19 @@ snapshots: dependencies: which: 4.0.0 - '@npmcli/run-script@7.0.2': + '@npmcli/query@3.1.0': dependencies: - '@npmcli/node-gyp': 3.0.0 - '@npmcli/promise-spawn': 7.0.1 - node-gyp: 10.0.1 - read-package-json-fast: 3.0.2 - which: 4.0.0 - transitivePeerDependencies: - - supports-color + postcss-selector-parser: 6.1.0 - '@npmcli/run-script@7.0.4': + '@npmcli/redact@2.0.1': {} + + '@npmcli/run-script@8.1.0': dependencies: '@npmcli/node-gyp': 3.0.0 - '@npmcli/package-json': 5.0.0 + '@npmcli/package-json': 5.2.0 '@npmcli/promise-spawn': 7.0.1 node-gyp: 10.0.1 + proc-log: 4.2.0 which: 4.0.0 transitivePeerDependencies: - bluebird @@ -11866,7 +11416,7 @@ snapshots: '@octokit/auth-token@3.0.4': {} - '@octokit/auth-token@4.0.0': {} + '@octokit/auth-token@5.1.1': {} '@octokit/core@3.6.0(encoding@0.1.13)': dependencies: @@ -11892,15 +11442,20 @@ snapshots: transitivePeerDependencies: - encoding - '@octokit/core@5.1.0': + '@octokit/core@6.1.2': dependencies: - '@octokit/auth-token': 4.0.0 - '@octokit/graphql': 7.0.2 - '@octokit/request': 8.1.6 - '@octokit/request-error': 5.0.1 - '@octokit/types': 12.4.0 - before-after-hook: 2.2.3 - universal-user-agent: 6.0.1 + '@octokit/auth-token': 5.1.1 + '@octokit/graphql': 8.1.1 + '@octokit/request': 9.1.1 + '@octokit/request-error': 6.1.1 + '@octokit/types': 13.5.0 + before-after-hook: 3.0.2 + universal-user-agent: 7.0.2 + + '@octokit/endpoint@10.1.1': + dependencies: + '@octokit/types': 13.5.0 + universal-user-agent: 7.0.2 '@octokit/endpoint@6.0.12': dependencies: @@ -11914,11 +11469,6 @@ snapshots: is-plain-object: 5.0.0 universal-user-agent: 6.0.1 - '@octokit/endpoint@9.0.4': - dependencies: - '@octokit/types': 12.4.0 - universal-user-agent: 6.0.1 - '@octokit/graphql@4.8.0(encoding@0.1.13)': dependencies: '@octokit/request': 5.6.3(encoding@0.1.13) @@ -11935,25 +11485,23 @@ snapshots: transitivePeerDependencies: - encoding - '@octokit/graphql@7.0.2': + '@octokit/graphql@8.1.1': dependencies: - '@octokit/request': 8.1.6 - '@octokit/types': 12.4.0 - universal-user-agent: 6.0.1 + '@octokit/request': 9.1.1 + '@octokit/types': 13.5.0 + universal-user-agent: 7.0.2 '@octokit/openapi-types@12.11.0': {} '@octokit/openapi-types@18.1.1': {} - '@octokit/openapi-types@19.1.0': {} - '@octokit/openapi-types@22.2.0': {} '@octokit/plugin-enterprise-rest@6.0.1': {} - '@octokit/plugin-paginate-rest@11.3.1(@octokit/core@5.1.0)': + '@octokit/plugin-paginate-rest@11.3.1(@octokit/core@6.1.2)': dependencies: - '@octokit/core': 5.1.0 + '@octokit/core': 6.1.2 '@octokit/types': 13.5.0 '@octokit/plugin-paginate-rest@2.21.3(@octokit/core@3.6.0(encoding@0.1.13))': @@ -11975,13 +11523,13 @@ snapshots: dependencies: '@octokit/core': 4.2.4(encoding@0.1.13) - '@octokit/plugin-request-log@4.0.0(@octokit/core@5.1.0)': + '@octokit/plugin-request-log@5.3.0(@octokit/core@6.1.2)': dependencies: - '@octokit/core': 5.1.0 + '@octokit/core': 6.1.2 - '@octokit/plugin-rest-endpoint-methods@13.2.2(@octokit/core@5.1.0)': + '@octokit/plugin-rest-endpoint-methods@13.2.2(@octokit/core@6.1.2)': dependencies: - '@octokit/core': 5.1.0 + '@octokit/core': 6.1.2 '@octokit/types': 13.5.0 '@octokit/plugin-rest-endpoint-methods@5.16.2(@octokit/core@3.6.0(encoding@0.1.13))': @@ -11995,11 +11543,11 @@ snapshots: '@octokit/core': 4.2.4(encoding@0.1.13) '@octokit/types': 10.0.0 - '@octokit/plugin-retry@6.0.1(@octokit/core@4.2.4(encoding@0.1.13))': + '@octokit/plugin-retry@7.1.1(@octokit/core@4.2.4(encoding@0.1.13))': dependencies: '@octokit/core': 4.2.4(encoding@0.1.13) - '@octokit/request-error': 5.0.1 - '@octokit/types': 12.4.0 + '@octokit/request-error': 6.1.1 + '@octokit/types': 13.5.0 bottleneck: 2.19.5 '@octokit/request-error@2.1.0': @@ -12014,11 +11562,9 @@ snapshots: deprecation: 2.3.1 once: 1.4.0 - '@octokit/request-error@5.0.1': + '@octokit/request-error@6.1.1': dependencies: - '@octokit/types': 12.4.0 - deprecation: 2.3.1 - once: 1.4.0 + '@octokit/types': 13.5.0 '@octokit/request@5.6.3(encoding@0.1.13)': dependencies: @@ -12042,12 +11588,12 @@ snapshots: transitivePeerDependencies: - encoding - '@octokit/request@8.1.6': + '@octokit/request@9.1.1': dependencies: - '@octokit/endpoint': 9.0.4 - '@octokit/request-error': 5.0.1 - '@octokit/types': 12.4.0 - universal-user-agent: 6.0.1 + '@octokit/endpoint': 10.1.1 + '@octokit/request-error': 6.1.1 + '@octokit/types': 13.5.0 + universal-user-agent: 7.0.2 '@octokit/rest@18.12.0(encoding@0.1.13)': dependencies: @@ -12067,12 +11613,12 @@ snapshots: transitivePeerDependencies: - encoding - '@octokit/rest@20.1.1': + '@octokit/rest@21.0.0': dependencies: - '@octokit/core': 5.1.0 - '@octokit/plugin-paginate-rest': 11.3.1(@octokit/core@5.1.0) - '@octokit/plugin-request-log': 4.0.0(@octokit/core@5.1.0) - '@octokit/plugin-rest-endpoint-methods': 13.2.2(@octokit/core@5.1.0) + '@octokit/core': 6.1.2 + '@octokit/plugin-paginate-rest': 11.3.1(@octokit/core@6.1.2) + '@octokit/plugin-request-log': 5.3.0(@octokit/core@6.1.2) + '@octokit/plugin-rest-endpoint-methods': 13.2.2(@octokit/core@6.1.2) '@octokit/tsconfig@1.0.2': {} @@ -12080,10 +11626,6 @@ snapshots: dependencies: '@octokit/openapi-types': 18.1.1 - '@octokit/types@12.4.0': - dependencies: - '@octokit/openapi-types': 19.1.0 - '@octokit/types@13.5.0': dependencies: '@octokit/openapi-types': 22.2.0 @@ -12096,75 +11638,8 @@ snapshots: dependencies: '@octokit/openapi-types': 18.1.1 - '@opentelemetry/api-logs@0.50.0': - dependencies: - '@opentelemetry/api': 1.8.0 - - '@opentelemetry/api@1.8.0': {} - - '@opentelemetry/core@1.23.0(@opentelemetry/api@1.8.0)': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/semantic-conventions': 1.23.0 - - '@opentelemetry/core@1.24.1(@opentelemetry/api@1.8.0)': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/semantic-conventions': 1.24.1 - - '@opentelemetry/otlp-transformer@0.50.0(@opentelemetry/api@1.8.0)': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/api-logs': 0.50.0 - '@opentelemetry/core': 1.23.0(@opentelemetry/api@1.8.0) - '@opentelemetry/resources': 1.23.0(@opentelemetry/api@1.8.0) - '@opentelemetry/sdk-logs': 0.50.0(@opentelemetry/api-logs@0.50.0)(@opentelemetry/api@1.8.0) - '@opentelemetry/sdk-metrics': 1.23.0(@opentelemetry/api@1.8.0) - '@opentelemetry/sdk-trace-base': 1.23.0(@opentelemetry/api@1.8.0) - - '@opentelemetry/resources@1.23.0(@opentelemetry/api@1.8.0)': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.23.0(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.23.0 - - '@opentelemetry/resources@1.24.1(@opentelemetry/api@1.8.0)': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 - - '@opentelemetry/sdk-logs@0.50.0(@opentelemetry/api-logs@0.50.0)(@opentelemetry/api@1.8.0)': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/api-logs': 0.50.0 - '@opentelemetry/core': 1.23.0(@opentelemetry/api@1.8.0) - '@opentelemetry/resources': 1.23.0(@opentelemetry/api@1.8.0) - - '@opentelemetry/sdk-metrics@1.23.0(@opentelemetry/api@1.8.0)': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.23.0(@opentelemetry/api@1.8.0) - '@opentelemetry/resources': 1.23.0(@opentelemetry/api@1.8.0) - lodash.merge: 4.6.2 - - '@opentelemetry/sdk-trace-base@1.23.0(@opentelemetry/api@1.8.0)': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.23.0(@opentelemetry/api@1.8.0) - '@opentelemetry/resources': 1.23.0(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.23.0 - - '@opentelemetry/sdk-trace-base@1.24.1(@opentelemetry/api@1.8.0)': - dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/resources': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 - - '@opentelemetry/semantic-conventions@1.23.0': {} - - '@opentelemetry/semantic-conventions@1.24.1': {} + '@opentelemetry/api@1.8.0': + optional: true '@pkgjs/parseargs@0.11.0': optional: true @@ -12179,45 +11654,41 @@ snapshots: '@popperjs/core@2.11.8': {} - '@react-spring/animated@9.7.3(react@18.2.0)': + '@react-spring/animated@9.7.3(react@18.3.1)': dependencies: - '@react-spring/shared': 9.7.3(react@18.2.0) + '@react-spring/shared': 9.7.3(react@18.3.1) '@react-spring/types': 9.7.3 - react: 18.2.0 + react: 18.3.1 - '@react-spring/core@9.7.3(react@18.2.0)': + '@react-spring/core@9.7.3(react@18.3.1)': dependencies: - '@react-spring/animated': 9.7.3(react@18.2.0) - '@react-spring/shared': 9.7.3(react@18.2.0) + '@react-spring/animated': 9.7.3(react@18.3.1) + '@react-spring/shared': 9.7.3(react@18.3.1) '@react-spring/types': 9.7.3 - react: 18.2.0 + react: 18.3.1 '@react-spring/rafz@9.7.3': {} - '@react-spring/shared@9.7.3(react@18.2.0)': + '@react-spring/shared@9.7.3(react@18.3.1)': dependencies: '@react-spring/types': 9.7.3 - react: 18.2.0 + react: 18.3.1 '@react-spring/types@9.7.3': {} - '@react-spring/web@9.7.3(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@react-spring/web@9.7.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@react-spring/animated': 9.7.3(react@18.2.0) - '@react-spring/core': 9.7.3(react@18.2.0) - '@react-spring/shared': 9.7.3(react@18.2.0) + '@react-spring/animated': 9.7.3(react@18.3.1) + '@react-spring/core': 9.7.3(react@18.3.1) + '@react-spring/shared': 9.7.3(react@18.3.1) '@react-spring/types': 9.7.3 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - '@remix-run/router@1.16.1': {} + '@remix-run/router@1.17.1': {} '@sec-ant/readable-stream@0.4.1': {} - '@sigstore/bundle@1.1.0': - dependencies: - '@sigstore/protobuf-specs': 0.2.1 - '@sigstore/bundle@2.1.1': dependencies: '@sigstore/protobuf-specs': 0.2.1 @@ -12226,14 +11697,6 @@ snapshots: '@sigstore/protobuf-specs@0.2.1': {} - '@sigstore/sign@1.0.0': - dependencies: - '@sigstore/bundle': 1.1.0 - '@sigstore/protobuf-specs': 0.2.1 - make-fetch-happen: 11.1.1 - transitivePeerDependencies: - - supports-color - '@sigstore/sign@2.2.1': dependencies: '@sigstore/bundle': 2.1.1 @@ -12243,13 +11706,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@sigstore/tuf@1.0.3': - dependencies: - '@sigstore/protobuf-specs': 0.2.1 - tuf-js: 1.1.7 - transitivePeerDependencies: - - supports-color - '@sigstore/tuf@2.3.0': dependencies: '@sigstore/protobuf-specs': 0.2.1 @@ -12293,7 +11749,7 @@ snapshots: '@sinonjs/text-encoding@0.7.2': {} - '@slack/bolt@3.18.0': + '@slack/bolt@3.19.0': dependencies: '@slack/logger': 4.0.0 '@slack/oauth': 2.6.2 @@ -12303,7 +11759,7 @@ snapshots: '@types/express': 4.17.21 '@types/promise.allsettled': 1.0.6 '@types/tsscmp': 1.0.2 - axios: 1.7.2(debug@4.3.4) + axios: 1.7.2(debug@4.3.5) express: 4.18.2 path-to-regexp: 6.2.1 please-upgrade-node: 3.2.0 @@ -12318,18 +11774,18 @@ snapshots: '@slack/logger@3.0.0': dependencies: - '@types/node': 18.19.34 + '@types/node': 18.19.39 '@slack/logger@4.0.0': dependencies: - '@types/node': 18.19.34 + '@types/node': 18.19.39 '@slack/oauth@2.6.2': dependencies: '@slack/logger': 3.0.0 '@slack/web-api': 6.12.0 '@types/jsonwebtoken': 8.5.9 - '@types/node': 18.19.34 + '@types/node': 18.19.39 jsonwebtoken: 9.0.2 lodash.isstring: 4.0.1 transitivePeerDependencies: @@ -12339,7 +11795,7 @@ snapshots: dependencies: '@slack/logger': 3.0.0 '@slack/web-api': 6.12.0 - '@types/node': 18.19.34 + '@types/node': 18.19.39 '@types/p-queue': 2.3.2 '@types/ws': 7.4.7 eventemitter3: 3.1.2 @@ -12359,8 +11815,8 @@ snapshots: '@slack/logger': 3.0.0 '@slack/types': 2.11.0 '@types/is-stream': 1.1.0 - '@types/node': 18.19.34 - axios: 1.7.2(debug@4.3.4) + '@types/node': 18.19.39 + axios: 1.7.2(debug@4.3.5) eventemitter3: 3.1.2 form-data: 2.5.1 is-electron: 2.2.2 @@ -12379,7 +11835,9 @@ snapshots: '@swc/counter': 0.1.3 tslib: 2.6.2 - '@testing-library/dom@10.1.0': + '@tanstack/query-core@5.50.1': {} + + '@testing-library/dom@10.3.1': dependencies: '@babel/code-frame': 7.24.7 '@babel/runtime': 7.24.7 @@ -12390,27 +11848,20 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/react@15.0.7(@types/react@18.2.60)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@testing-library/react@16.0.0(@testing-library/dom@10.3.1)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.7 - '@testing-library/dom': 10.1.0 - '@types/react-dom': 18.2.25 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@testing-library/dom': 10.3.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.2.60 + '@types/react': 18.3.3 + '@types/react-dom': 18.3.0 '@tootallnate/once@2.0.0': {} - '@tufjs/canonical-json@1.0.0': {} - '@tufjs/canonical-json@2.0.0': {} - '@tufjs/models@1.0.4': - dependencies: - '@tufjs/canonical-json': 1.0.0 - minimatch: 9.0.4 - '@tufjs/models@2.0.0': dependencies: '@tufjs/canonical-json': 2.0.0 @@ -12442,7 +11893,7 @@ snapshots: '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 18.19.34 + '@types/node': 18.19.39 '@types/chai-dom@1.11.3': dependencies: @@ -12452,19 +11903,15 @@ snapshots: '@types/chance@1.1.6': {} - '@types/cheerio@0.22.35': - dependencies: - '@types/node': 18.19.34 - '@types/connect@3.4.38': dependencies: - '@types/node': 18.19.34 + '@types/node': 18.19.39 '@types/cookie@0.4.1': {} '@types/cors@2.8.17': dependencies: - '@types/node': 18.19.34 + '@types/node': 18.19.39 '@types/d3-color@3.1.3': {} @@ -12476,6 +11923,8 @@ snapshots: '@types/d3-path@3.1.0': {} + '@types/d3-scale-chromatic@3.0.3': {} + '@types/d3-scale@4.0.8': dependencies: '@types/d3-time': 3.0.3 @@ -12488,11 +11937,6 @@ snapshots: '@types/doctrine@0.0.9': {} - '@types/enzyme@3.10.12': - dependencies: - '@types/cheerio': 0.22.35 - '@types/react': 18.2.60 - '@types/eslint-scope@3.7.7': dependencies: '@types/eslint': 8.56.10 @@ -12507,7 +11951,7 @@ snapshots: '@types/express-serve-static-core@4.17.42': dependencies: - '@types/node': 18.19.34 + '@types/node': 18.19.39 '@types/qs': 6.9.11 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -12524,7 +11968,7 @@ snapshots: '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 - '@types/node': 18.19.34 + '@types/node': 18.19.39 '@types/history@4.7.11': {} @@ -12534,7 +11978,7 @@ snapshots: '@types/is-stream@1.1.0': dependencies: - '@types/node': 18.19.34 + '@types/node': 18.19.39 '@types/istanbul-lib-coverage@2.0.6': {} @@ -12549,24 +11993,20 @@ snapshots: '@types/jsonfile@6.1.4': dependencies: - '@types/node': 18.19.34 + '@types/node': 18.19.39 '@types/jsonwebtoken@8.5.9': dependencies: - '@types/node': 18.19.34 + '@types/node': 18.19.39 '@types/karma@6.3.8': dependencies: - '@types/node': 18.19.34 + '@types/node': 18.19.39 log4js: 6.9.1 transitivePeerDependencies: - supports-color - '@types/lodash@4.17.5': {} - - '@types/lru-cache@7.10.10': - dependencies: - lru-cache: 7.18.3 + '@types/lodash@4.17.6': {} '@types/luxon@3.4.2': {} @@ -12582,7 +12022,7 @@ snapshots: '@types/minimist@1.2.5': {} - '@types/mocha@10.0.6': {} + '@types/mocha@10.0.7': {} '@types/moment-hijri@2.1.4': dependencies: @@ -12592,7 +12032,7 @@ snapshots: dependencies: moment: 2.30.1 - '@types/node@18.19.34': + '@types/node@18.19.39': dependencies: undici-types: 5.26.5 @@ -12610,51 +12050,48 @@ snapshots: '@types/range-parser@1.2.7': {} - '@types/react-dom@18.2.25': + '@types/react-dom@18.3.0': dependencies: - '@types/react': 18.2.60 + '@types/react': 18.3.3 '@types/react-router-dom@5.3.3': dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.60 + '@types/react': 18.3.3 '@types/react-router': 5.1.20 '@types/react-router@5.1.20': dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.60 + '@types/react': 18.3.3 '@types/react-test-renderer@18.3.0': dependencies: - '@types/react': 18.2.60 + '@types/react': 18.3.3 '@types/react-transition-group@4.4.10': dependencies: - '@types/react': 18.2.60 + '@types/react': 18.3.3 - '@types/react@18.2.60': + '@types/react@18.3.3': dependencies: '@types/prop-types': 15.7.12 - '@types/scheduler': 0.16.8 csstype: 3.1.3 '@types/requestidlecallback@0.3.7': {} '@types/retry@0.12.0': {} - '@types/scheduler@0.16.8': {} - '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 18.19.34 + '@types/node': 18.19.39 '@types/serve-static@1.15.5': dependencies: '@types/http-errors': 2.0.4 '@types/mime': 3.0.4 - '@types/node': 18.19.34 + '@types/node': 18.19.39 '@types/sinon@17.0.3': dependencies: @@ -12670,11 +12107,11 @@ snapshots: '@types/unist@2.0.10': {} - '@types/webpack-bundle-analyzer@4.7.0(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0))': + '@types/webpack-bundle-analyzer@4.7.0(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1))': dependencies: - '@types/node': 18.19.34 + '@types/node': 18.19.39 tapable: 2.2.1 - webpack: 5.92.0(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0)) + webpack: 5.92.1(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1)) transitivePeerDependencies: - '@swc/core' - esbuild @@ -12683,7 +12120,7 @@ snapshots: '@types/ws@7.4.7': dependencies: - '@types/node': 18.19.34 + '@types/node': 18.19.39 '@types/yargs-parser@21.0.3': {} @@ -12691,85 +12128,85 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/eslint-plugin@7.15.0(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)': dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.13.1(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/scope-manager': 7.13.1 - '@typescript-eslint/type-utils': 7.13.1(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.13.1(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.13.1 + '@typescript-eslint/parser': 7.15.0(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/scope-manager': 7.15.0 + '@typescript-eslint/type-utils': 7.15.0(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/utils': 7.15.0(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/visitor-keys': 7.15.0 eslint: 8.57.0 graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.4.5) + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3)': dependencies: - '@typescript-eslint/scope-manager': 7.13.1 - '@typescript-eslint/types': 7.13.1 - '@typescript-eslint/typescript-estree': 7.13.1(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.13.1 - debug: 4.3.4(supports-color@8.1.1) + '@typescript-eslint/scope-manager': 7.15.0 + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.5.3) + '@typescript-eslint/visitor-keys': 7.15.0 + debug: 4.3.5(supports-color@8.1.1) eslint: 8.57.0 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@7.13.1': + '@typescript-eslint/scope-manager@7.15.0': dependencies: - '@typescript-eslint/types': 7.13.1 - '@typescript-eslint/visitor-keys': 7.13.1 + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/visitor-keys': 7.15.0 - '@typescript-eslint/type-utils@7.13.1(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/type-utils@7.15.0(eslint@8.57.0)(typescript@5.5.3)': dependencies: - '@typescript-eslint/typescript-estree': 7.13.1(typescript@5.4.5) - '@typescript-eslint/utils': 7.13.1(eslint@8.57.0)(typescript@5.4.5) - debug: 4.3.4(supports-color@8.1.1) + '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.5.3) + '@typescript-eslint/utils': 7.15.0(eslint@8.57.0)(typescript@5.5.3) + debug: 4.3.5(supports-color@8.1.1) eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.4.5) + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@7.13.1': {} + '@typescript-eslint/types@7.15.0': {} - '@typescript-eslint/typescript-estree@7.13.1(typescript@5.4.5)': + '@typescript-eslint/typescript-estree@7.15.0(typescript@5.5.3)': dependencies: - '@typescript-eslint/types': 7.13.1 - '@typescript-eslint/visitor-keys': 7.13.1 - debug: 4.3.4(supports-color@8.1.1) + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/visitor-keys': 7.15.0 + debug: 4.3.5(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.4 semver: 7.6.2 - ts-api-utils: 1.3.0(typescript@5.4.5) + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@7.13.1(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/utils@7.15.0(eslint@8.57.0)(typescript@5.5.3)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@typescript-eslint/scope-manager': 7.13.1 - '@typescript-eslint/types': 7.13.1 - '@typescript-eslint/typescript-estree': 7.13.1(typescript@5.4.5) + '@typescript-eslint/scope-manager': 7.15.0 + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.5.3) eslint: 8.57.0 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/visitor-keys@7.13.1': + '@typescript-eslint/visitor-keys@7.15.0': dependencies: - '@typescript-eslint/types': 7.13.1 + '@typescript-eslint/types': 7.15.0 eslint-visitor-keys: 3.4.3 '@ungap/structured-clone@1.2.0': {} @@ -12850,20 +12287,20 @@ snapshots: '@webassemblyjs/ast': 1.12.1 '@xtuc/long': 4.2.2 - '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0))(webpack@5.92.0(webpack-cli@5.1.4))': + '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1))(webpack@5.92.1(webpack-cli@5.1.4))': dependencies: - webpack: 5.92.0(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0) + webpack: 5.92.1(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1) - '@webpack-cli/info@2.0.2(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0))(webpack@5.92.0(webpack-cli@5.1.4))': + '@webpack-cli/info@2.0.2(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1))(webpack@5.92.1(webpack-cli@5.1.4))': dependencies: - webpack: 5.92.0(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0) + webpack: 5.92.1(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1) - '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0))(webpack@5.92.0(webpack-cli@5.1.4))': + '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1))(webpack@5.92.1(webpack-cli@5.1.4))': dependencies: - webpack: 5.92.0(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0) + webpack: 5.92.1(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1) '@xtuc/ieee754@1.2.0': {} @@ -12914,20 +12351,16 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) transitivePeerDependencies: - supports-color agent-base@7.1.0: dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) transitivePeerDependencies: - supports-color - agentkeepalive@4.5.0: - dependencies: - humanize-ms: 1.2.1 - aggregate-error@3.1.0: dependencies: clean-stack: 2.2.0 @@ -12938,19 +12371,6 @@ snapshots: clean-stack: 4.2.0 indent-string: 5.0.0 - airbnb-prop-types@2.16.0(react@18.2.0): - dependencies: - array.prototype.find: 2.2.2 - function.prototype.name: 1.1.6 - is-regex: 1.1.4 - object-is: 1.1.5 - object.assign: 4.1.5 - object.entries: 1.1.8 - prop-types: 15.8.1 - prop-types-exact: 1.2.0 - react: 18.2.0 - react-is: 18.2.0 - ajv-formats@2.1.1(ajv@8.12.0): optionalDependencies: ajv: 8.12.0 @@ -13002,8 +12422,6 @@ snapshots: dependencies: string-width: 4.2.3 - ansi-colors@4.1.1: {} - ansi-colors@4.1.3: {} ansi-escapes@4.3.2: @@ -13081,11 +12499,6 @@ snapshots: are-docs-informative@0.0.2: {} - are-we-there-yet@3.0.1: - dependencies: - delegates: 1.0.0 - readable-stream: 3.6.2 - arg@5.0.2: {} argparse@1.0.10: @@ -13094,16 +12507,14 @@ snapshots: argparse@2.0.1: {} + aria-query@5.1.3: + dependencies: + deep-equal: 2.2.3 + aria-query@5.3.0: dependencies: dequal: 2.0.3 - arr-diff@4.0.0: {} - - arr-flatten@1.1.0: {} - - arr-union@3.1.0: {} - array-buffer-byte-length@1.0.1: dependencies: call-bind: 1.0.7 @@ -13130,16 +12541,6 @@ snapshots: array-union@2.1.0: {} - array-unique@0.3.2: {} - - array.prototype.filter@1.0.3: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-array-method-boxes-properly: 1.0.0 - is-string: 1.0.7 - array.prototype.find@2.2.2: dependencies: call-bind: 1.0.7 @@ -13201,7 +12602,7 @@ snapshots: es-abstract: 1.23.3 es-shim-unscopables: 1.0.2 - array.prototype.tosorted@1.1.3: + array.prototype.tosorted@1.1.4: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 @@ -13228,8 +12629,6 @@ snapshots: assertion-error@1.1.0: {} - assign-symbols@1.0.0: {} - ast-types-flow@0.0.8: {} ast-types@0.14.2: @@ -13250,55 +12649,47 @@ snapshots: asynckit@0.4.0: {} - atob@2.1.2: {} - - autoprefixer@10.4.19(postcss@8.4.38): + autoprefixer@10.4.19(postcss@8.4.39): dependencies: browserslist: 4.23.0 caniuse-lite: 1.0.30001606 fraction.js: 4.3.7 normalize-range: 0.1.2 - picocolors: 1.0.0 - postcss: 8.4.38 + picocolors: 1.0.1 + postcss: 8.4.39 postcss-value-parser: 4.2.0 available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 - axe-core@4.7.0: {} - axe-core@4.9.1: {} - axios@1.7.2(debug@4.3.4): + axios@1.7.2(debug@4.3.5): dependencies: - follow-redirects: 1.15.6(debug@4.3.4) + follow-redirects: 1.15.6(debug@4.3.5) form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: - debug - axobject-query@3.2.1: + axobject-query@3.1.1: dependencies: - dequal: 2.0.3 - - babel-core@7.0.0-bridge.0(@babel/core@7.24.7): - dependencies: - '@babel/core': 7.24.7 + deep-equal: 2.2.3 - babel-loader@9.1.3(@babel/core@7.24.7)(webpack@5.92.0(webpack-cli@5.1.4)): + babel-loader@9.1.3(@babel/core@7.24.7)(webpack@5.92.1(webpack-cli@5.1.4)): dependencies: '@babel/core': 7.24.7 find-cache-dir: 4.0.0 schema-utils: 4.2.0 - webpack: 5.92.0(webpack-cli@5.1.4) + webpack: 5.92.1(webpack-cli@5.1.4) - babel-plugin-istanbul@6.1.1: + babel-plugin-istanbul@7.0.0: dependencies: '@babel/helper-plugin-utils': 7.24.7 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.3 - istanbul-lib-instrument: 5.2.1 + istanbul-lib-instrument: 6.0.2 test-exclude: 6.0.0 transitivePeerDependencies: - supports-color @@ -13379,24 +12770,23 @@ snapshots: base64id@2.0.0: {} - base@0.11.2: - dependencies: - cache-base: 1.0.1 - class-utils: 0.3.6 - component-emitter: 1.3.1 - define-property: 1.0.0 - isobject: 3.0.1 - mixin-deep: 1.3.2 - pascalcase: 0.1.1 - before-after-hook@2.2.3: {} + before-after-hook@3.0.2: {} + big-integer@1.6.52: {} big.js@5.2.2: {} bignumber.js@9.1.2: {} + bin-links@4.0.4: + dependencies: + cmd-shim: 6.0.3 + npm-normalize-package-bin: 3.0.1 + read-cmd-shim: 4.0.0 + write-file-atomic: 5.0.1 + binary-extensions@2.2.0: {} binary@0.3.0: @@ -13470,24 +12860,9 @@ snapshots: dependencies: balanced-match: 1.0.2 - braces@2.3.2: - dependencies: - arr-flatten: 1.1.0 - array-unique: 0.3.2 - extend-shallow: 2.0.1 - fill-range: 4.0.0 - isobject: 3.0.1 - repeat-element: 1.1.4 - snapdragon: 0.8.2 - snapdragon-node: 2.1.1 - split-string: 3.1.0 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - - braces@3.0.2: + braces@3.0.3: dependencies: - fill-range: 7.0.1 + fill-range: 7.1.1 browser-stdout@1.3.1: {} @@ -13515,12 +12890,6 @@ snapshots: buffers@0.1.1: {} - builtins@1.0.3: {} - - builtins@5.0.1: - dependencies: - semver: 7.6.2 - busboy@1.6.0: dependencies: streamsearch: 1.1.0 @@ -13546,48 +12915,21 @@ snapshots: yargs: 16.2.0 yargs-parser: 20.2.9 - cacache@17.1.4: + cacache@18.0.3: dependencies: - '@npmcli/fs': 3.1.0 + '@npmcli/fs': 3.1.1 fs-minipass: 3.0.3 glob: 10.3.10 - lru-cache: 7.18.3 - minipass: 7.0.4 - minipass-collect: 1.0.2 - minipass-flush: 1.0.5 - minipass-pipeline: 1.2.4 - p-map: 4.0.0 - ssri: 10.0.5 - tar: 6.2.1 - unique-filename: 3.0.0 - - cacache@18.0.2: - dependencies: - '@npmcli/fs': 3.1.0 - fs-minipass: 3.0.3 - glob: 10.3.10 - lru-cache: 10.2.0 + lru-cache: 10.3.0 minipass: 7.0.4 minipass-collect: 2.0.1 minipass-flush: 1.0.5 minipass-pipeline: 1.2.4 p-map: 4.0.0 - ssri: 10.0.5 + ssri: 10.0.6 tar: 6.2.1 unique-filename: 3.0.0 - cache-base@1.0.1: - dependencies: - collection-visit: 1.0.0 - component-emitter: 1.3.1 - get-value: 2.0.6 - has-value: 1.0.0 - isobject: 3.0.1 - set-value: 2.0.1 - to-object-path: 0.3.0 - union-value: 1.0.1 - unset-value: 1.0.0 - caching-transform@4.0.0: dependencies: hasha: 5.2.2 @@ -13682,29 +13024,10 @@ snapshots: dependencies: get-func-name: 2.0.2 - cheerio-select@2.1.0: - dependencies: - boolbase: 1.0.0 - css-select: 5.1.0 - css-what: 6.1.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - domutils: 3.1.0 - - cheerio@1.0.0-rc.12: - dependencies: - cheerio-select: 2.1.0 - dom-serializer: 2.0.0 - domhandler: 5.0.3 - domutils: 3.1.0 - htmlparser2: 8.0.2 - parse5: 7.1.2 - parse5-htmlparser2-tree-adapter: 7.0.0 - chokidar@3.5.3: dependencies: anymatch: 3.1.3 - braces: 3.0.2 + braces: 3.0.3 glob-parent: 5.1.2 is-binary-path: 2.1.0 is-glob: 4.0.3 @@ -13719,12 +13042,7 @@ snapshots: ci-info@3.9.0: {} - class-utils@0.3.6: - dependencies: - arr-union: 3.1.0 - define-property: 0.2.5 - isobject: 3.0.1 - static-extend: 0.1.2 + ci-info@4.0.0: {} clean-css@5.3.3: dependencies: @@ -13786,12 +13104,7 @@ snapshots: clsx@2.1.1: {} - cmd-shim@6.0.1: {} - - collection-visit@1.0.0: - dependencies: - map-visit: 1.0.0 - object-visit: 1.0.1 + cmd-shim@6.0.3: {} color-convert@1.9.3: dependencies: @@ -13844,6 +13157,8 @@ snapshots: comment-parser@1.4.1: {} + common-ancestor-path@1.0.1: {} + common-path-prefix@3.0.0: {} commondir@1.0.1: {} @@ -13853,8 +13168,6 @@ snapshots: array-ify: 1.0.0 dot-prop: 5.3.0 - component-emitter@1.3.1: {} - compress-commons@4.1.2: dependencies: buffer-crc32: 0.2.13 @@ -13866,11 +13179,11 @@ snapshots: dependencies: mime-db: 1.52.0 - compression-webpack-plugin@11.1.0(webpack@5.92.0(webpack-cli@5.1.4)): + compression-webpack-plugin@11.1.0(webpack@5.92.1(webpack-cli@5.1.4)): dependencies: schema-utils: 4.2.0 serialize-javascript: 6.0.2 - webpack: 5.92.0(webpack-cli@5.1.4) + webpack: 5.92.1(webpack-cli@5.1.4) compression@1.7.4: dependencies: @@ -13993,8 +13306,6 @@ snapshots: cookie@0.5.0: {} - copy-descriptor@0.1.1: {} - core-js-compat@3.36.1: dependencies: browserslist: 4.23.0 @@ -14018,14 +13329,14 @@ snapshots: path-type: 4.0.0 yaml: 1.10.2 - cosmiconfig@8.3.6(typescript@5.4.5): + cosmiconfig@8.3.6(typescript@5.5.3): dependencies: import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 cp-file@10.0.0: dependencies: @@ -14044,7 +13355,7 @@ snapshots: cp-file: 10.0.0 globby: 13.2.2 junk: 4.0.1 - micromatch: 4.0.5 + micromatch: 4.0.7 nested-error-stacks: 2.1.1 p-filter: 3.0.0 p-map: 6.0.0 @@ -14081,14 +13392,6 @@ snapshots: domutils: 2.8.0 nth-check: 2.1.1 - css-select@5.1.0: - dependencies: - boolbase: 1.0.0 - css-what: 6.1.0 - domhandler: 5.0.3 - domutils: 3.1.0 - nth-check: 2.1.1 - css-to-react-native@3.2.0: dependencies: camelize: 1.0.1 @@ -14102,6 +13405,8 @@ snapshots: css-what@6.1.0: {} + cssesc@3.0.0: {} + cssjanus@2.1.0: {} cssstyle@4.0.1: @@ -14130,6 +13435,11 @@ snapshots: d3-path@3.1.0: {} + d3-scale-chromatic@3.1.0: + dependencies: + d3-color: 3.1.0 + d3-interpolate: 3.0.1 + d3-scale@4.0.2: dependencies: d3-array: 3.2.4 @@ -14152,7 +13462,7 @@ snapshots: damerau-levenshtein@1.0.8: {} - danger@12.3.1(encoding@0.1.13): + danger@12.3.3(encoding@0.1.13): dependencies: '@gitbeaker/rest': 38.12.1 '@octokit/rest': 18.12.0(encoding@0.1.13) @@ -14160,7 +13470,7 @@ snapshots: chalk: 2.4.2 commander: 2.20.3 core-js: 3.35.1 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) fast-json-patch: 3.1.1 get-stdin: 6.0.0 http-proxy-agent: 5.0.0 @@ -14176,7 +13486,7 @@ snapshots: lodash.mapvalues: 4.6.0 lodash.memoize: 4.1.2 memfs-or-file-map-to-github-branch: 1.2.1(encoding@0.1.13) - micromatch: 4.0.5 + micromatch: 4.0.7 node-cleanup: 2.1.2 node-fetch: 2.7.0(encoding@0.1.13) override-require: 1.1.1 @@ -14224,7 +13534,7 @@ snapshots: dependencies: '@babel/runtime': 7.24.7 - date-fns-jalali@3.6.0-0: {} + date-fns-jalali@3.6.0-1: {} date-fns@2.30.0: dependencies: @@ -14248,7 +13558,7 @@ snapshots: dependencies: ms: 2.1.3 - debug@4.3.4(supports-color@8.1.1): + debug@4.3.5(supports-color@8.1.1): dependencies: ms: 2.1.2 optionalDependencies: @@ -14265,14 +13575,35 @@ snapshots: decimal.js@10.4.3: {} - decode-uri-component@0.2.2: {} - - dedent@0.7.0: {} + dedent@1.5.3(babel-plugin-macros@3.1.0): + optionalDependencies: + babel-plugin-macros: 3.1.0 deep-eql@4.1.3: dependencies: type-detect: 4.0.8 + deep-equal@2.2.3: + dependencies: + array-buffer-byte-length: 1.0.1 + call-bind: 1.0.7 + es-get-iterator: 1.1.3 + get-intrinsic: 1.2.4 + is-arguments: 1.1.1 + is-array-buffer: 3.0.4 + is-date-object: 1.0.5 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.3 + isarray: 2.0.5 + object-is: 1.1.5 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.2 + side-channel: 1.0.6 + which-boxed-primitive: 1.0.2 + which-collection: 1.0.1 + which-typed-array: 1.1.15 + deep-extend@0.6.0: {} deep-is@0.1.4: {} @@ -14299,27 +13630,12 @@ snapshots: has-property-descriptors: 1.0.2 object-keys: 1.1.1 - define-property@0.2.5: - dependencies: - is-descriptor: 0.1.7 - - define-property@1.0.0: - dependencies: - is-descriptor: 1.0.3 - - define-property@2.0.2: - dependencies: - is-descriptor: 1.0.3 - isobject: 3.0.1 - delaunator@5.0.1: dependencies: robust-predicates: 3.0.2 delayed-stream@1.0.0: {} - delegates@1.0.0: {} - depd@2.0.0: {} deprecation@2.3.1: {} @@ -14336,16 +13652,12 @@ snapshots: diff-sequences@29.6.3: {} - diff@5.0.0: {} - - diff@5.1.0: {} + diff@5.2.0: {} dir-glob@3.0.1: dependencies: path-type: 4.0.0 - discontinuous-range@1.0.0: {} - doctrine@2.1.0: dependencies: esutils: 2.0.3 @@ -14380,34 +13692,18 @@ snapshots: domhandler: 4.3.1 entities: 2.2.0 - dom-serializer@2.0.0: - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - entities: 4.5.0 - domelementtype@2.3.0: {} domhandler@4.3.1: dependencies: domelementtype: 2.3.0 - domhandler@5.0.3: - dependencies: - domelementtype: 2.3.0 - domutils@2.8.0: dependencies: dom-serializer: 1.4.1 domelementtype: 2.3.0 domhandler: 4.3.1 - domutils@3.1.0: - dependencies: - dom-serializer: 2.0.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - dot-case@3.0.4: dependencies: no-case: 3.0.4 @@ -14464,12 +13760,12 @@ snapshots: dependencies: '@types/cookie': 0.4.1 '@types/cors': 2.8.17 - '@types/node': 18.19.34 + '@types/node': 18.19.39 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.4.2 cors: 2.8.5 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) engine.io-parser: 5.2.1 ws: 8.11.0 transitivePeerDependencies: @@ -14500,50 +13796,7 @@ snapshots: env-paths@2.2.1: {} - envinfo@7.11.0: {} - - envinfo@7.8.1: {} - - enzyme-adapter-utils@1.14.1(react@18.2.0): - dependencies: - airbnb-prop-types: 2.16.0(react@18.2.0) - function.prototype.name: 1.1.6 - has: 1.0.4 - object.assign: 4.1.5 - object.fromentries: 2.0.8 - prop-types: 15.8.1 - react: 18.2.0 - semver: 5.7.2 - - enzyme-shallow-equal@1.0.5: - dependencies: - has: 1.0.4 - object-is: 1.1.5 - - enzyme@3.11.0: - dependencies: - array.prototype.flat: 1.3.2 - cheerio: 1.0.0-rc.12 - enzyme-shallow-equal: 1.0.5 - function.prototype.name: 1.1.6 - has: 1.0.4 - html-element-map: 1.3.1 - is-boolean-object: 1.1.2 - is-callable: 1.2.7 - is-number-object: 1.0.7 - is-regex: 1.1.4 - is-string: 1.0.7 - is-subset: 0.1.1 - lodash.escape: 4.0.1 - lodash.isequal: 4.5.0 - object-inspect: 1.13.1 - object-is: 1.1.5 - object.assign: 4.1.5 - object.entries: 1.1.8 - object.values: 1.2.0 - raf: 3.4.1 - rst-selector-parser: 2.2.3 - string.prototype.trim: 1.2.9 + envinfo@7.13.0: {} err-code@2.0.3: {} @@ -14637,7 +13890,7 @@ snapshots: iterator.prototype: 1.1.2 safe-array-concat: 1.1.2 - es-module-lexer@1.4.1: {} + es-module-lexer@1.5.4: {} es-object-atoms@1.0.0: dependencies: @@ -14706,31 +13959,31 @@ snapshots: optionalDependencies: source-map: 0.2.0 - eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0))(eslint@8.57.0): + eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0))(eslint@8.57.0): dependencies: confusing-browser-globals: 1.0.11 eslint: 8.57.0 - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0) object.assign: 4.1.5 object.entries: 1.1.8 semver: 6.3.1 - eslint-config-airbnb-typescript@18.0.0(@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0))(eslint@8.57.0): + eslint-config-airbnb-typescript@18.0.0(@typescript-eslint/eslint-plugin@7.15.0(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3))(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0))(eslint@8.57.0): dependencies: - '@typescript-eslint/eslint-plugin': 7.13.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/parser': 7.13.1(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/eslint-plugin': 7.15.0(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/parser': 7.15.0(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 - eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0))(eslint@8.57.0) + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0))(eslint@8.57.0) transitivePeerDependencies: - eslint-plugin-import - eslint-config-airbnb@19.0.4(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0))(eslint-plugin-jsx-a11y@6.8.0(eslint@8.57.0))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.0))(eslint-plugin-react@7.34.2(eslint@8.57.0))(eslint@8.57.0): + eslint-config-airbnb@19.0.4(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0))(eslint-plugin-jsx-a11y@6.9.0(eslint@8.57.0))(eslint-plugin-react-hooks@4.6.2(eslint@8.57.0))(eslint-plugin-react@7.34.3(eslint@8.57.0))(eslint@8.57.0): dependencies: eslint: 8.57.0 - eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0) - eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) - eslint-plugin-react: 7.34.2(eslint@8.57.0) + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0) + eslint-plugin-jsx-a11y: 6.9.0(eslint@8.57.0) + eslint-plugin-react: 7.34.3(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) object.assign: 4.1.5 object.entries: 1.1.8 @@ -14747,12 +14000,12 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.92.0(webpack-cli@5.1.4)): + eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.92.1(webpack-cli@5.1.4)): dependencies: array.prototype.find: 2.2.2 debug: 3.2.7 enhanced-resolve: 0.9.1 - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0) find-root: 1.1.0 hasown: 2.0.2 interpret: 1.4.0 @@ -14761,18 +14014,18 @@ snapshots: lodash: 4.17.21 resolve: 2.0.0-next.5 semver: 5.7.2 - webpack: 5.92.0(webpack-cli@5.1.4) + webpack: 5.92.1(webpack-cli@5.1.4) transitivePeerDependencies: - supports-color - eslint-module-utils@2.8.0(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.92.0(webpack-cli@5.1.4)))(eslint@8.57.0): + eslint-module-utils@2.8.0(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.92.1(webpack-cli@5.1.4)))(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 7.13.1(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': 7.15.0(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-webpack: 0.13.8(eslint-plugin-import@2.29.1)(webpack@5.92.0(webpack-cli@5.1.4)) + eslint-import-resolver-webpack: 0.13.8(eslint-plugin-import@2.29.1)(webpack@5.92.1(webpack-cli@5.1.4)) transitivePeerDependencies: - supports-color @@ -14784,7 +14037,7 @@ snapshots: lodash.snakecase: 4.1.1 lodash.upperfirst: 4.3.1 - eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0): dependencies: array-includes: 3.1.8 array.prototype.findlastindex: 1.2.3 @@ -14794,7 +14047,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.92.0(webpack-cli@5.1.4)))(eslint@8.57.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-webpack@0.13.8(eslint-plugin-import@2.29.1)(webpack@5.92.1(webpack-cli@5.1.4)))(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -14805,35 +14058,36 @@ snapshots: semver: 6.3.1 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 7.13.1(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': 7.15.0(eslint@8.57.0)(typescript@5.5.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-jsdoc@48.2.12(eslint@8.57.0): + eslint-plugin-jsdoc@48.5.2(eslint@8.57.0): dependencies: '@es-joy/jsdoccomment': 0.43.1 are-docs-informative: 0.0.2 comment-parser: 1.4.1 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) escape-string-regexp: 4.0.0 eslint: 8.57.0 esquery: 1.5.0 + parse-imports: 2.1.0 semver: 7.6.2 spdx-expression-parse: 4.0.0 + synckit: 0.9.0 transitivePeerDependencies: - supports-color - eslint-plugin-jsx-a11y@6.8.0(eslint@8.57.0): + eslint-plugin-jsx-a11y@6.9.0(eslint@8.57.0): dependencies: - '@babel/runtime': 7.24.7 - aria-query: 5.3.0 + aria-query: 5.1.3 array-includes: 3.1.8 array.prototype.flatmap: 1.3.2 ast-types-flow: 0.0.8 - axe-core: 4.7.0 - axobject-query: 3.2.1 + axe-core: 4.9.1 + axobject-query: 3.1.1 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 es-iterator-helpers: 1.0.19 @@ -14842,8 +14096,9 @@ snapshots: jsx-ast-utils: 3.3.5 language-tags: 1.0.9 minimatch: 3.1.2 - object.entries: 1.1.8 object.fromentries: 2.0.8 + safe-regex-test: 1.0.3 + string.prototype.includes: 2.0.0 eslint-plugin-mocha@10.4.3(eslint@8.57.0): dependencies: @@ -14878,13 +14133,13 @@ snapshots: dependencies: eslint: 8.57.0 - eslint-plugin-react@7.34.2(eslint@8.57.0): + eslint-plugin-react@7.34.3(eslint@8.57.0): dependencies: array-includes: 3.1.8 array.prototype.findlast: 1.2.5 array.prototype.flatmap: 1.3.2 array.prototype.toreversed: 1.1.2 - array.prototype.tosorted: 1.1.3 + array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.0.19 eslint: 8.57.0 @@ -14932,7 +14187,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -15040,7 +14295,7 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 - execa@9.2.0: + execa@9.3.0: dependencies: '@sindresorhus/merge-streams': 4.0.0 cross-spawn: 7.0.3 @@ -15055,18 +14310,6 @@ snapshots: strip-final-newline: 4.0.0 yoctocolors: 2.0.2 - expand-brackets@2.1.4: - dependencies: - debug: 2.6.9 - define-property: 0.2.5 - extend-shallow: 2.0.1 - posix-character-classes: 0.1.1 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - expand-tilde@2.0.2: dependencies: homedir-polyfill: 1.0.3 @@ -15113,11 +14356,6 @@ snapshots: dependencies: is-extendable: 0.1.1 - extend-shallow@3.0.2: - dependencies: - assign-symbols: 1.0.0 - is-extendable: 1.0.1 - extend@3.0.2: {} external-editor@3.1.0: @@ -15126,19 +14364,6 @@ snapshots: iconv-lite: 0.4.24 tmp: 0.0.33 - extglob@2.0.4: - dependencies: - array-unique: 0.3.2 - define-property: 1.0.0 - expand-brackets: 2.1.4 - extend-shallow: 2.0.1 - fragment-cache: 0.2.1 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - fast-csv@4.3.6: dependencies: '@fast-csv/format': 4.3.5 @@ -15154,7 +14379,7 @@ snapshots: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.7 fast-json-patch@3.1.1: {} @@ -15190,14 +14415,7 @@ snapshots: dependencies: minimatch: 5.1.6 - fill-range@4.0.0: - dependencies: - extend-shallow: 2.0.1 - is-number: 3.0.0 - repeat-string: 1.6.1 - to-regex-range: 2.1.1 - - fill-range@7.0.1: + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -15286,16 +14504,14 @@ snapshots: flow-parser@0.227.0: {} - follow-redirects@1.15.6(debug@4.3.4): + follow-redirects@1.15.6(debug@4.3.5): optionalDependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) for-each@0.3.3: dependencies: is-callable: 1.2.7 - for-in@1.0.2: {} - foreground-child@2.0.0: dependencies: cross-spawn: 7.0.3 @@ -15324,10 +14540,6 @@ snapshots: fraction.js@4.3.7: {} - fragment-cache@0.2.1: - dependencies: - map-cache: 0.2.2 - fresh@0.5.2: {} fromentries@1.3.2: {} @@ -15384,17 +14596,6 @@ snapshots: functions-have-names@1.2.3: {} - gauge@4.0.4: - dependencies: - aproba: 2.0.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - gaxios@6.1.1(encoding@0.1.13): dependencies: extend: 3.0.2 @@ -15459,8 +14660,6 @@ snapshots: dependencies: resolve-pkg-maps: 1.0.0 - get-value@2.0.6: {} - git-config-path@1.0.1: dependencies: extend-shallow: 2.0.1 @@ -15488,7 +14687,7 @@ snapshots: is-ssh: 1.4.0 parse-url: 8.1.0 - git-url-parse@13.1.0: + git-url-parse@14.0.0: dependencies: git-up: 7.0.0 @@ -15600,7 +14799,7 @@ snapshots: transitivePeerDependencies: - supports-color - google-auth-library@9.10.0(encoding@0.1.13): + google-auth-library@9.11.0(encoding@0.1.13): dependencies: base64-js: 1.5.1 ecdsa-sig-formatter: 1.0.11 @@ -15616,7 +14815,7 @@ snapshots: dependencies: extend: 3.0.2 gaxios: 6.1.1(encoding@0.1.13) - google-auth-library: 9.10.0(encoding@0.1.13) + google-auth-library: 9.11.0(encoding@0.1.13) qs: 6.11.2 url-template: 2.0.8 uuid: 9.0.1 @@ -15679,27 +14878,6 @@ snapshots: has-unicode@2.0.1: {} - has-value@0.3.1: - dependencies: - get-value: 2.0.6 - has-values: 0.1.4 - isobject: 2.1.0 - - has-value@1.0.0: - dependencies: - get-value: 2.0.6 - has-values: 1.0.0 - isobject: 3.0.1 - - has-values@0.1.4: {} - - has-values@1.0.0: - dependencies: - is-number: 3.0.0 - kind-of: 4.0.0 - - has@1.0.4: {} - hasha@5.2.2: dependencies: is-stream: 2.0.1 @@ -15719,7 +14897,7 @@ snapshots: hoist-non-react-statics@3.3.2: dependencies: - react-is: 18.2.0 + react-is: 18.3.1 homedir-polyfill@1.0.3: dependencies: @@ -15727,26 +14905,13 @@ snapshots: hosted-git-info@2.8.9: {} - hosted-git-info@3.0.8: - dependencies: - lru-cache: 6.0.0 - hosted-git-info@4.1.0: dependencies: lru-cache: 6.0.0 - hosted-git-info@6.1.1: - dependencies: - lru-cache: 7.18.3 - - hosted-git-info@7.0.1: + hosted-git-info@7.0.2: dependencies: - lru-cache: 10.2.0 - - html-element-map@1.3.1: - dependencies: - array.prototype.filter: 1.0.3 - call-bind: 1.0.7 + lru-cache: 10.3.0 html-encoding-sniffer@4.0.0: dependencies: @@ -15772,7 +14937,7 @@ snapshots: readable-stream: 1.0.34 through2: 0.4.2 - html-webpack-plugin@5.6.0(webpack@5.92.0(webpack-cli@5.1.4)): + html-webpack-plugin@5.6.0(webpack@5.92.1(webpack-cli@5.1.4)): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -15780,7 +14945,7 @@ snapshots: pretty-error: 4.0.0 tapable: 2.2.1 optionalDependencies: - webpack: 5.92.0(webpack-cli@5.1.4) + webpack: 5.92.1(webpack-cli@5.1.4) htmlparser2@6.1.0: dependencies: @@ -15789,13 +14954,6 @@ snapshots: domutils: 2.8.0 entities: 2.2.0 - htmlparser2@8.0.2: - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - domutils: 3.1.0 - entities: 4.5.0 - http-cache-semantics@4.1.1: {} http-errors@2.0.0: @@ -15810,21 +14968,21 @@ snapshots: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) transitivePeerDependencies: - supports-color http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) transitivePeerDependencies: - supports-color http-proxy@1.18.1: dependencies: eventemitter3: 4.0.7 - follow-redirects: 1.15.6(debug@4.3.4) + follow-redirects: 1.15.6(debug@4.3.5) requires-port: 1.0.0 transitivePeerDependencies: - debug @@ -15832,14 +14990,14 @@ snapshots: https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) transitivePeerDependencies: - supports-color https-proxy-agent@7.0.4: dependencies: agent-base: 7.1.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -15847,10 +15005,6 @@ snapshots: human-signals@7.0.0: {} - humanize-ms@1.2.1: - dependencies: - ms: 2.1.3 - hyperlinker@1.0.0: {} hyphenate-style-name@1.0.4: {} @@ -15865,10 +15019,6 @@ snapshots: ieee754@1.2.1: {} - ignore-walk@5.0.1: - dependencies: - minimatch: 5.1.6 - ignore-walk@6.0.4: dependencies: minimatch: 9.0.4 @@ -15902,15 +15052,17 @@ snapshots: ini@1.3.8: {} - init-package-json@5.0.0: + init-package-json@6.0.3: dependencies: - npm-package-arg: 10.1.0 + '@npmcli/package-json': 5.2.0 + npm-package-arg: 11.0.2 promzard: 1.0.0 - read: 2.1.0 - read-package-json: 6.0.4 + read: 3.0.1 semver: 7.6.2 validate-npm-package-license: 3.0.4 - validate-npm-package-name: 5.0.0 + validate-npm-package-name: 5.0.1 + transitivePeerDependencies: + - bluebird inquirer@8.2.6: dependencies: @@ -15946,10 +15098,6 @@ snapshots: ipaddr.js@1.9.1: {} - is-accessor-descriptor@1.0.1: - dependencies: - hasown: 2.0.2 - is-alphabetical@1.0.4: {} is-alphanumerical@1.0.4: @@ -15988,8 +15136,6 @@ snapshots: call-bind: 1.0.7 has-tostringtag: 1.0.2 - is-buffer@1.1.6: {} - is-buffer@2.0.5: {} is-callable@1.2.7: {} @@ -16002,10 +15148,6 @@ snapshots: dependencies: hasown: 2.0.2 - is-data-descriptor@1.0.1: - dependencies: - hasown: 2.0.2 - is-data-view@1.0.1: dependencies: is-typed-array: 1.1.13 @@ -16016,26 +15158,12 @@ snapshots: is-decimal@1.0.4: {} - is-descriptor@0.1.7: - dependencies: - is-accessor-descriptor: 1.0.1 - is-data-descriptor: 1.0.1 - - is-descriptor@1.0.3: - dependencies: - is-accessor-descriptor: 1.0.1 - is-data-descriptor: 1.0.1 - is-docker@2.2.1: {} is-electron@2.2.2: {} is-extendable@0.1.1: {} - is-extendable@1.0.1: - dependencies: - is-plain-object: 2.0.4 - is-extglob@2.1.1: {} is-finalizationregistry@1.0.2: @@ -16068,10 +15196,6 @@ snapshots: dependencies: has-tostringtag: 1.0.2 - is-number@3.0.0: - dependencies: - kind-of: 3.2.2 - is-number@7.0.0: {} is-obj@2.0.0: {} @@ -16121,8 +15245,6 @@ snapshots: dependencies: has-tostringtag: 1.0.2 - is-subset@0.1.1: {} - is-symbol@1.0.4: dependencies: has-symbols: 1.0.3 @@ -16170,10 +15292,6 @@ snapshots: isexe@3.1.1: {} - isobject@2.1.0: - dependencies: - isarray: 1.0.0 - isobject@3.0.1: {} istanbul-lib-coverage@3.2.2: {} @@ -16182,16 +15300,6 @@ snapshots: dependencies: append-transform: 2.0.0 - istanbul-lib-instrument@5.2.1: - dependencies: - '@babel/core': 7.24.7 - '@babel/parser': 7.24.7 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - istanbul-lib-instrument@6.0.2: dependencies: '@babel/core': 7.24.7 @@ -16219,7 +15327,7 @@ snapshots: istanbul-lib-source-maps@4.0.1: dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) istanbul-lib-coverage: 3.2.2 source-map: 0.6.1 transitivePeerDependencies: @@ -16288,7 +15396,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 18.19.34 + '@types/node': 18.19.39 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -16303,40 +15411,29 @@ snapshots: dependencies: argparse: 2.0.1 - jscodeshift-add-imports@1.0.10(jscodeshift@0.13.1(@babel/preset-env@7.24.7(@babel/core@7.24.7))): - dependencies: - '@babel/traverse': 7.24.7 - jscodeshift: 0.13.1(@babel/preset-env@7.24.7(@babel/core@7.24.7)) - jscodeshift-find-imports: 2.0.4(jscodeshift@0.13.1(@babel/preset-env@7.24.7(@babel/core@7.24.7))) - transitivePeerDependencies: - - supports-color - - jscodeshift-find-imports@2.0.4(jscodeshift@0.13.1(@babel/preset-env@7.24.7(@babel/core@7.24.7))): - dependencies: - jscodeshift: 0.13.1(@babel/preset-env@7.24.7(@babel/core@7.24.7)) - - jscodeshift@0.13.1(@babel/preset-env@7.24.7(@babel/core@7.24.7)): + jscodeshift@0.16.1(@babel/preset-env@7.24.7(@babel/core@7.24.7)): dependencies: '@babel/core': 7.24.7 '@babel/parser': 7.24.7 - '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.24.7) - '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.24.7) - '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.24.7) + '@babel/plugin-transform-class-properties': 7.24.7(@babel/core@7.24.7) '@babel/plugin-transform-modules-commonjs': 7.24.7(@babel/core@7.24.7) - '@babel/preset-env': 7.24.7(@babel/core@7.24.7) - '@babel/preset-flow': 7.23.3(@babel/core@7.24.7) + '@babel/plugin-transform-nullish-coalescing-operator': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-optional-chaining': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-private-methods': 7.24.7(@babel/core@7.24.7) + '@babel/preset-flow': 7.24.7(@babel/core@7.24.7) '@babel/preset-typescript': 7.24.7(@babel/core@7.24.7) '@babel/register': 7.24.6(@babel/core@7.24.7) - babel-core: 7.0.0-bridge.0(@babel/core@7.24.7) chalk: 4.1.2 flow-parser: 0.227.0 graceful-fs: 4.2.11 - micromatch: 3.1.10 + micromatch: 4.0.7 neo-async: 2.6.2 node-dir: 0.1.17 - recast: 0.20.5 - temp: 0.8.4 - write-file-atomic: 2.4.3 + recast: 0.23.9 + temp: 0.9.4 + write-file-atomic: 5.0.1 + optionalDependencies: + '@babel/preset-env': 7.24.7(@babel/core@7.24.7) transitivePeerDependencies: - supports-color @@ -16384,7 +15481,7 @@ snapshots: json-parse-even-better-errors@2.3.1: {} - json-parse-even-better-errors@3.0.1: {} + json-parse-even-better-errors@3.0.2: {} json-schema-traverse@0.4.1: {} @@ -16392,6 +15489,8 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} + json-stringify-nice@1.1.4: {} + json-stringify-safe@5.0.1: {} json5@1.0.2: @@ -16504,6 +15603,10 @@ snapshots: junk@4.0.1: {} + just-diff-apply@5.5.0: {} + + just-diff@6.0.2: {} + just-extend@6.2.0: {} jwa@1.4.1: @@ -16546,18 +15649,18 @@ snapshots: dependencies: graceful-fs: 4.2.11 - karma-webpack@5.0.1(webpack@5.92.0(webpack-cli@5.1.4)): + karma-webpack@5.0.1(webpack@5.92.1(webpack-cli@5.1.4)): dependencies: glob: 7.2.3 minimatch: 9.0.4 - webpack: 5.92.0(webpack-cli@5.1.4) + webpack: 5.92.1(webpack-cli@5.1.4) webpack-merge: 4.2.2 karma@6.4.3: dependencies: '@colors/colors': 1.5.0 body-parser: 1.20.2 - braces: 3.0.2 + braces: 3.0.3 chokidar: 3.5.3 connect: 3.7.0 di: 0.0.1 @@ -16589,14 +15692,6 @@ snapshots: dependencies: json-buffer: 3.0.1 - kind-of@3.2.2: - dependencies: - is-buffer: 1.1.6 - - kind-of@4.0.0: - dependencies: - is-buffer: 1.1.6 - kind-of@6.0.3: {} language-subtag-registry@0.3.22: {} @@ -16609,53 +15704,57 @@ snapshots: dependencies: readable-stream: 2.3.8 - lerna@8.1.3(encoding@0.1.13): + lerna@8.1.6(babel-plugin-macros@3.1.0)(encoding@0.1.13): dependencies: - '@lerna/create': 8.1.3(encoding@0.1.13)(typescript@5.4.5) - '@npmcli/run-script': 7.0.2 + '@lerna/create': 8.1.6(babel-plugin-macros@3.1.0)(encoding@0.1.13)(typescript@5.5.3) + '@npmcli/arborist': 7.5.3 + '@npmcli/package-json': 5.2.0 + '@npmcli/run-script': 8.1.0 '@nx/devkit': 17.3.0(nx@17.3.0) '@octokit/plugin-enterprise-rest': 6.0.1 '@octokit/rest': 19.0.11(encoding@0.1.13) + aproba: 2.0.0 byte-size: 8.1.1 chalk: 4.1.0 clone-deep: 4.0.1 - cmd-shim: 6.0.1 + cmd-shim: 6.0.3 + color-support: 1.1.3 columnify: 1.6.0 + console-control-strings: 1.1.0 conventional-changelog-angular: 7.0.0 conventional-changelog-core: 5.0.1 conventional-recommended-bump: 7.0.1 - cosmiconfig: 8.3.6(typescript@5.4.5) - dedent: 0.7.0 - envinfo: 7.8.1 + cosmiconfig: 8.3.6(typescript@5.5.3) + dedent: 1.5.3(babel-plugin-macros@3.1.0) + envinfo: 7.13.0 execa: 5.0.0 fs-extra: 11.2.0 get-port: 5.1.1 get-stream: 6.0.0 - git-url-parse: 13.1.0 - glob-parent: 5.1.2 + git-url-parse: 14.0.0 + glob-parent: 6.0.2 globby: 11.1.0 graceful-fs: 4.2.11 has-unicode: 2.0.1 import-local: 3.1.0 ini: 1.3.8 - init-package-json: 5.0.0 + init-package-json: 6.0.3 inquirer: 8.2.6 is-ci: 3.0.1 is-stream: 2.0.0 jest-diff: 29.7.0 js-yaml: 4.1.0 - libnpmaccess: 7.0.2 - libnpmpublish: 7.3.0 + libnpmaccess: 8.0.6 + libnpmpublish: 9.0.9 load-json-file: 6.2.0 lodash: 4.17.21 make-dir: 4.0.0 minimatch: 3.0.5 multimatch: 5.0.0 node-fetch: 2.6.7(encoding@0.1.13) - npm-package-arg: 8.1.1 - npm-packlist: 5.1.1 - npm-registry-fetch: 14.0.5 - npmlog: 6.0.2 + npm-package-arg: 11.0.2 + npm-packlist: 8.0.2 + npm-registry-fetch: 17.1.0 nx: 17.3.0 p-map: 4.0.0 p-map-series: 2.1.0 @@ -16663,24 +15762,26 @@ snapshots: p-queue: 6.6.2 p-reduce: 2.1.0 p-waterfall: 2.1.1 - pacote: 17.0.6 + pacote: 18.0.6 pify: 5.0.0 read-cmd-shim: 4.0.0 - read-package-json: 6.0.4 resolve-from: 5.0.0 rimraf: 4.4.1 semver: 7.6.2 + set-blocking: 2.0.0 signal-exit: 3.0.7 slash: 3.0.0 - ssri: 9.0.1 + ssri: 10.0.6 + string-width: 4.2.3 strong-log-transformer: 2.1.0 tar: 6.2.1 temp-dir: 1.0.0 - typescript: 5.4.5 + typescript: 5.5.3 upath: 2.0.1 - uuid: 9.0.1 + uuid: 10.0.0 validate-npm-package-license: 3.0.4 - validate-npm-package-name: 5.0.0 + validate-npm-package-name: 5.0.1 + wide-align: 1.1.5 write-file-atomic: 5.0.1 write-pkg: 4.0.0 yargs: 17.7.2 @@ -16688,6 +15789,7 @@ snapshots: transitivePeerDependencies: - '@swc-node/register' - '@swc/core' + - babel-plugin-macros - bluebird - debug - encoding @@ -16703,23 +15805,23 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - libnpmaccess@7.0.2: + libnpmaccess@8.0.6: dependencies: - npm-package-arg: 10.1.0 - npm-registry-fetch: 14.0.5 + npm-package-arg: 11.0.2 + npm-registry-fetch: 17.1.0 transitivePeerDependencies: - supports-color - libnpmpublish@7.3.0: + libnpmpublish@9.0.9: dependencies: - ci-info: 3.9.0 - normalize-package-data: 5.0.0 - npm-package-arg: 10.1.0 - npm-registry-fetch: 14.0.5 - proc-log: 3.0.0 + ci-info: 4.0.0 + normalize-package-data: 6.0.2 + npm-package-arg: 11.0.2 + npm-registry-fetch: 17.1.0 + proc-log: 4.2.0 semver: 7.6.2 - sigstore: 1.9.0 - ssri: 10.0.5 + sigstore: 2.2.0 + ssri: 10.0.6 transitivePeerDependencies: - supports-color @@ -16791,8 +15893,6 @@ snapshots: lodash.difference@4.5.0: {} - lodash.escape@4.0.1: {} - lodash.escaperegexp@4.1.2: {} lodash.find@4.6.0: {} @@ -16863,7 +15963,7 @@ snapshots: log4js@6.9.1: dependencies: date-format: 4.0.14 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) flatted: 3.2.9 rfdc: 1.3.1 streamroller: 3.1.5 @@ -16884,7 +15984,7 @@ snapshots: dependencies: tslib: 2.6.2 - lru-cache@10.2.0: {} + lru-cache@10.3.0: {} lru-cache@4.1.5: dependencies: @@ -16899,8 +15999,6 @@ snapshots: dependencies: yallist: 4.0.0 - lru-cache@7.18.3: {} - luxon@3.4.4: {} lz-string@1.5.0: {} @@ -16920,30 +16018,10 @@ snapshots: dependencies: semver: 7.6.2 - make-fetch-happen@11.1.1: - dependencies: - agentkeepalive: 4.5.0 - cacache: 17.1.4 - http-cache-semantics: 4.1.1 - http-proxy-agent: 5.0.0 - https-proxy-agent: 5.0.1 - is-lambda: 1.0.1 - lru-cache: 7.18.3 - minipass: 5.0.0 - minipass-fetch: 3.0.4 - minipass-flush: 1.0.5 - minipass-pipeline: 1.2.4 - negotiator: 0.6.3 - promise-retry: 2.0.1 - socks-proxy-agent: 7.0.0 - ssri: 10.0.5 - transitivePeerDependencies: - - supports-color - make-fetch-happen@13.0.0: dependencies: '@npmcli/agent': 2.2.0 - cacache: 18.0.2 + cacache: 18.0.3 http-cache-semantics: 4.1.1 is-lambda: 1.0.1 minipass: 7.0.4 @@ -16952,20 +16030,14 @@ snapshots: minipass-pipeline: 1.2.4 negotiator: 0.6.3 promise-retry: 2.0.1 - ssri: 10.0.5 + ssri: 10.0.6 transitivePeerDependencies: - supports-color - map-cache@0.2.2: {} - map-obj@1.0.1: {} map-obj@4.3.0: {} - map-visit@1.0.0: - dependencies: - object-visit: 1.0.1 - markdown-it@14.1.0: dependencies: argparse: 2.0.1 @@ -16975,9 +16047,9 @@ snapshots: punycode.js: 2.3.1 uc.micro: 2.1.0 - markdown-to-jsx@7.4.7(react@18.2.0): + markdown-to-jsx@7.4.7(react@18.3.1): dependencies: - react: 18.2.0 + react: 18.3.1 markdownlint-cli2-formatter-default@0.0.4(markdownlint-cli2@0.13.0): dependencies: @@ -16999,7 +16071,7 @@ snapshots: markdown-it: 14.1.0 markdownlint-micromark: 0.1.9 - marked@5.1.2: {} + marked@13.0.1: {} mdast-util-from-markdown@0.8.5: dependencies: @@ -17060,32 +16132,19 @@ snapshots: micromark@2.11.4: dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) parse-entities: 2.0.0 transitivePeerDependencies: - supports-color - micromatch@3.1.10: + micromatch@4.0.5: dependencies: - arr-diff: 4.0.0 - array-unique: 0.3.2 - braces: 2.3.2 - define-property: 2.0.2 - extend-shallow: 3.0.2 - extglob: 2.0.4 - fragment-cache: 0.2.1 - kind-of: 6.0.3 - nanomatch: 1.2.13 - object.pick: 1.3.0 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color + braces: 3.0.3 + picomatch: 2.3.1 - micromatch@4.0.5: + micromatch@4.0.7: dependencies: - braces: 3.0.2 + braces: 3.0.3 picomatch: 2.3.1 mime-db@1.33.0: {} @@ -17116,10 +16175,6 @@ snapshots: dependencies: brace-expansion: 1.1.11 - minimatch@5.0.1: - dependencies: - brace-expansion: 2.0.1 - minimatch@5.1.6: dependencies: brace-expansion: 2.0.1 @@ -17144,10 +16199,6 @@ snapshots: minimist@1.2.8: {} - minipass-collect@1.0.2: - dependencies: - minipass: 3.3.6 - minipass-collect@2.0.1: dependencies: minipass: 7.0.4 @@ -17164,11 +16215,6 @@ snapshots: dependencies: minipass: 3.3.6 - minipass-json-stream@1.0.1: - dependencies: - jsonparse: 1.3.1 - minipass: 3.3.6 - minipass-pipeline@1.2.4: dependencies: minipass: 3.3.6 @@ -17192,38 +16238,33 @@ snapshots: minipass: 3.3.6 yallist: 4.0.0 - mixin-deep@1.3.2: - dependencies: - for-in: 1.0.2 - is-extendable: 1.0.1 - mkdirp@0.5.6: dependencies: minimist: 1.2.8 mkdirp@1.0.4: {} - mocha@10.4.0: + mocha@10.6.0: dependencies: - ansi-colors: 4.1.1 + ansi-colors: 4.1.3 browser-stdout: 1.3.1 chokidar: 3.5.3 - debug: 4.3.4(supports-color@8.1.1) - diff: 5.0.0 + debug: 4.3.5(supports-color@8.1.1) + diff: 5.2.0 escape-string-regexp: 4.0.0 find-up: 5.0.0 glob: 8.1.0 he: 1.2.0 js-yaml: 4.1.0 log-symbols: 4.1.0 - minimatch: 5.0.1 + minimatch: 5.1.6 ms: 2.1.3 - serialize-javascript: 6.0.0 + serialize-javascript: 6.0.2 strip-json-comments: 3.1.1 supports-color: 8.1.1 - workerpool: 6.2.1 + workerpool: 6.5.1 yargs: 16.2.0 - yargs-parser: 20.2.4 + yargs-parser: 20.2.9 yargs-unparser: 2.0.0 modify-values@1.0.1: {} @@ -17232,7 +16273,7 @@ snapshots: dependencies: moment: 2.30.1 - moment-jalaali@0.10.0: + moment-jalaali@0.10.1: dependencies: jalaali-js: 1.2.6 moment: 2.30.1 @@ -17245,8 +16286,6 @@ snapshots: moment@2.30.1: {} - moo@0.5.2: {} - mri@1.2.0: {} mrmime@2.0.0: {} @@ -17282,38 +16321,15 @@ snapshots: nanoid@3.3.7: {} - nanomatch@1.2.13: - dependencies: - arr-diff: 4.0.0 - array-unique: 0.3.2 - define-property: 2.0.2 - extend-shallow: 3.0.2 - fragment-cache: 0.2.1 - is-windows: 1.0.2 - kind-of: 6.0.3 - object.pick: 1.3.0 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - natural-compare@1.4.0: {} - nearley@2.20.1: - dependencies: - commander: 2.20.3 - moo: 0.5.2 - railroad-diagrams: 1.0.0 - randexp: 0.4.6 - negotiator@0.6.3: {} neo-async@2.6.2: {} nested-error-stacks@2.1.1: {} - next@14.2.4(@babel/core@7.24.7)(@opentelemetry/api@1.8.0)(@playwright/test@1.44.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + next@14.2.4(@babel/core@7.24.7)(@opentelemetry/api@1.8.0)(@playwright/test@1.44.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@next/env': 14.2.4 '@swc/helpers': 0.5.5 @@ -17321,9 +16337,9 @@ snapshots: caniuse-lite: 1.0.30001606 graceful-fs: 4.2.11 postcss: 8.4.31 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - styled-jsx: 5.1.1(@babel/core@7.24.7)(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + styled-jsx: 5.1.1(@babel/core@7.24.7)(babel-plugin-macros@3.1.0)(react@18.3.1) optionalDependencies: '@next/swc-darwin-arm64': 14.2.4 '@next/swc-darwin-x64': 14.2.4 @@ -17383,7 +16399,7 @@ snapshots: glob: 10.3.10 graceful-fs: 4.2.11 make-fetch-happen: 13.0.0 - nopt: 7.2.0 + nopt: 7.2.1 proc-log: 3.0.0 semver: 7.6.2 tar: 6.2.1 @@ -17403,7 +16419,7 @@ snapshots: dependencies: abbrev: 1.1.1 - nopt@7.2.0: + nopt@7.2.1: dependencies: abbrev: 2.0.0 @@ -17421,17 +16437,9 @@ snapshots: semver: 7.6.2 validate-npm-package-license: 3.0.4 - normalize-package-data@5.0.0: - dependencies: - hosted-git-info: 6.1.1 - is-core-module: 2.13.1 - semver: 7.6.2 - validate-npm-package-license: 3.0.4 - - normalize-package-data@6.0.0: + normalize-package-data@6.0.2: dependencies: - hosted-git-info: 7.0.1 - is-core-module: 2.13.1 + hosted-git-info: 7.0.2 semver: 7.6.2 validate-npm-package-license: 3.0.4 @@ -17439,10 +16447,6 @@ snapshots: normalize-range@0.1.2: {} - npm-bundled@1.1.2: - dependencies: - npm-normalize-package-bin: 1.0.1 - npm-bundled@3.0.0: dependencies: npm-normalize-package-bin: 3.0.1 @@ -17451,69 +16455,36 @@ snapshots: dependencies: semver: 7.6.2 - npm-normalize-package-bin@1.0.1: {} - npm-normalize-package-bin@3.0.1: {} - npm-package-arg@10.1.0: - dependencies: - hosted-git-info: 6.1.1 - proc-log: 3.0.0 - semver: 7.6.2 - validate-npm-package-name: 5.0.0 - - npm-package-arg@11.0.1: - dependencies: - hosted-git-info: 7.0.1 - proc-log: 3.0.0 - semver: 7.6.2 - validate-npm-package-name: 5.0.0 - - npm-package-arg@8.1.1: + npm-package-arg@11.0.2: dependencies: - hosted-git-info: 3.0.8 + hosted-git-info: 7.0.2 + proc-log: 4.2.0 semver: 7.6.2 - validate-npm-package-name: 3.0.0 - - npm-packlist@5.1.1: - dependencies: - glob: 8.1.0 - ignore-walk: 5.0.1 - npm-bundled: 1.1.2 - npm-normalize-package-bin: 1.0.1 + validate-npm-package-name: 5.0.1 npm-packlist@8.0.2: dependencies: ignore-walk: 6.0.4 - npm-pick-manifest@9.0.0: + npm-pick-manifest@9.0.1: dependencies: npm-install-checks: 6.3.0 npm-normalize-package-bin: 3.0.1 - npm-package-arg: 11.0.1 + npm-package-arg: 11.0.2 semver: 7.6.2 - npm-registry-fetch@14.0.5: - dependencies: - make-fetch-happen: 11.1.1 - minipass: 5.0.0 - minipass-fetch: 3.0.4 - minipass-json-stream: 1.0.1 - minizlib: 2.1.2 - npm-package-arg: 10.1.0 - proc-log: 3.0.0 - transitivePeerDependencies: - - supports-color - - npm-registry-fetch@16.1.0: + npm-registry-fetch@17.1.0: dependencies: + '@npmcli/redact': 2.0.1 + jsonparse: 1.3.1 make-fetch-happen: 13.0.0 minipass: 7.0.4 minipass-fetch: 3.0.4 - minipass-json-stream: 1.0.1 minizlib: 2.1.2 - npm-package-arg: 11.0.1 - proc-log: 3.0.0 + npm-package-arg: 11.0.2 + proc-log: 4.2.0 transitivePeerDependencies: - supports-color @@ -17525,13 +16496,6 @@ snapshots: dependencies: path-key: 4.0.0 - npmlog@6.0.2: - dependencies: - are-we-there-yet: 3.0.1 - console-control-strings: 1.1.0 - gauge: 4.0.4 - set-blocking: 2.0.0 - nprogress@0.2.0: {} nth-check@2.1.1: @@ -17546,7 +16510,7 @@ snapshots: '@yarnpkg/lockfile': 1.1.0 '@yarnpkg/parsers': 3.0.0-rc.46 '@zkochan/js-yaml': 0.0.6 - axios: 1.7.2(debug@4.3.4) + axios: 1.7.2(debug@4.3.5) chalk: 4.1.2 cli-cursor: 3.1.0 cli-spinners: 2.6.1 @@ -17624,12 +16588,6 @@ snapshots: object-assign@4.1.1: {} - object-copy@0.1.0: - dependencies: - copy-descriptor: 0.1.1 - define-property: 0.2.5 - kind-of: 3.2.2 - object-hash@2.2.0: {} object-inspect@1.13.1: {} @@ -17643,10 +16601,6 @@ snapshots: object-keys@1.1.1: {} - object-visit@1.0.1: - dependencies: - isobject: 3.0.1 - object.assign@4.1.5: dependencies: call-bind: 1.0.7 @@ -17688,10 +16642,6 @@ snapshots: es-abstract: 1.23.3 es-object-atoms: 1.0.0 - object.pick@1.3.0: - dependencies: - isobject: 3.0.1 - object.values@1.2.0: dependencies: call-bind: 1.0.7 @@ -17870,25 +16820,24 @@ snapshots: lodash.flattendeep: 4.4.0 release-zalgo: 1.0.0 - pacote@17.0.6: + pacote@18.0.6: dependencies: '@npmcli/git': 5.0.4 - '@npmcli/installed-package-contents': 2.0.2 + '@npmcli/installed-package-contents': 2.1.0 + '@npmcli/package-json': 5.2.0 '@npmcli/promise-spawn': 7.0.1 - '@npmcli/run-script': 7.0.4 - cacache: 18.0.2 + '@npmcli/run-script': 8.1.0 + cacache: 18.0.3 fs-minipass: 3.0.3 minipass: 7.0.4 - npm-package-arg: 11.0.1 + npm-package-arg: 11.0.2 npm-packlist: 8.0.2 - npm-pick-manifest: 9.0.0 - npm-registry-fetch: 16.1.0 - proc-log: 3.0.0 + npm-pick-manifest: 9.0.1 + npm-registry-fetch: 17.1.0 + proc-log: 4.2.0 promise-retry: 2.0.1 - read-package-json: 7.0.0 - read-package-json-fast: 3.0.2 sigstore: 2.2.0 - ssri: 10.0.5 + ssri: 10.0.6 tar: 6.2.1 transitivePeerDependencies: - bluebird @@ -17905,6 +16854,12 @@ snapshots: dependencies: callsites: 3.1.0 + parse-conflict-json@3.0.1: + dependencies: + json-parse-even-better-errors: 3.0.2 + just-diff: 6.0.2 + just-diff-apply: 5.5.0 + parse-diff@0.7.1: {} parse-entities@2.0.0: @@ -17924,6 +16879,11 @@ snapshots: parse-github-url@1.0.2: {} + parse-imports@2.1.0: + dependencies: + es-module-lexer: 1.5.4 + slashes: 3.0.12 + parse-json@4.0.0: dependencies: error-ex: 1.3.2 @@ -17952,11 +16912,6 @@ snapshots: dependencies: parse-path: 7.0.0 - parse5-htmlparser2-tree-adapter@7.0.0: - dependencies: - domhandler: 5.0.3 - parse5: 7.1.2 - parse5@7.1.2: dependencies: entities: 4.5.0 @@ -17968,8 +16923,6 @@ snapshots: no-case: 3.0.4 tslib: 2.6.2 - pascalcase@0.1.1: {} - path-exists@3.0.0: {} path-exists@4.0.0: {} @@ -17988,7 +16941,7 @@ snapshots: path-scurry@1.10.1: dependencies: - lru-cache: 10.2.0 + lru-cache: 10.3.0 minipass: 7.0.4 path-to-regexp@0.1.7: {} @@ -18007,9 +16960,7 @@ snapshots: pathval@1.1.1: {} - performance-now@2.1.0: {} - - picocolors@1.0.0: {} + picocolors@1.0.1: {} picomatch@2.3.1: {} @@ -18045,32 +16996,49 @@ snapshots: playwright-core@1.44.1: {} + playwright-core@1.45.1: {} + playwright@1.44.1: dependencies: playwright-core: 1.44.1 optionalDependencies: fsevents: 2.3.2 + playwright@1.45.1: + dependencies: + playwright-core: 1.45.1 + optionalDependencies: + fsevents: 2.3.2 + please-upgrade-node@3.2.0: dependencies: semver-compare: 1.0.0 - posix-character-classes@0.1.1: {} - possible-typed-array-names@1.0.0: {} + postcss-selector-parser@6.1.0: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + postcss-value-parser@4.2.0: {} postcss@8.4.31: dependencies: nanoid: 3.3.7 - picocolors: 1.0.0 + picocolors: 1.0.1 source-map-js: 1.2.0 postcss@8.4.38: dependencies: nanoid: 3.3.7 - picocolors: 1.0.0 + picocolors: 1.0.1 + source-map-js: 1.2.0 + + postcss@8.4.39: + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.1 source-map-js: 1.2.0 prelude-ls@1.1.2: {} @@ -18092,13 +17060,13 @@ snapshots: dependencies: ansi-regex: 5.0.1 ansi-styles: 5.2.0 - react-is: 18.2.0 + react-is: 18.3.1 pretty-format@29.7.0: dependencies: '@jest/schemas': 29.6.3 ansi-styles: 5.2.0 - react-is: 18.2.0 + react-is: 18.3.1 pretty-ms@9.0.0: dependencies: @@ -18110,7 +17078,7 @@ snapshots: find-up: 5.0.0 ignore: 5.3.1 mri: 1.2.0 - picocolors: 1.0.0 + picocolors: 1.0.1 picomatch: 3.0.1 prettier: 3.3.2 tslib: 2.6.2 @@ -18124,6 +17092,8 @@ snapshots: proc-log@3.0.0: {} + proc-log@4.2.0: {} + process-nextick-args@2.0.1: {} process-on-spawn@1.0.0: @@ -18132,6 +17102,12 @@ snapshots: process@0.11.10: {} + proggy@2.0.0: {} + + promise-all-reject-late@1.0.1: {} + + promise-call-limit@3.0.1: {} + promise-inflight@1.0.1: {} promise-retry@2.0.1: @@ -18152,17 +17128,11 @@ snapshots: dependencies: read: 2.1.0 - prop-types-exact@1.2.0: - dependencies: - has: 1.0.4 - object.assign: 4.1.5 - reflect.ownkeys: 0.2.0 - prop-types@15.8.1: dependencies: loose-envify: 1.4.0 object-assign: 4.1.1 - react-is: 18.2.0 + react-is: 18.3.1 protocols@2.0.1: {} @@ -18199,19 +17169,8 @@ snapshots: quick-lru@4.0.1: {} - raf@3.4.1: - dependencies: - performance-now: 2.1.0 - - railroad-diagrams@1.0.0: {} - rambda@7.5.0: {} - randexp@0.4.6: - dependencies: - discontinuous-range: 1.0.0 - ret: 0.1.15 - randombytes@2.1.0: dependencies: safe-buffer: 5.2.1 @@ -18256,70 +17215,51 @@ snapshots: transitivePeerDependencies: - supports-color - react-dom@18.2.0(react@18.2.0): + react-dom@18.3.1(react@18.3.1): dependencies: loose-envify: 1.4.0 - react: 18.2.0 - scheduler: 0.23.0 + react: 18.3.1 + scheduler: 0.23.2 - react-hook-form@7.52.0(react@18.2.0): + react-hook-form@7.52.1(react@18.3.1): dependencies: - react: 18.2.0 - - react-is@18.2.0: {} + react: 18.3.1 - react-reconciler@0.29.0(react@18.2.0): - dependencies: - loose-envify: 1.4.0 - react: 18.2.0 - scheduler: 0.23.0 + react-is@18.3.1: {} - react-router-dom@6.23.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-router-dom@6.24.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@remix-run/router': 1.16.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-router: 6.23.1(react@18.2.0) + '@remix-run/router': 1.17.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-router: 6.24.1(react@18.3.1) - react-router@6.23.1(react@18.2.0): + react-router@6.24.1(react@18.3.1): dependencies: - '@remix-run/router': 1.16.1 - react: 18.2.0 + '@remix-run/router': 1.17.1 + react: 18.3.1 - react-runner@1.0.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-runner@1.0.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) sucrase: 3.35.0 - react-shallow-renderer@16.15.0(react@18.2.0): - dependencies: - object-assign: 4.1.1 - react: 18.2.0 - react-is: 18.2.0 - - react-simple-code-editor@0.13.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0): - dependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - - react-test-renderer@18.2.0(react@18.2.0): + react-simple-code-editor@0.14.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - react: 18.2.0 - react-is: 18.2.0 - react-shallow-renderer: 16.15.0(react@18.2.0) - scheduler: 0.23.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - react-transition-group@4.4.5(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.24.7 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - react@18.2.0: + react@18.3.1: dependencies: loose-envify: 1.4.0 @@ -18327,21 +17267,7 @@ snapshots: read-package-json-fast@3.0.2: dependencies: - json-parse-even-better-errors: 3.0.1 - npm-normalize-package-bin: 3.0.1 - - read-package-json@6.0.4: - dependencies: - glob: 10.3.10 - json-parse-even-better-errors: 3.0.1 - normalize-package-data: 5.0.0 - npm-normalize-package-bin: 3.0.1 - - read-package-json@7.0.0: - dependencies: - glob: 10.3.10 - json-parse-even-better-errors: 3.0.1 - normalize-package-data: 6.0.0 + json-parse-even-better-errors: 3.0.2 npm-normalize-package-bin: 3.0.1 read-pkg-up@3.0.0: @@ -18372,6 +17298,10 @@ snapshots: dependencies: mute-stream: 1.0.0 + read@3.0.1: + dependencies: + mute-stream: 1.0.0 + readable-stream@1.0.34: dependencies: core-util-is: 1.0.3 @@ -18438,8 +17368,6 @@ snapshots: globalthis: 1.0.3 which-builtin-type: 1.1.3 - reflect.ownkeys@0.2.0: {} - regenerate-unicode-properties@10.1.1: dependencies: regenerate: 1.4.2 @@ -18454,11 +17382,6 @@ snapshots: dependencies: '@babel/runtime': 7.24.7 - regex-not@1.0.2: - dependencies: - extend-shallow: 3.0.2 - safe-regex: 1.1.0 - regexp.prototype.flags@1.5.2: dependencies: call-bind: 1.0.7 @@ -18520,8 +17443,6 @@ snapshots: lodash: 4.17.21 strip-ansi: 6.0.1 - repeat-element@1.1.4: {} - repeat-string@1.6.1: {} require-directory@2.1.1: {} @@ -18544,8 +17465,6 @@ snapshots: resolve-pkg-maps@1.0.0: {} - resolve-url@0.2.1: {} - resolve@1.1.7: {} resolve@1.22.8: @@ -18565,8 +17484,6 @@ snapshots: onetime: 5.1.2 signal-exit: 3.0.7 - ret@0.1.15: {} - retry@0.12.0: {} retry@0.13.1: {} @@ -18591,7 +17508,7 @@ snapshots: dependencies: glob: 9.3.5 - rimraf@5.0.7: + rimraf@5.0.8: dependencies: glob: 10.3.10 @@ -18601,11 +17518,6 @@ snapshots: rrweb-cssom@0.7.0: {} - rst-selector-parser@2.2.3: - dependencies: - lodash.flattendeep: 4.4.0 - nearley: 2.20.1 - rtl-css-js@1.16.1: dependencies: '@babel/runtime': 7.24.7 @@ -18637,10 +17549,6 @@ snapshots: es-errors: 1.3.0 is-regex: 1.1.4 - safe-regex@1.1.0: - dependencies: - ret: 0.1.15 - safer-buffer@2.1.2: {} saxes@5.0.1: @@ -18651,7 +17559,7 @@ snapshots: dependencies: xmlchars: 2.2.0 - scheduler@0.23.0: + scheduler@0.23.2: dependencies: loose-envify: 1.4.0 @@ -18700,10 +17608,6 @@ snapshots: transitivePeerDependencies: - supports-color - serialize-javascript@6.0.0: - dependencies: - randombytes: 2.1.0 - serialize-javascript@6.0.2: dependencies: randombytes: 2.1.0 @@ -18762,13 +17666,6 @@ snapshots: functions-have-names: 1.2.3 has-property-descriptors: 1.0.2 - set-value@2.0.1: - dependencies: - extend-shallow: 2.0.1 - is-extendable: 0.1.1 - is-plain-object: 2.0.4 - split-string: 3.1.0 - setimmediate@1.0.5: {} setprototypeof@1.2.0: {} @@ -18824,16 +17721,6 @@ snapshots: signal-exit@4.1.0: {} - sigstore@1.9.0: - dependencies: - '@sigstore/bundle': 1.1.0 - '@sigstore/protobuf-specs': 0.2.1 - '@sigstore/sign': 1.0.0 - '@sigstore/tuf': 1.0.3 - make-fetch-happen: 11.1.1 - transitivePeerDependencies: - - supports-color - sigstore@2.2.0: dependencies: '@sigstore/bundle': 2.1.1 @@ -18854,7 +17741,7 @@ snapshots: '@sinonjs/commons': 3.0.1 '@sinonjs/fake-timers': 10.3.0 '@sinonjs/samsam': 8.0.0 - diff: 5.1.0 + diff: 5.2.0 nise: 5.1.7 supports-color: 7.2.0 @@ -18872,30 +17759,9 @@ snapshots: slash@5.1.0: {} - smart-buffer@4.2.0: {} - - snapdragon-node@2.1.1: - dependencies: - define-property: 1.0.0 - isobject: 3.0.1 - snapdragon-util: 3.0.1 - - snapdragon-util@3.0.1: - dependencies: - kind-of: 3.2.2 + slashes@3.0.12: {} - snapdragon@0.8.2: - dependencies: - base: 0.11.2 - debug: 2.6.9 - define-property: 0.2.5 - extend-shallow: 2.0.1 - map-cache: 0.2.2 - source-map: 0.5.7 - source-map-resolve: 0.5.3 - use: 3.1.1 - transitivePeerDependencies: - - supports-color + smart-buffer@4.2.0: {} socket.io-adapter@2.5.2: dependencies: @@ -18907,7 +17773,7 @@ snapshots: socket.io-parser@4.2.4: dependencies: '@socket.io/component-emitter': 3.1.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -18916,7 +17782,7 @@ snapshots: accepts: 1.3.8 base64id: 2.0.0 cors: 2.8.5 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) engine.io: 6.5.4 socket.io-adapter: 2.5.2 socket.io-parser: 4.2.4 @@ -18925,18 +17791,10 @@ snapshots: - supports-color - utf-8-validate - socks-proxy-agent@7.0.0: - dependencies: - agent-base: 6.0.2 - debug: 4.3.4(supports-color@8.1.1) - socks: 2.7.1 - transitivePeerDependencies: - - supports-color - socks-proxy-agent@8.0.2: dependencies: agent-base: 7.1.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) socks: 2.7.1 transitivePeerDependencies: - supports-color @@ -18952,21 +17810,11 @@ snapshots: source-map-js@1.2.0: {} - source-map-resolve@0.5.3: - dependencies: - atob: 2.1.2 - decode-uri-component: 0.2.2 - resolve-url: 0.2.1 - source-map-url: 0.4.1 - urix: 0.1.0 - source-map-support@0.5.21: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 - source-map-url@0.4.1: {} - source-map@0.2.0: dependencies: amdefine: 1.0.1 @@ -19006,10 +17854,6 @@ snapshots: spdx-license-ids@3.0.16: {} - split-string@3.1.0: - dependencies: - extend-shallow: 3.0.2 - split2@3.2.2: dependencies: readable-stream: 3.6.2 @@ -19020,19 +17864,10 @@ snapshots: sprintf-js@1.0.3: {} - ssri@10.0.5: + ssri@10.0.6: dependencies: minipass: 7.0.4 - ssri@9.0.1: - dependencies: - minipass: 3.3.6 - - static-extend@0.1.2: - dependencies: - define-property: 0.2.5 - object-copy: 0.1.0 - statuses@1.5.0: {} statuses@2.0.1: {} @@ -19049,18 +17884,18 @@ snapshots: streamroller@3.1.5: dependencies: date-format: 4.0.14 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) fs-extra: 8.1.0 transitivePeerDependencies: - supports-color streamsearch@1.1.0: {} - string-replace-loader@3.1.0(webpack@5.92.0(webpack-cli@5.1.4)): + string-replace-loader@3.1.0(webpack@5.92.1(webpack-cli@5.1.4)): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.92.0(webpack-cli@5.1.4) + webpack: 5.92.1(webpack-cli@5.1.4) string-width@4.2.3: dependencies: @@ -19074,6 +17909,11 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.0 + string.prototype.includes@2.0.0: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.23.3 + string.prototype.matchall@4.0.11: dependencies: call-bind: 1.0.7 @@ -19148,7 +17988,7 @@ snapshots: minimist: 1.2.8 through: 2.3.8 - styled-components@6.1.11(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + styled-components@6.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@emotion/is-prop-valid': 1.2.2 '@emotion/unitless': 0.8.1 @@ -19156,18 +17996,19 @@ snapshots: css-to-react-native: 3.2.0 csstype: 3.1.3 postcss: 8.4.38 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) shallowequal: 1.1.0 stylis: 4.3.2 tslib: 2.6.2 - styled-jsx@5.1.1(@babel/core@7.24.7)(react@18.2.0): + styled-jsx@5.1.1(@babel/core@7.24.7)(babel-plugin-macros@3.1.0)(react@18.3.1): dependencies: client-only: 0.0.1 - react: 18.2.0 + react: 18.3.1 optionalDependencies: '@babel/core': 7.24.7 + babel-plugin-macros: 3.1.0 stylis-plugin-rtl@2.1.1(stylis@4.3.2): dependencies: @@ -19218,6 +18059,11 @@ snapshots: '@pkgr/core': 0.1.1 tslib: 2.6.2 + synckit@0.9.0: + dependencies: + '@pkgr/core': 0.1.1 + tslib: 2.6.2 + tapable@0.1.10: {} tapable@2.2.1: {} @@ -19241,27 +18087,28 @@ snapshots: temp-dir@1.0.0: {} - temp@0.8.4: + temp@0.9.4: dependencies: + mkdirp: 0.5.6 rimraf: 2.6.3 - terser-webpack-plugin@5.3.10(webpack@5.92.0(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0))): + terser-webpack-plugin@5.3.10(webpack@5.92.1(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1))): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 terser: 5.27.0 - webpack: 5.92.0(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0)) + webpack: 5.92.1(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1)) - terser-webpack-plugin@5.3.10(webpack@5.92.0(webpack-cli@5.1.4)): + terser-webpack-plugin@5.3.10(webpack@5.92.1(webpack-cli@5.1.4)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 terser: 5.27.0 - webpack: 5.92.0(webpack-cli@5.1.4) + webpack: 5.92.1(webpack-cli@5.1.4) terser@5.27.0: dependencies: @@ -19312,26 +18159,10 @@ snapshots: to-fast-properties@2.0.0: {} - to-object-path@0.3.0: - dependencies: - kind-of: 3.2.2 - - to-regex-range@2.1.1: - dependencies: - is-number: 3.0.0 - repeat-string: 1.6.1 - to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - to-regex@3.0.2: - dependencies: - define-property: 2.0.2 - extend-shallow: 3.0.2 - regex-not: 1.0.2 - safe-regex: 1.1.0 - toidentifier@1.0.1: {} totalist@3.0.1: {} @@ -19353,13 +18184,15 @@ snapshots: tree-kill@1.2.2: {} + treeverse@3.0.0: {} + trim-newlines@3.0.1: {} trough@1.0.5: {} - ts-api-utils@1.3.0(typescript@5.4.5): + ts-api-utils@1.3.0(typescript@5.5.3): dependencies: - typescript: 5.4.5 + typescript: 5.5.3 ts-interface-checker@0.1.13: {} @@ -19380,25 +18213,17 @@ snapshots: tsscmp@1.0.6: {} - tsx@4.15.5: + tsx@4.16.2: dependencies: esbuild: 0.21.5 get-tsconfig: 4.7.5 optionalDependencies: fsevents: 2.3.3 - tuf-js@1.1.7: - dependencies: - '@tufjs/models': 1.0.4 - debug: 4.3.4(supports-color@8.1.1) - make-fetch-happen: 11.1.1 - transitivePeerDependencies: - - supports-color - tuf-js@2.2.0: dependencies: '@tufjs/models': 2.0.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) make-fetch-happen: 13.0.0 transitivePeerDependencies: - supports-color @@ -19470,7 +18295,7 @@ snapshots: typedarray@0.0.6: {} - typescript@5.4.5: {} + typescript@5.5.3: {} ua-parser-js@0.7.37: {} @@ -19511,13 +18336,6 @@ snapshots: trough: 1.0.5 vfile: 4.2.1 - union-value@1.0.1: - dependencies: - arr-union: 3.1.0 - get-value: 2.0.6 - is-extendable: 0.1.1 - set-value: 2.0.1 - unique-filename@3.0.0: dependencies: unique-slug: 4.0.0 @@ -19545,6 +18363,8 @@ snapshots: universal-user-agent@6.0.1: {} + universal-user-agent@7.0.2: {} + universalify@0.1.2: {} universalify@0.2.0: {} @@ -19553,11 +18373,6 @@ snapshots: unpipe@1.0.0: {} - unset-value@1.0.0: - dependencies: - has-value: 0.3.1 - isobject: 3.0.1 - unzipper@0.10.14: dependencies: big-integer: 1.6.52 @@ -19577,7 +18392,7 @@ snapshots: dependencies: browserslist: 4.23.0 escalade: 3.1.1 - picocolors: 1.0.0 + picocolors: 1.0.1 update-check@1.5.4: dependencies: @@ -19588,8 +18403,6 @@ snapshots: dependencies: punycode: 2.3.1 - urix@0.1.0: {} - url-parse@1.5.10: dependencies: querystringify: 2.2.0 @@ -19599,8 +18412,6 @@ snapshots: urlpattern-polyfill@8.0.2: {} - use@3.1.1: {} - util-deprecate@1.0.2: {} util.inherits@1.0.3: {} @@ -19617,6 +18428,8 @@ snapshots: utils-merge@1.0.1: {} + uuid@10.0.0: {} + uuid@8.3.2: {} uuid@9.0.1: {} @@ -19636,13 +18449,7 @@ snapshots: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - validate-npm-package-name@3.0.0: - dependencies: - builtins: 1.0.3 - - validate-npm-package-name@5.0.0: - dependencies: - builtins: 5.0.1 + validate-npm-package-name@5.0.1: {} vary@1.1.2: {} @@ -19664,6 +18471,8 @@ snapshots: dependencies: xml-name-validator: 5.0.0 + walk-up-path@3.0.1: {} + watchpack@2.4.1: dependencies: glob-to-regexp: 0.4.1 @@ -19688,28 +18497,28 @@ snapshots: gzip-size: 6.0.0 html-escaper: 2.0.2 opener: 1.5.2 - picocolors: 1.0.0 + picocolors: 1.0.1 sirv: 2.0.4 ws: 7.5.9 transitivePeerDependencies: - bufferutil - utf-8-validate - webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0): + webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1): dependencies: '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0))(webpack@5.92.0(webpack-cli@5.1.4)) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0))(webpack@5.92.0(webpack-cli@5.1.4)) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0))(webpack@5.92.0(webpack-cli@5.1.4)) + '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1))(webpack@5.92.1(webpack-cli@5.1.4)) + '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1))(webpack@5.92.1(webpack-cli@5.1.4)) + '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1))(webpack@5.92.1(webpack-cli@5.1.4)) colorette: 2.0.20 commander: 10.0.1 cross-spawn: 7.0.3 - envinfo: 7.11.0 + envinfo: 7.13.0 fastest-levenshtein: 1.0.16 import-local: 3.1.0 interpret: 3.1.1 rechoir: 0.8.0 - webpack: 5.92.0(webpack-cli@5.1.4) + webpack: 5.92.1(webpack-cli@5.1.4) webpack-merge: 5.10.0 optionalDependencies: webpack-bundle-analyzer: 4.10.2 @@ -19726,7 +18535,7 @@ snapshots: webpack-sources@3.2.3: {} - webpack@5.92.0(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0)): + webpack@5.92.1(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1)): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.5 @@ -19738,7 +18547,7 @@ snapshots: browserslist: 4.23.0 chrome-trace-event: 1.0.3 enhanced-resolve: 5.17.0 - es-module-lexer: 1.4.1 + es-module-lexer: 1.5.4 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -19749,17 +18558,17 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(webpack@5.92.0(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0))) + terser-webpack-plugin: 5.3.10(webpack@5.92.1(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1))) watchpack: 2.4.1 webpack-sources: 3.2.3 optionalDependencies: - webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0) + webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1) transitivePeerDependencies: - '@swc/core' - esbuild - uglify-js - webpack@5.92.0(webpack-cli@5.1.4): + webpack@5.92.1(webpack-cli@5.1.4): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.5 @@ -19771,7 +18580,7 @@ snapshots: browserslist: 4.23.0 chrome-trace-event: 1.0.3 enhanced-resolve: 5.17.0 - es-module-lexer: 1.4.1 + es-module-lexer: 1.5.4 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -19782,11 +18591,11 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(webpack@5.92.0(webpack-cli@5.1.4)) + terser-webpack-plugin: 5.3.10(webpack@5.92.1(webpack-cli@5.1.4)) watchpack: 2.4.1 webpack-sources: 3.2.3 optionalDependencies: - webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.0) + webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.2)(webpack@5.92.1) transitivePeerDependencies: - '@swc/core' - esbuild @@ -19874,7 +18683,7 @@ snapshots: wordwrap@1.0.0: {} - workerpool@6.2.1: {} + workerpool@6.5.1: {} wrap-ansi@6.2.0: dependencies: @@ -19964,8 +18773,6 @@ snapshots: camelcase: 5.3.1 decamelize: 1.2.0 - yargs-parser@20.2.4: {} - yargs-parser@20.2.9: {} yargs-parser@21.1.1: {} diff --git a/renovate.json b/renovate.json index 5c6bf29584a6..7b6ef34b9f95 100644 --- a/renovate.json +++ b/renovate.json @@ -6,7 +6,6 @@ "commitMessageTopic": "{{depName}}", "dependencyDashboard": true, "rebaseWhen": "conflicted", - "ignoreDeps": ["@mui/joy"], "labels": ["dependencies"], "stopUpdatingLabel": "on hold", "packageRules": [ diff --git a/scripts/buildApiDocs/tsconfig.json b/scripts/buildApiDocs/tsconfig.json index f8afa28bc48b..97bb1febd6cf 100644 --- a/scripts/buildApiDocs/tsconfig.json +++ b/scripts/buildApiDocs/tsconfig.json @@ -14,9 +14,6 @@ "strict": true, "baseUrl": "./", "paths": { - "@mui/material-nextjs/*": [ - "../../node_modules/@mui/monorepo/packages/mui-material-nextjs/src/*" - ], "docs/config": ["../../node_modules/@mui/monorepo/docs/config.d.ts"], "@mui-internal/api-docs-builder": [ "../../node_modules/@mui/monorepo/packages/api-docs-builder/index.ts" diff --git a/scripts/useReactVersion.mjs b/scripts/useReactVersion.mjs new file mode 100644 index 000000000000..1a36599fce68 --- /dev/null +++ b/scripts/useReactVersion.mjs @@ -0,0 +1,109 @@ +/* eslint-disable no-console */ +/** + * Given the dist tag fetch the corresponding + * version and make sure this version is used throughout the repository. + * + * If you work on this file: + * WARNING: This script can only use built-in modules since it has to run before + * `pnpm install` + */ +import childProcess from 'child_process'; +import fs from 'fs'; +import os from 'os'; +import path from 'path'; +import { promisify } from 'util'; +import { getWorkspaceRoot } from './utils.mjs'; + +// TODO: reuse the `useReactVersion.mjs` from the monorepo + +const exec = promisify(childProcess.exec); + +// packages published from the react monorepo using the same version +const reactPackageNames = ['react', 'react-dom', 'react-is', 'react-test-renderer', 'scheduler']; +const devDependenciesPackageNames = ['@testing-library/react']; + +// if we need to support more versions we will need to add new mapping here +const additionalVersionsMappings = { + 17: { + '@testing-library/react': '^12.1.0', + }, + 19: {}, +}; + +async function main(version) { + if (typeof version !== 'string') { + throw new TypeError(`expected version: string but got '${version}'`); + } + + if (version === 'stable') { + console.log('Nothing to do with stable'); + return; + } + + const packageJsonPath = path.resolve(getWorkspaceRoot(), 'package.json'); + const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, { encoding: 'utf8' })); + + // the version is something in format: "17.0.0" + let majorVersion = null; + + if (version.startsWith('^') || version.startsWith('~') || !Number.isNaN(version.charAt(0))) { + majorVersion = version.replace('^', '').replace('~', '').split('.')[0]; + } + + await Promise.all( + reactPackageNames.map(async (reactPackageName) => { + const { stdout: versions } = await exec(`npm dist-tag ls ${reactPackageName} ${version}`); + const tagMapping = versions.split('\n').find((mapping) => { + return mapping.startsWith(`${version}: `); + }); + + let packageVersion = null; + + if (tagMapping === undefined) { + // Some specific version is being requested + if (majorVersion) { + packageVersion = version; + if (reactPackageName === 'scheduler') { + // get the scheduler version from the react-dom's dependencies entry + const { stdout: reactDOMDependenciesString } = await exec( + `npm view --json react-dom@${version} dependencies`, + ); + packageVersion = JSON.parse(reactDOMDependenciesString).scheduler; + } + } else { + throw new Error(`Could not find '${version}' in "${versions}"`); + } + } else { + packageVersion = tagMapping.replace(`${version}: `, ''); + } + + packageJson.resolutions[reactPackageName] = packageVersion; + }), + ); + + // At this moment all dist tags reference React 18 version, so we don't need + // to update these dependencies unless an older version is used, or when the + // next/experimental dist tag reference to a future version of React + // packageJson.devDependencies['@testing-library/react'] = 'alpha'; + + if (majorVersion && additionalVersionsMappings[majorVersion]) { + devDependenciesPackageNames.forEach((packageName) => { + if (!additionalVersionsMappings[majorVersion][packageName]) { + throw new Error( + `Version ${majorVersion} does not have version defined for the ${packageName}`, + ); + } + packageJson.devDependencies[packageName] = + additionalVersionsMappings[majorVersion][packageName]; + }); + } + + // add newline for clean diff + fs.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}${os.EOL}`); +} + +const [version = process.env.REACT_VERSION] = process.argv.slice(2); +main(version).catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/scripts/x-charts.exports.json b/scripts/x-charts.exports.json index a38d3220182e..3dfc2afb4eec 100644 --- a/scripts/x-charts.exports.json +++ b/scripts/x-charts.exports.json @@ -79,8 +79,9 @@ { "name": "ChartsGridClasses", "kind": "Interface" }, { "name": "ChartsGridClassKey", "kind": "TypeAlias" }, { "name": "ChartsGridProps", "kind": "Interface" }, - { "name": "ChartsItemContentProps", "kind": "TypeAlias" }, + { "name": "ChartsItemContentProps", "kind": "Interface" }, { "name": "ChartsItemTooltipContent", "kind": "Function" }, + { "name": "ChartsItemTooltipContentProps", "kind": "Interface" }, { "name": "ChartsLegend", "kind": "Function" }, { "name": "ChartsLegendClasses", "kind": "Interface" }, { "name": "ChartsLegendClassKey", "kind": "TypeAlias" }, @@ -102,12 +103,17 @@ { "name": "ChartsTextProps", "kind": "Interface" }, { "name": "ChartsTextStyle", "kind": "Interface" }, { "name": "ChartsTooltip", "kind": "Function" }, + { "name": "ChartsTooltipCell", "kind": "Variable" }, { "name": "chartsTooltipClasses", "kind": "Variable" }, { "name": "ChartsTooltipClasses", "kind": "Interface" }, { "name": "ChartsTooltipClassKey", "kind": "TypeAlias" }, - { "name": "ChartsTooltipProps", "kind": "TypeAlias" }, + { "name": "ChartsTooltipMark", "kind": "Variable" }, + { "name": "ChartsTooltipPaper", "kind": "Variable" }, + { "name": "ChartsTooltipProps", "kind": "Interface" }, + { "name": "ChartsTooltipRow", "kind": "Variable" }, { "name": "ChartsTooltipSlotProps", "kind": "Interface" }, { "name": "ChartsTooltipSlots", "kind": "Interface" }, + { "name": "ChartsTooltipTable", "kind": "Variable" }, { "name": "ChartsVoronoiHandler", "kind": "Function" }, { "name": "ChartsVoronoiHandlerProps", "kind": "TypeAlias" }, { "name": "ChartsXAxis", "kind": "Function" }, @@ -288,8 +294,10 @@ { "name": "useHighlighted", "kind": "Function" }, { "name": "useItemHighlighted", "kind": "Function" }, { "name": "useSvgRef", "kind": "Function" }, + { "name": "useXAxis", "kind": "Function" }, { "name": "useXColorScale", "kind": "Function" }, { "name": "useXScale", "kind": "Function" }, + { "name": "useYAxis", "kind": "Function" }, { "name": "useYColorScale", "kind": "Function" }, { "name": "useYScale", "kind": "Function" }, { "name": "useZColorScale", "kind": "Function" }, diff --git a/scripts/x-data-grid-generator.exports.json b/scripts/x-data-grid-generator.exports.json index e69f7b247f04..06a34db6fa23 100644 --- a/scripts/x-data-grid-generator.exports.json +++ b/scripts/x-data-grid-generator.exports.json @@ -1,9 +1,12 @@ [ + { "name": "BASE_URL", "kind": "Variable" }, { "name": "ColumnsOptions", "kind": "Interface" }, { "name": "createFakeServer", "kind": "Variable" }, { "name": "currencyPairs", "kind": "Variable" }, + { "name": "deepFreeze", "kind": "Variable" }, { "name": "DemoDataReturnType", "kind": "TypeAlias" }, { "name": "DemoLink", "kind": "Variable" }, + { "name": "extrapolateSeed", "kind": "Function" }, { "name": "generateFilledQuantity", "kind": "Variable" }, { "name": "generateIsFilled", "kind": "Variable" }, { "name": "getBasicGridData", "kind": "Variable" }, @@ -77,5 +80,6 @@ { "name": "useBasicDemoData", "kind": "Variable" }, { "name": "useDemoData", "kind": "Variable" }, { "name": "UseDemoDataOptions", "kind": "Interface" }, + { "name": "useMockServer", "kind": "Variable" }, { "name": "useMovieData", "kind": "Variable" } ] diff --git a/scripts/x-data-grid-premium.exports.json b/scripts/x-data-grid-premium.exports.json index 8958c94d078b..095b9e762608 100644 --- a/scripts/x-data-grid-premium.exports.json +++ b/scripts/x-data-grid-premium.exports.json @@ -16,6 +16,7 @@ { "name": "checkGridRowIdIsValid", "kind": "Function" }, { "name": "ColumnHeaderFilterIconButtonProps", "kind": "Interface" }, { "name": "ColumnHeaderFilterIconButtonPropsOverrides", "kind": "Interface" }, + { "name": "ColumnHeaderSortIconPropsOverrides", "kind": "Interface" }, { "name": "ColumnMenuPropsOverrides", "kind": "Interface" }, { "name": "ColumnsManagementPropsOverrides", "kind": "Interface" }, { "name": "ColumnsPanelPropsOverrides", "kind": "Interface" }, @@ -244,6 +245,14 @@ { "name": "GridDataGroupNode", "kind": "Interface" }, { "name": "GridDataPinnedRowNode", "kind": "Interface" }, { "name": "gridDataRowIdsSelector", "kind": "Variable" }, + { "name": "GridDataSource", "kind": "Interface" }, + { "name": "GridDataSourceApi", "kind": "Interface" }, + { "name": "GridDataSourceApiBase", "kind": "Interface" }, + { "name": "GridDataSourceCache", "kind": "Interface" }, + { "name": "GridDataSourceCacheDefault", "kind": "Class" }, + { "name": "GridDataSourceGroupNode", "kind": "Interface" }, + { "name": "GridDataSourcePrivateApi", "kind": "Interface" }, + { "name": "GridDataSourceState", "kind": "Interface" }, { "name": "gridDateComparator", "kind": "Variable" }, { "name": "gridDateFormatter", "kind": "Variable" }, { "name": "gridDateTimeFormatter", "kind": "Variable" }, @@ -315,6 +324,8 @@ { "name": "GridFilterAltIcon", "kind": "Variable" }, { "name": "GridFilterApi", "kind": "Interface" }, { "name": "gridFilteredDescendantCountLookupSelector", "kind": "Variable" }, + { "name": "gridFilteredDescendantRowCountSelector", "kind": "Variable" }, + { "name": "gridFilteredRowCountSelector", "kind": "Variable" }, { "name": "gridFilteredRowsLookupSelector", "kind": "Variable" }, { "name": "gridFilteredSortedRowEntriesSelector", "kind": "Variable" }, { "name": "gridFilteredSortedRowIdsSelector", "kind": "Variable" }, @@ -357,6 +368,8 @@ { "name": "GridFunctionsIcon", "kind": "Variable" }, { "name": "GridGenericColumnMenu", "kind": "Variable" }, { "name": "GridGenericColumnMenuProps", "kind": "Interface" }, + { "name": "GridGetRowsParams", "kind": "Interface" }, + { "name": "GridGetRowsResponse", "kind": "Interface" }, { "name": "GridGetRowsToExportParams", "kind": "Interface" }, { "name": "GridGroupingColDefOverride", "kind": "Interface" }, { "name": "GridGroupingColDefOverrideParams", "kind": "Interface" }, @@ -388,6 +401,8 @@ { "name": "GridLeafNode", "kind": "Interface" }, { "name": "GridLoadIcon", "kind": "Variable" }, { "name": "GridLoadingOverlay", "kind": "Variable" }, + { "name": "GridLoadingOverlayProps", "kind": "Interface" }, + { "name": "GridLoadingOverlayVariant", "kind": "TypeAlias" }, { "name": "GridLocaleText", "kind": "Interface" }, { "name": "GridLocaleTextApi", "kind": "Interface" }, { "name": "GridLogicOperator", "kind": "Enum" }, @@ -413,7 +428,9 @@ { "name": "GridPaginationMeta", "kind": "Interface" }, { "name": "gridPaginationMetaSelector", "kind": "Variable" }, { "name": "GridPaginationModel", "kind": "Interface" }, + { "name": "GridPaginationModelApi", "kind": "Interface" }, { "name": "gridPaginationModelSelector", "kind": "Variable" }, + { "name": "GridPaginationRowCountApi", "kind": "Interface" }, { "name": "gridPaginationRowCountSelector", "kind": "Variable" }, { "name": "gridPaginationRowRangeSelector", "kind": "Variable" }, { "name": "gridPaginationSelector", "kind": "Variable" }, @@ -508,6 +525,7 @@ { "name": "GridRowPinningApi", "kind": "Interface" }, { "name": "GridRowPinningInternalCache", "kind": "Interface" }, { "name": "GridRowProApi", "kind": "Interface" }, + { "name": "GridRowProPrivateApi", "kind": "Interface" }, { "name": "GridRowProps", "kind": "Interface" }, { "name": "GridRowScrollEndParams", "kind": "Interface" }, { "name": "gridRowsDataRowIdToIdLookupSelector", "kind": "Variable" }, @@ -649,7 +667,6 @@ { "name": "useGridVirtualization", "kind": "Function" }, { "name": "useKeepGroupedColumnsHidden", "kind": "Variable" }, { "name": "useOnMount", "kind": "Function" }, - { "name": "useResizeObserver", "kind": "Function" }, { "name": "useRunOnce", "kind": "Variable" }, { "name": "ValueOptions", "kind": "TypeAlias" }, { "name": "virtualizationStateInitializer", "kind": "Variable" } diff --git a/scripts/x-data-grid-pro.exports.json b/scripts/x-data-grid-pro.exports.json index 6a7d1870c023..1f61374d2036 100644 --- a/scripts/x-data-grid-pro.exports.json +++ b/scripts/x-data-grid-pro.exports.json @@ -16,6 +16,7 @@ { "name": "checkGridRowIdIsValid", "kind": "Function" }, { "name": "ColumnHeaderFilterIconButtonProps", "kind": "Interface" }, { "name": "ColumnHeaderFilterIconButtonPropsOverrides", "kind": "Interface" }, + { "name": "ColumnHeaderSortIconPropsOverrides", "kind": "Interface" }, { "name": "ColumnMenuPropsOverrides", "kind": "Interface" }, { "name": "ColumnsManagementPropsOverrides", "kind": "Interface" }, { "name": "ColumnsPanelPropsOverrides", "kind": "Interface" }, @@ -218,6 +219,14 @@ { "name": "GridDataGroupNode", "kind": "Interface" }, { "name": "GridDataPinnedRowNode", "kind": "Interface" }, { "name": "gridDataRowIdsSelector", "kind": "Variable" }, + { "name": "GridDataSource", "kind": "Interface" }, + { "name": "GridDataSourceApi", "kind": "Interface" }, + { "name": "GridDataSourceApiBase", "kind": "Interface" }, + { "name": "GridDataSourceCache", "kind": "Interface" }, + { "name": "GridDataSourceCacheDefault", "kind": "Class" }, + { "name": "GridDataSourceGroupNode", "kind": "Interface" }, + { "name": "GridDataSourcePrivateApi", "kind": "Interface" }, + { "name": "GridDataSourceState", "kind": "Interface" }, { "name": "gridDateComparator", "kind": "Variable" }, { "name": "gridDateFormatter", "kind": "Variable" }, { "name": "gridDateTimeFormatter", "kind": "Variable" }, @@ -284,6 +293,8 @@ { "name": "GridFilterAltIcon", "kind": "Variable" }, { "name": "GridFilterApi", "kind": "Interface" }, { "name": "gridFilteredDescendantCountLookupSelector", "kind": "Variable" }, + { "name": "gridFilteredDescendantRowCountSelector", "kind": "Variable" }, + { "name": "gridFilteredRowCountSelector", "kind": "Variable" }, { "name": "gridFilteredRowsLookupSelector", "kind": "Variable" }, { "name": "gridFilteredSortedRowEntriesSelector", "kind": "Variable" }, { "name": "gridFilteredSortedRowIdsSelector", "kind": "Variable" }, @@ -325,6 +336,8 @@ { "name": "GridFooterPlaceholder", "kind": "Function" }, { "name": "GridGenericColumnMenu", "kind": "Variable" }, { "name": "GridGenericColumnMenuProps", "kind": "Interface" }, + { "name": "GridGetRowsParams", "kind": "Interface" }, + { "name": "GridGetRowsResponse", "kind": "Interface" }, { "name": "GridGetRowsToExportParams", "kind": "Interface" }, { "name": "GridGroupingColDefOverride", "kind": "Interface" }, { "name": "GridGroupingColDefOverrideParams", "kind": "Interface" }, @@ -352,6 +365,8 @@ { "name": "GridLeafNode", "kind": "Interface" }, { "name": "GridLoadIcon", "kind": "Variable" }, { "name": "GridLoadingOverlay", "kind": "Variable" }, + { "name": "GridLoadingOverlayProps", "kind": "Interface" }, + { "name": "GridLoadingOverlayVariant", "kind": "TypeAlias" }, { "name": "GridLocaleText", "kind": "Interface" }, { "name": "GridLocaleTextApi", "kind": "Interface" }, { "name": "GridLogicOperator", "kind": "Enum" }, @@ -377,7 +392,9 @@ { "name": "GridPaginationMeta", "kind": "Interface" }, { "name": "gridPaginationMetaSelector", "kind": "Variable" }, { "name": "GridPaginationModel", "kind": "Interface" }, + { "name": "GridPaginationModelApi", "kind": "Interface" }, { "name": "gridPaginationModelSelector", "kind": "Variable" }, + { "name": "GridPaginationRowCountApi", "kind": "Interface" }, { "name": "gridPaginationRowCountSelector", "kind": "Variable" }, { "name": "gridPaginationRowRangeSelector", "kind": "Variable" }, { "name": "gridPaginationSelector", "kind": "Variable" }, @@ -462,6 +479,7 @@ { "name": "GridRowPinningApi", "kind": "Interface" }, { "name": "GridRowPinningInternalCache", "kind": "Interface" }, { "name": "GridRowProApi", "kind": "Interface" }, + { "name": "GridRowProPrivateApi", "kind": "Interface" }, { "name": "GridRowProps", "kind": "Interface" }, { "name": "GridRowScrollEndParams", "kind": "Interface" }, { "name": "gridRowsDataRowIdToIdLookupSelector", "kind": "Variable" }, @@ -599,7 +617,6 @@ { "name": "useGridSelector", "kind": "Variable" }, { "name": "useGridVirtualization", "kind": "Function" }, { "name": "useOnMount", "kind": "Function" }, - { "name": "useResizeObserver", "kind": "Function" }, { "name": "useRunOnce", "kind": "Variable" }, { "name": "ValueOptions", "kind": "TypeAlias" }, { "name": "virtualizationStateInitializer", "kind": "Variable" } diff --git a/scripts/x-data-grid.exports.json b/scripts/x-data-grid.exports.json index c23d717cd34b..d6ba9efe3d01 100644 --- a/scripts/x-data-grid.exports.json +++ b/scripts/x-data-grid.exports.json @@ -16,6 +16,7 @@ { "name": "checkGridRowIdIsValid", "kind": "Function" }, { "name": "ColumnHeaderFilterIconButtonProps", "kind": "Interface" }, { "name": "ColumnHeaderFilterIconButtonPropsOverrides", "kind": "Interface" }, + { "name": "ColumnHeaderSortIconPropsOverrides", "kind": "Interface" }, { "name": "ColumnMenuPropsOverrides", "kind": "Interface" }, { "name": "ColumnsManagementPropsOverrides", "kind": "Interface" }, { "name": "ColumnsPanelPropsOverrides", "kind": "Interface" }, @@ -204,6 +205,7 @@ { "name": "GridDataGroupNode", "kind": "Interface" }, { "name": "GridDataPinnedRowNode", "kind": "Interface" }, { "name": "gridDataRowIdsSelector", "kind": "Variable" }, + { "name": "GridDataSourceGroupNode", "kind": "Interface" }, { "name": "gridDateComparator", "kind": "Variable" }, { "name": "gridDateFormatter", "kind": "Variable" }, { "name": "gridDateTimeFormatter", "kind": "Variable" }, @@ -261,6 +263,8 @@ { "name": "GridFilterAltIcon", "kind": "Variable" }, { "name": "GridFilterApi", "kind": "Interface" }, { "name": "gridFilteredDescendantCountLookupSelector", "kind": "Variable" }, + { "name": "gridFilteredDescendantRowCountSelector", "kind": "Variable" }, + { "name": "gridFilteredRowCountSelector", "kind": "Variable" }, { "name": "gridFilteredRowsLookupSelector", "kind": "Variable" }, { "name": "gridFilteredSortedRowEntriesSelector", "kind": "Variable" }, { "name": "gridFilteredSortedRowIdsSelector", "kind": "Variable" }, @@ -323,6 +327,8 @@ { "name": "GridLeafNode", "kind": "Interface" }, { "name": "GridLoadIcon", "kind": "Variable" }, { "name": "GridLoadingOverlay", "kind": "Variable" }, + { "name": "GridLoadingOverlayProps", "kind": "Interface" }, + { "name": "GridLoadingOverlayVariant", "kind": "TypeAlias" }, { "name": "GridLocaleText", "kind": "Interface" }, { "name": "GridLocaleTextApi", "kind": "Interface" }, { "name": "GridLogicOperator", "kind": "Enum" }, @@ -348,7 +354,9 @@ { "name": "GridPaginationMeta", "kind": "Interface" }, { "name": "gridPaginationMetaSelector", "kind": "Variable" }, { "name": "GridPaginationModel", "kind": "Interface" }, + { "name": "GridPaginationModelApi", "kind": "Interface" }, { "name": "gridPaginationModelSelector", "kind": "Variable" }, + { "name": "GridPaginationRowCountApi", "kind": "Interface" }, { "name": "gridPaginationRowCountSelector", "kind": "Variable" }, { "name": "gridPaginationRowRangeSelector", "kind": "Variable" }, { "name": "gridPaginationSelector", "kind": "Variable" }, @@ -423,6 +431,7 @@ { "name": "GridRowMultiSelectionApi", "kind": "Interface" }, { "name": "GridRowParams", "kind": "Interface" }, { "name": "GridRowProApi", "kind": "Interface" }, + { "name": "GridRowProPrivateApi", "kind": "Interface" }, { "name": "GridRowProps", "kind": "Interface" }, { "name": "gridRowsDataRowIdToIdLookupSelector", "kind": "Variable" }, { "name": "GridRowSelectionApi", "kind": "Interface" }, @@ -557,7 +566,6 @@ { "name": "useGridSelector", "kind": "Variable" }, { "name": "useGridVirtualization", "kind": "Function" }, { "name": "useOnMount", "kind": "Function" }, - { "name": "useResizeObserver", "kind": "Function" }, { "name": "useRunOnce", "kind": "Variable" }, { "name": "ValueOptions", "kind": "TypeAlias" }, { "name": "virtualizationStateInitializer", "kind": "Variable" } diff --git a/scripts/x-date-pickers-pro.exports.json b/scripts/x-date-pickers-pro.exports.json index f6927f93c456..5891788d2c99 100644 --- a/scripts/x-date-pickers-pro.exports.json +++ b/scripts/x-date-pickers-pro.exports.json @@ -413,6 +413,7 @@ { "name": "UseMultiInputTimeRangeFieldComponentProps", "kind": "TypeAlias" }, { "name": "UseMultiInputTimeRangeFieldProps", "kind": "Interface" }, { "name": "usePickerLayout", "kind": "ExportAssignment" }, + { "name": "usePickersTranslations", "kind": "Variable" }, { "name": "UseSingleInputDateRangeFieldProps", "kind": "Interface" }, { "name": "UseSingleInputDateTimeRangeFieldProps", "kind": "Interface" }, { "name": "UseSingleInputTimeRangeFieldProps", "kind": "Interface" }, diff --git a/scripts/x-date-pickers.exports.json b/scripts/x-date-pickers.exports.json index 9c5800f297e9..7ee79ca3a9e1 100644 --- a/scripts/x-date-pickers.exports.json +++ b/scripts/x-date-pickers.exports.json @@ -298,6 +298,7 @@ { "name": "UseDateTimeFieldComponentProps", "kind": "TypeAlias" }, { "name": "UseDateTimeFieldProps", "kind": "Interface" }, { "name": "usePickerLayout", "kind": "ExportAssignment" }, + { "name": "usePickersTranslations", "kind": "Variable" }, { "name": "UseTimeFieldComponentProps", "kind": "TypeAlias" }, { "name": "UseTimeFieldProps", "kind": "Interface" }, { "name": "YearCalendar", "kind": "Variable" }, diff --git a/test/README.md b/test/README.md new file mode 100644 index 000000000000..e2bb080720fb --- /dev/null +++ b/test/README.md @@ -0,0 +1,46 @@ +# Testing + +## Testing multiple versions of React + +You can check integration of different versions of React (for example different [release channels](https://react.dev/community/versioning-policy) or PRs to React) by running the following commands: + +1. `node scripts/useReactVersion.mjs `. + + Possible values for `version`: + + - default: `stable` (minimum supported React version) + - a tag on npm, for example `next`, `experimental` or `latest` + - an older version, for example `^17.0.0` + +2. `pnpm install` + +### CI + +#### `next` version + +For `react@next` specifically, there's a `react-next` workflow in our CircleCI pipeline that you can trigger in CircleCI on the PR you want to test: + +1. Go to https://app.circleci.com/pipelines/github/mui/mui-x?branch=pull/PR_NUMBER and replace `PR_NUMBER` with the PR number you want to test. +2. Click `Trigger Pipeline` button. +3. Expand `Add parameters (optional)` and add the following parameter: + + | Parameter type | Name | Value | + | :------------- | :--------- | :----------- | + | `string` | `workflow` | `react-next` | + +4. Click `Trigger Pipeline` button. + +#### Other versions + +You can pass the same `version` to our CircleCI pipeline as well: + +With the following API request we're triggering a run of the default workflow in +PR #24289 for `react@next` + +```bash +curl --request POST \ + --url https://circleci.com/api/v2/project/gh/mui/mui-x/pipeline \ + --header 'content-type: application/json' \ + --header 'Circle-Token: $CIRCLE_TOKEN' \ + --data-raw '{"branch":"pull/24289/head","parameters":{"react-version":"next"}}' +``` diff --git a/test/karma.conf.js b/test/karma.conf.js index 483d8e8ca368..3da8db12d540 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -3,7 +3,7 @@ const webpack = require('webpack'); const CI = Boolean(process.env.CI); -process.env.CHROME_BIN = chromium.executablePath(); +process.env.CHROME_BIN ||= chromium.executablePath(); // Karma configuration module.exports = function setKarmaConfig(config) { diff --git a/test/package.json b/test/package.json index b0d4d1ae3124..177777629ea6 100644 --- a/test/package.json +++ b/test/package.json @@ -1,6 +1,6 @@ { "name": "@mui-x-internal/test", - "version": "7.2.0", + "version": "7.8.0", "private": true, "scripts": { "typescript": "tsc -p tsconfig.json" @@ -9,27 +9,27 @@ "@babel/runtime": "^7.24.7", "@emotion/cache": "^11.11.0", "@emotion/react": "^11.11.4", - "@mui/material": "^5.15.20", + "@mui/material": "^5.16.0", "@mui/x-data-grid": "workspace:*", "@mui/x-data-grid-pro": "workspace:*", "@mui/x-date-pickers": "workspace:*", "@mui/x-date-pickers-pro": "workspace:*", "@mui/x-license": "workspace:*", - "@react-spring/web": "^9.7.3", "@playwright/test": "^1.44.1", + "@react-spring/web": "^9.7.3", "@types/chai": "^4.3.16", "@types/karma": "^6.3.8", "@types/moment-jalaali": "^0.7.9", "@types/prop-types": "^15.7.12", - "@types/react": "^18.2.60", + "@types/react": "^18.3.3", "chai": "^4.4.1", "dayjs": "^1.11.11", "moment": "^2.30.1", - "moment-jalaali": "^0.10.0", + "moment-jalaali": "^0.10.1", "prop-types": "^15.8.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router-dom": "^6.23.1", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.24.1", "stylis": "^4.3.2", "stylis-plugin-rtl": "^2.1.1" } diff --git a/test/regressions/data-grid/DataGridPinnedBottomRow.js b/test/regressions/data-grid/DataGridPinnedBottomRow.js new file mode 100644 index 000000000000..1b3d5c71c9f5 --- /dev/null +++ b/test/regressions/data-grid/DataGridPinnedBottomRow.js @@ -0,0 +1,44 @@ +import * as React from 'react'; +import { DataGridPro } from '@mui/x-data-grid-pro'; +import { + randomCity, + randomEmail, + randomId, + randomInt, + randomTraderName, + randomUserName, +} from '@mui/x-data-grid-generator'; + +const columns = [ + { field: 'name', headerName: 'Name', width: 150 }, + { field: 'city', headerName: 'City', width: 150 }, + { field: 'username', headerName: 'Username' }, + { field: 'email', headerName: 'Email', width: 200 }, + { field: 'age', type: 'number', headerName: 'Age' }, +]; + +const rows = []; + +function getRow() { + return { + id: randomId(), + name: randomTraderName(), + city: randomCity(), + username: randomUserName(), + email: randomEmail(), + age: randomInt(10, 80), + }; +} + +const pinnedRows = { + top: [getRow()], + bottom: [getRow()], +}; + +export default function RowPinning() { + return ( +
+ +
+ ); +} diff --git a/test/regressions/webpack.config.js b/test/regressions/webpack.config.js index 5ed03d88068e..816e18309df5 100644 --- a/test/regressions/webpack.config.js +++ b/test/regressions/webpack.config.js @@ -25,7 +25,7 @@ module.exports = { DISABLE_CHANCE_RANDOM: JSON.stringify(true), }), new webpack.ProvidePlugin({ - // required by enzyme > cheerio > parse5 > util + // required by code accessing `process.env` in the browser process: 'process/browser.js', }), ], @@ -47,7 +47,7 @@ module.exports = { fallback: { // Exclude polyfill and treat 'fs' as an empty module since it is not required. next -> gzip-size relies on it. fs: false, - // needed by enzyme > cheerio + // Exclude polyfill and treat 'stream' as an empty module since it is not required. next -> gzip-size relies on it. stream: false, // Exclude polyfill and treat 'zlib' as an empty module since it is not required. next -> gzip-size relies on it. zlib: false, diff --git a/test/utils/describeSlotsConformance.tsx b/test/utils/describeSlotsConformance.tsx index ffb2e2da4eea..0d638bfa8fb0 100644 --- a/test/utils/describeSlotsConformance.tsx +++ b/test/utils/describeSlotsConformance.tsx @@ -33,7 +33,7 @@ export function innerDescribeSlotsConformance(params: DescribeSlotsConformancePa expect(response.container.querySelector(`.${slotConfig.className}`)).to.equal(null); // Check if the custom slot is being rendered - expect(response.getByTestId('custom-slot')).to.not.equal(null); + expect(response.getByTestId('custom-slot')).not.to.equal(null); }); it('should pass props to the default slot', () => { diff --git a/test/utils/pickers/createPickerRenderer.tsx b/test/utils/pickers/createPickerRenderer.tsx index 6013582361c5..25da543cf517 100644 --- a/test/utils/pickers/createPickerRenderer.tsx +++ b/test/utils/pickers/createPickerRenderer.tsx @@ -10,13 +10,6 @@ interface CreatePickerRendererOptions extends CreateRendererOptions { instance?: any; } -export function wrapPickerMount( - mount: (node: React.ReactElement) => import('enzyme').ReactWrapper, -) { - return (node: React.ReactElement) => - mount({node}); -} - export function createPickerRenderer({ locale, adapterName, diff --git a/test/utils/tree-view/fakeContextValue.ts b/test/utils/tree-view/fakeContextValue.ts index 5f4e44545102..0ea85c4881dc 100644 --- a/test/utils/tree-view/fakeContextValue.ts +++ b/test/utils/tree-view/fakeContextValue.ts @@ -18,6 +18,8 @@ export const getFakeContextValue = ( focusItem: () => {}, getItem: () => ({}), setItemExpansion: () => {}, + getItemDOMElement: () => null, + selectItem: () => {}, }, runItemPlugins: () => ({ rootRef: null, @@ -39,4 +41,5 @@ export const getFakeContextValue = ( rootRef: { current: null, }, + expansion: { expansionTrigger: 'content' }, }); diff --git a/tsconfig.json b/tsconfig.json index a94255b6f09c..6a9b26ef2fdf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -31,6 +31,8 @@ "@mui/x-tree-view-pro/*": ["./packages/x-tree-view-pro/src/*"], "@mui/x-license": ["./packages/x-license/src"], "@mui/x-license/*": ["./packages/x-license/src/*"], + "@mui/x-internals": ["./packages/x-internals/src"], + "@mui/x-internals/*": ["./packages/x-internals/src/*"], "@mui/docs": ["./node_modules/@mui/monorepo/packages/mui-docs/src"], "@mui/docs/*": ["./node_modules/@mui/monorepo/packages/mui-docs/src/*"], "@mui-internal/api-docs-builder": ["./node_modules/@mui/monorepo/packages/api-docs-builder"], diff --git a/webpackBaseConfig.js b/webpackBaseConfig.js index ab1b0fe068fd..22dddfcfed4f 100644 --- a/webpackBaseConfig.js +++ b/webpackBaseConfig.js @@ -19,6 +19,7 @@ module.exports = { '@mui/x-tree-view': path.resolve(__dirname, './packages/x-tree-view/src'), '@mui/x-tree-view-pro': path.resolve(__dirname, './packages/x-tree-view-pro/src'), '@mui/x-license': path.resolve(__dirname, './packages/x-license/src'), + '@mui/x-internals': path.resolve(__dirname, './packages/x-internals/src'), '@mui/material-nextjs': path.resolve( __dirname, './node_modules/@mui/monorepo/packages/mui-material-nextjs/src',