diff --git a/CHANGELOG.md b/CHANGELOG.md index 763047bb2b8c46..df6173b8dc7add 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,70 @@ # [Versions](https://mui.com/versions/) +## 5.8.5 + + + +_Jun 20, 2022_ + +A big thanks to the 14 contributors who made this release possible. Here are some highlights ✨: + +- 🚀 Added support for CSS variables in the `Avatar` component and the `SpeedDialAction` component respectively by @vicasas and @gin1314 +- many other 🐛 bug fixes and 📚 documentation improvements + +### `@mui/material@5.8.5` + +- ​[Avatar] Add support for CSS variables (#32499) @vicasas +- ​[Dialog] Fix broken styles if `maxWidth` is set to `false` (#32987) @kmurgic +- ​[SpeedDialAction] Add support for CSS variables (#32608) @gin1314 +- ​[Tabs] Increment scroll of the minimum amount possible (#33103) @oliviertassinari + +### `@mui/codemod@5.8.5` + +- ​[codemod] Preserve comments within jss-to-tss-react (#33170) @ryancogswell + +### `@mui/lab@5.0.0-alpha.87` + +- ​[Masonry] Fix flickering when used with React 18 (#33163) @mnajdova + +### `@mui/base@5.0.0-alpha.86` + +- ​[BadgeUnstyled] Accept callbacks in componentsProps (#33176) @michaldudak +- ​[ButtonUnstyled] Use useSlotProps (#33096) @michaldudak +- ​[FormControlUnstyled] Accept callbacks in componentsProps (#33180) @michaldudak +- ​[InputUnstyled] Use useSlotProps (#33094) @michaldudak +- ​[ModalUnstyled] Define ownerState and slot props' types (#32901) @michaldudak +- ​[SwitchUnstyled] Use useSlotProps (#33174) @michaldudak + +### `@mui/joy@5.0.0-alpha.33` + +- ​[Joy] Add Checkbox documentation (#33171) @siriwatknp +- ​[Joy] Add List documentation (#33120) @siriwatknp +- ​[Joy] Make slider displays Joy classname (#33051) @siriwatknp + +### Docs + +- ​[blog] Update Blogpost to clear confusion on "no impact" disclaimer. (#33131) @joserodolfofreitas +- ​[blog] Add post about v5 Migration guide update (#33063) @samuelsycamore +- ​[blog] Fix display on Safari (#33102) @oliviertassinari +- ​[docs] Add guide on how to use MUI Base with Tailwind CSS (#33100) @mnajdova +- ​[docs] Improve Joy template UX (#33159) @siriwatknp +- ​[docs] Update Shadow DOM guide (#33160) @cherniavskii +- ​[docs] Fix SEO regressions (#33106) @oliviertassinari +- ​[docs] Add job ad in table of content (#33143) @mnajdova +- ​[docs] Add customization as a value proposition (#33014) @oliviertassinari +- ​[examples] Add example using nextjs & @mui/styles as a starter for the migration to v5 (#33005) @mnajdova +- ​[website] Replace Airtable with Ashby links for applying to a opened position (#33193) @DanailH + +### Core + +- ​[core] Add CSS variables support for Material UI components (#32835) @siriwatknp +- ​[core] Add name to workspace root package.json (#33226) @Janpot +- ​[core] Update bug template with generic instruction (#33153) @joserodolfofreitas +- ​[core] Remove dead and redundant code (#33125) @oliviertassinari +- ​[core] Improve inline code rendering within the details tag (#33086) @Harmouch101 + +All contributors of this release in alphabetical order: @cherniavskii, @DanailH, @gin1314, @Harmouch101, @Janpot, @joserodolfofreitas, @kmurgic, @michaldudak, @mnajdova, @oliviertassinari, @ryancogswell, @samuelsycamore, @siriwatknp, @vicasas + ## 5.8.4 diff --git a/benchmark/package.json b/benchmark/package.json index 5d4ba2f42e1a37..e0510917f6e0ab 100644 --- a/benchmark/package.json +++ b/benchmark/package.json @@ -11,13 +11,13 @@ "server:system": "cd ../ && cross-env NODE_ENV=production BABEL_ENV=benchmark babel-node benchmark/server/scenarios/system.js --inspect=0.0.0.0:9229 --extensions \".tsx,.ts,.js\"" }, "dependencies": { - "@chakra-ui/system": "^1.12.1", + "@chakra-ui/system": "^2.1.3", "@emotion/react": "^11.9.0", "@emotion/styled": "^11.8.1", - "@mdx-js/react": "^2.1.1", - "@mui/material": "^5.8.4", + "@mdx-js/react": "^2.1.2", + "@mui/material": "^5.8.5", "@mui/styles": "^5.8.4", - "@mui/system": "^5.8.4", + "@mui/system": "^5.8.5", "@styled-system/css": "^5.1.5", "benchmark": "^2.1.4", "playwright": "^1.17.1", diff --git a/docs/data/base/guides/working-with-tailwind-css/working-with-tailwind-css.md b/docs/data/base/guides/working-with-tailwind-css/working-with-tailwind-css.md new file mode 100644 index 00000000000000..ec326bcb65ff33 --- /dev/null +++ b/docs/data/base/guides/working-with-tailwind-css/working-with-tailwind-css.md @@ -0,0 +1,503 @@ +# Working with Tailwind CSS + +

Learn how to style MUI Base components with Tailwind CSS.

+ +## Getting started + +The goal of this guide is to teach you how to style MUI Base components using Tailwind CSS while building an interactive and accessible app. + +### Prerequisites + +This guide assumes that you have a basic working knowledge of the following: + +- Tailwind CSS +- TypeScript in React +- building React UI components + +We will not be covering these topics in detail here. + +The end result of this guide is an interactive media player interface. +Here's what it will look like in the end: + +Screenshot of the media player used as example in the guide, designed by the Tailwind Labs team + +:::info +💡 All credits go to the Tailwind Labs team for designing this component, found on the [Tailwind CSS website](https://tailwindcss.com/). +::: + +## Setting up the project + +We'll use [`create-react-app` with typescript](https://create-react-app.dev/docs/adding-typescript/#installation) for this guide. +After you have created the project, follow the instructions given on the [Tailwind CSS installation page](https://tailwindcss.com/docs/guides/create-react-app) in order to configure `tailwind`. +Next, install `@mui/base` in the project: + +```sh +npm install @mui/base +``` + +## Adding the player markup + +Now, create a file called `Player.tsx` and add the markup below, which includes Tailwind CSS classes: + +**Player.tsx** + +```tsx +import * as React from 'react'; + +const Player = React.forwardRef(function Player( + props: { className?: string }, + ref: React.ForwardedRef, +) { + const { className, ...other } = props; + return ( +
+
+
+ +
+

+ Ep. 128 +

+

+ Scaling CSS at Heroku with Utility Classes +

+

+ Full Stack Radio +

+
+
+
+
+
+
+
+
+
+
+
+
+
24:16
+
75:50
+
+
+
+
+
+ + + +
+ +
+ + + +
+
+
+ ); +}); + +export default Player; +``` + +Next, add the `Player` component to the `App.tsx` file. + +**App.tsx** + +```tsx +import * as React from 'react'; +import Player from './Player'; + +function App() { + return ; +} + +export default App; +``` + +You should now see the player render as shown on the screenshot above. +But the component is not yet interactive—that's what we'll cover in the next step. + +## Adding an interactive slider component + +### Create the Slider component + +Let's start by giving life to the slider with the `SliderUnstyled` component from MUI Base. +First, create a new file called `Slider.tsx`. +Copy and paste the code below into the file: + +**Slider.tsx** + +```tsx +import * as React from 'react'; +import SliderUnstyled, { SliderUnstyledThumbSlotProps, SliderUnstyledProps } from '@mui/base/SliderUnstyled'; + +const Slider = React.forwardRef(function Slider( + props: SliderUnstyledProps, + ref: React.ForwardedRef, +){ + return (); +}); + +export default Slider; +``` + +To assign specific Tailwind CSS utility classes for each part of the component, we're using `componentsProps`. +Most of them were copied from the original markup with small adjustments now that it is interactive. + +### Add the slider to the player + +Let's add the `Slider` into the `Player` component now: + +**Player.tsx** + +```diff +--- a/src/Player.tsx ++++ b/src/Player.tsx +@@ -1,4 +1,5 @@ + import * as React from 'react'; ++import Slider from './Slider'; + + const Player = React.forwardRef(function Player(props: { className?: string }, ref: React.ForwardedRef) { + const { className, ...other } = props; +@@ -21,12 +22,7 @@ const Player = React.forwardRef(function Player(props: { className?: string }, r + +
+
+-
+-
+-
+-
+-
+-
++ +
+
+
24:16
+``` + +You should see this: + +Screenshot of the media player used as example in the guide, designed by the Tailwind Labs team + +### Customize the slider thumb + +Even though the slider is now interactive, it still does not look exactly like the original design. +This is because we haven't defined the element that represents the dot inside the thumb. + +To do this, it's not enough to just use classes for the thumb—we need also to render a custom component that gets passed in the `components` prop of the `Slider`: + +**Slider.tsx** + +```diff +--- a/src/Slider.tsx ++++ b/src/Slider.tsx +@@ -1,6 +1,17 @@ + import * as React from 'react'; + import SliderUnstyled, { SliderUnstyledThumbSlotProps, SliderUnstyledProps } from '@mui/base/SliderUnstyled'; + ++const Thumb = React.forwardRef(function Thumb( ++ props: SliderUnstyledThumbSlotProps, ++ ref: React.ForwardedRef, ++) { ++ const { ownerState, className, children, ...other } = props; ++ return ( ++ ++ {children} ++ ); ++}); ++ + const Slider = React.forwardRef(function Slider( + props: SliderUnstyledProps, + ref: React.ForwardedRef, +@@ -8,9 +19,11 @@ const Slider = React.forwardRef(function Slider( + return (`. +Note that after the thumb, we are still rendering the `children` passed via props. +This is important because the `children` in this case contain a hidden `` element which makes the thumb accessible. + +This is just one example, but this pattern of building custom components for each slot is possible with all MUI Base components. + +:::warning +When building custom components for the slots, always propagate the props sent from the owner component on the root element. +This is necessary because the props contain event handlers and aria properties required to make the component accessible. +::: + +Additionally, each of the slots receives an `ownerState` object, which contains the props and state of the owner component. +This is useful if you want to style the component based on some internal state. + +## Adding a custom focus selector to the buttons + +To finish this guide off, let's see how you can add custom styles based on a component's internal state. +We'll create a custom `Button` component that uses the `focusVisible` state from the MUI Base `ButtonUnstyled` to apply a cyan ring around it. + +This is what it'll look like: + +Screenshot of a button used as example in the guide, designed by the Tailwind Labs team + +Create a `Button.tsx` file and copy the following code: + +**Button.tsx** + +```tsx +import * as React from 'react'; +import ButtonUnstyled, { + ButtonUnstyledOwnerState, + ButtonUnstyledProps, +} from '@mui/base/ButtonUnstyled'; + +const Button = React.forwardRef(function Button( + props: ButtonUnstyledProps, + ref: React.ForwardedRef, +) { + return ( + ({ + className: `hover:text-cyan-500 transition-colors ${ + state.focusVisible ? 'outline-0 ring-2 ring-cyan-500' : '' + }`, + }), + }} + ref={ref} + /> + ); +}); + +export default Button; +``` + +Note that we're using a callback for the `root` element inside `componentsProps`. +This allows us to conditionally apply utility classes if `focusVisible` is true. + +Now, let's replace all buttons in the initial markup with the new custom `Button` component. + +**Player.tsx** + +```diff +--- a/src/Player.tsx ++++ b/src/Player.tsx +@@ -1,4 +1,5 @@ + import * as React from 'react'; ++import Button from './Button'; + import Slider from './Slider'; + + const Player = React.forwardRef(function Player(props: { className?: string }, ref: React.ForwardedRef) { +@@ -32,46 +33,46 @@ const Player = React.forwardRef(function Player(props: { className?: string }, r +
+
+- +- ++ +- ++ ++ +
+- ++ +
+- +- ++ +- ++ ++ +
+
+
+``` + +Some classes were slightly changed on some buttons so we have a consistent focus indicator. + +## What we learned + +These are the things we covered in this guide: + +✅ How to use Tailwind CSS utility classes to style MUI Base components, using the `componentsProps` prop for targeting specific slots within the component.\ +✅ How to create custom components for specific slots in more complex customization scenarios. +We used the `component` prop to pass them into the parent component.\ +✅ How to apply conditional styling based on the owner component's state using a callback as value for the `componentsProps` prop. + +Get all the code used in this guide in the [MUI Base with Tailwind CSS](https://github.com/mui/material-ui/tree/master/examples/mui-base-with-tailwind-css) example project. diff --git a/docs/data/base/pages.ts b/docs/data/base/pages.ts index 47131fd01fed15..ed0ff3b07a8c4f 100644 --- a/docs/data/base/pages.ts +++ b/docs/data/base/pages.ts @@ -20,7 +20,6 @@ const pages = [ pathname: '/base/components/inputs', subheader: 'inputs', children: [ - { pathname: '/base/react-badge', title: 'Badge' }, { pathname: '/base/react-button', title: 'Button' }, { pathname: '/base/react-input', title: 'Input' }, { pathname: '/base/react-select', title: 'Select' }, @@ -28,6 +27,16 @@ const pages = [ { pathname: '/base/react-switch', title: 'Switch' }, ], }, + { + pathname: '/base/components/data-display', + subheader: 'data-display', + children: [ + { + pathname: '/base/react-badge', + title: 'Badge', + }, + ], + }, { pathname: '/base/components/navigation', subheader: 'navigation', @@ -59,6 +68,17 @@ const pages = [ icon: 'CodeIcon', children: pagesApi, }, + { + pathname: '/base/guides', + title: 'How To Guides', + icon: 'VisibilityIcon', + children: [ + { + pathname: '/base/guides/working-with-tailwind-css', + title: 'Working with Tailwind CSS', + }, + ], + }, ]; export default pages; diff --git a/docs/data/joy/components/sheet/SheetUsage.js b/docs/data/joy/components/sheet/SheetUsage.js new file mode 100644 index 00000000000000..70c796699aa0c9 --- /dev/null +++ b/docs/data/joy/components/sheet/SheetUsage.js @@ -0,0 +1,40 @@ +import * as React from 'react'; +import JoyUsageDemo from 'docs/src/modules/components/JoyUsageDemo'; +import Sheet from '@mui/joy/Sheet'; + +export default function SheetUsage() { + return ( + ( + + Sheet + + )} + /> + ); +} diff --git a/docs/data/joy/components/sheet/SimpleSheet.js b/docs/data/joy/components/sheet/SimpleSheet.js new file mode 100644 index 00000000000000..1cd5e7cc7fcf6e --- /dev/null +++ b/docs/data/joy/components/sheet/SimpleSheet.js @@ -0,0 +1,10 @@ +import Sheet from '@mui/joy/Sheet'; +import * as React from 'react'; + +export default function SimpleSheet() { + return ( + + Hello world! + + ); +} diff --git a/docs/data/joy/components/sheet/SimpleSheet.tsx b/docs/data/joy/components/sheet/SimpleSheet.tsx new file mode 100644 index 00000000000000..1cd5e7cc7fcf6e --- /dev/null +++ b/docs/data/joy/components/sheet/SimpleSheet.tsx @@ -0,0 +1,10 @@ +import Sheet from '@mui/joy/Sheet'; +import * as React from 'react'; + +export default function SimpleSheet() { + return ( + + Hello world! + + ); +} diff --git a/docs/data/joy/components/sheet/SimpleSheet.tsx.preview b/docs/data/joy/components/sheet/SimpleSheet.tsx.preview new file mode 100644 index 00000000000000..af5198b0005732 --- /dev/null +++ b/docs/data/joy/components/sheet/SimpleSheet.tsx.preview @@ -0,0 +1,3 @@ + + Hello world! + \ No newline at end of file diff --git a/docs/data/joy/components/sheet/sheet.md b/docs/data/joy/components/sheet/sheet.md new file mode 100644 index 00000000000000..739ff379a29466 --- /dev/null +++ b/docs/data/joy/components/sheet/sheet.md @@ -0,0 +1,35 @@ +--- +product: joy-ui +title: React Sheet component +--- + +# Sheet + +

Sheet is a useful surface component that implements the global variant feature.

+ +## Introduction + +The `Sheet` container is a generic container. +It's a sibling to the `Box` component with the difference being that it supports Joy UI's global variants out of the box. + +{{"demo": "SheetUsage.js", "hideToolbar": true, "bg": true}} + +{{"component": "modules/components/ComponentLinkHeader.js"}} + +## Component + +After [installation](/joy-ui/getting-started/installation/), you can start building with this component using the following basic elements: + +```jsx +import Sheet from '@mui/joy/Sheet'; + +export default function MyApp() { + return Holy sheet!; +} +``` + +### Basic usage + +The `Sheet` component, in addition to the variants, also has access to the `color` prop, allowing you to use every palette of the theme. + +{{"demo": "SimpleSheet.js"}} diff --git a/docs/data/joy/pages.ts b/docs/data/joy/pages.ts index dc228f172e50bb..1875758257a596 100644 --- a/docs/data/joy/pages.ts +++ b/docs/data/joy/pages.ts @@ -48,7 +48,7 @@ const pages = [ { pathname: '/joy-ui/components/surfaces', subheader: 'surfaces', - children: [{ pathname: '/joy-ui/react-card' }], + children: [{ pathname: '/joy-ui/react-card' }, { pathname: '/joy-ui/react-sheet' }], }, { pathname: '/joy-ui/components/navigation', diff --git a/docs/data/material/components/box/box.md b/docs/data/material/components/box/box.md index a694802ef00dfb..48c6abfd5702dc 100644 --- a/docs/data/material/components/box/box.md +++ b/docs/data/material/components/box/box.md @@ -9,7 +9,7 @@ githubLabel: 'component: Box'

The Box component serves as a wrapper component for most of the CSS utility needs.

-The Box component packages [all the style functions](/system/basics/#all-inclusive) that are exposed in `@mui/system`. +The Box component packages [all the style functions](/system/properties/) that are exposed in `@mui/system`. {{"component": "modules/components/ComponentLinkHeader.js", "design": false}} diff --git a/docs/data/material/customization/palette/palette.md b/docs/data/material/customization/palette/palette.md index 2eb22a39bb91aa..9066b1e9865934 100644 --- a/docs/data/material/customization/palette/palette.md +++ b/docs/data/material/customization/palette/palette.md @@ -87,6 +87,16 @@ const theme = createTheme({ // dark: will be calculated from palette.secondary.main, contrastText: '#ffcc00', }, + // Provide every color token (light, main, dark, and contrastText) when using + // custom colors for props in Material UI's components. + // Then you will be able to use it like this: ` + ); +}; + +export default function CssVarsTemplate() { + return ( + + + + + + + div': { + placeSelf: 'center', + }, + }} + > + + This is an error alert — check it out! + + + This is a warning alert — check it out! + + + This is an info alert — check it out! + + + This is a success alert — check it out! + + + This is an error alert — check it out! + + + This is a warning alert — check it out! + + + This is an info alert — check it out! + + + This is a success alert — check it out! + + + This is an error alert — check it out! + + + This is a warning alert — check it out! + + + This is an info alert — check it out! + + + This is a success alert — check it out! + + + + + ); +} diff --git a/docs/pages/joy-ui/react-sheet.js b/docs/pages/joy-ui/react-sheet.js new file mode 100644 index 00000000000000..c93c07e7d6e346 --- /dev/null +++ b/docs/pages/joy-ui/react-sheet.js @@ -0,0 +1,7 @@ +import * as React from 'react'; +import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; +import { demos, docs, demoComponents } from 'docs/data/joy/components/sheet/sheet.md?@mui/markdown'; + +export default function Page() { + return ; +} diff --git a/docs/public/_redirects b/docs/public/_redirects index 624891dca459f1..243dba17e9f419 100644 --- a/docs/public/_redirects +++ b/docs/public/_redirects @@ -52,9 +52,13 @@ /api/mui-theme-provider/ /system/styles/api/ 301 /components/expansion-panels/ /material-ui/react-accordion/ 301 /api/expansion-panel/ /material-ui/api/accordion/ 301 +/:lang/api/expansion-panel/ /:lang/material-ui/api/accordion/ 301 /api/expansion-panel-actions/ /material-ui/api/accordion-actions/ 301 +/:lang/api/expansion-panel-actions/ /:lang/material-ui/api/accordion-actions/ 301 /api/expansion-panel-details/ /material-ui/api/accordion-details/ 301 +/:lang/api/expansion-panel-details/ /:lang/material-ui/api/accordion-details/ 301 /api/expansion-panel-summary/ /material-ui/api/accordion-summary/ 301 +/:lang/api/expansion-panel-summary/ /:lang/material-ui/api/accordion-summary/ 301 # 2020 /premium-themes* https://mui.com/store/ 301 /customization/themes/ /material-ui/customization/theming/ 301 @@ -62,17 +66,22 @@ https://v1-5-0.mui.com/* https://v1.mui.com/:splat 301! https://v3-9-0.mui.com/* https://v3.mui.com/:splat 301! /components/grid-list/ /material-ui/react-image-list/ 301 /api/grid-list/ /material-ui/api/image-list/ 301 +/:lang/api/grid-list/ /:lang/material-ui/api/image-list/ 301 /api/grid-list-tile/ /material-ui/api/image-list-item/ 301 +/:lang/api/grid-list-tile/ /:lang/material-ui/api/image-list-item/ 301 /api/grid-list-tile-bar/ /material-ui/api/image-list-item-bar/ 301 +/:lang/api/grid-list-tile-bar/ /:lang/material-ui/api/image-list-item-bar/ 301 /customization/components/ /material-ui/customization/how-to-customize/ 301 /:lang/customization/components/ /:lang/material-ui/customization/how-to-customize/ 301 /customization/globals/ /material-ui/customization/theme-components/ 301 +/:lang/customization/globals/ /:lang/material-ui/customization/theme-components/ 301 # 2021 /api/root-ref/ https://v4.mui.com/api/root-ref/ 301 /:lang/api/root-ref/ https://v4.mui.com/:lang/api/root-ref/ 301 /components/slider-styled/ /material-ui/react-slider/ 301 /customization/styled/ /system/styled/ 301 /api/data-grid/x-grid/ /x/api/data-grid/data-grid-pro/ 301 +/api/x-grid/ /x/api/data-grid/data-grid-pro/ 301 https://next.material-ui.com/* https://mui.com/:splat 301! https://v0.material-ui.com/* https://v0.mui.com/:splat 301! https://v1.material-ui.com/* https://v1.mui.com/:splat 301! @@ -81,6 +90,7 @@ https://v4.material-ui.com/* https://v4.mui.com/:splat 301! /company/careers/ /careers/ 301 /:lang/company/careers/ /:lang/careers/ 301 /discover-more/team/ /about/ 301 +/:lang/discover-more/team/ /:lang/about/ 301 /api/data-grid/grid-export-csv-options/ /x/api/data-grid/grid-csv-export-options/ 301 /fr/* /:splat 301 /de/* /:splat 301 @@ -318,20 +328,42 @@ https://v4.material-ui.com/* https://v4.mui.com/:splat 301! /api/modal-unstyled/ /base/api/modal-unstyled/ 301 /pt/api/modal-unstyled/ /pt/base/api/modal-unstyled/ 301 /zh/api/modal-unstyled/ /zh/base/api/modal-unstyled/ 301 +/api/option-group-unstyled/ /base/api/option-group-unstyled/ 301 +/:lang/api/option-group-unstyled/ /:lang/base/api/option-group-unstyled/ 301 +/api/portal/ /base/api/portal/ 301 +/:lang/api/portal/ /:lang/base/api/portal/ 301 +/api/menu-item-unstyled/ /base/api/menu-item-unstyled/ 301 +/:lang/api/menu-item-unstyled/ /:lang/base/api/menu-item-unstyled/ 301 +/api/tabs-list-unstyled/ /base/api/tabs-list-unstyled/ 301 +/:lang/api/tabs-list-unstyled/ /:lang/base/api/tabs-list-unstyled/ 301 +/api/api/menu-unstyled/ /base/api/api/menu-unstyled/ 301 +/:lang/api/api/menu-unstyled/ /:lang/base/api/api/menu-unstyled/ 301 /api/* /material-ui/api/:splat 301 /zh/api/* /zh/material-ui/api/:splat 301 /pt/api/* /pt/material-ui/api/:splat 301 /company/about/ /about/ 301 /company/jobs/ /careers/ 301 /material-ui/customization/unstyled-components/ /base/getting-started/overview/ 301 +/:lang/material-ui/customization/unstyled-components/ /:lang/base/getting-started/overview/ 301 /material-ui/guides/migration-v4/ /material-ui/migration/migration-v4/ 301 +/:lang/material-ui/guides/migration-v4/ /:lang/material-ui/migration/migration-v4/ 301 /material-ui/guides/migration-v3/ /material-ui/migration/migration-v3/ 301 +/:lang/material-ui/guides/migration-v3/ /:lang/material-ui/migration/migration-v3/ 301 /material-ui/guides/migration-v0x/ /material-ui/migration/migration-v0x/ 301 +/:lang/material-ui/guides/migration-v0x/ /:lang/material-ui/migration/migration-v0x/ 301 /material/* /material-ui/:splat 301 /zh/material/* /zh/material-ui/:splat 301 /pt/material/* /pt/material-ui/:splat 301 /zh/blog/* /blog/:splat 301 /pt/blog/* /blog/:splat 301 +/legal/mui-x-eula/ /store/legal/mui-x-eula/ 301 +/:lang/size-snapshot/ /size-snapshot/ 301 +/joy-ui/customization/themed-tokens/ /joy-ui/customization/themed-components/ 301 +/joy-ui/customization/one-off-styling/ /joy-ui/customization/approaches/#one-off-customization 301 +/joy-ui/customization/theme-components/ /joy-ui/customization/themed-components/ 301 +/base/react-chip/ /material-ui/react-chip/ 301 +/system/api/ /system/properties/ 301 +/:lang/system/api/ /:lang/system/properties/ 301 # 2023 # Proxies diff --git a/docs/public/static/blog/migration-update/intellisense-tooltip.png b/docs/public/static/blog/migration-update/intellisense-tooltip.png deleted file mode 100644 index fdd0b988974476..00000000000000 Binary files a/docs/public/static/blog/migration-update/intellisense-tooltip.png and /dev/null differ diff --git a/docs/public/static/blog/migration-update/style-engine.png b/docs/public/static/blog/migration-update/style-engine.png deleted file mode 100644 index 7d300de57853d1..00000000000000 Binary files a/docs/public/static/blog/migration-update/style-engine.png and /dev/null differ diff --git a/docs/public/static/blog/migration-update/card.png b/docs/public/static/blog/mui-core-v5-migration-update/card.png similarity index 100% rename from docs/public/static/blog/migration-update/card.png rename to docs/public/static/blog/mui-core-v5-migration-update/card.png diff --git a/docs/public/static/blog/mui-core-v5-migration-update/intellisense-tooltip.png b/docs/public/static/blog/mui-core-v5-migration-update/intellisense-tooltip.png new file mode 100644 index 00000000000000..37728851d53f40 Binary files /dev/null and b/docs/public/static/blog/mui-core-v5-migration-update/intellisense-tooltip.png differ diff --git a/docs/public/static/blog/mui-core-v5-migration-update/style-engine.png b/docs/public/static/blog/mui-core-v5-migration-update/style-engine.png new file mode 100644 index 00000000000000..e736cc87af5177 Binary files /dev/null and b/docs/public/static/blog/mui-core-v5-migration-update/style-engine.png differ diff --git a/docs/public/static/images/base-with-tailwind-css/player-buttons.png b/docs/public/static/images/base-with-tailwind-css/player-buttons.png new file mode 100644 index 00000000000000..531cf4638d4dcd Binary files /dev/null and b/docs/public/static/images/base-with-tailwind-css/player-buttons.png differ diff --git a/docs/public/static/images/base-with-tailwind-css/player-final.png b/docs/public/static/images/base-with-tailwind-css/player-final.png new file mode 100644 index 00000000000000..414acb0482072c Binary files /dev/null and b/docs/public/static/images/base-with-tailwind-css/player-final.png differ diff --git a/docs/public/static/images/base-with-tailwind-css/player-slider.png b/docs/public/static/images/base-with-tailwind-css/player-slider.png new file mode 100644 index 00000000000000..0dd4f29ef36d3f Binary files /dev/null and b/docs/public/static/images/base-with-tailwind-css/player-slider.png differ diff --git a/docs/src/components/header/HeaderNavBar.tsx b/docs/src/components/header/HeaderNavBar.tsx index 8dc1328eee840b..6bee5aa7b764aa 100644 --- a/docs/src/components/header/HeaderNavBar.tsx +++ b/docs/src/components/header/HeaderNavBar.tsx @@ -3,6 +3,7 @@ import { styled, alpha } from '@mui/material/styles'; import Box from '@mui/material/Box'; import Popper from '@mui/material/Popper'; import Paper from '@mui/material/Paper'; +import { unstable_debounce as debounce } from '@mui/utils'; import Fade from '@mui/material/Fade'; import Typography from '@mui/material/Typography'; import IconImage from 'docs/src/components/icon/IconImage'; @@ -116,9 +117,8 @@ function getNextIndex(eventKey: KeyboardEvent['key'], currentIndex: number, leng } export default function HeaderNavBar() { - const [subMenuOpen, setSubMenuOpen] = React.useState(false); + const [subMenuOpen, setSubMenuOpen] = React.useState(null); const [subMenuIndex, setSubMenuIndex] = React.useState(null); - const [docsMenuOpen, setDocsMenuOpen] = React.useState(false); const navRef = React.useRef(null); const productsMenuRef = React.useRef(null); const docsMenuRef = React.useRef(null); @@ -165,7 +165,7 @@ export default function HeaderNavBar() { if (event.key === 'ArrowDown') { event.preventDefault(); if (event.target === productsMenuRef.current) { - setSubMenuOpen(true); + setSubMenuOpen('products'); } setSubMenuIndex((prevValue) => { if (prevValue === null) { @@ -190,20 +190,40 @@ export default function HeaderNavBar() { }); } if (event.key === 'Escape') { - setSubMenuOpen(false); + setSubMenuOpen(null); setSubMenuIndex(null); } } + + const setSubMenuOpenDebounced = React.useMemo( + () => debounce(setSubMenuOpen, 40), + [setSubMenuOpen], + ); + + const setSubMenuOpenUndebounce = React.useMemo( + () => (value: typeof subMenuOpen) => { + setSubMenuOpenDebounced.clear(); + setSubMenuOpen(value); + }, + [setSubMenuOpen, setSubMenuOpenDebounced], + ); + + React.useEffect(() => { + return () => { + setSubMenuOpenDebounced.clear(); + }; + }, [setSubMenuOpenDebounced]); + return (
    {FEATURE_TOGGLE.nav_products && (
  • setSubMenuOpen(true)} - onFocus={() => setSubMenuOpen(true)} - onMouseOut={() => setSubMenuOpen(false)} - onBlur={() => setSubMenuOpen(false)} + onMouseEnter={() => setSubMenuOpenUndebounce('products')} + onFocus={() => setSubMenuOpenUndebounce('products')} + onMouseLeave={() => setSubMenuOpenDebounced(null)} + onBlur={() => setSubMenuOpenUndebounce(null)} > {({ TransitionProps }) => ( @@ -304,10 +327,10 @@ export default function HeaderNavBar() { )}
  • setDocsMenuOpen(true)} - onFocus={() => setDocsMenuOpen(true)} - onMouseOut={() => setDocsMenuOpen(false)} - onBlur={() => setDocsMenuOpen(false)} + onMouseEnter={() => setSubMenuOpenUndebounce('docs')} + onFocus={() => setSubMenuOpenUndebounce('docs')} + onMouseLeave={() => setSubMenuOpenDebounced(null)} + onBlur={() => setSubMenuOpenUndebounce(null)} > {({ TransitionProps }) => ( diff --git a/docs/src/modules/components/AppTableOfContents.js b/docs/src/modules/components/AppTableOfContents.js index b3f455f44587b3..eaa9bf5d3c5708 100644 --- a/docs/src/modules/components/AppTableOfContents.js +++ b/docs/src/modules/components/AppTableOfContents.js @@ -218,7 +218,7 @@ export default function AppTableOfContents(props) { {showAddJob && ( ({ mb: 2, diff --git a/docs/src/modules/components/Link.tsx b/docs/src/modules/components/Link.tsx index 90b15f25201ce8..bb0fafff200d71 100644 --- a/docs/src/modules/components/Link.tsx +++ b/docs/src/modules/components/Link.tsx @@ -5,6 +5,7 @@ import NextLink, { LinkProps as NextLinkProps } from 'next/link'; import MuiLink, { LinkProps as MuiLinkProps } from '@mui/material/Link'; import { styled } from '@mui/material/styles'; import { useUserLanguage } from 'docs/src/modules/utils/i18n'; +import { LANGUAGES_IGNORE_PAGES } from 'docs/src/modules/constants'; /** * File to keep in sync with: @@ -96,7 +97,7 @@ const Link = React.forwardRef(function Link(props, userLanguage !== 'en' && pathname && pathname.indexOf('/') === 0 && - pathname.indexOf('/blog') !== 0 && + !LANGUAGES_IGNORE_PAGES(pathname) && !pathname.startsWith(`/${userLanguage}/`) ) { linkAs = `/${userLanguage}${linkAs}`; diff --git a/docs/src/modules/components/MarkdownElement.js b/docs/src/modules/components/MarkdownElement.js index 7ce30e4a4a5e1c..16c6e19c95845a 100644 --- a/docs/src/modules/components/MarkdownElement.js +++ b/docs/src/modules/components/MarkdownElement.js @@ -23,6 +23,7 @@ const Root = styled('div')(({ theme }) => ({ overflow: 'auto', WebkitOverflowScrolling: 'touch', maxWidth: 'calc(100vw - 32px)', + maxHeight: '350px', [theme.breakpoints.up('md')]: { maxWidth: 'calc(100vw - 32px - 16px)', }, diff --git a/docs/src/modules/components/TopLayoutCompany.js b/docs/src/modules/components/TopLayoutCareers.js similarity index 87% rename from docs/src/modules/components/TopLayoutCompany.js rename to docs/src/modules/components/TopLayoutCareers.js index 0b7c3d1f7a1360..0964163a895dcd 100644 --- a/docs/src/modules/components/TopLayoutCompany.js +++ b/docs/src/modules/components/TopLayoutCareers.js @@ -22,14 +22,16 @@ const StyledAppContainer = styled(AppContainer)(({ theme }) => ({ }, })); -function TopLayoutCompany(props) { +function TopLayoutCareers(props) { const { docs } = props; const { description, rendered, title } = docs.en; return ( - + + + { + // We don't have the bandwidth like Qt to translate our blog posts + // https://www.qt.io/zh-cn/blog + if (pathname === '/blog' || pathname.startsWith('/blog/')) { + return true; + } + + if (pathname === '/size-snapshot/') { + return true; + } + + return false; +}; + module.exports = { CODE_VARIANTS, LANGUAGES, LANGUAGES_SSR, LANGUAGES_LABEL, LANGUAGES_IN_PROGRESS, + LANGUAGES_IGNORE_PAGES, }; diff --git a/docs/src/pages/careers/ROLE_TEMPLATE.md b/docs/src/pages/careers/ROLE_TEMPLATE.md index 8d2db79c5ce70c..68b9ed1b462db1 100644 --- a/docs/src/pages/careers/ROLE_TEMPLATE.md +++ b/docs/src/pages/careers/ROLE_TEMPLATE.md @@ -69,4 +69,4 @@ You can find the other perks & benefits on the [careers](https://mui.com/careers ## How to apply? -[Apply now for this position 📮](https://airtable.com/shrdqo1Z6srZXGcvh?prefill_Applying+for=XXXXXX&prefill_source=mui.com) +[Apply now for this position 📮](https://jobs.ashbyhq.com/MUI/__ID__/application?utm_source=ZNRrPGBkqO) diff --git a/docs/src/pages/careers/designer.md b/docs/src/pages/careers/designer.md index 29aa4857e08d5d..1dac3e1cf37548 100644 --- a/docs/src/pages/careers/designer.md +++ b/docs/src/pages/careers/designer.md @@ -79,7 +79,7 @@ Other perks are described on [the careers page](/careers/#perks-amp-benefits/). ## How to apply? -[Apply now for this position 📮](https://airtable.com/shrdqo1Z6srZXGcvh?prefill_Applying+for=Designer&prefill_source=mui.com). +[Apply now for this position 📮](https://jobs.ashbyhq.com/MUI/__ID__/application?utm_source=ZNRrPGBkqO). ## What happens next? diff --git a/docs/src/pages/careers/developer-advocate.md b/docs/src/pages/careers/developer-advocate.md index 1ee278ebd49e00..d9eed117731500 100644 --- a/docs/src/pages/careers/developer-advocate.md +++ b/docs/src/pages/careers/developer-advocate.md @@ -108,4 +108,4 @@ You can find the other perks & benefits on the [careers](/careers/#perks-amp-ben ## How to apply? -[Apply now for this position 📮](https://airtable.com/shrdqo1Z6srZXGcvh?prefill_Applying+for=Developer%20Advocate&prefill_source=mui.com) +[Apply now for this position 📮](https://jobs.ashbyhq.com/MUI/__ID__/application?utm_source=ZNRrPGBkqO) diff --git a/docs/src/pages/careers/developer-experience-engineer.md b/docs/src/pages/careers/developer-experience-engineer.md index b8dc8e6d27f922..960af6c84d2db5 100644 --- a/docs/src/pages/careers/developer-experience-engineer.md +++ b/docs/src/pages/careers/developer-experience-engineer.md @@ -100,4 +100,4 @@ You can find the other perks & benefits on the [careers](/careers/#perks-amp-ben ## How to apply? -[Apply now for this position 📮](https://airtable.com/shrdqo1Z6srZXGcvh?prefill_Applying+for=Developer%20Experience%20Engineer&prefill_source=mui.com) +[Apply now for this position 📮](https://jobs.ashbyhq.com/MUI/__ID__/application?utm_source=ZNRrPGBkqO) diff --git a/docs/src/pages/careers/engineering-manager.md b/docs/src/pages/careers/engineering-manager.md index a16a3fac787772..200bc224625db2 100644 --- a/docs/src/pages/careers/engineering-manager.md +++ b/docs/src/pages/careers/engineering-manager.md @@ -87,4 +87,4 @@ You can find the other perks & benefits on the [careers](https://mui.com/careers ## How to apply? -[Apply now for this position 📮](https://airtable.com/shrdqo1Z6srZXGcvh?prefill_Applying+for=Engineering%20Manager%20-%20Toolpad&prefill_source=mui.com) +[Apply now for this position 📮](https://jobs.ashbyhq.com/MUI/__ID__/application?utm_source=ZNRrPGBkqO) diff --git a/docs/src/pages/careers/full-stack-engineer.md b/docs/src/pages/careers/full-stack-engineer.md index 98915d5e502381..33fd7a6d8809e6 100644 --- a/docs/src/pages/careers/full-stack-engineer.md +++ b/docs/src/pages/careers/full-stack-engineer.md @@ -54,7 +54,7 @@ The MUI Toolpad application offers a wide variety of engineering challenges. Inc Depending on the day, you'll: - **Help guide architectural decisions**. You'll join us in defining and refining the initial product and also help bring the conversation public as the MVP grows. You'll also interface with other teams at MUI as you'll be building on top of their work. -- **Contribute to implementing new features**. MUI is a complex codebase. It's built on top of cutting edge web technologies to build the low-code tool for the future. +- **Contribute to implementing new features**. MUI is a complex codebase. It's built on top of cutting-edge web technologies to build the low-code tool for the future. - **Reduce friction**. A large amount of the work on MUI Toolpad is reducing friction and making it easier to use. As our MVP grows, our focus will shift from "making it work" towards "making it easy to work with". - **Collaborate with the community**. MUI Toolpad will be open-sourced. As the community grows you'll act as a steward to steer it towards success. This includes reviewing issues, pull requests and questions, and guiding aspiring contributors to make meaningful contributions. - **Experiment and play**. Great, unexpected features and heisenbug fixes have come from a number of sources — relentlessly methodical processes of elimination, free-flowing team collaboration, inspiration by adjacent libraries and projects, and difficult-to-explain individual strokes of brilliance. Whatever your preferred style is for creating new things that others might not have thought of, you'll find a welcome home on the team. @@ -64,7 +64,7 @@ Depending on the day, you'll: ## The best parts of this job -- **You'll be at the cutting edge of application development** — working on one of the fastest-growing UI libraries on the market. +- **You'll be at the cutting-edge of application development** — working on one of the fastest-growing UI libraries on the market. - **You'll be part of an active, open, friendly community** of developers that are excited about building awesome applications. - **Your role will be key to making MUI Toolpad the go-to low code tool** for internal application building. @@ -102,7 +102,7 @@ You can find the other perks & benefits on the [careers](/careers/#perks-amp-ben ## How to apply? -[Apply now for this position 📮](https://airtable.com/shrdqo1Z6srZXGcvh?prefill_Applying+for=Full-stack%20Engineer%20-%20Toolpad&prefill_source=mui.com) +[Apply now for this position 📮](https://jobs.ashbyhq.com/MUI/4f76b45b-a18e-4bdb-8a34-8bb5a3c9c2ef/application?utm_source=ZNRrPGBkqO) ## What happens next? diff --git a/docs/src/pages/careers/people-operation-manager.md b/docs/src/pages/careers/people-operation-manager.md index 392e4e33f003a5..624c0763e66bbf 100644 --- a/docs/src/pages/careers/people-operation-manager.md +++ b/docs/src/pages/careers/people-operation-manager.md @@ -50,7 +50,7 @@ Depending on the day, you'll: - You will help all individuals understand their primary role within the wider organization. - You will partner with Finance for budgeting/compensation purposes. You will manage compensation, benefits, leave, and other people-related matters. - You will shape a strategy that aligns and moves MUI towards continued growth, innovation, and improvement. -- **Improve employees experience**. +- **Improve employees' experience**. - You will work on the employee engagement survey results. - You will reduce the admin burden. - You will own the Retreat. Bring our remote team together. Being a fully distributed remote team has its challenges. You organize team events, make sure everybody has what they need to be productive, and find creative ways to engage as a team. @@ -86,4 +86,4 @@ You can find the other perks & benefits on the [careers](/careers/#perks-amp-ben ## How to apply? -[Apply now for this position 📮](https://airtable.com/shrdqo1Z6srZXGcvh?prefill_Applying+for=People%20Operations%20Manager&prefill_source=mui.com) +[Apply now for this position 📮](https://jobs.ashbyhq.com/MUI/b46968b7-dde3-4b91-9785-a05aa0a816d8/application?utm_source=ZNRrPGBkqO) diff --git a/docs/src/pages/careers/product-engineer.md b/docs/src/pages/careers/product-engineer.md index aa349a87c5c289..57a40b01f903e8 100644 --- a/docs/src/pages/careers/product-engineer.md +++ b/docs/src/pages/careers/product-engineer.md @@ -93,4 +93,4 @@ You can find the other perks & benefits on the [careers](/careers/#perks-amp-ben ## How to apply? -[Apply now for this position 📮](https://airtable.com/shrdqo1Z6srZXGcvh?prefill_Applying+for=Product%20Engineer%20-%20Store&prefill_source=mui.com) +[Apply now for this position 📮](https://jobs.ashbyhq.com/MUI/e641bac3-5538-4ec8-8d73-eaa1a03704d6/application?utm_source=ZNRrPGBkqO) diff --git a/docs/src/pages/careers/product-manager.md b/docs/src/pages/careers/product-manager.md index fe63104454d06e..120fd820f94fc9 100644 --- a/docs/src/pages/careers/product-manager.md +++ b/docs/src/pages/careers/product-manager.md @@ -80,4 +80,4 @@ You can find the other perks & benefits on the [careers](/careers/#perks-amp-ben ## How to apply? -[Apply now for this position 📮](https://airtable.com/shrdqo1Z6srZXGcvh?prefill_Applying+for=Product%20Manager&prefill_source=mui.com) +[Apply now for this position 📮](https://jobs.ashbyhq.com/MUI/__ID__/application?utm_source=ZNRrPGBkqO) diff --git a/docs/src/pages/careers/react-engineer-core.md b/docs/src/pages/careers/react-engineer-core.md index 82b1bb3619ac24..8972e3d3cff58e 100644 --- a/docs/src/pages/careers/react-engineer-core.md +++ b/docs/src/pages/careers/react-engineer-core.md @@ -73,7 +73,7 @@ Depending on the day, you'll: ### The best parts of this job -- **You'll be at the cutting edge of application development** — working on one of the fastest-growing UI libraries on the market. +- **You'll be at the cutting-edge of application development** — working on one of the fastest-growing UI libraries on the market. - **You'll be part of an active, open, friendly community** of developers that are excited about building awesome applications. - **Your role will be key to making MUI the go-to UI framework** for building applications, websites, and design systems with React. @@ -145,4 +145,4 @@ You can find the other perks & benefits on the [careers](/careers/#perks-amp-ben ## How to apply? -[Apply now for this position 📮](https://jobs.ashbyhq.com/mui/e71433e9-2ddf-42bd-9da6-d0a102d1ce3c/application) +[Apply now for this position 📮](https://jobs.ashbyhq.com/MUI/e6d7cc26-3003-442f-bafb-464373fb2624/application?utm_source=ZNRrPGBkqO) diff --git a/docs/src/pages/careers/react-engineer-x.md b/docs/src/pages/careers/react-engineer-x.md index 5a72c16950a446..b1a7d65b9d122e 100644 --- a/docs/src/pages/careers/react-engineer-x.md +++ b/docs/src/pages/careers/react-engineer-x.md @@ -70,7 +70,7 @@ Depending on the day, you'll: ### The best parts of this job -- **You'll be at the cutting edge of application development** — working on one of the fastest-growing UI libraries on the market. +- **You'll be at the cutting-edge of application development** — working on one of the fastest-growing UI libraries on the market. - **You'll be part of an active, open, friendly community** of developers that are excited about building awesome applications. - **Your role will be key to making MUI the go-to UI framework** for building applications, websites, and design systems with React. @@ -126,4 +126,4 @@ You can find the other perks & benefits on the [careers](/careers/#perks-amp-ben ## How to apply? -[Apply now for this position 📮](https://jobs.ashbyhq.com/mui/decc9f01-70c3-40ef-b660-70ed2d631e41/application) +[Apply now for this position 📮](https://jobs.ashbyhq.com/MUI/decc9f01-70c3-40ef-b660-70ed2d631e41/application?utm_source=ZNRrPGBkqO) diff --git a/docs/src/pages/careers/react-support-engineer.md b/docs/src/pages/careers/react-support-engineer.md index f3d0983a2fbd3a..5d7e4425165edc 100644 --- a/docs/src/pages/careers/react-support-engineer.md +++ b/docs/src/pages/careers/react-support-engineer.md @@ -119,4 +119,4 @@ You can find the other perks & benefits on the [careers](/careers/#perks-amp-ben ## How to apply? -[Apply now for this position 📮](https://jobs.ashbyhq.com/mui/e362a14c-6674-4ac9-8eee-bcf44a8767c8/application) +[Apply now for this position 📮](https://jobs.ashbyhq.com/MUI/e362a14c-6674-4ac9-8eee-bcf44a8767c8/application?utm_source=ZNRrPGBkqO) diff --git a/docs/src/pages/careers/support-agent.md b/docs/src/pages/careers/support-agent.md index 731243958710a8..05ea2ef33d8491 100644 --- a/docs/src/pages/careers/support-agent.md +++ b/docs/src/pages/careers/support-agent.md @@ -70,4 +70,4 @@ You can find the other perks & benefits on the [careers](/careers/#perks-amp-ben ## How to apply? -[Apply now for this position 📮](https://airtable.com/shrdqo1Z6srZXGcvh?prefill_Applying+for=Support%20Agent%20-%20Store&prefill_source=mui.com) +[Apply now for this position 📮](https://jobs.ashbyhq.com/MUI/79a9b5ec-6fb3-41ec-b48b-0a792ced7c19/application?utm_source=ZNRrPGBkqO) diff --git a/docs/src/pages/careers/technical-product-manager.md b/docs/src/pages/careers/technical-product-manager.md index f84bd35c1a6d4b..b91efdd8aa8f62 100644 --- a/docs/src/pages/careers/technical-product-manager.md +++ b/docs/src/pages/careers/technical-product-manager.md @@ -77,4 +77,4 @@ You can find the other perks & benefits on the [careers](/careers/#perks-amp-ben ## How to apply? -[Apply now for this position 📮](https://airtable.com/shrdqo1Z6srZXGcvh?prefill_Applying+for=Technical%20Product%20Manager&prefill_source=mui.com) +[Apply now for this position 📮](https://jobs.ashbyhq.com/MUI/__ID__/application?utm_source=ZNRrPGBkqO) diff --git a/docs/translations/translations.json b/docs/translations/translations.json index 7a25709baba9e9..88c570ad15c4ea 100644 --- a/docs/translations/translations.json +++ b/docs/translations/translations.json @@ -190,12 +190,13 @@ "/base/getting-started/customization": "Customization", "/base/react-": "Components", "inputs": "Inputs", - "/base/react-badge": "Badge", "/base/react-button": "Button", "/base/react-input": "Input", "/base/react-select": "Select", "/base/react-slider": "Slider", "/base/react-switch": "Switch", + "data-display": "Data display", + "/base/react-badge": "Badge", "navigation": "Navigation", "/base/react-menu": "Menu", "/base/react-table-pagination": "Table pagination", @@ -209,6 +210,8 @@ "/base/react-portal": "Portal", "/base/react-textarea-autosize": "Textarea autosize", "/base/react-trap-focus": "Trap focus", + "/base/guides": "How To Guides", + "/base/guides/working-with-tailwind-css": "Working with Tailwind CSS", "/material-ui/getting-started": "Getting started", "/material-ui/getting-started/overview": "Overview", "/material-ui/getting-started/installation": "Installation", @@ -234,7 +237,6 @@ "/material-ui/react-text-field": "Text field", "/material-ui/react-transfer-list": "Transfer list", "/material-ui/react-toggle-button": "Toggle button", - "data-display": "Data display", "/material-ui/react-avatar": "Avatar", "/material-ui/react-badge": "Badge", "/material-ui/react-chip": "Chip", diff --git a/examples/mui-base-with-tailwind-css/.gitignore b/examples/mui-base-with-tailwind-css/.gitignore new file mode 100644 index 00000000000000..4d29575de80483 --- /dev/null +++ b/examples/mui-base-with-tailwind-css/.gitignore @@ -0,0 +1,23 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/examples/mui-base-with-tailwind-css/README.md b/examples/mui-base-with-tailwind-css/README.md new file mode 100644 index 00000000000000..3bfee38edc93cb --- /dev/null +++ b/examples/mui-base-with-tailwind-css/README.md @@ -0,0 +1,47 @@ +# Getting Started with Create React App + +This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). +It shows how you can use @mui/base together with Tailwind CSS to build your application. + +## Available Scripts + +In the project directory, you can run: + +### `npm start` + +Runs the app in the development mode.\ +Open [http://localhost:3000](http://localhost:3000) to view it in the browser. + +The page will reload if you make edits.\ +You will also see any lint errors in the console. + +### `npm test` + +Launches the test runner in interactive watch mode.\ +See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. + +### `npm run build` + +Builds the app for production in the `build` folder.\ +It correctly bundles React in production mode and optimizes the build for the best performance. + +The build is minified and the filenames include the hashes.\ +Your app is ready to be deployed! + +See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) in the Create React App docs for more information. + +### `npm run eject` + +**Note: this is a one-way operation. Once you `eject`, you can’t go back!** + +If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. + +In its place, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. + +You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. + +## Learn more + +You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). + +To learn React, check out the [React documentation](https://reactjs.org/). diff --git a/examples/mui-base-with-tailwind-css/package.json b/examples/mui-base-with-tailwind-css/package.json new file mode 100644 index 00000000000000..a89404f4f62c2e --- /dev/null +++ b/examples/mui-base-with-tailwind-css/package.json @@ -0,0 +1,40 @@ +{ + "name": "mui-base-with-tailwind-css", + "version": "0.1.0", + "private": true, + "dependencies": { + "@mui/base": "^5.0.0-alpha.84", + "@testing-library/jest-dom": "^5.16.4", + "@testing-library/react": "^13.3.0", + "@testing-library/user-event": "^13.5.0", + "@types/jest": "^27.5.2", + "@types/node": "^16.11.38", + "@types/react": "^18.0.12", + "@types/react-dom": "^18.0.5", + "autoprefixer": "^10.4.7", + "postcss": "^8.4.14", + "react": "^18.1.0", + "react-dom": "^18.1.0", + "react-scripts": "5.0.1", + "typescript": "^4.7.3", + "web-vitals": "^2.1.4" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/examples/mui-base-with-tailwind-css/postcss.config.js b/examples/mui-base-with-tailwind-css/postcss.config.js new file mode 100644 index 00000000000000..12a703d900da81 --- /dev/null +++ b/examples/mui-base-with-tailwind-css/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/examples/mui-base-with-tailwind-css/public/favicon.ico b/examples/mui-base-with-tailwind-css/public/favicon.ico new file mode 100644 index 00000000000000..a11777cc471a43 Binary files /dev/null and b/examples/mui-base-with-tailwind-css/public/favicon.ico differ diff --git a/examples/mui-base-with-tailwind-css/public/index.html b/examples/mui-base-with-tailwind-css/public/index.html new file mode 100644 index 00000000000000..6a9f8c26bb7b9c --- /dev/null +++ b/examples/mui-base-with-tailwind-css/public/index.html @@ -0,0 +1,40 @@ + + + + + + + + + + + + + React App + + + +
    + + + diff --git a/examples/mui-base-with-tailwind-css/public/logo192.png b/examples/mui-base-with-tailwind-css/public/logo192.png new file mode 100644 index 00000000000000..fc44b0a3796c0e Binary files /dev/null and b/examples/mui-base-with-tailwind-css/public/logo192.png differ diff --git a/examples/mui-base-with-tailwind-css/public/logo512.png b/examples/mui-base-with-tailwind-css/public/logo512.png new file mode 100644 index 00000000000000..a4e47a6545bc15 Binary files /dev/null and b/examples/mui-base-with-tailwind-css/public/logo512.png differ diff --git a/examples/mui-base-with-tailwind-css/public/manifest.json b/examples/mui-base-with-tailwind-css/public/manifest.json new file mode 100644 index 00000000000000..080d6c77ac21bb --- /dev/null +++ b/examples/mui-base-with-tailwind-css/public/manifest.json @@ -0,0 +1,25 @@ +{ + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/examples/mui-base-with-tailwind-css/public/robots.txt b/examples/mui-base-with-tailwind-css/public/robots.txt new file mode 100644 index 00000000000000..e9e57dc4d41b9b --- /dev/null +++ b/examples/mui-base-with-tailwind-css/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/examples/mui-base-with-tailwind-css/src/App.tsx b/examples/mui-base-with-tailwind-css/src/App.tsx new file mode 100644 index 00000000000000..e601eabd239c2b --- /dev/null +++ b/examples/mui-base-with-tailwind-css/src/App.tsx @@ -0,0 +1,8 @@ +import * as React from 'react'; +import Player from './Player'; + +function App() { + return ; +} + +export default App; diff --git a/examples/mui-base-with-tailwind-css/src/Button.tsx b/examples/mui-base-with-tailwind-css/src/Button.tsx new file mode 100644 index 00000000000000..81392aef4fbe49 --- /dev/null +++ b/examples/mui-base-with-tailwind-css/src/Button.tsx @@ -0,0 +1,26 @@ +import * as React from 'react'; +import ButtonUnstyled, { + ButtonUnstyledOwnerState, + ButtonUnstyledProps, +} from '@mui/base/ButtonUnstyled'; + +const Button = React.forwardRef(function Button( + props: ButtonUnstyledProps, + ref: React.ForwardedRef, +) { + return ( + ({ + className: `hover:text-cyan-500 transition-colors ${ + state.focusVisible ? 'outline-0 ring-2 ring-cyan-500' : '' + }`, + }), + }} + ref={ref} + /> + ); +}); + +export default Button; diff --git a/examples/mui-base-with-tailwind-css/src/Player.tsx b/examples/mui-base-with-tailwind-css/src/Player.tsx new file mode 100644 index 00000000000000..f6d13b95820ebb --- /dev/null +++ b/examples/mui-base-with-tailwind-css/src/Player.tsx @@ -0,0 +1,150 @@ +import * as React from 'react'; +import Button from './Button'; +import Slider from './Slider'; + +const Player = React.forwardRef(function Player( + props: { className?: string }, + ref: React.ForwardedRef, +) { + const { className, ...other } = props; + return ( +
    +
    +
    + +
    +

    + Ep. 128 +

    +

    + Scaling CSS at Heroku with Utility Classes +

    +

    Full Stack Radio

    +
    +
    +
    +
    + +
    +
    +
    24:16
    +
    75:50
    +
    +
    +
    +
    +
    + + + +
    + +
    + + + +
    +
    +
    + ); +}); + +export default Player; diff --git a/examples/mui-base-with-tailwind-css/src/Slider.tsx b/examples/mui-base-with-tailwind-css/src/Slider.tsx new file mode 100644 index 00000000000000..f2b307d1b62cbe --- /dev/null +++ b/examples/mui-base-with-tailwind-css/src/Slider.tsx @@ -0,0 +1,46 @@ +import * as React from 'react'; +import SliderUnstyled, { + SliderUnstyledThumbSlotProps, + SliderUnstyledProps, +} from '@mui/base/SliderUnstyled'; + +const Thumb = React.forwardRef(function Thumb( + props: SliderUnstyledThumbSlotProps, + ref: React.ForwardedRef, +) { + const { ownerState, className, children, ...other } = props; + return ( + + + {children} + + ); +}); + +const Slider = React.forwardRef(function Slider( + props: SliderUnstyledProps, + ref: React.ForwardedRef, +) { + return ( + + ); +}); + +export default Slider; diff --git a/examples/mui-base-with-tailwind-css/src/index.css b/examples/mui-base-with-tailwind-css/src/index.css new file mode 100644 index 00000000000000..b5c61c956711f9 --- /dev/null +++ b/examples/mui-base-with-tailwind-css/src/index.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/examples/mui-base-with-tailwind-css/src/index.tsx b/examples/mui-base-with-tailwind-css/src/index.tsx new file mode 100644 index 00000000000000..edfd0b9c280b9b --- /dev/null +++ b/examples/mui-base-with-tailwind-css/src/index.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import './index.css'; +import App from './App'; +import reportWebVitals from './reportWebVitals'; + +const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement); +root.render( + + + , +); + +// If you want to start measuring performance in your app, pass a function +// to log results (for example: reportWebVitals(console.log)) +// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals +reportWebVitals(); diff --git a/examples/mui-base-with-tailwind-css/src/logo.svg b/examples/mui-base-with-tailwind-css/src/logo.svg new file mode 100644 index 00000000000000..9dfc1c058cebbe --- /dev/null +++ b/examples/mui-base-with-tailwind-css/src/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/mui-base-with-tailwind-css/src/react-app-env.d.ts b/examples/mui-base-with-tailwind-css/src/react-app-env.d.ts new file mode 100644 index 00000000000000..6431bc5fc6b2c9 --- /dev/null +++ b/examples/mui-base-with-tailwind-css/src/react-app-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/mui-base-with-tailwind-css/src/reportWebVitals.ts b/examples/mui-base-with-tailwind-css/src/reportWebVitals.ts new file mode 100644 index 00000000000000..49a2a16e0fbc76 --- /dev/null +++ b/examples/mui-base-with-tailwind-css/src/reportWebVitals.ts @@ -0,0 +1,15 @@ +import { ReportHandler } from 'web-vitals'; + +const reportWebVitals = (onPerfEntry?: ReportHandler) => { + if (onPerfEntry && onPerfEntry instanceof Function) { + import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { + getCLS(onPerfEntry); + getFID(onPerfEntry); + getFCP(onPerfEntry); + getLCP(onPerfEntry); + getTTFB(onPerfEntry); + }); + } +}; + +export default reportWebVitals; diff --git a/examples/mui-base-with-tailwind-css/src/setupTests.ts b/examples/mui-base-with-tailwind-css/src/setupTests.ts new file mode 100644 index 00000000000000..8f2609b7b3e0e3 --- /dev/null +++ b/examples/mui-base-with-tailwind-css/src/setupTests.ts @@ -0,0 +1,5 @@ +// jest-dom adds custom jest matchers for asserting on DOM nodes. +// allows you to do things like: +// expect(element).toHaveTextContent(/react/i) +// learn more: https://github.com/testing-library/jest-dom +import '@testing-library/jest-dom'; diff --git a/examples/mui-base-with-tailwind-css/tailwind.config.js b/examples/mui-base-with-tailwind-css/tailwind.config.js new file mode 100644 index 00000000000000..b15032567b2d6c --- /dev/null +++ b/examples/mui-base-with-tailwind-css/tailwind.config.js @@ -0,0 +1,7 @@ +module.exports = { + content: ['./src/**/*.{js,jsx,ts,tsx}'], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/examples/mui-base-with-tailwind-css/tsconfig.json b/examples/mui-base-with-tailwind-css/tsconfig.json new file mode 100644 index 00000000000000..9d379a3c4af84a --- /dev/null +++ b/examples/mui-base-with-tailwind-css/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": ["src"] +} diff --git a/examples/nextjs-with-typescript-v4-migration/pages/_document.tsx b/examples/nextjs-with-typescript-v4-migration/pages/_document.tsx index eff5c47e478538..cd27da44036b1f 100644 --- a/examples/nextjs-with-typescript-v4-migration/pages/_document.tsx +++ b/examples/nextjs-with-typescript-v4-migration/pages/_document.tsx @@ -105,7 +105,7 @@ MyDocument.getInitialProps = async (ctx) => { /> )); - // Gemerate the css string for the styles coming from jss + // Generate the css string for the styles coming from jss let css = jssSheets.toString(); // It might be undefined, e.g. after an error. if (css && process.env.NODE_ENV === 'production') { diff --git a/package.json b/package.json index 46ff51e72ce66e..2697f19ba5e61c 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { - "version": "5.8.4", + "name": "@mui/monorepo", + "version": "5.8.5", "private": true, "scripts": { "proptypes": "cross-env BABEL_ENV=development babel-node --extensions \".tsx,.ts,.js\" ./scripts/generateProptypes.ts", @@ -117,7 +118,7 @@ "chai-dom": "^1.11.0", "chalk": "^4.1.2", "compression-webpack-plugin": "^9.2.0", - "concurrently": "^7.2.1", + "concurrently": "^7.2.2", "confusing-browser-globals": "^1.0.11", "core-js": "^2.6.11", "cpy-cli": "^4.1.0", @@ -167,7 +168,7 @@ "react-test-renderer": "^17.0.2", "remark": "^13.0.0", "rimraf": "^3.0.2", - "rollup": "^2.70.2", + "rollup": "^2.75.7", "rollup-plugin-babel": "^4.4.0", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-node-globals": "^1.4.0", diff --git a/packages/mui-base/package.json b/packages/mui-base/package.json index 0c2932ccfd08ee..28bdc55642f784 100644 --- a/packages/mui-base/package.json +++ b/packages/mui-base/package.json @@ -1,6 +1,6 @@ { "name": "@mui/base", - "version": "5.0.0-alpha.85", + "version": "5.0.0-alpha.86", "private": false, "author": "MUI Team", "description": "A library of headless ('unstyled') React UI components and low-level hooks.", diff --git a/packages/mui-base/src/FormControlUnstyled/FormControlUnstyled.spec.tsx b/packages/mui-base/src/FormControlUnstyled/FormControlUnstyled.spec.tsx index 6c46361dae0147..a029a461ebac01 100644 --- a/packages/mui-base/src/FormControlUnstyled/FormControlUnstyled.spec.tsx +++ b/packages/mui-base/src/FormControlUnstyled/FormControlUnstyled.spec.tsx @@ -36,8 +36,12 @@ const FormControlUnstyledTest = () => ( ); function Root(props: FormControlUnstyledRootSlotProps) { - const { ownerState, ...other } = props; - return
    ; + const { ownerState, children, ...other } = props; + return ( +
    + {children as React.ReactNode} +
    + ); } const StyledFormControl = ; diff --git a/packages/mui-base/src/InputUnstyled/useInput.ts b/packages/mui-base/src/InputUnstyled/useInput.ts index ea64e6aaf303d8..2e65e79aefa51c 100644 --- a/packages/mui-base/src/InputUnstyled/useInput.ts +++ b/packages/mui-base/src/InputUnstyled/useInput.ts @@ -61,7 +61,7 @@ export default function useInput(parameters: UseInputParameters) { const { current: isControlled } = React.useRef(value != null); - const handleInputRefWarning = React.useCallback((instance) => { + const handleInputRefWarning = React.useCallback((instance: HTMLElement) => { if (process.env.NODE_ENV !== 'production') { if (instance && instance.nodeName !== 'INPUT' && !instance.focus) { console.error( diff --git a/packages/mui-base/src/ListboxUnstyled/useListbox.test.tsx b/packages/mui-base/src/ListboxUnstyled/useListbox.test.tsx index 1b510ccf881553..f3109b79987bb1 100644 --- a/packages/mui-base/src/ListboxUnstyled/useListbox.test.tsx +++ b/packages/mui-base/src/ListboxUnstyled/useListbox.test.tsx @@ -1,7 +1,8 @@ import * as React from 'react'; -import { useListbox } from '@mui/base/ListboxUnstyled'; import { expect } from 'chai'; -import { createRenderer } from 'test/utils'; +import { SinonSpy, spy } from 'sinon'; +import { useListbox } from '@mui/base/ListboxUnstyled'; +import { createRenderer, createEvent, fireEvent } from 'test/utils'; describe('useListbox', () => { const { render } = createRenderer(); @@ -56,4 +57,72 @@ describe('useListbox', () => { expect(listboxes[0].id).not.to.equal(listboxes[1].id); }); }); + + describe('preventing default behavior on keyDown', () => { + ['ArrowUp', 'ArrowDown', 'Home', 'End', 'PageUp', 'PageDown', 'Enter', ' '].forEach((key) => + it(`prevents default behavior when ${key} is pressed in activeDescendant focus management mode`, () => { + const Listbox = () => { + const { getRootProps } = useListbox({ options: [], focusManagement: 'activeDescendant' }); + return
    ; + }; + + const { getByRole } = render(); + const listbox = getByRole('listbox'); + listbox.focus(); + + const event = createEvent.keyDown(listbox, { + key, + }); + + event.preventDefault = spy(); + fireEvent(listbox, event); + + expect((event.preventDefault as SinonSpy).calledOnce).to.equal(true); + }), + ); + + ['ArrowUp', 'ArrowDown', 'Home', 'End', 'PageUp', 'PageDown'].forEach((key) => + it(`prevents default behavior when ${key} is pressed in DOM focus management mode`, () => { + const Listbox = () => { + const { getRootProps } = useListbox({ options: [], focusManagement: 'DOM' }); + return
    ; + }; + + const { getByRole } = render(); + const listbox = getByRole('listbox'); + listbox.focus(); + + const event = createEvent.keyDown(listbox, { + key, + }); + + event.preventDefault = spy(); + fireEvent(listbox, event); + + expect((event.preventDefault as SinonSpy).calledOnce).to.equal(true); + }), + ); + + ['Enter', ' '].forEach((key) => + it(`does not prevent default behavior when ${key} is pressed in DOM focus management mode`, () => { + const Listbox = () => { + const { getRootProps } = useListbox({ options: [], focusManagement: 'DOM' }); + return
    ; + }; + + const { getByRole } = render(); + const listbox = getByRole('listbox'); + listbox.focus(); + + const event = createEvent.keyDown(listbox, { + key, + }); + + event.preventDefault = spy(); + fireEvent(listbox, event); + + expect((event.preventDefault as SinonSpy).notCalled).to.equal(true); + }), + ); + }); }); diff --git a/packages/mui-base/src/ListboxUnstyled/useListbox.ts b/packages/mui-base/src/ListboxUnstyled/useListbox.ts index f6d769f103c335..40a96391b717ab 100644 --- a/packages/mui-base/src/ListboxUnstyled/useListbox.ts +++ b/packages/mui-base/src/ListboxUnstyled/useListbox.ts @@ -160,16 +160,15 @@ export default function useListbox(props: UseListboxParameters return; } - const keysToPreventDefault = [ - ' ', - 'Enter', - 'ArrowUp', - 'ArrowDown', - 'Home', - 'End', - 'PageUp', - 'PageDown', - ]; + const keysToPreventDefault = ['ArrowUp', 'ArrowDown', 'Home', 'End', 'PageUp', 'PageDown']; + + if (focusManagement === 'activeDescendant') { + // When the child element is focused using the activeDescendant attribute, + // the listbox handles keyboard events on its behalf. + // We have to `preventDefault()` is this case to prevent the browser from + // scrolling the view when space is pressed or submitting forms when enter is pressed. + keysToPreventDefault.push(' ', 'Enter'); + } if (keysToPreventDefault.includes(event.key)) { event.preventDefault(); diff --git a/packages/mui-base/src/MenuUnstyled/useMenu.ts b/packages/mui-base/src/MenuUnstyled/useMenu.ts index aeeb24c456a071..5b5b064e2c6cb4 100644 --- a/packages/mui-base/src/MenuUnstyled/useMenu.ts +++ b/packages/mui-base/src/MenuUnstyled/useMenu.ts @@ -51,7 +51,7 @@ export default function useMenu(parameters: UseMenuParameters = {}) { const listboxRef = React.useRef(null); const handleRef = useForkRef(listboxRef, listboxRefProp); - const registerItem = React.useCallback((id, metadata) => { + const registerItem = React.useCallback((id: string, metadata: MenuItemMetadata) => { setMenuItems((previousState) => { const newState = { ...previousState }; newState[id] = metadata; @@ -59,7 +59,7 @@ export default function useMenu(parameters: UseMenuParameters = {}) { }); }, []); - const unregisterItem = React.useCallback((id) => { + const unregisterItem = React.useCallback((id: string) => { setMenuItems((previousState) => { const newState = { ...previousState }; delete newState[id]; diff --git a/packages/mui-base/src/ModalUnstyled/ModalManager.test.js b/packages/mui-base/src/ModalUnstyled/ModalManager.test.js index cd5581ccb6ab1f..6c2d303982abb8 100644 --- a/packages/mui-base/src/ModalUnstyled/ModalManager.test.js +++ b/packages/mui-base/src/ModalUnstyled/ModalManager.test.js @@ -167,6 +167,39 @@ describe('ModalManager', () => { expect(fixedNode.style.paddingRight).to.equal(''); }); + describe('shadow dom', () => { + let shadowContainer; + let container2; + + beforeEach(() => { + shadowContainer = document.createElement('div'); + const shadowRoot = shadowContainer.attachShadow({ mode: 'open' }); + container2 = document.createElement('div'); + shadowRoot.appendChild(container2); + }); + + afterEach(() => { + document.body.removeChild(shadowContainer); + }); + + it('should scroll body when parent is shadow root', () => { + const modal = {}; + + container2.style.overflow = 'scroll'; + + document.body.appendChild(shadowContainer); + modalManager.add(modal, container2); + modalManager.mount(modal, {}); + + expect(container2.style.overflow).to.equal('scroll'); + expect(document.body.style.overflow).to.equal('hidden'); + modalManager.remove(modal); + + expect(container2.style.overflow).to.equal('scroll'); + expect(document.body.style.overflow).to.equal(''); + }); + }); + describe('restore styles', () => { let container2; diff --git a/packages/mui-base/src/ModalUnstyled/ModalManager.ts b/packages/mui-base/src/ModalUnstyled/ModalManager.ts index d1993e039ecf28..afefc95384459c 100644 --- a/packages/mui-base/src/ModalUnstyled/ModalManager.ts +++ b/packages/mui-base/src/ModalUnstyled/ModalManager.ts @@ -122,14 +122,21 @@ function handleContainer(containerInfo: Container, props: ManagedModalProps) { }); } - // Improve Gatsby support - // https://css-tricks.com/snippets/css/force-vertical-scrollbar/ - const parent = container.parentElement; - const containerWindow = ownerWindow(container); - const scrollContainer = - parent?.nodeName === 'HTML' && containerWindow.getComputedStyle(parent).overflowY === 'scroll' - ? parent - : container; + let scrollContainer: HTMLElement; + + if (container.parentNode instanceof DocumentFragment) { + scrollContainer = ownerDocument(container).body; + } else { + // Improve Gatsby support + // https://css-tricks.com/snippets/css/force-vertical-scrollbar/ + const parent = container.parentElement; + const containerWindow = ownerWindow(container); + scrollContainer = + parent?.nodeName === 'HTML' && + containerWindow.getComputedStyle(parent).overflowY === 'scroll' + ? parent + : container; + } // Block the scroll even if no scrollbar is visible to account for mobile keyboard // screensize shrink. diff --git a/packages/mui-base/src/MultiSelectUnstyled/MultiSelectUnstyled.types.ts b/packages/mui-base/src/MultiSelectUnstyled/MultiSelectUnstyled.types.ts index 48f5281d5028e9..1fc94e47fdd3de 100644 --- a/packages/mui-base/src/MultiSelectUnstyled/MultiSelectUnstyled.types.ts +++ b/packages/mui-base/src/MultiSelectUnstyled/MultiSelectUnstyled.types.ts @@ -77,7 +77,7 @@ export type MultiSelectUnstyledListboxSlotProps = Simplify< export type MultiSelectUnstyledPopperSlotProps = { anchorEl: PopperUnstyledProps['anchorEl']; - children?: React.ReactNode; + children?: PopperUnstyledProps['children']; className: string | undefined; disablePortal: PopperUnstyledProps['disablePortal']; open: boolean; diff --git a/packages/mui-base/src/SelectUnstyled/SelectUnstyled.types.ts b/packages/mui-base/src/SelectUnstyled/SelectUnstyled.types.ts index d2d4c4babf07dd..ef93a1c7614ca9 100644 --- a/packages/mui-base/src/SelectUnstyled/SelectUnstyled.types.ts +++ b/packages/mui-base/src/SelectUnstyled/SelectUnstyled.types.ts @@ -106,7 +106,7 @@ export type SelectUnstyledListboxSlotProps = Simplify< export type SelectUnstyledPopperSlotProps = { anchorEl: PopperUnstyledProps['anchorEl']; - children?: React.ReactNode; + children?: PopperUnstyledProps['children']; className: string | undefined; disablePortal: PopperUnstyledProps['disablePortal']; open: boolean; diff --git a/packages/mui-base/src/TabsUnstyled/TabsUnstyled.types.ts b/packages/mui-base/src/TabsUnstyled/TabsUnstyled.types.ts index d612133cc94dff..a56a801ec5dcb9 100644 --- a/packages/mui-base/src/TabsUnstyled/TabsUnstyled.types.ts +++ b/packages/mui-base/src/TabsUnstyled/TabsUnstyled.types.ts @@ -50,7 +50,7 @@ export interface TabsUnstyledOwnProps { /** * Callback invoked when new value is being set. */ - onChange?: (event: React.SyntheticEvent, value: number | string) => void; + onChange?: (event: React.SyntheticEvent, value: number | string | boolean) => void; /** * If `true` the selected tab changes on focus. Otherwise it only * changes on activation. diff --git a/packages/mui-base/src/TabsUnstyled/useTabs.ts b/packages/mui-base/src/TabsUnstyled/useTabs.ts index b7ea9dc957813f..ca27bb92cf0961 100644 --- a/packages/mui-base/src/TabsUnstyled/useTabs.ts +++ b/packages/mui-base/src/TabsUnstyled/useTabs.ts @@ -24,7 +24,7 @@ export interface UseTabsParameters { /** * Callback invoked when new value is being set. */ - onChange?: (event: React.SyntheticEvent, value: number | string) => void; + onChange?: (event: React.SyntheticEvent, value: number | string | boolean) => void; /** * If `true` the selected tab changes on focus. Otherwise it only * changes on activation. @@ -52,7 +52,7 @@ const useTabs = (parameters: UseTabsParameters) => { const idPrefix = useId(); const onSelected = React.useCallback( - (e, newValue) => { + (e: React.SyntheticEvent, newValue: string | number | false) => { setValue(newValue); if (onChange) { onChange(e, newValue); diff --git a/packages/mui-base/src/TextareaAutosize/TextareaAutosize.js b/packages/mui-base/src/TextareaAutosize/TextareaAutosize.js index f3e4cdbc222e1e..360d6433ab91dd 100644 --- a/packages/mui-base/src/TextareaAutosize/TextareaAutosize.js +++ b/packages/mui-base/src/TextareaAutosize/TextareaAutosize.js @@ -1,5 +1,6 @@ import * as React from 'react'; import PropTypes from 'prop-types'; +import { flushSync } from 'react-dom'; import { unstable_debounce as debounce, unstable_useForkRef as useForkRef, @@ -27,6 +28,10 @@ const styles = { }, }; +function isEmpty(obj) { + return obj === undefined || obj === null || Object.keys(obj).length === 0; +} + const TextareaAutosize = React.forwardRef(function TextareaAutosize(props, ref) { const { onChange, maxRows, minRows = 1, style, value, ...other } = props; @@ -37,14 +42,14 @@ const TextareaAutosize = React.forwardRef(function TextareaAutosize(props, ref) const renders = React.useRef(0); const [state, setState] = React.useState({}); - const syncHeight = React.useCallback(() => { + const getUpdatedState = React.useCallback(() => { const input = inputRef.current; const containerWindow = ownerWindow(input); const computedStyle = containerWindow.getComputedStyle(input); // If input's width is shrunk and it's not visible, don't sync height. if (computedStyle.width === '0px') { - return; + return {}; } const inputShallow = shadowRef.current; @@ -86,41 +91,80 @@ const TextareaAutosize = React.forwardRef(function TextareaAutosize(props, ref) const outerHeightStyle = outerHeight + (boxSizing === 'border-box' ? padding + border : 0); const overflow = Math.abs(outerHeight - innerHeight) <= 1; - setState((prevState) => { - // Need a large enough difference to update the height. - // This prevents infinite rendering loop. - if ( - renders.current < 20 && - ((outerHeightStyle > 0 && - Math.abs((prevState.outerHeightStyle || 0) - outerHeightStyle) > 1) || - prevState.overflow !== overflow) - ) { - renders.current += 1; - return { - overflow, - outerHeightStyle, - }; - } + return { outerHeightStyle, overflow }; + }, [maxRows, minRows, props.placeholder]); - if (process.env.NODE_ENV !== 'production') { - if (renders.current === 20) { - console.error( - [ - 'MUI: Too many re-renders. The layout is unstable.', - 'TextareaAutosize limits the number of renders to prevent an infinite loop.', - ].join('\n'), - ); - } + const updateState = (prevState, newState) => { + const { outerHeightStyle, overflow } = newState; + // Need a large enough difference to update the height. + // This prevents infinite rendering loop. + if ( + renders.current < 20 && + ((outerHeightStyle > 0 && + Math.abs((prevState.outerHeightStyle || 0) - outerHeightStyle) > 1) || + prevState.overflow !== overflow) + ) { + renders.current += 1; + return { + overflow, + outerHeightStyle, + }; + } + if (process.env.NODE_ENV !== 'production') { + if (renders.current === 20) { + console.error( + [ + 'MUI: Too many re-renders. The layout is unstable.', + 'TextareaAutosize limits the number of renders to prevent an infinite loop.', + ].join('\n'), + ); } + } + return prevState; + }; + + const syncHeight = React.useCallback(() => { + const newState = getUpdatedState(); + + if (isEmpty(newState)) { + return; + } - return prevState; + setState((prevState) => { + return updateState(prevState, newState); }); - }, [maxRows, minRows, props.placeholder]); + }, [getUpdatedState]); + + const syncHeightWithFlushSycn = () => { + const newState = getUpdatedState(); + + if (isEmpty(newState)) { + return; + } + + // In React 18, state updates in a ResizeObserver's callback are happening after the paint which causes flickering + // when doing some visual updates in it. Using flushSync ensures that the dom will be painted after the states updates happen + // Related issue - https://github.com/facebook/react/issues/24331 + flushSync(() => { + setState((prevState) => { + return updateState(prevState, newState); + }); + }); + }; React.useEffect(() => { const handleResize = debounce(() => { renders.current = 0; - syncHeight(); + + // If the TextareaAutosize component is replaced by Suspense with a fallback, the last + // ResizeObserver's handler that runs because of the change in the layout is trying to + // access a dom node that is no longer there (as the fallback component is being shown instead). + // See https://github.com/mui/material-ui/issues/32640 + // TODO: Add tests that will ensure the component is not failing when + // replaced by Suspense with a fallback, once React is updated to version 18 + if (inputRef.current) { + syncHeightWithFlushSycn(); + } }); const containerWindow = ownerWindow(inputRef.current); containerWindow.addEventListener('resize', handleResize); @@ -138,7 +182,7 @@ const TextareaAutosize = React.forwardRef(function TextareaAutosize(props, ref) resizeObserver.disconnect(); } }; - }, [syncHeight]); + }); useEnhancedEffect(() => { syncHeight(); diff --git a/packages/mui-codemod/package.json b/packages/mui-codemod/package.json index 32c5c5044362a2..fdbd36447d1451 100644 --- a/packages/mui-codemod/package.json +++ b/packages/mui-codemod/package.json @@ -1,6 +1,6 @@ { "name": "@mui/codemod", - "version": "5.8.4", + "version": "5.8.5", "bin": "./codemod.js", "private": false, "author": "MUI Team", diff --git a/packages/mui-joy/package.json b/packages/mui-joy/package.json index 8880ee8ca14d82..e8fff2870d6fd7 100644 --- a/packages/mui-joy/package.json +++ b/packages/mui-joy/package.json @@ -1,6 +1,6 @@ { "name": "@mui/joy", - "version": "5.0.0-alpha.32", + "version": "5.0.0-alpha.33", "private": false, "author": "MUI Team", "description": "A library of beautifully designed React UI components.", @@ -57,8 +57,8 @@ }, "dependencies": { "@babel/runtime": "^7.17.2", - "@mui/base": "5.0.0-alpha.85", - "@mui/system": "^5.8.4", + "@mui/base": "5.0.0-alpha.86", + "@mui/system": "^5.8.5", "@mui/types": "^7.1.4", "@mui/utils": "^5.8.4", "clsx": "^1.1.1", diff --git a/packages/mui-joy/src/AspectRatio/aspectRatioClasses.ts b/packages/mui-joy/src/AspectRatio/aspectRatioClasses.ts index 72118bcdac3cc5..e1b1034503222d 100644 --- a/packages/mui-joy/src/AspectRatio/aspectRatioClasses.ts +++ b/packages/mui-joy/src/AspectRatio/aspectRatioClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface AspectRatioClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Avatar/avatarClasses.ts b/packages/mui-joy/src/Avatar/avatarClasses.ts index d4ce28452fb641..4d42d4c9d2d8ea 100644 --- a/packages/mui-joy/src/Avatar/avatarClasses.ts +++ b/packages/mui-joy/src/Avatar/avatarClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface AvatarClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/AvatarGroup/avatarGroupClasses.ts b/packages/mui-joy/src/AvatarGroup/avatarGroupClasses.ts index bd724ea5924659..3ac0acdd62d454 100644 --- a/packages/mui-joy/src/AvatarGroup/avatarGroupClasses.ts +++ b/packages/mui-joy/src/AvatarGroup/avatarGroupClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface AvatarGroupClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Badge/badgeClasses.ts b/packages/mui-joy/src/Badge/badgeClasses.ts index 6dc62ce22a71ae..aba4663a19aba5 100644 --- a/packages/mui-joy/src/Badge/badgeClasses.ts +++ b/packages/mui-joy/src/Badge/badgeClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface BadgeClasses { /** Class name applied to the root element. */ diff --git a/packages/mui-joy/src/Button/buttonClasses.ts b/packages/mui-joy/src/Button/buttonClasses.ts index 5ef5369398782b..6f72ab08ef4961 100644 --- a/packages/mui-joy/src/Button/buttonClasses.ts +++ b/packages/mui-joy/src/Button/buttonClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface ButtonClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Card/cardClasses.ts b/packages/mui-joy/src/Card/cardClasses.ts index 85daa83d8e466d..687062fdf18d50 100644 --- a/packages/mui-joy/src/Card/cardClasses.ts +++ b/packages/mui-joy/src/Card/cardClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface CardClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/CardContent/cardContentClasses.ts b/packages/mui-joy/src/CardContent/cardContentClasses.ts index 467c0cb3c648bd..0cda1a38dd9bd9 100644 --- a/packages/mui-joy/src/CardContent/cardContentClasses.ts +++ b/packages/mui-joy/src/CardContent/cardContentClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface CardContentClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/CardCover/cardCoverClasses.ts b/packages/mui-joy/src/CardCover/cardCoverClasses.ts index 391abcadc19e3c..382f467d22b39b 100644 --- a/packages/mui-joy/src/CardCover/cardCoverClasses.ts +++ b/packages/mui-joy/src/CardCover/cardCoverClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface CardCoverClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/CardOverflow/cardOverflowClasses.ts b/packages/mui-joy/src/CardOverflow/cardOverflowClasses.ts index 173a0cae896add..dd445e4e83e4d2 100644 --- a/packages/mui-joy/src/CardOverflow/cardOverflowClasses.ts +++ b/packages/mui-joy/src/CardOverflow/cardOverflowClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface CardOverflowClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Checkbox/Checkbox.tsx b/packages/mui-joy/src/Checkbox/Checkbox.tsx index 80291ec996682d..fd134f48ee9d49 100644 --- a/packages/mui-joy/src/Checkbox/Checkbox.tsx +++ b/packages/mui-joy/src/Checkbox/Checkbox.tsx @@ -59,12 +59,12 @@ const CheckboxRoot = styled('span', { display: 'inline-flex', fontFamily: theme.vars.fontFamily.body, lineHeight: 'var(--Checkbox-size)', // prevent label from having larger height than the checkbox - '&.Mui-disabled': { + [`&.${checkboxClasses.disabled}`]: { color: theme.vars.palette[ownerState.color!]?.plainDisabledColor, }, ...(ownerState.disableIcon && { color: theme.vars.palette[ownerState.color!]?.[`${ownerState.variant!}Color`], - '&.Mui-disabled': { + [`&.${checkboxClasses.disabled}`]: { color: theme.vars.palette[ownerState.color!]?.[`${ownerState.variant!}DisabledColor`], }, }), diff --git a/packages/mui-joy/src/Checkbox/checkboxClasses.ts b/packages/mui-joy/src/Checkbox/checkboxClasses.ts index 469d7c3e234074..41c5a8725fdfcb 100644 --- a/packages/mui-joy/src/Checkbox/checkboxClasses.ts +++ b/packages/mui-joy/src/Checkbox/checkboxClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface CheckboxClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Chip/chipClasses.ts b/packages/mui-joy/src/Chip/chipClasses.ts index 4619b7ffa4c3de..ef79e47e44af79 100644 --- a/packages/mui-joy/src/Chip/chipClasses.ts +++ b/packages/mui-joy/src/Chip/chipClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface ChipClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/ChipDelete/chipDeleteClasses.ts b/packages/mui-joy/src/ChipDelete/chipDeleteClasses.ts index fce130dbc7652b..6b44ed513cc84e 100644 --- a/packages/mui-joy/src/ChipDelete/chipDeleteClasses.ts +++ b/packages/mui-joy/src/ChipDelete/chipDeleteClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface ChipDeleteClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Container/containerClasses.ts b/packages/mui-joy/src/Container/containerClasses.ts index df3cff6f60208a..cc6ae505c27b0f 100644 --- a/packages/mui-joy/src/Container/containerClasses.ts +++ b/packages/mui-joy/src/Container/containerClasses.ts @@ -1,5 +1,5 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; import { ContainerClasses } from '@mui/system'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export type { ContainerClassKey } from '@mui/system'; export type { ContainerClasses }; diff --git a/packages/mui-joy/src/FormHelperText/formHelperTextClasses.ts b/packages/mui-joy/src/FormHelperText/formHelperTextClasses.ts index bd61b0ae42fd1c..c9a2e633615d08 100644 --- a/packages/mui-joy/src/FormHelperText/formHelperTextClasses.ts +++ b/packages/mui-joy/src/FormHelperText/formHelperTextClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface FormHelperTextClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/FormLabel/formLabelClasses.ts b/packages/mui-joy/src/FormLabel/formLabelClasses.ts index 1b5a13c5cfe680..b2624a7ef4c39a 100644 --- a/packages/mui-joy/src/FormLabel/formLabelClasses.ts +++ b/packages/mui-joy/src/FormLabel/formLabelClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface FormLabelClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/IconButton/iconButtonClasses.ts b/packages/mui-joy/src/IconButton/iconButtonClasses.ts index 72722ead0e3191..2d89f71fc67376 100644 --- a/packages/mui-joy/src/IconButton/iconButtonClasses.ts +++ b/packages/mui-joy/src/IconButton/iconButtonClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface IconButtonClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Input/inputClasses.ts b/packages/mui-joy/src/Input/inputClasses.ts index 1e378534359e7d..6f853d154ba8ee 100644 --- a/packages/mui-joy/src/Input/inputClasses.ts +++ b/packages/mui-joy/src/Input/inputClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface InputClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Link/Link.tsx b/packages/mui-joy/src/Link/Link.tsx index 3dd57cf0cf1fbf..30e88ba4003d15 100644 --- a/packages/mui-joy/src/Link/Link.tsx +++ b/packages/mui-joy/src/Link/Link.tsx @@ -103,7 +103,7 @@ const LinkRoot = styled('a', { : { color: `rgba(${theme.vars.palette[ownerState.color!]?.mainChannel} / 1)`, cursor: 'pointer', - '&.Mui-disabled': { + [`&.${linkClasses.disabled}`]: { pointerEvents: 'none', color: `rgba(${theme.vars.palette[ownerState.color!]?.mainChannel} / 0.6)`, }, diff --git a/packages/mui-joy/src/Link/linkClasses.ts b/packages/mui-joy/src/Link/linkClasses.ts index ec49fc9537c79a..0fa388bdc91d78 100644 --- a/packages/mui-joy/src/Link/linkClasses.ts +++ b/packages/mui-joy/src/Link/linkClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface LinkClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/List/listClasses.ts b/packages/mui-joy/src/List/listClasses.ts index 173f5975b918b6..bf6a8b5293e342 100644 --- a/packages/mui-joy/src/List/listClasses.ts +++ b/packages/mui-joy/src/List/listClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface ListClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/ListDivider/listDividerClasses.ts b/packages/mui-joy/src/ListDivider/listDividerClasses.ts index cbec7d500527c6..7ed0ad0b202fd6 100644 --- a/packages/mui-joy/src/ListDivider/listDividerClasses.ts +++ b/packages/mui-joy/src/ListDivider/listDividerClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface ListDividerClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/ListItem/listItemClasses.ts b/packages/mui-joy/src/ListItem/listItemClasses.ts index beb041b8d3fdf0..5d7049737e097f 100644 --- a/packages/mui-joy/src/ListItem/listItemClasses.ts +++ b/packages/mui-joy/src/ListItem/listItemClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface ListItemClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/ListItemButton/listItemButtonClasses.ts b/packages/mui-joy/src/ListItemButton/listItemButtonClasses.ts index d870153e5e1860..639cf7a5b1ce5a 100644 --- a/packages/mui-joy/src/ListItemButton/listItemButtonClasses.ts +++ b/packages/mui-joy/src/ListItemButton/listItemButtonClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface ListItemButtonClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/ListItemContent/listItemContentClasses.ts b/packages/mui-joy/src/ListItemContent/listItemContentClasses.ts index 8788b63ba39f78..02ce494988f50f 100644 --- a/packages/mui-joy/src/ListItemContent/listItemContentClasses.ts +++ b/packages/mui-joy/src/ListItemContent/listItemContentClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface ListItemContentClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/ListItemDecorator/listItemDecoratorClasses.ts b/packages/mui-joy/src/ListItemDecorator/listItemDecoratorClasses.ts index 41e15419519f66..3a06f107e9c91c 100644 --- a/packages/mui-joy/src/ListItemDecorator/listItemDecoratorClasses.ts +++ b/packages/mui-joy/src/ListItemDecorator/listItemDecoratorClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface ListItemDecoratorClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Radio/Radio.tsx b/packages/mui-joy/src/Radio/Radio.tsx index dbdfc44d1c0634..055c6a34f5c9a3 100644 --- a/packages/mui-joy/src/Radio/Radio.tsx +++ b/packages/mui-joy/src/Radio/Radio.tsx @@ -71,12 +71,12 @@ const RadioRoot = styled('span', { minWidth: 0, fontFamily: theme.vars.fontFamily.body, lineHeight: 'var(--Radio-size)', // prevent label from having larger height than the checkbox - '&.Mui-disabled': { + [`&.${radioClasses.disabled}`]: { color: theme.vars.palette[ownerState.color!]?.plainDisabledColor, }, ...(ownerState.disableIcon && { color: theme.vars.palette[ownerState.color!]?.[`${ownerState.variant!}Color`], - '&.Mui-disabled': { + [`&.${radioClasses.disabled}`]: { color: theme.vars.palette[ownerState.color!]?.[`${ownerState.variant!}DisabledColor`], }, }), diff --git a/packages/mui-joy/src/Radio/radioClasses.ts b/packages/mui-joy/src/Radio/radioClasses.ts index fe7ca089d90bae..6e26201525ea6a 100644 --- a/packages/mui-joy/src/Radio/radioClasses.ts +++ b/packages/mui-joy/src/Radio/radioClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface RadioClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/RadioGroup/radioGroupClasses.ts b/packages/mui-joy/src/RadioGroup/radioGroupClasses.ts index d490e4a587493c..55c9494c11f7be 100644 --- a/packages/mui-joy/src/RadioGroup/radioGroupClasses.ts +++ b/packages/mui-joy/src/RadioGroup/radioGroupClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface RadioGroupClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Sheet/Sheet.spec.tsx b/packages/mui-joy/src/Sheet/Sheet.spec.tsx index 9191bd58531f69..cd6a10f90b2e2e 100644 --- a/packages/mui-joy/src/Sheet/Sheet.spec.tsx +++ b/packages/mui-joy/src/Sheet/Sheet.spec.tsx @@ -19,18 +19,8 @@ import * as React from 'react'; ; ; -// `elevation` -; -; -; -; -; - // @ts-expect-error there is no variant `filled` ; // @ts-expect-error there is no color `secondary` ; - -// @ts-expect-error there is no elevation `xl2` -; diff --git a/packages/mui-joy/src/Sheet/Sheet.test.js b/packages/mui-joy/src/Sheet/Sheet.test.js index 187fa4eaf49f24..dac9eb34a6265d 100644 --- a/packages/mui-joy/src/Sheet/Sheet.test.js +++ b/packages/mui-joy/src/Sheet/Sheet.test.js @@ -59,27 +59,4 @@ describe('', () => { }); }); }); - - describe('prop: elevation', () => { - it('undefined by default', () => { - const { getByTestId } = render(Hello World); - - expect(getByTestId('root')).not.to.have.class(classes.elevationXs); - expect(getByTestId('root')).not.to.have.class(classes.elevationSm); - expect(getByTestId('root')).not.to.have.class(classes.elevationMd); - expect(getByTestId('root')).not.to.have.class(classes.elevationLg); - expect(getByTestId('root')).not.to.have.class(classes.elevationXl); - }); - ['xs', 'sm', 'md', 'lg', 'xl'].forEach((elevation) => { - it(`should render ${elevation}`, () => { - const { getByTestId } = render( - - Hello World - , - ); - - expect(getByTestId('root')).to.have.class(classes[`elevation${capitalize(elevation)}`]); - }); - }); - }); }); diff --git a/packages/mui-joy/src/Sheet/Sheet.tsx b/packages/mui-joy/src/Sheet/Sheet.tsx index 6897817704629b..4bf85e258c184f 100644 --- a/packages/mui-joy/src/Sheet/Sheet.tsx +++ b/packages/mui-joy/src/Sheet/Sheet.tsx @@ -5,20 +5,19 @@ import clsx from 'clsx'; import PropTypes from 'prop-types'; import * as React from 'react'; import { useThemeProps } from '../styles'; -import { resolveSxValue } from '../styles/styleUtils'; import styled from '../styles/styled'; +import { resolveSxValue } from '../styles/styleUtils'; import { getSheetUtilityClass } from './sheetClasses'; import { SheetProps, SheetTypeMap } from './SheetProps'; const useUtilityClasses = (ownerState: SheetProps) => { - const { elevation, variant, color } = ownerState; + const { variant, color } = ownerState; const slots = { root: [ 'root', variant && `variant${capitalize(variant)}`, color && `color${capitalize(color)}`, - elevation && `elevation${capitalize(elevation)}`, ], }; @@ -43,7 +42,6 @@ const SheetRoot = styled('div', { // TODO: discuss the theme transition. // This value is copied from mui-material Sheet. transition: 'box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms', - boxShadow: theme.vars.shadow[ownerState.elevation!], backgroundColor: theme.vars.palette.background.body, position: 'relative', }, @@ -57,20 +55,12 @@ const Sheet = React.forwardRef(function Sheet(inProps, ref) { name: 'JoySheet', }); - const { - className, - color = 'neutral', - component = 'div', - variant = 'plain', - elevation, - ...other - } = props; + const { className, color = 'neutral', component = 'div', variant = 'plain', ...other } = props; const ownerState = { ...props, color, component, - elevation, variant, }; @@ -113,14 +103,6 @@ Sheet.propTypes /* remove-proptypes */ = { * Either a string to use a HTML element or a component. */ component: PropTypes.elementType, - /** - * Shadow depth, corresponds to the `theme.shadow` scale. - * It accepts theme values between 'xs' and 'xl'. - */ - elevation: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ - PropTypes.oneOf(['lg', 'md', 'sm', 'xl', 'xs']), - PropTypes.string, - ]), /** * The system prop that allows defining system overrides as well as additional CSS styles. */ diff --git a/packages/mui-joy/src/Sheet/SheetProps.ts b/packages/mui-joy/src/Sheet/SheetProps.ts index fcd5258f073e18..993305b7657764 100644 --- a/packages/mui-joy/src/Sheet/SheetProps.ts +++ b/packages/mui-joy/src/Sheet/SheetProps.ts @@ -1,6 +1,6 @@ import { OverridableStringUnion, OverrideProps } from '@mui/types'; import * as React from 'react'; -import { ColorPaletteProp, VariantProp, SxProps } from '../styles/types'; +import { ColorPaletteProp, SxProps, VariantProp } from '../styles/types'; export type SheetSlot = 'root'; @@ -18,11 +18,6 @@ export interface SheetTypeMap

    { * @default 'neutral' */ color?: OverridableStringUnion; - /** - * Shadow depth, corresponds to the `theme.shadow` scale. - * It accepts theme values between 'xs' and 'xl'. - */ - elevation?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'; /** * The system prop that allows defining system overrides as well as additional CSS styles. */ diff --git a/packages/mui-joy/src/Sheet/sheetClasses.ts b/packages/mui-joy/src/Sheet/sheetClasses.ts index a4f7d8cb2839f6..7e255adfd4659e 100644 --- a/packages/mui-joy/src/Sheet/sheetClasses.ts +++ b/packages/mui-joy/src/Sheet/sheetClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface SheetClasses { /** Styles applied to the root element. */ @@ -23,16 +23,6 @@ export interface SheetClasses { variantSoft: string; /** Styles applied to the root element if `variant="solid"`. */ variantSolid: string; - /** Styles applied to the root element if `elevation="xs"`. */ - elevationXs: string; - /** Styles applied to the root element if `elevation="sm"`. */ - elevationSm: string; - /** Styles applied to the root element if `elevation="md"`. */ - elevationMd: string; - /** Styles applied to the root element if `elevation="lg"`. */ - elevationLg: string; - /** Styles applied to the root element if `elevation="xl"`. */ - elevationXl: string; } export type SheetClassKey = keyof SheetClasses; @@ -53,11 +43,6 @@ const sheetClasses: SheetClasses = generateUtilityClasses('JoySheet', [ 'variantOutlined', 'variantSoft', 'variantSolid', - 'elevationXs', - 'elevationSm', - 'elevationMd', - 'elevationLg', - 'elevationXl', ]); export default sheetClasses; diff --git a/packages/mui-joy/src/Slider/Slider.tsx b/packages/mui-joy/src/Slider/Slider.tsx index 4499cd86d4329b..8f3cf7570e699b 100644 --- a/packages/mui-joy/src/Slider/Slider.tsx +++ b/packages/mui-joy/src/Slider/Slider.tsx @@ -633,7 +633,10 @@ Slider.propTypes /* remove-proptypes */ = { * The color of the component. It supports those theme colors that make sense for this component. * @default 'primary' */ - color: PropTypes.oneOf(['danger', 'info', 'neutral', 'primary', 'success', 'warning']), + color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ + PropTypes.oneOf(['danger', 'info', 'neutral', 'primary', 'success', 'warning']), + PropTypes.string, + ]), /** * The component used for the root node. * Either a string to use a HTML element or a component. @@ -767,7 +770,10 @@ Slider.propTypes /* remove-proptypes */ = { * It accepts theme values between 'sm' and 'lg'. * @default 'md' */ - size: PropTypes.oneOf(['sm', 'md', 'lg']), + size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ + PropTypes.oneOf(['sm', 'md', 'lg']), + PropTypes.string, + ]), /** * The granularity with which the slider can step through values. (A "discrete" slider.) * The `min` prop serves as the origin for the valid values. diff --git a/packages/mui-joy/src/Slider/sliderClasses.ts b/packages/mui-joy/src/Slider/sliderClasses.ts index 8ab9451a2a23f1..8270536f911901 100644 --- a/packages/mui-joy/src/Slider/sliderClasses.ts +++ b/packages/mui-joy/src/Slider/sliderClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface SliderClasses { /** Class name applied to the root element. */ diff --git a/packages/mui-joy/src/SvgIcon/svgIconClasses.ts b/packages/mui-joy/src/SvgIcon/svgIconClasses.ts index 903da31cc73940..69a3ac7895e944 100644 --- a/packages/mui-joy/src/SvgIcon/svgIconClasses.ts +++ b/packages/mui-joy/src/SvgIcon/svgIconClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface SvgIconClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Switch/switchClasses.ts b/packages/mui-joy/src/Switch/switchClasses.ts index ddf8a57f112596..3593ae58fa310c 100644 --- a/packages/mui-joy/src/Switch/switchClasses.ts +++ b/packages/mui-joy/src/Switch/switchClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface SwitchClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/TextField/textFieldClasses.ts b/packages/mui-joy/src/TextField/textFieldClasses.ts index 2d07bb289a5136..018c4fe5aaca91 100644 --- a/packages/mui-joy/src/TextField/textFieldClasses.ts +++ b/packages/mui-joy/src/TextField/textFieldClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface TextFieldClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Typography/typographyClasses.ts b/packages/mui-joy/src/Typography/typographyClasses.ts index e007d51c4d8e8e..57edadf5315222 100644 --- a/packages/mui-joy/src/Typography/typographyClasses.ts +++ b/packages/mui-joy/src/Typography/typographyClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface TypographyClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/className/index.ts b/packages/mui-joy/src/className/index.ts index ac4bb27c3b0d48..1d47a7d752fa78 100644 --- a/packages/mui-joy/src/className/index.ts +++ b/packages/mui-joy/src/className/index.ts @@ -1,10 +1,9 @@ -/** - * Caution! this module must not include unstyled components import from `@mui/base`, otherwise, it will break the ClassNameGenerator. - * ❌ import { ... } from '@mui/base'; - * ✅ import { ... } from '@mui/base/utils'; // must be specific base module - * - * Issue: https://github.com/mui/material-ui/issues/30011#issuecomment-1024993401 - */ +import { unstable_generateUtilityClass, unstable_generateUtilityClasses } from '@mui/utils'; -// eslint-disable-next-line import/prefer-default-export -export { unstable_ClassNameGenerator } from '@mui/base/className'; +export { unstable_ClassNameGenerator } from '@mui/utils'; + +export const generateUtilityClass = (componentName: string, slot: string) => + unstable_generateUtilityClass(componentName, slot, 'Joy'); + +export const generateUtilityClasses = (componentName: string, slots: Array) => + unstable_generateUtilityClasses(componentName, slots, 'Joy'); diff --git a/packages/mui-joy/src/styles/extendTheme.ts b/packages/mui-joy/src/styles/extendTheme.ts index 0617111bf1c49a..b0f48cc833e474 100644 --- a/packages/mui-joy/src/styles/extendTheme.ts +++ b/packages/mui-joy/src/styles/extendTheme.ts @@ -16,6 +16,7 @@ import { TypographySystem, FontSize } from './types/typography'; import { Variants } from './types/variants'; import { Theme, ThemeCSSVar, ThemeScales } from './types'; import { Components } from './components'; +import { generateUtilityClass } from '../className'; type CSSProperties = CSS.Properties; @@ -360,7 +361,7 @@ export default function extendTheme(themeInput?: ThemeInput): Theme { xl3: 900, }, focus: { - selector: '&.Mui-focusVisible, &:focus-visible', + selector: `&.${generateUtilityClass('', 'focusVisible')}, &:focus-visible`, default: { outlineOffset: 'var(--joy-focus-outlineOffset, 0px)', // reset user agent stylesheet outline: '4px solid var(--joy-palette-focusVisible)', diff --git a/packages/mui-lab/package.json b/packages/mui-lab/package.json index 43c6c990fb829e..f65c3576e711cd 100644 --- a/packages/mui-lab/package.json +++ b/packages/mui-lab/package.json @@ -1,6 +1,6 @@ { "name": "@mui/lab", - "version": "5.0.0-alpha.86", + "version": "5.0.0-alpha.87", "private": false, "author": "MUI Team", "description": "Laboratory for new MUI modules.", @@ -77,8 +77,8 @@ }, "dependencies": { "@babel/runtime": "^7.17.2", - "@mui/base": "5.0.0-alpha.85", - "@mui/system": "^5.8.4", + "@mui/base": "5.0.0-alpha.86", + "@mui/system": "^5.8.5", "@mui/utils": "^5.8.4", "@mui/x-date-pickers": "5.0.0-alpha.1", "clsx": "^1.1.1", diff --git a/packages/mui-material-next/package.json b/packages/mui-material-next/package.json index 226db73b919b40..6bf1258daea12b 100644 --- a/packages/mui-material-next/package.json +++ b/packages/mui-material-next/package.json @@ -1,6 +1,6 @@ { "name": "@mui/material-next", - "version": "6.0.0-alpha.40", + "version": "6.0.0-alpha.41", "private": false, "author": "MUI Team", "description": "v6-alpha: React components that implement Google's Material Design", @@ -59,9 +59,9 @@ }, "dependencies": { "@babel/runtime": "^7.17.2", - "@mui/base": "5.0.0-alpha.85", - "@mui/material": "^5.8.4", - "@mui/system": "^5.8.4", + "@mui/base": "5.0.0-alpha.86", + "@mui/material": "^5.8.5", + "@mui/system": "^5.8.5", "@mui/types": "^7.1.4", "@mui/utils": "^5.8.4", "@popperjs/core": "^2.11.5", diff --git a/packages/mui-material/package.json b/packages/mui-material/package.json index 34e35970a2379d..94264e51abf313 100644 --- a/packages/mui-material/package.json +++ b/packages/mui-material/package.json @@ -1,6 +1,6 @@ { "name": "@mui/material", - "version": "5.8.4", + "version": "5.8.5", "private": false, "author": "MUI Team", "description": "React components that implement Google's Material Design.", @@ -61,8 +61,8 @@ }, "dependencies": { "@babel/runtime": "^7.17.2", - "@mui/base": "5.0.0-alpha.85", - "@mui/system": "^5.8.4", + "@mui/base": "5.0.0-alpha.86", + "@mui/system": "^5.8.5", "@mui/types": "^7.1.4", "@mui/utils": "^5.8.4", "@types/react-transition-group": "^4.4.4", diff --git a/packages/mui-material/src/Alert/Alert.js b/packages/mui-material/src/Alert/Alert.js index 3d1195f9305e24..5cfcd0492e59e0 100644 --- a/packages/mui-material/src/Alert/Alert.js +++ b/packages/mui-material/src/Alert/Alert.js @@ -52,28 +52,55 @@ const AlertRoot = styled(Paper, { padding: '6px 16px', ...(color && ownerState.variant === 'standard' && { - color: getColor(theme.palette[color].light, 0.6), - backgroundColor: getBackgroundColor(theme.palette[color].light, 0.9), - [`& .${alertClasses.icon}`]: { - color: - theme.palette.mode === 'dark' ? theme.palette[color].main : theme.palette[color].light, - }, + color: theme.vars + ? theme.vars.palette.Alert[`${color}Color`] + : getColor(theme.palette[color].light, 0.6), + backgroundColor: theme.vars + ? theme.vars.palette.Alert[`${color}StandardBg`] + : getBackgroundColor(theme.palette[color].light, 0.9), + [`& .${alertClasses.icon}`]: theme.vars + ? { color: theme.vars.palette.Alert[`${color}IconColor`] } + : { + color: + theme.palette.mode === 'dark' + ? theme.palette[color].main + : theme.palette[color].light, + }, }), ...(color && ownerState.variant === 'outlined' && { - color: getColor(theme.palette[color].light, 0.6), - border: `1px solid ${theme.palette[color].light}`, - [`& .${alertClasses.icon}`]: { - color: - theme.palette.mode === 'dark' ? theme.palette[color].main : theme.palette[color].light, - }, + color: theme.vars + ? theme.vars.palette.Alert[`${color}Color`] + : getColor(theme.palette[color].light, 0.6), + border: `1px solid ${(theme.vars || theme).palette[color].light}`, + [`& .${alertClasses.icon}`]: theme.vars + ? { color: theme.vars.palette.Alert[`${color}IconColor`] } + : { + color: + theme.palette.mode === 'dark' + ? theme.palette[color].main + : theme.palette[color].light, + }, }), ...(color && ownerState.variant === 'filled' && { - color: '#fff', fontWeight: theme.typography.fontWeightMedium, - backgroundColor: - theme.palette.mode === 'dark' ? theme.palette[color].dark : theme.palette[color].main, + ...(theme.vars + ? { + color: theme.vars.palette.Alert[`${color}FilledColor`], + backgroundColor: theme.vars.palette.Alert[`${color}FilledBg`], + } + : { + backgroundColor: + theme.palette.mode === 'dark' + ? theme.palette[color].dark + : theme.palette[color].main, + color: theme.palette.getContrastText( + theme.palette.mode === 'dark' + ? theme.palette[color].dark + : theme.palette[color].main, + ), + }), }), }; }); diff --git a/packages/mui-material/src/FilledInput/FilledInput.js b/packages/mui-material/src/FilledInput/FilledInput.js index a772873cc6b478..e694645c49adf8 100644 --- a/packages/mui-material/src/FilledInput/FilledInput.js +++ b/packages/mui-material/src/FilledInput/FilledInput.js @@ -98,7 +98,7 @@ const FilledInputRoot = styled(InputBaseRoot, { '&:before': { borderBottom: `1px solid ${ theme.vars - ? `rgba(${theme.vars.palette.common.onBackgroundChannel} / ${theme.vars.opacity.inputTouchBottomLine})` + ? `rgba(${theme.vars.palette.common.onBackgroundChannel} / ${theme.vars.opacity.inputUnderline})` : bottomLineColor }`, left: 0, diff --git a/packages/mui-material/src/Input/Input.js b/packages/mui-material/src/Input/Input.js index ccec45f3f3255a..644764c9de882e 100644 --- a/packages/mui-material/src/Input/Input.js +++ b/packages/mui-material/src/Input/Input.js @@ -45,7 +45,7 @@ const InputRoot = styled(InputBaseRoot, { const light = theme.palette.mode === 'light'; let bottomLineColor = light ? 'rgba(0, 0, 0, 0.42)' : 'rgba(255, 255, 255, 0.7)'; if (theme.vars) { - bottomLineColor = `rgba(${theme.vars.palette.common.onBackgroundChannel} / ${theme.vars.opacity.inputTouchBottomLine})`; + bottomLineColor = `rgba(${theme.vars.palette.common.onBackgroundChannel} / ${theme.vars.opacity.inputUnderline})`; } return { position: 'relative', diff --git a/packages/mui-material/src/OutlinedInput/OutlinedInput.js b/packages/mui-material/src/OutlinedInput/OutlinedInput.js index 1b4c9fcf574295..2f8700425494dc 100644 --- a/packages/mui-material/src/OutlinedInput/OutlinedInput.js +++ b/packages/mui-material/src/OutlinedInput/OutlinedInput.js @@ -155,11 +155,26 @@ const OutlinedInput = React.forwardRef(function OutlinedInput(inProps, ref) { states: ['required'], }); + const ownerState = { + ...props, + color: fcs.color || 'primary', + disabled: fcs.disabled, + error: fcs.error, + focused: fcs.focused, + formControl: muiFormControl, + fullWidth, + hiddenLabel: fcs.hiddenLabel, + multiline, + size: fcs.size, + type, + }; + return ( ( ', () => { ); expect(document.querySelector('[data-test=test]')).toHaveComputedStyle({ marginTop: '10px' }); }); + + it('should have ownerState in the theme style overrides', () => { + expect(() => + render( + ({ + // test that ownerState is not undefined + ...(ownerState.disabled && {}), + }), + }, + }, + }, + })} + > + + , + ), + ).not.to.throw(); + }); }); diff --git a/packages/mui-material/src/Tabs/Tabs.js b/packages/mui-material/src/Tabs/Tabs.js index d9a85d0668a69e..a9623d9f7afc25 100644 --- a/packages/mui-material/src/Tabs/Tabs.js +++ b/packages/mui-material/src/Tabs/Tabs.js @@ -562,8 +562,16 @@ const Tabs = React.forwardRef(function Tabs(inProps, ref) { React.useEffect(() => { const handleResize = debounce(() => { - updateIndicatorState(); - updateScrollButtonState(); + // If the Tabs component is replaced by Suspense with a fallback, the last + // ResizeObserver's handler that runs because of the change in the layout is trying to + // access a dom node that is no longer there (as the fallback component is being shown instead). + // See https://github.com/mui/material-ui/issues/33276 + // TODO: Add tests that will ensure the component is not failing when + // replaced by Suspense with a fallback, once React is updated to version 18 + if (tabsRef.current) { + updateIndicatorState(); + updateScrollButtonState(); + } }); const win = ownerWindow(tabsRef.current); win.addEventListener('resize', handleResize); diff --git a/packages/mui-material/src/styles/CssVarsProvider.d.ts b/packages/mui-material/src/styles/CssVarsProvider.d.ts deleted file mode 100644 index 158de8ddee8ecf..00000000000000 --- a/packages/mui-material/src/styles/CssVarsProvider.d.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { CreateCssVarsProviderResult } from '@mui/system'; -import { ThemeOptions, SupportedColorScheme } from './experimental_extendTheme'; -import { PaletteWithChannels } from './createPalette'; - -export interface ThemeInput extends Omit { - colorSchemes: Partial< - Record< - SupportedColorScheme, - { - palette: PaletteWithChannels; - } - > - >; -} - -type MDCreateCssVarsProviderResult = CreateCssVarsProviderResult; - -declare const useColorScheme: MDCreateCssVarsProviderResult['useColorScheme']; -declare const getInitColorSchemeScript: MDCreateCssVarsProviderResult['getInitColorSchemeScript']; - -/** - * This component is an experimental Theme Provider that generates CSS variabels out of the theme tokens. - * It should preferably be used at **the root of your component tree**. - */ -declare const Experimental_CssVarsProvider: MDCreateCssVarsProviderResult['CssVarsProvider']; - -export { useColorScheme, getInitColorSchemeScript, Experimental_CssVarsProvider }; diff --git a/packages/mui-material/src/styles/CssVarsProvider.spec.tsx b/packages/mui-material/src/styles/CssVarsProvider.spec.tsx new file mode 100644 index 00000000000000..f55a5d7b79341f --- /dev/null +++ b/packages/mui-material/src/styles/CssVarsProvider.spec.tsx @@ -0,0 +1,72 @@ +import * as React from 'react'; +import { + experimental_extendTheme as extendTheme, + Experimental_CssVarsProvider as CssVarsProvider, + styled, + useTheme, + Overlays, +} from '@mui/material/styles'; +import type {} from '@mui/material/themeCssVarsAugmentation'; + +const customTheme = extendTheme({ + colorSchemes: { + light: { + opacity: { + inputPlaceholder: 0.1, + inputUnderline: 0.1, + }, + overlays: Array(25).fill('') as Overlays, + palette: { + AppBar: { + darkBg: '', + darkColor: '', + defaultBg: '', + }, + // @ts-expect-error + mode: '', + getContrastText: () => '', + tonalOffset: 1, + }, + }, + dark: { + opacity: {}, + palette: {}, + }, + }, + components: { + MuiButton: { + styleOverrides: { + root: ({ theme }) => ({ + color: theme.vars.palette.primary.main, + }), + }, + }, + }, +}); + +const TestStyled = styled('div')(({ theme }) => ({ + // test that `theme.vars` works + color: theme.vars.palette.primary.main, + // test that `theme.getColorSchemeSelector` works + [theme.getColorSchemeSelector('dark')]: { + color: theme.vars.palette.common.onBackground, + }, +})); + +const TestUseTheme = () => { + const theme = useTheme(); + // test that `theme` from useTheme has access to CSS vars + return

    test
    ; +}; + + + ({ + // test that `theme` in sx has access to CSS vars + [theme.getColorSchemeSelector('dark')]: { + border: '1px solid', + borderColor: theme.vars.palette.divider, + }, + })} + /> +; diff --git a/packages/mui-material/src/styles/CssVarsProvider.test.js b/packages/mui-material/src/styles/CssVarsProvider.test.js index a796f1b7daa8fb..369244261f757c 100644 --- a/packages/mui-material/src/styles/CssVarsProvider.test.js +++ b/packages/mui-material/src/styles/CssVarsProvider.test.js @@ -200,7 +200,7 @@ describe('[Material UI] CssVarsProvider', () => { expect(screen.getByTestId('opacity').textContent).to.equal( JSON.stringify({ inputPlaceholder: 'var(--mui-opacity-inputPlaceholder)', - inputTouchBottomLine: 'var(--mui-opacity-inputTouchBottomLine)', + inputUnderline: 'var(--mui-opacity-inputUnderline)', switchTrackDisabled: 'var(--mui-opacity-switchTrackDisabled)', switchTrack: 'var(--mui-opacity-switchTrack)', }), diff --git a/packages/mui-material/src/styles/CssVarsProvider.js b/packages/mui-material/src/styles/CssVarsProvider.tsx similarity index 76% rename from packages/mui-material/src/styles/CssVarsProvider.js rename to packages/mui-material/src/styles/CssVarsProvider.tsx index b1708765bd6b89..76df9707a2f323 100644 --- a/packages/mui-material/src/styles/CssVarsProvider.js +++ b/packages/mui-material/src/styles/CssVarsProvider.tsx @@ -1,6 +1,9 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { unstable_createCssVarsProvider as createCssVarsProvider } from '@mui/system'; -import experimental_extendTheme from './experimental_extendTheme'; +import experimental_extendTheme, { + SupportedColorScheme, + CssVarsTheme, +} from './experimental_extendTheme'; import createTypography from './createTypography'; const defaultTheme = experimental_extendTheme(); @@ -9,7 +12,7 @@ const { CssVarsProvider: Experimental_CssVarsProvider, useColorScheme, getInitColorSchemeScript, -} = createCssVarsProvider({ +} = createCssVarsProvider({ theme: defaultTheme, attribute: 'data-mui-color-scheme', modeStorageKey: 'mui-mode', @@ -28,7 +31,8 @@ const { return newTheme; }, shouldSkipGeneratingVar: (keys) => - !!keys[0].match(/(typography|mixins|breakpoints|direction|transitions)/), + !!keys[0].match(/(typography|mixins|breakpoints|direction|transitions)/) || + (keys[0] === 'palette' && !!keys[1]?.match(/(mode|contrastThreshold|tonalOffset)/)), }); export { useColorScheme, getInitColorSchemeScript, Experimental_CssVarsProvider }; diff --git a/packages/mui-material/src/styles/createPalette.d.ts b/packages/mui-material/src/styles/createPalette.d.ts index 22fe76f2500fae..5e28388e36a8bb 100644 --- a/packages/mui-material/src/styles/createPalette.d.ts +++ b/packages/mui-material/src/styles/createPalette.d.ts @@ -105,95 +105,6 @@ export interface Channels { contrastTextChannel: string; } -export interface PaletteWithChannels { - common: CommonColors & { - background: string; - onBackground: string; - backgroundChannel: string; - onBackgroundChannel: string; - }; - mode: PaletteMode; - contrastThreshold: number; - tonalOffset: PaletteTonalOffset; - primary: PaletteColor & Channels; - secondary: PaletteColor & Channels; - error: PaletteColor & Channels; - warning: PaletteColor & Channels; - info: PaletteColor & Channels; - success: PaletteColor & Channels; - grey: Color & { darkChannel: string }; - text: TypeText & { primaryChannel: string; secondaryChannel: string }; - divider: TypeDivider; - dividerChannel: TypeDivider; - action: TypeAction & { activeChannel: string; selectedChannel: string }; - background: TypeBackground; - getContrastText: (background: string) => string; - augmentColor: (options: PaletteAugmentColorOptions) => PaletteColor; - // component tokens - AppBar: { - defaultBg: string; - darkBg: string; - darkColor: string; - }; - Avatar: { - defaultBg: string; - }; - Chip: { - defaultBorder: string; - defaultAvatarColor: string; - defaultIconColor: string; - }; - FilledInput: { - bg: string; - hoverBg: string; - disabledBg: string; - }; - LinearProgress: { - primaryBg: string; - secondaryBg: string; - errorBg: string; - infoBg: string; - successBg: string; - warningBg: string; - }; - Slider: { - primaryTrack: string; - secondaryTrack: string; - errorTrack: string; - infoTrack: string; - successTrack: string; - warningTrack: string; - }; - SnackbarContent: { - bg: string; - }; - SpeedDialAction: { - fabHoverBg: string; - }; - StepConnector: { - border: string; - }; - StepContent: { - border: string; - }; - Switch: { - defaultColor: string; - defaultDisabledColor: string; - primaryDisabledColor: string; - secondaryDisabledColor: string; - errorDisabledColor: string; - infoDisabledColor: string; - successDisabledColor: string; - warningDisabledColor: string; - }; - TableCell: { - border: string; - }; - Tooltip: { - bg: string; - }; -} - export type PartialTypeObject = { [P in keyof TypeObject]?: Partial }; export interface PaletteOptions { diff --git a/packages/mui-material/src/styles/createPalette.spec.ts b/packages/mui-material/src/styles/createPalette.spec.ts index e7d73a2ed7e770..1bcfc61c8cd254 100644 --- a/packages/mui-material/src/styles/createPalette.spec.ts +++ b/packages/mui-material/src/styles/createPalette.spec.ts @@ -17,5 +17,5 @@ import { createTheme, Theme } from '@mui/material/styles'; } { - const themeCommons: Theme['palette']['common'] = common; + const themeCommons: Pick = common; } diff --git a/packages/mui-material/src/styles/experimental_extendTheme.d.ts b/packages/mui-material/src/styles/experimental_extendTheme.d.ts index 94e49691f1aa05..a8af5506ca007f 100644 --- a/packages/mui-material/src/styles/experimental_extendTheme.d.ts +++ b/packages/mui-material/src/styles/experimental_extendTheme.d.ts @@ -1,12 +1,9 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { ThemeOptions as SystemThemeOptions, Theme as SystemTheme } from '@mui/system'; import { OverridableStringUnion } from '@mui/types'; -import { Mixins, MixinsOptions } from './createMixins'; +import { ThemeOptions, Theme } from './createTheme'; import { Palette, PaletteOptions } from './createPalette'; -import { Typography, TypographyOptions } from './createTypography'; import { Shadows } from './shadows'; -import { Transitions, TransitionsOptions } from './createTransitions'; -import { ZIndex, ZIndexOptions } from './zIndex'; +import { ZIndex } from './zIndex'; import { Components } from './components'; /** @@ -35,8 +32,8 @@ export type ExtendedColorScheme = OverridableStringUnion { - mixins?: MixinsOptions; - components?: Components; - colorSchemes?: Record< - SupportedColorScheme, - { - palette?: PaletteOptions; - opacity?: Partial; - overlays?: Overlays; - } - >; - shadows?: Shadows; - transitions?: TransitionsOptions; - typography?: TypographyOptions | ((palette: Palette) => TypographyOptions); - zIndex?: ZIndexOptions; - unstable_strictMode?: boolean; +export interface PaletteCommonChannel { + background: string; + backgroundChannel: string; + onBackground: string; + onBackgroundChannel: string; +} + +export interface PaletteColorChannel { + mainChannel: string; + lightChannel: string; + darkChannel: string; + contrastTextChannel: string; +} + +export interface PaletteActionChannel { + activeChannel: string; + selectedChannel: string; +} + +export interface PaletteTextChannel { + primaryChannel: string; + secondaryChannel: string; +} + +export interface PaletteAlert { + errorColor: string; + infoColor: string; + successColor: string; + warningColor: string; + errorFilledBg: string; + infoFilledBg: string; + successFilledBg: string; + warningFilledBg: string; + errorFilledColor: string; + infoFilledColor: string; + successFilledColor: string; + warningFilledColor: string; + errorStandardBg: string; + infoStandardBg: string; + successStandardBg: string; + warningStandardBg: string; + errorIconColor: string; + infoIconColor: string; + successIconColor: string; + warningIconColor: string; +} + +export interface PaletteAppBar { + defaultBg: string; + darkBg: string; + darkColor: string; +} + +export interface PaletteAvatar { + defaultBg: string; +} + +export interface PaletteChip { + defaultBorder: string; + defaultAvatarColor: string; + defaultIconColor: string; +} + +export interface PaletteFilledInput { + bg: string; + hoverBg: string; + disabledBg: string; +} + +export interface PaletteLinearProgress { + primaryBg: string; + secondaryBg: string; + errorBg: string; + infoBg: string; + successBg: string; + warningBg: string; +} + +export interface PaletteSkeleton { + bg: string; +} + +export interface PaletteSlider { + primaryTrack: string; + secondaryTrack: string; + errorTrack: string; + infoTrack: string; + successTrack: string; + warningTrack: string; +} + +export interface PaletteSnackbarContent { + bg: string; +} + +export interface PaletteSpeedDialAction { + fabHoverBg: string; +} + +export interface PaletteStepConnector { + border: string; +} + +export interface PaletteStepContent { + border: string; +} + +export interface PaletteSwitch { + defaultColor: string; + defaultDisabledColor: string; + primaryDisabledColor: string; + secondaryDisabledColor: string; + errorDisabledColor: string; + infoDisabledColor: string; + successDisabledColor: string; + warningDisabledColor: string; +} + +export interface PaletteTableCell { + border: string; +} + +export interface PaletteTooltip { + bg: string; +} + +// The Palette should be sync with `../themeCssVarsAugmentation/index.d.ts` +export interface ColorSystemOptions { + palette?: Omit & { + common?: Partial; + primary?: Partial; + secondary?: Partial; + error?: Partial; + info?: Partial; + success?: Partial; + text?: Partial; + dividerChannel?: Partial; + action?: Partial; + Alert?: Partial; + AppBar?: Partial; + Avatar?: Partial; + Chip?: Partial; + FilledInput?: Partial; + LinearProgress?: Partial; + Skeleton?: Partial; + Slider?: Partial; + SnackbarContent?: Partial; + SpeedDialAction?: Partial; + StepConnector?: Partial; + StepContent?: Partial; + Switch?: Partial; + TableCell?: Partial; + Tooltip?: Partial; + }; + opacity?: Partial; + overlays?: Overlays; +} + +// The Palette should be sync with `../themeCssVarsAugmentation/index.d.ts` +export interface ColorSystem { + palette: Palette & { + colorScheme: SupportedColorScheme; + common: PaletteCommonChannel; + primary: PaletteColorChannel; + secondary: PaletteColorChannel; + error: PaletteColorChannel; + info: PaletteColorChannel; + success: PaletteColorChannel; + text: PaletteTextChannel; + dividerChannel: string; + action: PaletteActionChannel; + Alert: PaletteAlert; + AppBar: PaletteAppBar; + Avatar: PaletteAvatar; + Chip: PaletteChip; + FilledInput: PaletteFilledInput; + LinearProgress: PaletteLinearProgress; + Skeleton: PaletteSkeleton; + Slider: PaletteSlider; + SnackbarContent: PaletteSnackbarContent; + SpeedDialAction: PaletteSpeedDialAction; + StepConnector: PaletteStepConnector; + StepContent: PaletteStepContent; + Switch: PaletteSwitch; + TableCell: PaletteTableCell; + Tooltip: PaletteTooltip; + }; + opacity: Opacity; + overlays: Overlays; +} + +export interface CssVarsThemeOptions extends Omit { + components?: Components>; + colorSchemes?: Partial>; } -interface BaseTheme extends SystemTheme { - mixins: Mixins; - palette: Palette; +// should not include keys defined in `shouldSkipGeneratingVar` and have value typeof function +interface ThemeVars { + palette: Omit< + ColorSystem['palette'], + | 'colorScheme' + | 'mode' + | 'contrastThreshold' + | 'tonalOffset' + | 'getContrastText' + | 'augmentColor' + >; opacity: Opacity; overlays: Overlays; shadows: Shadows; - transitions: Transitions; - typography: Typography; zIndex: ZIndex; - unstable_strictMode?: boolean; - colorSchemes: Record; + shape: Theme['shape']; } -// shut off automatic exporting for the `BaseTheme` above +// shut off automatic exporting for the `ThemeVars` above export {}; -/** - * Our [TypeScript guide on theme customization](https://mui.com/material-ui/guides/typescript/#customization-of-theme) explains in detail how you would add custom properties. - */ -export interface Theme extends BaseTheme { - components?: Components; +export interface CssVarsTheme extends Omit, ColorSystem { + components?: Components>; + colorSchemes: Record; + prefix: string; + vars: ThemeVars; + getCssVar: ( + field: string | CustomVar, + ...vars: Array + ) => string; + getColorSchemeSelector: (colorScheme: SupportedColorScheme) => string; } /** @@ -114,4 +299,7 @@ export interface Theme extends BaseTheme { * @param args Deep merge the arguments with the about to be returned theme. * @returns A complete, ready-to-use theme object. */ -export default function experimental_extendTheme(options?: ThemeOptions, ...args: object[]): Theme; +export default function experimental_extendTheme( + options?: CssVarsThemeOptions, + ...args: object[] +): CssVarsTheme; diff --git a/packages/mui-material/src/styles/experimental_extendTheme.js b/packages/mui-material/src/styles/experimental_extendTheme.js index 3ca76fa36c4bf1..d2184c2ad5eed8 100644 --- a/packages/mui-material/src/styles/experimental_extendTheme.js +++ b/packages/mui-material/src/styles/experimental_extendTheme.js @@ -43,7 +43,7 @@ export default function extendTheme(options = {}, ...args) { palette: lightPalette, opacity: { inputPlaceholder: 0.42, - inputTouchBottomLine: 0.42, + inputUnderline: 0.42, switchTrackDisabled: 0.12, switchTrack: 0.38, ...colorSchemesInput.light?.opacity, @@ -55,7 +55,7 @@ export default function extendTheme(options = {}, ...args) { palette: darkPalette, opacity: { inputPlaceholder: 0.5, - inputTouchBottomLine: 0.7, + inputUnderline: 0.7, switchTrackDisabled: 0.2, switchTrack: 0.3, ...colorSchemesInput.dark?.opacity, @@ -79,6 +79,7 @@ export default function extendTheme(options = {}, ...args) { // assign component variables assignNode(palette, [ + 'Alert', 'AppBar', 'Avatar', 'Chip', @@ -95,6 +96,34 @@ export default function extendTheme(options = {}, ...args) { 'Tooltip', ]); if (key === 'light') { + setColor(palette.Alert, 'errorColor', darken(palette.error.light, 0.6)); + setColor(palette.Alert, 'infoColor', darken(palette.info.light, 0.6)); + setColor(palette.Alert, 'successColor', darken(palette.success.light, 0.6)); + setColor(palette.Alert, 'warningColor', darken(palette.warning.light, 0.6)); + setColor(palette.Alert, 'errorFilledBg', 'var(--mui-palette-error-main)'); + setColor(palette.Alert, 'infoFilledBg', 'var(--mui-palette-info-main)'); + setColor(palette.Alert, 'successFilledBg', 'var(--mui-palette-success-main)'); + setColor(palette.Alert, 'warningFilledBg', 'var(--mui-palette-warning-main)'); + setColor(palette.Alert, 'errorFilledColor', lightPalette.getContrastText(palette.error.main)); + setColor(palette.Alert, 'infoFilledColor', lightPalette.getContrastText(palette.info.main)); + setColor( + palette.Alert, + 'successFilledColor', + lightPalette.getContrastText(palette.success.main), + ); + setColor( + palette.Alert, + 'warningFilledColor', + lightPalette.getContrastText(palette.warning.main), + ); + setColor(palette.Alert, 'errorStandardBg', lighten(palette.error.light, 0.9)); + setColor(palette.Alert, 'infoStandardBg', lighten(palette.info.light, 0.9)); + setColor(palette.Alert, 'successStandardBg', lighten(palette.success.light, 0.9)); + setColor(palette.Alert, 'warningStandardBg', lighten(palette.warning.light, 0.9)); + setColor(palette.Alert, 'errorIconColor', 'var(--mui-palette-error-light)'); + setColor(palette.Alert, 'infoIconColor', 'var(--mui-palette-info-light)'); + setColor(palette.Alert, 'successIconColor', 'var(--mui-palette-success-light)'); + setColor(palette.Alert, 'warningIconColor', 'var(--mui-palette-warning-light)'); setColor(palette.AppBar, 'defaultBg', 'var(--mui-palette-grey-100)'); setColor(palette.Avatar, 'defaultBg', 'var(--mui-palette-grey-400)'); setColor(palette.Chip, 'defaultBorder', 'var(--mui-palette-grey-400)'); @@ -131,6 +160,34 @@ export default function extendTheme(options = {}, ...args) { setColor(palette.TableCell, 'border', lighten(alpha(palette.divider, 1), 0.88)); setColor(palette.Tooltip, 'bg', alpha(palette.grey[700], 0.92)); } else { + setColor(palette.Alert, 'errorColor', lighten(palette.error.light, 0.6)); + setColor(palette.Alert, 'infoColor', lighten(palette.info.light, 0.6)); + setColor(palette.Alert, 'successColor', lighten(palette.success.light, 0.6)); + setColor(palette.Alert, 'warningColor', lighten(palette.warning.light, 0.6)); + setColor(palette.Alert, 'errorFilledBg', 'var(--mui-palette-error-dark)'); + setColor(palette.Alert, 'infoFilledBg', 'var(--mui-palette-info-dark)'); + setColor(palette.Alert, 'successFilledBg', 'var(--mui-palette-success-dark)'); + setColor(palette.Alert, 'warningFilledBg', 'var(--mui-palette-warning-dark)'); + setColor(palette.Alert, 'errorFilledColor', darkPalette.getContrastText(palette.error.dark)); + setColor(palette.Alert, 'infoFilledColor', darkPalette.getContrastText(palette.info.dark)); + setColor( + palette.Alert, + 'successFilledColor', + darkPalette.getContrastText(palette.success.dark), + ); + setColor( + palette.Alert, + 'warningFilledColor', + darkPalette.getContrastText(palette.warning.dark), + ); + setColor(palette.Alert, 'errorStandardBg', darken(palette.error.light, 0.9)); + setColor(palette.Alert, 'infoStandardBg', darken(palette.info.light, 0.9)); + setColor(palette.Alert, 'successStandardBg', darken(palette.success.light, 0.9)); + setColor(palette.Alert, 'warningStandardBg', darken(palette.warning.light, 0.9)); + setColor(palette.Alert, 'errorIconColor', 'var(--mui-palette-error-main)'); + setColor(palette.Alert, 'infoIconColor', 'var(--mui-palette-info-main)'); + setColor(palette.Alert, 'successIconColor', 'var(--mui-palette-success-main)'); + setColor(palette.Alert, 'warningIconColor', 'var(--mui-palette-warning-main)'); setColor(palette.AppBar, 'defaultBg', 'var(--mui-palette-grey-900)'); setColor(palette.AppBar, 'darkBg', 'var(--mui-palette-background-paper)'); // specific for dark mode setColor(palette.AppBar, 'darkColor', 'var(--mui-palette-text-primary)'); // specific for dark mode diff --git a/packages/mui-material/src/styles/experimental_extendTheme.test.js b/packages/mui-material/src/styles/experimental_extendTheme.test.js index a0c27dd65e8d13..57dd62f51bc7f5 100644 --- a/packages/mui-material/src/styles/experimental_extendTheme.test.js +++ b/packages/mui-material/src/styles/experimental_extendTheme.test.js @@ -203,13 +203,13 @@ describe('experimental_extendTheme', () => { const theme = extendTheme(); expect(theme.colorSchemes.light.opacity).to.deep.equal({ inputPlaceholder: 0.42, - inputTouchBottomLine: 0.42, + inputUnderline: 0.42, switchTrackDisabled: 0.12, switchTrack: 0.38, }); expect(theme.colorSchemes.dark.opacity).to.deep.equal({ inputPlaceholder: 0.5, - inputTouchBottomLine: 0.7, + inputUnderline: 0.7, switchTrackDisabled: 0.2, switchTrack: 0.3, }); @@ -232,11 +232,11 @@ describe('experimental_extendTheme', () => { }); expect(theme.colorSchemes.light.opacity).to.deep.include({ inputPlaceholder: 1, - inputTouchBottomLine: 0.42, + inputUnderline: 0.42, }); expect(theme.colorSchemes.dark.opacity).to.deep.include({ inputPlaceholder: 0.2, - inputTouchBottomLine: 0.7, + inputUnderline: 0.7, }); }); }); diff --git a/packages/mui-material/src/styles/index.d.ts b/packages/mui-material/src/styles/index.d.ts index eb9d652af76161..19c63d6e1dabde 100644 --- a/packages/mui-material/src/styles/index.d.ts +++ b/packages/mui-material/src/styles/index.d.ts @@ -94,4 +94,27 @@ export { default as withTheme } from './withTheme'; export * from './CssVarsProvider'; export { default as experimental_extendTheme } from './experimental_extendTheme'; -export * from './experimental_extendTheme'; +export type { + ColorSchemeOverrides, + SupportedColorScheme, + Opacity, + Overlays, + PaletteActionChannel, + PaletteAppBar, + PaletteAvatar, + PaletteChip, + PaletteColorChannel, + PaletteCommonChannel, + PaletteFilledInput, + PaletteLinearProgress, + PaletteSlider, + PaletteSnackbarContent, + PaletteStepConnector, + PaletteStepContent, + PaletteSwitch, + PaletteTableCell, + PaletteTextChannel, + PaletteTooltip, + CssVarsThemeOptions, + CssVarsTheme, +} from './experimental_extendTheme'; diff --git a/packages/mui-material/src/themeCssVarsAugmentation/index.d.ts b/packages/mui-material/src/themeCssVarsAugmentation/index.d.ts new file mode 100644 index 00000000000000..6941f947756341 --- /dev/null +++ b/packages/mui-material/src/themeCssVarsAugmentation/index.d.ts @@ -0,0 +1,61 @@ +import type { + CssVarsTheme, + ColorSystem, + PaletteCommonChannel, + PaletteColorChannel, + PaletteTextChannel, + PaletteActionChannel, + PaletteAppBar, + PaletteAvatar, + PaletteChip, + PaletteFilledInput, + PaletteLinearProgress, + PaletteSlider, + PaletteSnackbarContent, + PaletteStepConnector, + PaletteStepContent, + PaletteSwitch, + PaletteTableCell, + PaletteTooltip, +} from '../styles/experimental_extendTheme'; + +/** + * Enhance the theme types to include new properties from the CssVarsProvider. + * The theme is typed with CSS variables in `styled`, `sx`, `useTheme`, etc. + */ +declare module '@mui/material/styles' { + // The palette must be extended in each node. + interface Theme extends Omit { + prefix: string; + vars: CssVarsTheme['vars']; + getCssVar: CssVarsTheme['getCssVar']; + getColorSchemeSelector: CssVarsTheme['getColorSchemeSelector']; + } + + // The extended Palette should be in sync with `extendTheme` + interface Palette { + dividerChannel: string; + AppBar: PaletteAppBar; + Avatar: PaletteAvatar; + Chip: PaletteChip; + FilledInput: PaletteFilledInput; + LinearProgress: PaletteLinearProgress; + Slider: PaletteSlider; + SnackbarContent: PaletteSnackbarContent; + StepConnector: PaletteStepConnector; + StepContent: PaletteStepContent; + Switch: PaletteSwitch; + TableCell: PaletteTableCell; + Tooltip: PaletteTooltip; + } +} + +declare module '@mui/material/styles/createPalette' { + interface CommonColors extends PaletteCommonChannel {} + + interface PaletteColor extends PaletteColorChannel {} + + interface TypeText extends PaletteTextChannel {} + + interface TypeAction extends PaletteActionChannel {} +} diff --git a/packages/mui-material/test/typescript/moduleAugmentation/themeCssVariables.spec.tsx b/packages/mui-material/test/typescript/moduleAugmentation/themeCssVariables.spec.tsx new file mode 100644 index 00000000000000..089272e6e61d38 --- /dev/null +++ b/packages/mui-material/test/typescript/moduleAugmentation/themeCssVariables.spec.tsx @@ -0,0 +1,45 @@ +// testing docs/src/pages/customization/theme-components/theme-components.md +import { styled, experimental_extendTheme as extendTheme } from '@mui/material/styles'; +import type {} from '@mui/material/themeCssVarsAugmentation'; + +declare module '@mui/material/styles' { + interface PaletteOptions { + gradient: { + default: string; + }; + } + + interface Palette { + gradient: { + default: string; + }; + } +} + +const StyledComponent = styled('button')(({ theme }) => ({ + background: theme.vars.palette.gradient.default, +})); + +const StyledComponent2 = styled('button')(({ theme }) => ({ + // @ts-expect-error `default2` is not defined + background: theme.vars.palette.gradient.default2, +})); + +const theme = extendTheme({ + colorSchemes: { + light: { + palette: { + gradient: { + default: '', + }, + }, + }, + dark: { + palette: { + gradient: { + default: '', + }, + }, + }, + }, +}); diff --git a/packages/mui-material/test/typescript/moduleAugmentation/themeCssVariables.tsconfig.json b/packages/mui-material/test/typescript/moduleAugmentation/themeCssVariables.tsconfig.json new file mode 100644 index 00000000000000..46d8e363821a69 --- /dev/null +++ b/packages/mui-material/test/typescript/moduleAugmentation/themeCssVariables.tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../../../../tsconfig", + "files": ["themeCssVariables.spec.tsx"] +} diff --git a/packages/mui-system/package.json b/packages/mui-system/package.json index 98a13aa22815a6..742f0747298699 100644 --- a/packages/mui-system/package.json +++ b/packages/mui-system/package.json @@ -1,6 +1,6 @@ { "name": "@mui/system", - "version": "5.8.4", + "version": "5.8.5", "private": false, "author": "MUI Team", "description": "CSS utilities for rapidly laying out custom designs.", diff --git a/packages/mui-system/src/cssVars/createCssVarsProvider.js b/packages/mui-system/src/cssVars/createCssVarsProvider.js index 8bdc1b88d46ea8..a6046484906089 100644 --- a/packages/mui-system/src/cssVars/createCssVarsProvider.js +++ b/packages/mui-system/src/cssVars/createCssVarsProvider.js @@ -305,6 +305,7 @@ export default function createCssVarsProvider(options) { attribute: defaultAttribute, colorSchemeStorageKey: defaultColorSchemeStorageKey, modeStorageKey: defaultModeStorageKey, + enableColorScheme: designSystemEnableColorScheme, ...params, }); diff --git a/packages/mui-system/src/cssVars/getInitColorSchemeScript.tsx b/packages/mui-system/src/cssVars/getInitColorSchemeScript.tsx index 7660a81d353582..100e04d2d2937a 100644 --- a/packages/mui-system/src/cssVars/getInitColorSchemeScript.tsx +++ b/packages/mui-system/src/cssVars/getInitColorSchemeScript.tsx @@ -5,6 +5,11 @@ export const DEFAULT_COLOR_SCHEME_STORAGE_KEY = 'color-scheme'; export const DEFAULT_ATTRIBUTE = 'data-color-scheme'; export interface GetInitColorSchemeScriptOptions { + /** + * Indicate to the browser which color scheme is used (light or dark) for rendering built-in UI + * @default true + */ + enableColorScheme?: boolean; /** * If `true`, the initial color scheme is set to the user's prefers-color-scheme mode * @default false @@ -42,6 +47,7 @@ export interface GetInitColorSchemeScriptOptions { export default function getInitColorSchemeScript(options?: GetInitColorSchemeScriptOptions) { const { + enableColorScheme = true, enableSystem = false, defaultLightColorScheme = 'light', defaultDarkColorScheme = 'dark', @@ -56,13 +62,16 @@ export default function getInitColorSchemeScript(options?: GetInitColorSchemeScr dangerouslySetInnerHTML={{ __html: `(function() { try { var mode = localStorage.getItem('${modeStorageKey}'); + var cssColorScheme = mode; var colorScheme = ''; if (mode === 'system' || (!mode && !!${enableSystem})) { // handle system mode var mql = window.matchMedia('(prefers-color-scheme: dark)'); if (mql.matches) { + cssColorScheme = 'dark'; colorScheme = localStorage.getItem('${colorSchemeStorageKey}-dark') || '${defaultDarkColorScheme}'; } else { + cssColorScheme = 'light'; colorScheme = localStorage.getItem('${colorSchemeStorageKey}-light') || '${defaultLightColorScheme}'; } } @@ -75,6 +84,9 @@ export default function getInitColorSchemeScript(options?: GetInitColorSchemeScr if (colorScheme) { ${colorSchemeNode}.setAttribute('${attribute}', colorScheme); } + if (${enableColorScheme} && !!cssColorScheme) { + ${colorSchemeNode}.style.setProperty('color-scheme', cssColorScheme); + } } catch (e) {} })();`, }} /> diff --git a/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.test.ts b/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.test.ts index ec4a28cb0b510b..acf655563d8925 100644 --- a/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.test.ts +++ b/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.test.ts @@ -48,4 +48,8 @@ describe('generateUtilityClass', () => { expect(generateUtilityClass('MuiTest', 'selected')).to.equal('Mui-selected'); }); }); + + it('custom state prefix', () => { + expect(generateUtilityClass('JoyButton', 'focusVisible', 'Joy')).to.equal('Joy-focusVisible'); + }); }); diff --git a/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.ts b/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.ts index 711436453acfe3..4d5def219b690c 100644 --- a/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.ts +++ b/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.ts @@ -13,19 +13,25 @@ export type GlobalStateSlot = | 'selected'; const globalStateClassesMapping: Record = { - active: 'Mui-active', - checked: 'Mui-checked', - completed: 'Mui-completed', - disabled: 'Mui-disabled', - error: 'Mui-error', - expanded: 'Mui-expanded', - focused: 'Mui-focused', - focusVisible: 'Mui-focusVisible', - required: 'Mui-required', - selected: 'Mui-selected', + active: 'active', + checked: 'checked', + completed: 'completed', + disabled: 'disabled', + error: 'error', + expanded: 'expanded', + focused: 'focused', + focusVisible: 'focusVisible', + required: 'required', + selected: 'selected', }; -export default function generateUtilityClass(componentName: string, slot: string): string { +export default function generateUtilityClass( + componentName: string, + slot: string, + globalStatePrefix = 'Mui', +): string { const globalStateClass = globalStateClassesMapping[slot as GlobalStateSlot]; - return globalStateClass || `${ClassNameGenerator.generate(componentName)}-${slot}`; + return globalStateClass + ? `${globalStatePrefix}-${globalStateClass}` + : `${ClassNameGenerator.generate(componentName)}-${slot}`; } diff --git a/packages/mui-utils/src/generateUtilityClasses/generateUtilityClasses.ts b/packages/mui-utils/src/generateUtilityClasses/generateUtilityClasses.ts index 61973f3aa9a26c..235916d2ea8f1e 100644 --- a/packages/mui-utils/src/generateUtilityClasses/generateUtilityClasses.ts +++ b/packages/mui-utils/src/generateUtilityClasses/generateUtilityClasses.ts @@ -3,11 +3,12 @@ import generateUtilityClass from '../generateUtilityClass'; export default function generateUtilityClasses( componentName: string, slots: T[], + globalStatePrefix = 'Mui', ): Record { const result: Record = {}; slots.forEach((slot) => { - result[slot] = generateUtilityClass(componentName, slot); + result[slot] = generateUtilityClass(componentName, slot, globalStatePrefix); }); return result; diff --git a/packages/typescript-to-proptypes/package.json b/packages/typescript-to-proptypes/package.json index cc0748b0867a5d..9cc9040d47100d 100644 --- a/packages/typescript-to-proptypes/package.json +++ b/packages/typescript-to-proptypes/package.json @@ -23,7 +23,7 @@ "@types/babel__core": "^7.1.19", "@types/doctrine": "^0.0.5", "@types/lodash": "^4.14.182", - "@types/node": "^16.11.39", + "@types/node": "^16.11.41", "@types/prettier": "^2.6.3", "@types/react": "^17.0.45", "@types/uuid": "^8.3.4", diff --git a/test/utils/createDOM.js b/test/utils/createDOM.js index 050e84a9bad60a..7a54d74d369f91 100644 --- a/test/utils/createDOM.js +++ b/test/utils/createDOM.js @@ -16,6 +16,7 @@ const whitelist = [ 'Node', 'Performance', 'document', + 'DocumentFragment', ]; const blacklist = ['sessionStorage', 'localStorage']; diff --git a/yarn.lock b/yarn.lock index e302f39171b588..5b427ae4c7f549 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1212,62 +1212,54 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@chakra-ui/color-mode@1.4.8": - version "1.4.8" - resolved "https://registry.yarnpkg.com/@chakra-ui/color-mode/-/color-mode-1.4.8.tgz#e5367b909f5b4c782b239f9d37d4cf1a44c28559" - integrity sha512-iD4126DVQi06c6ARr3uf3R2rtEu8aBVjW8rhZ+lOsV26Z15iCJA7OAut13Xu06fcZvgjSB/ChDy6Sx9sV9UjHA== +"@chakra-ui/color-mode@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@chakra-ui/color-mode/-/color-mode-2.0.4.tgz#143c1c0baa5f8b21a491776fc58107675075c5f8" + integrity sha512-DIR6CSPlkmi92LDR3IhjIediLk7GFWttlTUvJQP06ZUvN+iCpd5TjgchxOYzqlP4T9W0L62eZXsluOxmRF/JSQ== dependencies: - "@chakra-ui/hooks" "1.9.1" - "@chakra-ui/react-env" "1.1.6" - "@chakra-ui/utils" "1.10.4" + "@chakra-ui/hooks" "2.0.2" + "@chakra-ui/utils" "2.0.2" -"@chakra-ui/hooks@1.9.1": - version "1.9.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/hooks/-/hooks-1.9.1.tgz#7a00659e6bb4d56cf56022071eca0b77a7df1ac1" - integrity sha512-SEeh1alDKzrP9gMLWMnXOUDBQDKF/URL6iTmkumTn6vhawWNla6sPrcMyoCzWdMzwUhZp3QNtCKbUm7dxBXvPw== +"@chakra-ui/hooks@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@chakra-ui/hooks/-/hooks-2.0.2.tgz#6153f33957f23b8f156b7ce4ce1605f89e67c1b5" + integrity sha512-3B4zsl51tevmO6T6xUKcclwxf4FClKtScaNvb8jMmVczTGRL7WhZ6LxXeYUJMms11C8W9uZczE5yXSP0qweeAw== dependencies: - "@chakra-ui/react-utils" "1.2.3" - "@chakra-ui/utils" "1.10.4" + "@chakra-ui/react-utils" "2.0.1" + "@chakra-ui/utils" "2.0.2" compute-scroll-into-view "1.0.14" copy-to-clipboard "3.3.1" -"@chakra-ui/react-env@1.1.6": - version "1.1.6" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-env/-/react-env-1.1.6.tgz#9915b02fd1f8ca62ccf578eaec793f1c4dea78b0" - integrity sha512-L90LNvCfe04FTkN9OPok/o2e60zLJNBH8Im/5dUHvqy7dXLXok8ZDad5vEL46XmGbhe7O8fbxhG6FmAYdcCHrQ== - dependencies: - "@chakra-ui/utils" "1.10.4" - -"@chakra-ui/react-utils@1.2.3": - version "1.2.3" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-utils/-/react-utils-1.2.3.tgz#3356c9299bc8faada8fac6c5886ca65ec95bb5be" - integrity sha512-r8pUwCVVB7UPhb0AiRa9ZzSp4xkMz64yIeJ4O4aGy4WMw7TRH4j4QkbkE1YC9tQitrXrliOlvx4WWJR4VyiGpw== +"@chakra-ui/react-utils@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@chakra-ui/react-utils/-/react-utils-2.0.1.tgz#aebf12ee9f71fb7a27183d556131177f9ce745c8" + integrity sha512-xLiTn7WeUo2e3zvo8zUGpICgIGsLCPpkVbjEKhr1jAV41urqEtwlLc6uGir595OYqAC8zFDqs4HXhHouqNEtiw== dependencies: - "@chakra-ui/utils" "^1.10.4" + "@chakra-ui/utils" "^2.0.2" -"@chakra-ui/styled-system@1.19.0": - version "1.19.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/styled-system/-/styled-system-1.19.0.tgz#102fadaefc1a2dfd8e0c4837eafa660531a08419" - integrity sha512-z+bMfWs6jQGkpgarge1kmk78DuDhJIXRUMyRqZ3+CiIkze88bIIsww6mV2i8tEfUfTAvALeMnlYZ1DYsHsTTJw== +"@chakra-ui/styled-system@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@chakra-ui/styled-system/-/styled-system-2.2.0.tgz#d7fdca558db05100ea26ae8352b13c5840da9cc3" + integrity sha512-5THQlrMr6CsiulNtjzZV3DqYD85eQ+S8G6rsnjAKqFVJ1G29R392RKK/67R96WIRUJRtsHPq2REeTgAxGLDhOQ== dependencies: - "@chakra-ui/utils" "1.10.4" - csstype "3.0.9" + "@chakra-ui/utils" "2.0.2" + csstype "^3.0.11" -"@chakra-ui/system@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/system/-/system-1.12.1.tgz#608655ef3f7cb82eedd8f20d2546458d90d77cce" - integrity sha512-Rp09/rMuPA3hF38OJxeQciGO9N0Ie1GxwHRAw1AFA/TY3fVyK9pNI5oN+J/1cAxq7v9yKdIr1YfnruJTI9xfEg== +"@chakra-ui/system@^2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@chakra-ui/system/-/system-2.1.3.tgz#a140335f56087f761d0a8cef6e4c77f971f054da" + integrity sha512-f9GfJr7HGxxhyAbXmka/k/mPsLl8wl+5fZUWglfRg4iddmsuYQcJEYg8+ewCyr7MA1Ddw9bPVgsC5uf/KYlo3w== dependencies: - "@chakra-ui/color-mode" "1.4.8" - "@chakra-ui/react-utils" "1.2.3" - "@chakra-ui/styled-system" "1.19.0" - "@chakra-ui/utils" "1.10.4" + "@chakra-ui/color-mode" "2.0.4" + "@chakra-ui/react-utils" "2.0.1" + "@chakra-ui/styled-system" "2.2.0" + "@chakra-ui/utils" "2.0.2" react-fast-compare "3.2.0" -"@chakra-ui/utils@1.10.4", "@chakra-ui/utils@^1.10.4": - version "1.10.4" - resolved "https://registry.yarnpkg.com/@chakra-ui/utils/-/utils-1.10.4.tgz#40a32d4efd8684b2e7432a40b285796383eacfd3" - integrity sha512-AM91VQQxw8F4F1WDA28mqKY6NFIOuzc2Ekkna88imy2OiqqmYH0xkq8J16L2qj4cLiLozpYqba3C79pWioy6FA== +"@chakra-ui/utils@2.0.2", "@chakra-ui/utils@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@chakra-ui/utils/-/utils-2.0.2.tgz#130ba1647ea2b94ad956ae4cbcf685838d350593" + integrity sha512-9AC/ir9zm0shgFG7kdzOKUH2Wx5VB71M3uRMEsMZf75YlhhiU7AvBNtWXnJu+CBiTi41rKa5A+2ImMOsuPfGbA== dependencies: "@types/lodash.mergewith" "4.6.6" css-box-model "1.2.1" @@ -2329,10 +2321,10 @@ dependencies: "@types/react" "*" -"@mdx-js/react@^2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-2.1.1.tgz#c59d844fd61b776fea8673fb77405d4e14db48c5" - integrity sha512-7zlZDf5xmWH8I0kFE4DG91COOkxjaW9DX5f1HWztZpFcVua2gJgMYfIkFaDpO/DH/tWi6Mz+OheW4194r15igg== +"@mdx-js/react@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-2.1.2.tgz#02972f170cd3ad9113ce448245c5f636bb3e750d" + integrity sha512-52e3DTJBrjsw3U51ZCdZ3N1IBaqnbzLIngCSXpKtiYiGr7PIqp3/P/+kym0MPTwBL/y9ZBmCieD8FyrXuEDrRw== dependencies: "@types/mdx" "^2.0.0" "@types/react" ">=16" @@ -3327,10 +3319,10 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== -"@types/node@*", "@types/node@>=10.0.0", "@types/node@^16.11.39": - version "16.11.39" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.39.tgz#07223cd2bc332ad9d92135e3a522eebdee3b060e" - integrity sha512-K0MsdV42vPwm9L6UwhIxMAOmcvH/1OoVkZyCgEtVu4Wx7sElGloy/W7kMBNe/oJ7V/jW9BVt1F6RahH6e7tPXw== +"@types/node@*", "@types/node@>=10.0.0", "@types/node@^16.11.41": + version "16.11.41" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.41.tgz#88eb485b1bfdb4c224d878b7832239536aa2f813" + integrity sha512-mqoYK2TnVjdkGk8qXAVGc/x9nSaTpSrFaGFm43BUH3IdoBV0nta6hYaGmdOvIMlbHJbUEVen3gvwpwovAZKNdQ== "@types/node@^14.0.1", "@types/node@^14.14.35": version "14.18.18" @@ -5731,15 +5723,15 @@ concat-stream@^2.0.0: readable-stream "^3.0.2" typedarray "^0.0.6" -concurrently@^7.2.1: - version "7.2.1" - resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-7.2.1.tgz#88b144060443403060aad46f837dd17451f7e55e" - integrity sha512-7cab/QyqipqghrVr9qZmoWbidu0nHsmxrpNqQ7r/67vfl1DWJElexehQnTH1p+87tDkihaAjM79xTZyBQh7HLw== +concurrently@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-7.2.2.tgz#4ad4a4dfd3945f668d727379de2a29502e6a531c" + integrity sha512-DcQkI0ruil5BA/g7Xy3EWySGrFJovF5RYAYxwGvv9Jf9q9B1v3jPFP2tl6axExNf1qgF30kjoNYrangZ0ey4Aw== dependencies: chalk "^4.1.0" date-fns "^2.16.1" lodash "^4.17.21" - rxjs "^6.6.3" + rxjs "^7.0.0" shell-quote "^1.7.3" spawn-command "^0.0.2-1" supports-color "^8.1.0" @@ -6229,12 +6221,7 @@ cssstyle@^2.3.0: dependencies: cssom "~0.3.6" -csstype@3.0.9: - version "3.0.9" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.9.tgz#6410af31b26bd0520933d02cbc64fce9ce3fbf0b" - integrity sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw== - -csstype@^3.0.10, csstype@^3.0.2, csstype@^3.1.0: +csstype@^3.0.10, csstype@^3.0.11, csstype@^3.0.2, csstype@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2" integrity sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA== @@ -9753,9 +9740,9 @@ jmespath@0.16.0: integrity sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw== jpeg-js@^0.4.2: - version "0.4.3" - resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.3.tgz#6158e09f1983ad773813704be80680550eff977b" - integrity sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q== + version "0.4.4" + resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.4.tgz#a9f1c6f1f9f0fa80cdb3484ed9635054d28936aa" + integrity sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" @@ -14020,10 +14007,10 @@ rollup-pluginutils@^2.3.1, rollup-pluginutils@^2.8.1: dependencies: estree-walker "^0.6.1" -rollup@^2.70.2: - version "2.70.2" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.70.2.tgz#808d206a8851628a065097b7ba2053bd83ba0c0d" - integrity sha512-EitogNZnfku65I1DD5Mxe8JYRUCy0hkK5X84IlDtUs+O6JRMpRciXTzyCUuX11b5L5pvjH+OmFXiQ3XjabcXgg== +rollup@^2.75.7: + version "2.75.7" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.75.7.tgz#221ff11887ae271e37dcc649ba32ce1590aaa0b9" + integrity sha512-VSE1iy0eaAYNCxEXaleThdFXqZJ42qDBatAwrfnPlENEZ8erQ+0LYX4JXOLPceWfZpV1VtZwZ3dFCuOZiSyFtQ== optionalDependencies: fsevents "~2.3.2" @@ -14064,13 +14051,20 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -rxjs@^6.6.0, rxjs@^6.6.3: +rxjs@^6.6.0: version "6.6.6" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.6.tgz#14d8417aa5a07c5e633995b525e1e3c0dec03b70" integrity sha512-/oTwee4N4iWzAMAL9xdGKjkEHmIwupR3oXbQjCKywF1BeFohswF3vZdogbmEF6pZkOsXTzWkrZszrWpQTByYVg== dependencies: tslib "^1.9.0" +rxjs@^7.0.0: + version "7.5.5" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.5.tgz#2ebad89af0f560f460ad5cc4213219e1f7dd4e9f" + integrity sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw== + dependencies: + tslib "^2.1.0" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"