@mui/system 7.1.0 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,158 @@
1
1
  # [Versions](https://mui.com/versions/)
2
2
 
3
+ ## 7.2.0
4
+
5
+ <!-- generated comparing v7.1.1..master -->
6
+
7
+ _Jun 26, 2025_
8
+
9
+ A big thanks to the 17 contributors who made this release possible. Here are the highlights ✨:
10
+
11
+ - ⚡️ Added `modularCssLayers` theme option for splitting styles into multiple CSS layers (#46001) @siriwatknp.
12
+ - 📖 Added example for using Material UI with React Router v7 (#46406) @siriwatknp.
13
+
14
+ ### `@mui/material@7.2.0`
15
+
16
+ - [Backdrop] Fix handling of `component` prop (#46269) @sai6855
17
+ - [Chip] Explicitly define line-height (#46260) @DiegoAndai
18
+ - [Chip] Fix handling on event handlers (#46263) @sai6855
19
+ - [OutlinedInput][Input] Deprecate composed classes (#46316) @sai6855
20
+ - [Select] Pass MenuProps.slotProps.list alongside MenuListProps (#46274) @scousino
21
+ - [l10] Enable `labelDisplayedRows` translation for Romanian (#46377) @dhu-redwoodtech
22
+ - Skip generating `modularCssLayers` CSS var (#46329) @siriwatknp
23
+
24
+ ### `@mui/system@7.2.0`
25
+
26
+ - Add `modularCssLayers` theme flag to split styles into multiple CSS layers (#46001) @siriwatknp
27
+
28
+ ### `@mui/styled-engine@7.2.0`
29
+
30
+ - Do not reuse the emotion cache across SSR requests (#46276) @robbtraister
31
+
32
+ ### `@mui/codemod@7.2.0`
33
+
34
+ - [Dialog] Add codemod for deprecated props (#46328) @sai6855
35
+
36
+ ### Docs
37
+
38
+ - Don't forward `hasAiSuggestion` (#46415) @bharatkashyap
39
+ - Add introduction to MCP (#46224) @bharatkashyap
40
+ - Fallback for searchbar during SSR (#46364) @Janpot
41
+ - Update InitColorSchemeScript options to match colorSchemeSelector (#46302) @humble-barnacle001
42
+ - Add `ListItemButton` to make the deprecation clear (#46356) @siriwatknp
43
+ - Remove "Unstyled" section from component docs (#46272) @mapache-salvaje
44
+ - Add Testing section to Rating component doc (#46268) @0210shivam
45
+ - Fix fade modal demo (#46271) @brijeshb42
46
+ - [ai] Add suggestions to edit with MUI Chat (#46309) @bharatkashyap
47
+ - [Dialog] Fix form dialog uses ARIA roles on incompatible elements (#46307) @ZeeshanTamboli
48
+ - [Menu] Fix dark mode styling of grouped header demo (#46317) @sai6855
49
+ - [TextField] Removed type="number" demos (#46314) @KirankumarAmbati
50
+ - [examples] Add `material-ui-react-router-ts` example (#46406) @siriwatknp
51
+
52
+ ### Core
53
+
54
+ - pnpm docs:sync-team (3641a0b) @oliviertassinari
55
+ - Add cross-env to eslint script (#46358) @ZeeshanTamboli
56
+ - Support merging of className and style from theme (#45975) @sai6855
57
+ - [code-infra] Create bundle size package (#45911) @Janpot
58
+ - [docs-infra] Add a script to generate Material UI `llms.txt` and docs markdown. (#46308) @siriwatknp
59
+ - [docs-infra] Fix stackblitz for js projects (#46220) @Janpot
60
+ - [infra] Add emotion as external for bundle monitor (#46372) @Janpot
61
+ - [infra] Create update PR on every canary publish for internal packages (#46367) @Janpot
62
+ - [infra] Remove deprecated esmExternals (#46365) @Janpot
63
+ - [infra] Support project-specific changelog in build scripts (#46425) @michaldudak
64
+ - [toolpad][website] Remove references to Toolpad (#46311) @prakhargupta1
65
+
66
+ All contributors of this release in alphabetical order: @0210shivam, @bharatkashyap, @brijeshb42, @dhu-redwoodtech, @DiegoAndai, @humble-barnacle001, @Janpot, @KirankumarAmbati, @mapache-salvaje, @michaldudak, @oliviertassinari, @prakhargupta1, @robbtraister, @sai6855, @scousino, @siriwatknp, @ZeeshanTamboli
67
+
68
+ ## 7.1.2
69
+
70
+ _Jun 18, 2025_
71
+
72
+ A big thanks to the 2 contributors who made this release possible.
73
+
74
+ ### `@mui/material@7.1.2`
75
+
76
+ - [Chip] Fix handling on event handlers (#46263) @sai6855
77
+
78
+ ### Docs
79
+
80
+ - Fix fade modal demo (#46271) @brijeshb42
81
+
82
+ All contributors of this release in alphabetical order: @brijeshb42, @sai6855
83
+
84
+ ## 7.1.1
85
+
86
+ <!-- generated comparing v7.1.0..master -->
87
+
88
+ _May 30, 2025_
89
+
90
+ A big thanks to the 15 contributors who made this release possible.
91
+
92
+ ### `@mui/material@7.1.1`
93
+
94
+ - [Autocomplete] Fix label shrink issue when `renderValue` is used with empty array in multiple mode (#46047) @ZeeshanTamboli
95
+ - [Autocomplete] Prevent `renderValue` from being skipped when value is 0 (#46145) @LakshitAgarwal
96
+ - [Autocomplete] Add note in JSDoc for non-TextField components in `renderInput` (#46141) @khllbnomrn
97
+ - [Chip] Add slots and slotProps (#46098) @sai6855
98
+ - [Menu] Remove depreacted `MenuListProps` from demos (#46144) @sai6855
99
+ - [TablePaginationActions] Export TablePaginationActions as new component (#46149) @sai6855
100
+ - [SnackbarContent] Fix `square` prop not working (#46196) @0210shivam
101
+ - [SnackbarContent] Fix error when theme value is CSS variable (#46198) @0210shivam
102
+
103
+ ### `@mui/codemod@7.1.1`
104
+
105
+ - Add package name option (#45977) @siriwatknp
106
+
107
+ ### `@mui/system@7.1.1`
108
+
109
+ - Skip styled component from being transformed (#46129) @siriwatknp
110
+ - Update the type for borderRadius (#46154) @codiini
111
+
112
+ ### `@mui/styled-engine@7.1.1`
113
+
114
+ - Fix variant props callback type to spread `ownerState` (#46187) @siriwatknp
115
+
116
+ ### `@mui/stylis-plugin-rtl@7.1.1`
117
+
118
+ - Fix RTL does not work with CSS layer with a new package (#46230) @siriwatknp
119
+
120
+ ### Docs
121
+
122
+ - [Dialog] Remove deprecated TransitionComponent from demo (#46185) @sai6855
123
+ - [Grid] Remove direction `column` and `column-reverse` from the demo (#46127) @0210shivam
124
+ - [Grid] Update grid migration guide (#46057) @sai6855
125
+ - [templates] Fix rendering of logos in dark mode (#46221) @sai6855
126
+ - [ToggleButtonGroup] Add spacing demo (#46058) @sai6855
127
+ - Fix typo in dark mode docs (#46229) @ZeeshanTamboli
128
+ - Clarify Next.js + Tailwind CSS v3 integration requirements (#46176) @chaitanyasharma1011
129
+ - Fix GridLegacy docs order (#46135) @oliviertassinari
130
+ - Update upgrade guide for resolution of `react-is` (#46002) @siriwatknp
131
+ - Remove oudated scaffoldhub ad (#46090) @oliviertassinari
132
+ - Show how to target global state classes with CSS Modules (#45992) @RubemMazzetto
133
+
134
+ ### Core
135
+
136
+ - [code-infra] Add plugin to check for index file access (#46178) @Janpot
137
+ - [code-infra] Bump eslint to v9 (#46222) @brijeshb42
138
+ - [code-infra] Move packages to mui/mui-public (#46155) @Janpot
139
+ - [code-infra] Move `chai` to peerDep (#46227) @JCQuintas
140
+ - [code-infra] Avoid loading barrel file during type checking (#46177) @Janpot
141
+ - [code-infra] Remove unnecessary ref from `HighlightedCode` component (#46151) @ZeeshanTamboli
142
+ - [code-infra] Import mocha type instead of global (#46108) @JCQuintas
143
+ - [code-infra] Dependabot also create branches (795a481) @oliviertassinari
144
+ - [code-infra] Avoid running continuous release on forks (#46103) @Janpot
145
+ - [code-infra] Remove checkout job altogether (#46100) @Janpot
146
+ - [code-infra] Remove required checkout workflows in circleci (#46099) @Janpot
147
+ - Run pnpm docs:sync-team (c8f1da5) @oliviertassinari
148
+ - Upgrade MUI X packages to v8 (#45990) @KenanYusuf
149
+ - Minor detail to reduce confusion (4c64b72) @oliviertassinari
150
+ - Update security.md (#45839) @DiegoAndai
151
+ - Apply yml convention, blank line only at top level (f273220) @oliviertassinari
152
+ - Add comment that lab should be in alpha (#45999) @oliviertassinari
153
+
154
+ All contributors of this release in alphabetical order: @0210shivam, @brijeshb42, @chaitanyasharma1011, @codiini, @DiegoAndai, @Janpot, @JCQuintas, @KenanYusuf, @khllbnomrn, @LakshitAgarwal, @oliviertassinari, @RubemMazzetto, @sai6855, @siriwatknp, @ZeeshanTamboli
155
+
3
156
  ## 7.1.0
4
157
 
5
158
  <!-- generated comparing v7.0.2..master -->
@@ -48,11 +48,11 @@ function getThemeProps(params) {
48
48
  const config = theme.components[name];
49
49
  if (config.defaultProps) {
50
50
  // compatible with v5 signature
51
- return (0, _resolveProps.default)(config.defaultProps, props);
51
+ return (0, _resolveProps.default)(config.defaultProps, props, theme.components.mergeClassNameAndStyle);
52
52
  }
53
53
  if (!config.styleOverrides && !config.variants) {
54
54
  // v6 signature, no property 'defaultProps'
55
- return (0, _resolveProps.default)(config, props);
55
+ return (0, _resolveProps.default)(config, props, theme.components.mergeClassNameAndStyle);
56
56
  }
57
57
  return props;
58
58
  }
@@ -12,13 +12,37 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
12
12
  var _styledEngine = require("@mui/styled-engine");
13
13
  var _useTheme = _interopRequireDefault(require("../useTheme"));
14
14
  var _jsxRuntime = require("react/jsx-runtime");
15
+ function wrapGlobalLayer(styles) {
16
+ const serialized = (0, _styledEngine.internal_serializeStyles)(styles);
17
+ if (styles !== serialized && serialized.styles) {
18
+ if (!serialized.styles.match(/^@layer\s+[^{]*$/)) {
19
+ // If the styles are not already wrapped in a layer, wrap them in a global layer.
20
+ serialized.styles = `@layer global{${serialized.styles}}`;
21
+ }
22
+ return serialized;
23
+ }
24
+ return styles;
25
+ }
15
26
  function GlobalStyles({
16
27
  styles,
17
28
  themeId,
18
29
  defaultTheme = {}
19
30
  }) {
20
31
  const upperTheme = (0, _useTheme.default)(defaultTheme);
21
- const globalStyles = typeof styles === 'function' ? styles(themeId ? upperTheme[themeId] || upperTheme : upperTheme) : styles;
32
+ const resolvedTheme = themeId ? upperTheme[themeId] || upperTheme : upperTheme;
33
+ let globalStyles = typeof styles === 'function' ? styles(resolvedTheme) : styles;
34
+ if (resolvedTheme.modularCssLayers) {
35
+ if (Array.isArray(globalStyles)) {
36
+ globalStyles = globalStyles.map(styleArg => {
37
+ if (typeof styleArg === 'function') {
38
+ return wrapGlobalLayer(styleArg(resolvedTheme));
39
+ }
40
+ return wrapGlobalLayer(styleArg);
41
+ });
42
+ } else {
43
+ globalStyles = wrapGlobalLayer(globalStyles);
44
+ }
45
+ }
22
46
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_styledEngine.GlobalStyles, {
23
47
  styles: globalStyles
24
48
  });
@@ -15,6 +15,7 @@ var _styledEngine = require("@mui/styled-engine");
15
15
  var _useThemeWithoutDefault = _interopRequireDefault(require("../useThemeWithoutDefault"));
16
16
  var _RtlProvider = _interopRequireDefault(require("../RtlProvider"));
17
17
  var _DefaultPropsProvider = _interopRequireDefault(require("../DefaultPropsProvider"));
18
+ var _useLayerOrder = _interopRequireDefault(require("./useLayerOrder"));
18
19
  var _jsxRuntime = require("react/jsx-runtime");
19
20
  const EMPTY_THEME = {};
20
21
  function useThemeScoping(themeId, upperTheme, localTheme, isPrivate = false) {
@@ -66,15 +67,16 @@ function ThemeProvider(props) {
66
67
  const engineTheme = useThemeScoping(themeId, upperTheme, localTheme);
67
68
  const privateTheme = useThemeScoping(themeId, upperPrivateTheme, localTheme, true);
68
69
  const rtlValue = (themeId ? engineTheme[themeId] : engineTheme).direction === 'rtl';
70
+ const layerOrder = (0, _useLayerOrder.default)(engineTheme);
69
71
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_privateTheming.ThemeProvider, {
70
72
  theme: privateTheme,
71
73
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_styledEngine.ThemeContext.Provider, {
72
74
  value: engineTheme,
73
75
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_RtlProvider.default, {
74
76
  value: rtlValue,
75
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_DefaultPropsProvider.default, {
77
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_DefaultPropsProvider.default, {
76
78
  value: themeId ? engineTheme[themeId].components : engineTheme.components,
77
- children: children
79
+ children: [layerOrder, children]
78
80
  })
79
81
  })
80
82
  })
@@ -0,0 +1,8 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * This hook returns a `GlobalStyles` component that sets the CSS layer order (for server-side rendering).
4
+ * Then on client-side, it injects the CSS layer order into the document head to ensure that the layer order is always present first before other Emotion styles.
5
+ */
6
+ export default function useLayerOrder(theme: {
7
+ modularCssLayers?: boolean | string;
8
+ }): React.JSX.Element | null;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = useLayerOrder;
9
+ var React = _interopRequireWildcard(require("react"));
10
+ var _useEnhancedEffect = _interopRequireDefault(require("@mui/utils/useEnhancedEffect"));
11
+ var _useId = _interopRequireDefault(require("@mui/utils/useId"));
12
+ var _GlobalStyles = _interopRequireDefault(require("../GlobalStyles"));
13
+ var _useThemeWithoutDefault = _interopRequireDefault(require("../useThemeWithoutDefault"));
14
+ var _jsxRuntime = require("react/jsx-runtime");
15
+ /**
16
+ * This hook returns a `GlobalStyles` component that sets the CSS layer order (for server-side rendering).
17
+ * Then on client-side, it injects the CSS layer order into the document head to ensure that the layer order is always present first before other Emotion styles.
18
+ */function useLayerOrder(theme) {
19
+ const upperTheme = (0, _useThemeWithoutDefault.default)();
20
+ const id = (0, _useId.default)() || '';
21
+ const {
22
+ modularCssLayers
23
+ } = theme;
24
+ let layerOrder = 'mui.global, mui.components, mui.theme, mui.custom, mui.sx';
25
+ if (!modularCssLayers || upperTheme !== null) {
26
+ // skip this hook if upper theme exists.
27
+ layerOrder = '';
28
+ } else if (typeof modularCssLayers === 'string') {
29
+ layerOrder = modularCssLayers.replace(/mui(?!\.)/g, layerOrder);
30
+ } else {
31
+ layerOrder = `@layer ${layerOrder};`;
32
+ }
33
+ (0, _useEnhancedEffect.default)(() => {
34
+ const head = document.querySelector('head');
35
+ if (!head) {
36
+ return;
37
+ }
38
+ const firstChild = head.firstChild;
39
+ if (layerOrder) {
40
+ // Only insert if first child doesn't have data-mui-layer-order attribute
41
+ if (firstChild && firstChild.hasAttribute?.('data-mui-layer-order') && firstChild.getAttribute('data-mui-layer-order') === id) {
42
+ return;
43
+ }
44
+ const styleElement = document.createElement('style');
45
+ styleElement.setAttribute('data-mui-layer-order', id);
46
+ styleElement.textContent = layerOrder;
47
+ head.prepend(styleElement);
48
+ } else {
49
+ head.querySelector(`style[data-mui-layer-order="${id}"]`)?.remove();
50
+ }
51
+ }, [layerOrder, id]);
52
+ if (!layerOrder) {
53
+ return null;
54
+ }
55
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_GlobalStyles.default, {
56
+ styles: layerOrder
57
+ });
58
+ }
@@ -25,6 +25,13 @@ const systemDefaultTheme = exports.systemDefaultTheme = (0, _createTheme.default
25
25
  function shouldForwardProp(prop) {
26
26
  return prop !== 'ownerState' && prop !== 'theme' && prop !== 'sx' && prop !== 'as';
27
27
  }
28
+ function shallowLayer(serialized, layerName) {
29
+ if (layerName && serialized && typeof serialized === 'object' && serialized.styles && !serialized.styles.startsWith('@layer') // only add the layer if it is not already there.
30
+ ) {
31
+ serialized.styles = `@layer ${layerName}{${String(serialized.styles)}}`;
32
+ }
33
+ return serialized;
34
+ }
28
35
  function defaultOverridesResolver(slot) {
29
36
  if (!slot) {
30
37
  return null;
@@ -34,7 +41,7 @@ function defaultOverridesResolver(slot) {
34
41
  function attachTheme(props, themeId, defaultTheme) {
35
42
  props.theme = isObjectEmpty(props.theme) ? defaultTheme : props.theme[themeId] || props.theme;
36
43
  }
37
- function processStyle(props, style) {
44
+ function processStyle(props, style, layerName) {
38
45
  /*
39
46
  * Style types:
40
47
  * - null/undefined
@@ -46,27 +53,27 @@ function processStyle(props, style) {
46
53
 
47
54
  const resolvedStyle = typeof style === 'function' ? style(props) : style;
48
55
  if (Array.isArray(resolvedStyle)) {
49
- return resolvedStyle.flatMap(subStyle => processStyle(props, subStyle));
56
+ return resolvedStyle.flatMap(subStyle => processStyle(props, subStyle, layerName));
50
57
  }
51
58
  if (Array.isArray(resolvedStyle?.variants)) {
52
59
  let rootStyle;
53
60
  if (resolvedStyle.isProcessed) {
54
- rootStyle = resolvedStyle.style;
61
+ rootStyle = layerName ? shallowLayer(resolvedStyle.style, layerName) : resolvedStyle.style;
55
62
  } else {
56
63
  const {
57
64
  variants,
58
65
  ...otherStyles
59
66
  } = resolvedStyle;
60
- rootStyle = otherStyles;
67
+ rootStyle = layerName ? shallowLayer((0, _styledEngine.internal_serializeStyles)(otherStyles), layerName) : otherStyles;
61
68
  }
62
- return processStyleVariants(props, resolvedStyle.variants, [rootStyle]);
69
+ return processStyleVariants(props, resolvedStyle.variants, [rootStyle], layerName);
63
70
  }
64
71
  if (resolvedStyle?.isProcessed) {
65
- return resolvedStyle.style;
72
+ return layerName ? shallowLayer((0, _styledEngine.internal_serializeStyles)(resolvedStyle.style), layerName) : resolvedStyle.style;
66
73
  }
67
- return resolvedStyle;
74
+ return layerName ? shallowLayer((0, _styledEngine.internal_serializeStyles)(resolvedStyle), layerName) : resolvedStyle;
68
75
  }
69
- function processStyleVariants(props, variants, results = []) {
76
+ function processStyleVariants(props, variants, results = [], layerName = undefined) {
70
77
  let mergedState; // We might not need it, initialized lazily
71
78
 
72
79
  variantLoop: for (let i = 0; i < variants.length; i += 1) {
@@ -93,9 +100,9 @@ function processStyleVariants(props, variants, results = []) {
93
100
  ...props.ownerState,
94
101
  ownerState: props.ownerState
95
102
  });
96
- results.push(variant.style(mergedState));
103
+ results.push(layerName ? shallowLayer((0, _styledEngine.internal_serializeStyles)(variant.style(mergedState)), layerName) : variant.style(mergedState));
97
104
  } else {
98
- results.push(variant.style);
105
+ results.push(layerName ? shallowLayer((0, _styledEngine.internal_serializeStyles)(variant.style), layerName) : variant.style);
99
106
  }
100
107
  }
101
108
  return results;
@@ -124,6 +131,7 @@ function createStyled(input = {}) {
124
131
  overridesResolver = defaultOverridesResolver(lowercaseFirstLetter(componentSlot)),
125
132
  ...options
126
133
  } = inputOptions;
134
+ const layerName = componentName && componentName.startsWith('Mui') || !!componentSlot ? 'components' : 'custom';
127
135
 
128
136
  // if skipVariantsResolver option is defined, take the value, otherwise, true for root and false for other slots.
129
137
  const skipVariantsResolver = inputSkipVariantsResolver !== undefined ? inputSkipVariantsResolver :
@@ -150,21 +158,26 @@ function createStyled(input = {}) {
150
158
  ...options
151
159
  });
152
160
  const transformStyle = style => {
153
- // On the server Emotion doesn't use React.forwardRef for creating components, so the created
154
- // component stays as a function. This condition makes sure that we do not interpolate functions
155
- // which are basically components used as a selectors.
156
- if (typeof style === 'function' && style.__emotion_real !== style) {
161
+ // - On the server Emotion doesn't use React.forwardRef for creating components, so the created
162
+ // component stays as a function. This condition makes sure that we do not interpolate functions
163
+ // which are basically components used as a selectors.
164
+ // - `style` could be a styled component from a babel plugin for component selectors, This condition
165
+ // makes sure that we do not interpolate them.
166
+ if (style.__emotion_real === style) {
167
+ return style;
168
+ }
169
+ if (typeof style === 'function') {
157
170
  return function styleFunctionProcessor(props) {
158
- return processStyle(props, style);
171
+ return processStyle(props, style, props.theme.modularCssLayers ? layerName : undefined);
159
172
  };
160
173
  }
161
174
  if ((0, _deepmerge.isPlainObject)(style)) {
162
175
  const serialized = (0, _preprocessStyles.default)(style);
163
- if (!serialized.variants) {
164
- return serialized.style;
165
- }
166
176
  return function styleObjectProcessor(props) {
167
- return processStyle(props, serialized);
177
+ if (!serialized.variants) {
178
+ return props.theme.modularCssLayers ? shallowLayer(serialized.style, layerName) : serialized.style;
179
+ }
180
+ return processStyle(props, serialized, props.theme.modularCssLayers ? layerName : undefined);
168
181
  };
169
182
  }
170
183
  return style;
@@ -189,7 +202,7 @@ function createStyled(input = {}) {
189
202
  // TODO: v7 remove iteration and use `resolveStyleArg(styleOverrides[slot])` directly
190
203
  // eslint-disable-next-line guard-for-in
191
204
  for (const slotKey in styleOverrides) {
192
- resolvedStyleOverrides[slotKey] = processStyle(props, styleOverrides[slotKey]);
205
+ resolvedStyleOverrides[slotKey] = processStyle(props, styleOverrides[slotKey], props.theme.modularCssLayers ? 'theme' : undefined);
193
206
  }
194
207
  return overridesResolver(props, resolvedStyleOverrides);
195
208
  });
@@ -201,7 +214,7 @@ function createStyled(input = {}) {
201
214
  if (!themeVariants) {
202
215
  return null;
203
216
  }
204
- return processStyleVariants(props, themeVariants);
217
+ return processStyleVariants(props, themeVariants, [], props.theme.modularCssLayers ? 'theme' : undefined);
205
218
  });
206
219
  }
207
220
  if (!skipSx) {
@@ -1,5 +1,5 @@
1
1
  export interface Shape {
2
- borderRadius: number;
2
+ borderRadius: number | string;
3
3
  }
4
4
  export type ShapeOptions = Partial<Shape>;
5
5
  declare const shape: Shape;
@@ -40,11 +40,11 @@ function getThemeProps(params) {
40
40
  const config = theme.components[name];
41
41
  if (config.defaultProps) {
42
42
  // compatible with v5 signature
43
- return resolveProps(config.defaultProps, props);
43
+ return resolveProps(config.defaultProps, props, theme.components.mergeClassNameAndStyle);
44
44
  }
45
45
  if (!config.styleOverrides && !config.variants) {
46
46
  // v6 signature, no property 'defaultProps'
47
- return resolveProps(config, props);
47
+ return resolveProps(config, props, theme.components.mergeClassNameAndStyle);
48
48
  }
49
49
  return props;
50
50
  }
@@ -2,16 +2,40 @@
2
2
 
3
3
  import * as React from 'react';
4
4
  import PropTypes from 'prop-types';
5
- import { GlobalStyles as MuiGlobalStyles } from '@mui/styled-engine';
5
+ import { GlobalStyles as MuiGlobalStyles, internal_serializeStyles as serializeStyles } from '@mui/styled-engine';
6
6
  import useTheme from "../useTheme/index.js";
7
7
  import { jsx as _jsx } from "react/jsx-runtime";
8
+ function wrapGlobalLayer(styles) {
9
+ const serialized = serializeStyles(styles);
10
+ if (styles !== serialized && serialized.styles) {
11
+ if (!serialized.styles.match(/^@layer\s+[^{]*$/)) {
12
+ // If the styles are not already wrapped in a layer, wrap them in a global layer.
13
+ serialized.styles = `@layer global{${serialized.styles}}`;
14
+ }
15
+ return serialized;
16
+ }
17
+ return styles;
18
+ }
8
19
  function GlobalStyles({
9
20
  styles,
10
21
  themeId,
11
22
  defaultTheme = {}
12
23
  }) {
13
24
  const upperTheme = useTheme(defaultTheme);
14
- const globalStyles = typeof styles === 'function' ? styles(themeId ? upperTheme[themeId] || upperTheme : upperTheme) : styles;
25
+ const resolvedTheme = themeId ? upperTheme[themeId] || upperTheme : upperTheme;
26
+ let globalStyles = typeof styles === 'function' ? styles(resolvedTheme) : styles;
27
+ if (resolvedTheme.modularCssLayers) {
28
+ if (Array.isArray(globalStyles)) {
29
+ globalStyles = globalStyles.map(styleArg => {
30
+ if (typeof styleArg === 'function') {
31
+ return wrapGlobalLayer(styleArg(resolvedTheme));
32
+ }
33
+ return wrapGlobalLayer(styleArg);
34
+ });
35
+ } else {
36
+ globalStyles = wrapGlobalLayer(globalStyles);
37
+ }
38
+ }
15
39
  return /*#__PURE__*/_jsx(MuiGlobalStyles, {
16
40
  styles: globalStyles
17
41
  });
@@ -8,7 +8,8 @@ import { ThemeContext as StyledEngineThemeContext } from '@mui/styled-engine';
8
8
  import useThemeWithoutDefault from "../useThemeWithoutDefault/index.js";
9
9
  import RtlProvider from "../RtlProvider/index.js";
10
10
  import DefaultPropsProvider from "../DefaultPropsProvider/index.js";
11
- import { jsx as _jsx } from "react/jsx-runtime";
11
+ import useLayerOrder from "./useLayerOrder.js";
12
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
12
13
  const EMPTY_THEME = {};
13
14
  function useThemeScoping(themeId, upperTheme, localTheme, isPrivate = false) {
14
15
  return React.useMemo(() => {
@@ -59,15 +60,16 @@ function ThemeProvider(props) {
59
60
  const engineTheme = useThemeScoping(themeId, upperTheme, localTheme);
60
61
  const privateTheme = useThemeScoping(themeId, upperPrivateTheme, localTheme, true);
61
62
  const rtlValue = (themeId ? engineTheme[themeId] : engineTheme).direction === 'rtl';
63
+ const layerOrder = useLayerOrder(engineTheme);
62
64
  return /*#__PURE__*/_jsx(MuiThemeProvider, {
63
65
  theme: privateTheme,
64
66
  children: /*#__PURE__*/_jsx(StyledEngineThemeContext.Provider, {
65
67
  value: engineTheme,
66
68
  children: /*#__PURE__*/_jsx(RtlProvider, {
67
69
  value: rtlValue,
68
- children: /*#__PURE__*/_jsx(DefaultPropsProvider, {
70
+ children: /*#__PURE__*/_jsxs(DefaultPropsProvider, {
69
71
  value: themeId ? engineTheme[themeId].components : engineTheme.components,
70
- children: children
72
+ children: [layerOrder, children]
71
73
  })
72
74
  })
73
75
  })
@@ -0,0 +1,8 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * This hook returns a `GlobalStyles` component that sets the CSS layer order (for server-side rendering).
4
+ * Then on client-side, it injects the CSS layer order into the document head to ensure that the layer order is always present first before other Emotion styles.
5
+ */
6
+ export default function useLayerOrder(theme: {
7
+ modularCssLayers?: boolean | string;
8
+ }): React.JSX.Element | null;
@@ -0,0 +1,52 @@
1
+ import * as React from 'react';
2
+ import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
3
+ import useId from '@mui/utils/useId';
4
+ import GlobalStyles from "../GlobalStyles/index.js";
5
+ import useThemeWithoutDefault from "../useThemeWithoutDefault/index.js";
6
+
7
+ /**
8
+ * This hook returns a `GlobalStyles` component that sets the CSS layer order (for server-side rendering).
9
+ * Then on client-side, it injects the CSS layer order into the document head to ensure that the layer order is always present first before other Emotion styles.
10
+ */
11
+ import { jsx as _jsx } from "react/jsx-runtime";
12
+ export default function useLayerOrder(theme) {
13
+ const upperTheme = useThemeWithoutDefault();
14
+ const id = useId() || '';
15
+ const {
16
+ modularCssLayers
17
+ } = theme;
18
+ let layerOrder = 'mui.global, mui.components, mui.theme, mui.custom, mui.sx';
19
+ if (!modularCssLayers || upperTheme !== null) {
20
+ // skip this hook if upper theme exists.
21
+ layerOrder = '';
22
+ } else if (typeof modularCssLayers === 'string') {
23
+ layerOrder = modularCssLayers.replace(/mui(?!\.)/g, layerOrder);
24
+ } else {
25
+ layerOrder = `@layer ${layerOrder};`;
26
+ }
27
+ useEnhancedEffect(() => {
28
+ const head = document.querySelector('head');
29
+ if (!head) {
30
+ return;
31
+ }
32
+ const firstChild = head.firstChild;
33
+ if (layerOrder) {
34
+ // Only insert if first child doesn't have data-mui-layer-order attribute
35
+ if (firstChild && firstChild.hasAttribute?.('data-mui-layer-order') && firstChild.getAttribute('data-mui-layer-order') === id) {
36
+ return;
37
+ }
38
+ const styleElement = document.createElement('style');
39
+ styleElement.setAttribute('data-mui-layer-order', id);
40
+ styleElement.textContent = layerOrder;
41
+ head.prepend(styleElement);
42
+ } else {
43
+ head.querySelector(`style[data-mui-layer-order="${id}"]`)?.remove();
44
+ }
45
+ }, [layerOrder, id]);
46
+ if (!layerOrder) {
47
+ return null;
48
+ }
49
+ return /*#__PURE__*/_jsx(GlobalStyles, {
50
+ styles: layerOrder
51
+ });
52
+ }
@@ -1,4 +1,4 @@
1
- import styledEngineStyled, { internal_mutateStyles as mutateStyles } from '@mui/styled-engine';
1
+ import styledEngineStyled, { internal_mutateStyles as mutateStyles, internal_serializeStyles as serializeStyles } from '@mui/styled-engine';
2
2
  import { isPlainObject } from '@mui/utils/deepmerge';
3
3
  import capitalize from '@mui/utils/capitalize';
4
4
  import getDisplayName from '@mui/utils/getDisplayName';
@@ -16,6 +16,13 @@ export const systemDefaultTheme = createTheme();
16
16
  export function shouldForwardProp(prop) {
17
17
  return prop !== 'ownerState' && prop !== 'theme' && prop !== 'sx' && prop !== 'as';
18
18
  }
19
+ function shallowLayer(serialized, layerName) {
20
+ if (layerName && serialized && typeof serialized === 'object' && serialized.styles && !serialized.styles.startsWith('@layer') // only add the layer if it is not already there.
21
+ ) {
22
+ serialized.styles = `@layer ${layerName}{${String(serialized.styles)}}`;
23
+ }
24
+ return serialized;
25
+ }
19
26
  function defaultOverridesResolver(slot) {
20
27
  if (!slot) {
21
28
  return null;
@@ -25,7 +32,7 @@ function defaultOverridesResolver(slot) {
25
32
  function attachTheme(props, themeId, defaultTheme) {
26
33
  props.theme = isObjectEmpty(props.theme) ? defaultTheme : props.theme[themeId] || props.theme;
27
34
  }
28
- function processStyle(props, style) {
35
+ function processStyle(props, style, layerName) {
29
36
  /*
30
37
  * Style types:
31
38
  * - null/undefined
@@ -37,27 +44,27 @@ function processStyle(props, style) {
37
44
 
38
45
  const resolvedStyle = typeof style === 'function' ? style(props) : style;
39
46
  if (Array.isArray(resolvedStyle)) {
40
- return resolvedStyle.flatMap(subStyle => processStyle(props, subStyle));
47
+ return resolvedStyle.flatMap(subStyle => processStyle(props, subStyle, layerName));
41
48
  }
42
49
  if (Array.isArray(resolvedStyle?.variants)) {
43
50
  let rootStyle;
44
51
  if (resolvedStyle.isProcessed) {
45
- rootStyle = resolvedStyle.style;
52
+ rootStyle = layerName ? shallowLayer(resolvedStyle.style, layerName) : resolvedStyle.style;
46
53
  } else {
47
54
  const {
48
55
  variants,
49
56
  ...otherStyles
50
57
  } = resolvedStyle;
51
- rootStyle = otherStyles;
58
+ rootStyle = layerName ? shallowLayer(serializeStyles(otherStyles), layerName) : otherStyles;
52
59
  }
53
- return processStyleVariants(props, resolvedStyle.variants, [rootStyle]);
60
+ return processStyleVariants(props, resolvedStyle.variants, [rootStyle], layerName);
54
61
  }
55
62
  if (resolvedStyle?.isProcessed) {
56
- return resolvedStyle.style;
63
+ return layerName ? shallowLayer(serializeStyles(resolvedStyle.style), layerName) : resolvedStyle.style;
57
64
  }
58
- return resolvedStyle;
65
+ return layerName ? shallowLayer(serializeStyles(resolvedStyle), layerName) : resolvedStyle;
59
66
  }
60
- function processStyleVariants(props, variants, results = []) {
67
+ function processStyleVariants(props, variants, results = [], layerName = undefined) {
61
68
  let mergedState; // We might not need it, initialized lazily
62
69
 
63
70
  variantLoop: for (let i = 0; i < variants.length; i += 1) {
@@ -84,9 +91,9 @@ function processStyleVariants(props, variants, results = []) {
84
91
  ...props.ownerState,
85
92
  ownerState: props.ownerState
86
93
  };
87
- results.push(variant.style(mergedState));
94
+ results.push(layerName ? shallowLayer(serializeStyles(variant.style(mergedState)), layerName) : variant.style(mergedState));
88
95
  } else {
89
- results.push(variant.style);
96
+ results.push(layerName ? shallowLayer(serializeStyles(variant.style), layerName) : variant.style);
90
97
  }
91
98
  }
92
99
  return results;
@@ -115,6 +122,7 @@ export default function createStyled(input = {}) {
115
122
  overridesResolver = defaultOverridesResolver(lowercaseFirstLetter(componentSlot)),
116
123
  ...options
117
124
  } = inputOptions;
125
+ const layerName = componentName && componentName.startsWith('Mui') || !!componentSlot ? 'components' : 'custom';
118
126
 
119
127
  // if skipVariantsResolver option is defined, take the value, otherwise, true for root and false for other slots.
120
128
  const skipVariantsResolver = inputSkipVariantsResolver !== undefined ? inputSkipVariantsResolver :
@@ -141,21 +149,26 @@ export default function createStyled(input = {}) {
141
149
  ...options
142
150
  });
143
151
  const transformStyle = style => {
144
- // On the server Emotion doesn't use React.forwardRef for creating components, so the created
145
- // component stays as a function. This condition makes sure that we do not interpolate functions
146
- // which are basically components used as a selectors.
147
- if (typeof style === 'function' && style.__emotion_real !== style) {
152
+ // - On the server Emotion doesn't use React.forwardRef for creating components, so the created
153
+ // component stays as a function. This condition makes sure that we do not interpolate functions
154
+ // which are basically components used as a selectors.
155
+ // - `style` could be a styled component from a babel plugin for component selectors, This condition
156
+ // makes sure that we do not interpolate them.
157
+ if (style.__emotion_real === style) {
158
+ return style;
159
+ }
160
+ if (typeof style === 'function') {
148
161
  return function styleFunctionProcessor(props) {
149
- return processStyle(props, style);
162
+ return processStyle(props, style, props.theme.modularCssLayers ? layerName : undefined);
150
163
  };
151
164
  }
152
165
  if (isPlainObject(style)) {
153
166
  const serialized = preprocessStyles(style);
154
- if (!serialized.variants) {
155
- return serialized.style;
156
- }
157
167
  return function styleObjectProcessor(props) {
158
- return processStyle(props, serialized);
168
+ if (!serialized.variants) {
169
+ return props.theme.modularCssLayers ? shallowLayer(serialized.style, layerName) : serialized.style;
170
+ }
171
+ return processStyle(props, serialized, props.theme.modularCssLayers ? layerName : undefined);
159
172
  };
160
173
  }
161
174
  return style;
@@ -180,7 +193,7 @@ export default function createStyled(input = {}) {
180
193
  // TODO: v7 remove iteration and use `resolveStyleArg(styleOverrides[slot])` directly
181
194
  // eslint-disable-next-line guard-for-in
182
195
  for (const slotKey in styleOverrides) {
183
- resolvedStyleOverrides[slotKey] = processStyle(props, styleOverrides[slotKey]);
196
+ resolvedStyleOverrides[slotKey] = processStyle(props, styleOverrides[slotKey], props.theme.modularCssLayers ? 'theme' : undefined);
184
197
  }
185
198
  return overridesResolver(props, resolvedStyleOverrides);
186
199
  });
@@ -192,7 +205,7 @@ export default function createStyled(input = {}) {
192
205
  if (!themeVariants) {
193
206
  return null;
194
207
  }
195
- return processStyleVariants(props, themeVariants);
208
+ return processStyleVariants(props, themeVariants, [], props.theme.modularCssLayers ? 'theme' : undefined);
196
209
  });
197
210
  }
198
211
  if (!skipSx) {
@@ -1,5 +1,5 @@
1
1
  export interface Shape {
2
- borderRadius: number;
2
+ borderRadius: number | string;
3
3
  }
4
4
  export type ShapeOptions = Partial<Shape>;
5
5
  declare const shape: Shape;
package/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/system v7.1.0
2
+ * @mui/system v7.2.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -64,7 +64,8 @@ export function unstable_createStyleFunctionSx() {
64
64
  function styleFunctionSx(props) {
65
65
  const {
66
66
  sx,
67
- theme = {}
67
+ theme = {},
68
+ nested
68
69
  } = props || {};
69
70
  if (!sx) {
70
71
  return null; // Emotion & styled-components will neglect null
@@ -105,7 +106,8 @@ export function unstable_createStyleFunctionSx() {
105
106
  if (objectsHaveSameKeys(breakpointsValues, value)) {
106
107
  css[styleKey] = styleFunctionSx({
107
108
  sx: value,
108
- theme
109
+ theme,
110
+ nested: true
109
111
  });
110
112
  } else {
111
113
  css = merge(css, breakpointsValues);
@@ -116,6 +118,11 @@ export function unstable_createStyleFunctionSx() {
116
118
  }
117
119
  }
118
120
  });
121
+ if (!nested && theme.modularCssLayers) {
122
+ return {
123
+ '@layer sx': sortContainerQueries(theme, removeUnusedBreakpoints(breakpointsKeys, css))
124
+ };
125
+ }
119
126
  return sortContainerQueries(theme, removeUnusedBreakpoints(breakpointsKeys, css));
120
127
  }
121
128
  return Array.isArray(sx) ? sx.map(traverse) : traverse(sx);
@@ -1,6 +1,6 @@
1
- export const version = "7.1.0";
1
+ export const version = "7.2.0";
2
2
  export const major = Number("7");
3
- export const minor = Number("1");
3
+ export const minor = Number("2");
4
4
  export const patch = Number("0");
5
5
  export const prerelease = undefined;
6
6
  export default version;
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/system v7.1.0
2
+ * @mui/system v7.2.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/system",
3
- "version": "7.1.0",
3
+ "version": "7.2.0",
4
4
  "author": "MUI Team",
5
5
  "description": "MUI System is a set of CSS utilities to help you build custom designs more efficiently. It makes it possible to rapidly lay out custom designs.",
6
6
  "main": "./index.js",
@@ -25,14 +25,14 @@
25
25
  "url": "https://opencollective.com/mui-org"
26
26
  },
27
27
  "dependencies": {
28
- "@babel/runtime": "^7.27.1",
28
+ "@babel/runtime": "^7.27.6",
29
29
  "clsx": "^2.1.1",
30
30
  "csstype": "^3.1.3",
31
31
  "prop-types": "^15.8.1",
32
- "@mui/types": "^7.4.2",
33
- "@mui/private-theming": "^7.1.0",
34
- "@mui/utils": "^7.1.0",
35
- "@mui/styled-engine": "^7.1.0"
32
+ "@mui/private-theming": "^7.2.0",
33
+ "@mui/types": "^7.4.4",
34
+ "@mui/utils": "^7.2.0",
35
+ "@mui/styled-engine": "^7.2.0"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@emotion/react": "^11.5.0",
@@ -72,7 +72,8 @@ function unstable_createStyleFunctionSx() {
72
72
  function styleFunctionSx(props) {
73
73
  const {
74
74
  sx,
75
- theme = {}
75
+ theme = {},
76
+ nested
76
77
  } = props || {};
77
78
  if (!sx) {
78
79
  return null; // Emotion & styled-components will neglect null
@@ -113,7 +114,8 @@ function unstable_createStyleFunctionSx() {
113
114
  if (objectsHaveSameKeys(breakpointsValues, value)) {
114
115
  css[styleKey] = styleFunctionSx({
115
116
  sx: value,
116
- theme
117
+ theme,
118
+ nested: true
117
119
  });
118
120
  } else {
119
121
  css = (0, _merge.default)(css, breakpointsValues);
@@ -124,6 +126,11 @@ function unstable_createStyleFunctionSx() {
124
126
  }
125
127
  }
126
128
  });
129
+ if (!nested && theme.modularCssLayers) {
130
+ return {
131
+ '@layer sx': (0, _cssContainerQueries.sortContainerQueries)(theme, (0, _breakpoints.removeUnusedBreakpoints)(breakpointsKeys, css))
132
+ };
133
+ }
127
134
  return (0, _cssContainerQueries.sortContainerQueries)(theme, (0, _breakpoints.removeUnusedBreakpoints)(breakpointsKeys, css));
128
135
  }
129
136
  return Array.isArray(sx) ? sx.map(traverse) : traverse(sx);
package/version/index.js CHANGED
@@ -4,9 +4,9 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.version = exports.prerelease = exports.patch = exports.minor = exports.major = exports.default = void 0;
7
- const version = exports.version = "7.1.0";
7
+ const version = exports.version = "7.2.0";
8
8
  const major = exports.major = Number("7");
9
- const minor = exports.minor = Number("1");
9
+ const minor = exports.minor = Number("2");
10
10
  const patch = exports.patch = Number("0");
11
11
  const prerelease = exports.prerelease = undefined;
12
12
  var _default = exports.default = version;