@mui/system 7.1.1 → 7.3.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,162 @@
1
1
  # [Versions](https://mui.com/versions/)
2
2
 
3
+ ## 7.3.0
4
+
5
+ <!-- generated comparing v7.2.0..master -->
6
+
7
+ _Aug 5, 2025_
8
+
9
+ A big thanks to the 24 contributors who made this release possible. Here are some highlights ✨:
10
+
11
+ - 🚀 Shipped `nativeColor` feature that eliminates JS color manipulation and unlocks support for all modern color spaces (#43942) @siriwatknp!
12
+
13
+ To learn more, check out the [Native Color](https://mui.com/material-ui/customization/css-theme-variables/native-color/) guide.
14
+
15
+ ### `@mui/material@7.3.0`
16
+
17
+ - Support native color without JS manipulation (#43942) @siriwatknp
18
+ - [Accordion] Add `region` slot (#46659) @sai6855
19
+ - [SpeedDial] Fix navigation with arrow keys when slotProps.fab is defined (#46508) @sai6855
20
+ - [Select] Improve `MenuProps.slotProps` implementation (#46612) @ZeeshanTamboli
21
+ - [Select] Implement pointer cancellation (#45789) @Kartik-Murthy
22
+ - [Switch] Add role="switch" (#46482) @ZeeshanTamboli
23
+ - [Autocomplete] Fix auto highlight when options change but not the length (#46489) @yafeng-c
24
+
25
+ ### `@mui/codemod@7.3.0`
26
+
27
+ - Fix `v5.0.0/top-level-imports` codemod changing color imports (#46405) @AidanLDev
28
+
29
+ ### Docs
30
+
31
+ - Add JetBrains IDEs MCP configuration (#46470) @bernardobelchior
32
+ - Add warning to array spacing section (#46542) @cherniavskii
33
+ - Add MCP server installation details for Claude Code (#46621) @saschabratton
34
+ - Fix incorrect command for MCP Inspector in mcp.md (#46630) @EndiM
35
+ - Fix incorrect Typography override example for responsive styles (#46558) @aditi291soni
36
+ - Improve MCP docs (#46557) @siriwatknp
37
+ - Fix displaying of components in dark mode (#46544) @sai6855
38
+ - Generate `template` entries about documented generics (#46540) @LukasTy
39
+ - Use fixed dates for stable CRUD dashboard screenshots (#46546) @apedroferreira
40
+ - Add "Edit in Mui Chat" button on demos (#46480) @siriwatknp
41
+ - Fix Menu customization demo (#46535) @siriwatknp
42
+ - Add dashboard with CRUD template based on Toolpad Core (#46376) @apedroferreira
43
+ - Clarify `createTheme` warning for future compatibility (#46476) @satendra03
44
+ - Remove typo in `_redirects` (#46463) @bharatkashyap
45
+ - Change API docs to stay inside Material UI (#46414) @bharatkashyap
46
+ - [Dialog] Fix Form dialog demo's actions button padding (#46506) @frontman-git
47
+ - [SpeedDial] Remove deprecated props from demos (#46485) @sai6855
48
+ - [Switch] Use `slotProps.input` instead of deprecated `inputProps` for accessible controlled switch (#46625) @adiitxa
49
+
50
+ ### Core
51
+
52
+ - Fix ESLint reference name (80d32a2) @oliviertassinari
53
+ - Fix ESLint reference name (5fc166e) @oliviertassinari
54
+ - Add `@base-ui-components/*` to env info (#46539) @Janpot
55
+ - Remove dead property from routes (#46534) @oliviertassinari
56
+ - Fix unpinned version regression (#46438) @oliviertassinari
57
+ - [code-infra] Accomodate build requirements from mui-x (#46551) @brijeshb42
58
+ - [code-infra] Extend renovate preset from infra repo (#46483) @brijeshb42
59
+ - [code-infra] Use flat eslint config (#46258) @brijeshb42
60
+ - [docs-infra] Remove comment saving in G-sheet option (#46617) @alexfauquette
61
+ - [docs-infra] Move `Open in MUI Chat` to Demo toolbar and adjust styles (#46579) @siriwatknp
62
+ - [docs-infra] Fix codeblock issues (#46323) @atharva3333
63
+ - [docs-infra] Handle white spaces and generate either TS or JS demo for llms files (#46494) @siriwatknp
64
+ - [examples] Rename PopOverMenu.tsx file to match its usage (#46532) @rjray
65
+ - [infra] Fix `test_types_next`, `test_react_18`, `test_react_next` jobs (#46182) @Janpot
66
+ - [infra] Remove package.json `module` field (#46620) @Janpot
67
+ - [infra] Upgrade form-data to >4.0.4 (#46618) @Janpot
68
+ - [infra] Use cpu option only in CI (#46588) @Janpot
69
+ - [infra] Update scripts to delete publishConfig.directory (#46563) @brijeshb42
70
+ - [infra] Remove `transform-runtime` from `next/babel` (#46552) @Janpot
71
+ - [infra] Revert nx update (#46538) @Janpot
72
+ - [infra] Replace Argos script with code-infra CLI and update deps (#46475) @Janpot
73
+ - [infra] Update node group in renovate config (#46474) @Janpot
74
+ - [infra] Move @playwright/test to peer deps in @mui/internal-test-utils (#46459) @Janpot
75
+ - [infra] Add instructions for patch release (#46382) @mnajdova
76
+
77
+ All contributors of this release in alphabetical order: @adiitxa, @aditi291soni, @AidanLDev, @alexfauquette, @apedroferreira, @atharva3333, @bernardobelchior, @bharatkashyap, @brijeshb42, @cherniavskii, @EndiM, @frontman-git, @Janpot, @Kartik-Murthy, @LukasTy, @mnajdova, @oliviertassinari, @rjray, @sai6855, @saschabratton, @satendra03, @siriwatknp, @yafeng-c, @ZeeshanTamboli
78
+
79
+ ## 7.2.0
80
+
81
+ <!-- generated comparing v7.1.1..master -->
82
+
83
+ _Jun 26, 2025_
84
+
85
+ A big thanks to the 17 contributors who made this release possible. Here are the highlights ✨:
86
+
87
+ - ⚡️ Added `modularCssLayers` theme option for splitting styles into multiple CSS layers (#46001) @siriwatknp.
88
+ - 📖 Added example for using Material UI with React Router v7 (#46406) @siriwatknp.
89
+
90
+ ### `@mui/material@7.2.0`
91
+
92
+ - [Backdrop] Fix handling of `component` prop (#46269) @sai6855
93
+ - [Chip] Explicitly define line-height (#46260) @DiegoAndai
94
+ - [Chip] Fix handling on event handlers (#46263) @sai6855
95
+ - [OutlinedInput][Input] Deprecate composed classes (#46316) @sai6855
96
+ - [Select] Pass MenuProps.slotProps.list alongside MenuListProps (#46274) @scousino
97
+ - [l10] Enable `labelDisplayedRows` translation for Romanian (#46377) @dhu-redwoodtech
98
+ - Skip generating `modularCssLayers` CSS var (#46329) @siriwatknp
99
+
100
+ ### `@mui/system@7.2.0`
101
+
102
+ - Add `modularCssLayers` theme flag to split styles into multiple CSS layers (#46001) @siriwatknp
103
+
104
+ ### `@mui/styled-engine@7.2.0`
105
+
106
+ - Do not reuse the emotion cache across SSR requests (#46276) @robbtraister
107
+
108
+ ### `@mui/codemod@7.2.0`
109
+
110
+ - [Dialog] Add codemod for deprecated props (#46328) @sai6855
111
+
112
+ ### Docs
113
+
114
+ - Don't forward `hasAiSuggestion` (#46415) @bharatkashyap
115
+ - Add introduction to MCP (#46224) @bharatkashyap
116
+ - Fallback for searchbar during SSR (#46364) @Janpot
117
+ - Update InitColorSchemeScript options to match colorSchemeSelector (#46302) @humble-barnacle001
118
+ - Add `ListItemButton` to make the deprecation clear (#46356) @siriwatknp
119
+ - Remove "Unstyled" section from component docs (#46272) @mapache-salvaje
120
+ - Add Testing section to Rating component doc (#46268) @0210shivam
121
+ - Fix fade modal demo (#46271) @brijeshb42
122
+ - [ai] Add suggestions to edit with MUI Chat (#46309) @bharatkashyap
123
+ - [Dialog] Fix form dialog uses ARIA roles on incompatible elements (#46307) @ZeeshanTamboli
124
+ - [Menu] Fix dark mode styling of grouped header demo (#46317) @sai6855
125
+ - [TextField] Removed type="number" demos (#46314) @KirankumarAmbati
126
+ - [examples] Add `material-ui-react-router-ts` example (#46406) @siriwatknp
127
+
128
+ ### Core
129
+
130
+ - pnpm docs:sync-team (3641a0b) @oliviertassinari
131
+ - Add cross-env to eslint script (#46358) @ZeeshanTamboli
132
+ - Support merging of className and style from theme (#45975) @sai6855
133
+ - [code-infra] Create bundle size package (#45911) @Janpot
134
+ - [docs-infra] Add a script to generate Material UI `llms.txt` and docs markdown. (#46308) @siriwatknp
135
+ - [docs-infra] Fix stackblitz for js projects (#46220) @Janpot
136
+ - [infra] Add emotion as external for bundle monitor (#46372) @Janpot
137
+ - [infra] Create update PR on every canary publish for internal packages (#46367) @Janpot
138
+ - [infra] Remove deprecated esmExternals (#46365) @Janpot
139
+ - [infra] Support project-specific changelog in build scripts (#46425) @michaldudak
140
+ - [toolpad][website] Remove references to Toolpad (#46311) @prakhargupta1
141
+
142
+ 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
143
+
144
+ ## 7.1.2
145
+
146
+ _Jun 18, 2025_
147
+
148
+ A big thanks to the 2 contributors who made this release possible.
149
+
150
+ ### `@mui/material@7.1.2`
151
+
152
+ - [Chip] Fix handling on event handlers (#46263) @sai6855
153
+
154
+ ### Docs
155
+
156
+ - Fix fade modal demo (#46271) @brijeshb42
157
+
158
+ All contributors of this release in alphabetical order: @brijeshb42, @sai6855
159
+
3
160
  ## 7.1.1
4
161
 
5
162
  <!-- generated comparing v7.1.0..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 :
@@ -160,16 +168,16 @@ function createStyled(input = {}) {
160
168
  }
161
169
  if (typeof style === 'function') {
162
170
  return function styleFunctionProcessor(props) {
163
- return processStyle(props, style);
171
+ return processStyle(props, style, props.theme.modularCssLayers ? layerName : undefined);
164
172
  };
165
173
  }
166
174
  if ((0, _deepmerge.isPlainObject)(style)) {
167
175
  const serialized = (0, _preprocessStyles.default)(style);
168
- if (!serialized.variants) {
169
- return serialized.style;
170
- }
171
176
  return function styleObjectProcessor(props) {
172
- 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);
173
181
  };
174
182
  }
175
183
  return style;
@@ -194,7 +202,7 @@ function createStyled(input = {}) {
194
202
  // TODO: v7 remove iteration and use `resolveStyleArg(styleOverrides[slot])` directly
195
203
  // eslint-disable-next-line guard-for-in
196
204
  for (const slotKey in styleOverrides) {
197
- resolvedStyleOverrides[slotKey] = processStyle(props, styleOverrides[slotKey]);
205
+ resolvedStyleOverrides[slotKey] = processStyle(props, styleOverrides[slotKey], props.theme.modularCssLayers ? 'theme' : undefined);
198
206
  }
199
207
  return overridesResolver(props, resolvedStyleOverrides);
200
208
  });
@@ -206,7 +214,7 @@ function createStyled(input = {}) {
206
214
  if (!themeVariants) {
207
215
  return null;
208
216
  }
209
- return processStyleVariants(props, themeVariants);
217
+ return processStyleVariants(props, themeVariants, [], props.theme.modularCssLayers ? 'theme' : undefined);
210
218
  });
211
219
  }
212
220
  if (!skipSx) {
@@ -6,6 +6,7 @@ declare function prepareCssVars<T extends DefaultCssVarsTheme, ThemeVars extends
6
6
  prefix?: string;
7
7
  colorSchemeSelector?: 'media' | 'class' | 'data' | string;
8
8
  disableCssColorScheme?: boolean;
9
+ enableContrastVars?: boolean;
9
10
  shouldSkipGeneratingVar?: (objectPathKeys: Array<string>, value: string | number) => boolean;
10
11
  getSelector?: (colorScheme: keyof T['colorSchemes'] | undefined, css: Record<string, any>) => string | Record<string, any>;
11
12
  }): {
@@ -11,7 +11,8 @@ function prepareCssVars(theme, parserConfig = {}) {
11
11
  const {
12
12
  getSelector = defaultGetSelector,
13
13
  disableCssColorScheme,
14
- colorSchemeSelector: selector
14
+ colorSchemeSelector: selector,
15
+ enableContrastVars
15
16
  } = parserConfig;
16
17
  // @ts-ignore - ignore components do not exist
17
18
  const {
@@ -149,6 +150,16 @@ function prepareCssVars(theme, parserConfig = {}) {
149
150
  ...finalCss
150
151
  }), finalCss);
151
152
  });
153
+ if (enableContrastVars) {
154
+ stylesheets.push({
155
+ ':root': {
156
+ // use double underscore to indicate that these are private variables
157
+ '--__l-threshold': '0.7',
158
+ '--__l': 'clamp(0, (l / var(--__l-threshold) - 1) * -infinity, 1)',
159
+ '--__a': 'clamp(0.87, (l / var(--__l-threshold) - 1) * -infinity, 1)' // 0.87 is the default alpha value for black text.
160
+ }
161
+ });
162
+ }
152
163
  return stylesheets;
153
164
  };
154
165
  return {
@@ -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 :
@@ -151,16 +159,16 @@ export default function createStyled(input = {}) {
151
159
  }
152
160
  if (typeof style === 'function') {
153
161
  return function styleFunctionProcessor(props) {
154
- return processStyle(props, style);
162
+ return processStyle(props, style, props.theme.modularCssLayers ? layerName : undefined);
155
163
  };
156
164
  }
157
165
  if (isPlainObject(style)) {
158
166
  const serialized = preprocessStyles(style);
159
- if (!serialized.variants) {
160
- return serialized.style;
161
- }
162
167
  return function styleObjectProcessor(props) {
163
- 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);
164
172
  };
165
173
  }
166
174
  return style;
@@ -185,7 +193,7 @@ export default function createStyled(input = {}) {
185
193
  // TODO: v7 remove iteration and use `resolveStyleArg(styleOverrides[slot])` directly
186
194
  // eslint-disable-next-line guard-for-in
187
195
  for (const slotKey in styleOverrides) {
188
- resolvedStyleOverrides[slotKey] = processStyle(props, styleOverrides[slotKey]);
196
+ resolvedStyleOverrides[slotKey] = processStyle(props, styleOverrides[slotKey], props.theme.modularCssLayers ? 'theme' : undefined);
189
197
  }
190
198
  return overridesResolver(props, resolvedStyleOverrides);
191
199
  });
@@ -197,7 +205,7 @@ export default function createStyled(input = {}) {
197
205
  if (!themeVariants) {
198
206
  return null;
199
207
  }
200
- return processStyleVariants(props, themeVariants);
208
+ return processStyleVariants(props, themeVariants, [], props.theme.modularCssLayers ? 'theme' : undefined);
201
209
  });
202
210
  }
203
211
  if (!skipSx) {
@@ -6,6 +6,7 @@ declare function prepareCssVars<T extends DefaultCssVarsTheme, ThemeVars extends
6
6
  prefix?: string;
7
7
  colorSchemeSelector?: 'media' | 'class' | 'data' | string;
8
8
  disableCssColorScheme?: boolean;
9
+ enableContrastVars?: boolean;
9
10
  shouldSkipGeneratingVar?: (objectPathKeys: Array<string>, value: string | number) => boolean;
10
11
  getSelector?: (colorScheme: keyof T['colorSchemes'] | undefined, css: Record<string, any>) => string | Record<string, any>;
11
12
  }): {
@@ -4,7 +4,8 @@ function prepareCssVars(theme, parserConfig = {}) {
4
4
  const {
5
5
  getSelector = defaultGetSelector,
6
6
  disableCssColorScheme,
7
- colorSchemeSelector: selector
7
+ colorSchemeSelector: selector,
8
+ enableContrastVars
8
9
  } = parserConfig;
9
10
  // @ts-ignore - ignore components do not exist
10
11
  const {
@@ -142,6 +143,16 @@ function prepareCssVars(theme, parserConfig = {}) {
142
143
  ...finalCss
143
144
  }), finalCss);
144
145
  });
146
+ if (enableContrastVars) {
147
+ stylesheets.push({
148
+ ':root': {
149
+ // use double underscore to indicate that these are private variables
150
+ '--__l-threshold': '0.7',
151
+ '--__l': 'clamp(0, (l / var(--__l-threshold) - 1) * -infinity, 1)',
152
+ '--__a': 'clamp(0.87, (l / var(--__l-threshold) - 1) * -infinity, 1)' // 0.87 is the default alpha value for black text.
153
+ }
154
+ });
155
+ }
145
156
  return stylesheets;
146
157
  };
147
158
  return {
package/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/system v7.1.1
2
+ * @mui/system v7.3.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.1";
1
+ export const version = "7.3.0";
2
2
  export const major = Number("7");
3
- export const minor = Number("1");
4
- export const patch = Number("1");
3
+ export const minor = Number("3");
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.1
2
+ * @mui/system v7.3.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.1",
3
+ "version": "7.3.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.28.2",
29
29
  "clsx": "^2.1.1",
30
30
  "csstype": "^3.1.3",
31
31
  "prop-types": "^15.8.1",
32
- "@mui/private-theming": "^7.1.1",
33
- "@mui/types": "^7.4.3",
34
- "@mui/styled-engine": "^7.1.1",
35
- "@mui/utils": "^7.1.1"
32
+ "@mui/private-theming": "^7.3.0",
33
+ "@mui/utils": "^7.3.0",
34
+ "@mui/types": "^7.4.5",
35
+ "@mui/styled-engine": "^7.3.0"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@emotion/react": "^11.5.0",
@@ -53,14 +53,12 @@
53
53
  },
54
54
  "sideEffects": false,
55
55
  "publishConfig": {
56
- "access": "public",
57
- "directory": "build"
56
+ "access": "public"
58
57
  },
59
58
  "engines": {
60
59
  "node": ">=14.0.0"
61
60
  },
62
61
  "private": false,
63
- "module": "./esm/index.js",
64
62
  "exports": {
65
63
  "./package.json": "./package.json",
66
64
  ".": {
@@ -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.1";
7
+ const version = exports.version = "7.3.0";
8
8
  const major = exports.major = Number("7");
9
- const minor = exports.minor = Number("1");
10
- const patch = exports.patch = Number("1");
9
+ const minor = exports.minor = Number("3");
10
+ const patch = exports.patch = Number("0");
11
11
  const prerelease = exports.prerelease = undefined;
12
12
  var _default = exports.default = version;