@mui/material 9.1.0 → 9.1.2

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.
Files changed (50) hide show
  1. package/Autocomplete/Autocomplete.d.mts +5 -1
  2. package/Autocomplete/Autocomplete.d.ts +5 -1
  3. package/Autocomplete/Autocomplete.js +5 -1
  4. package/Autocomplete/Autocomplete.mjs +5 -1
  5. package/Avatar/Avatar.js +2 -0
  6. package/Avatar/Avatar.mjs +2 -0
  7. package/ButtonBase/TouchRipple.js +17 -9
  8. package/ButtonBase/TouchRipple.mjs +17 -9
  9. package/CHANGELOG.md +74 -0
  10. package/InitColorSchemeScript/InitColorSchemeScript.d.mts +5 -5
  11. package/InitColorSchemeScript/InitColorSchemeScript.d.ts +5 -5
  12. package/InputBase/InputBase.js +1 -0
  13. package/InputBase/InputBase.mjs +1 -0
  14. package/NoSsr/NoSsr.js +1 -0
  15. package/NoSsr/NoSsr.mjs +1 -0
  16. package/Popper/BasePopper.js +1 -6
  17. package/Popper/BasePopper.mjs +1 -6
  18. package/Select/utils/SelectFocusSourceContext.d.mts +2 -2
  19. package/Select/utils/SelectFocusSourceContext.d.ts +2 -2
  20. package/Slider/SliderValueLabel.d.mts +2 -2
  21. package/Slider/SliderValueLabel.d.ts +2 -2
  22. package/Step/StepContext.d.mts +1 -1
  23. package/Step/StepContext.d.ts +1 -1
  24. package/Stepper/StepperContext.d.mts +1 -1
  25. package/Stepper/StepperContext.d.ts +1 -1
  26. package/Tabs/Tabs.js +1 -0
  27. package/Tabs/Tabs.mjs +1 -0
  28. package/index.js +1 -1
  29. package/index.mjs +1 -1
  30. package/internal/Transition.js +17 -8
  31. package/internal/Transition.mjs +17 -8
  32. package/internal/react-transition-group.d.mts +8 -0
  33. package/internal/react-transition-group.d.ts +8 -0
  34. package/package.json +9 -6
  35. package/styles/ThemeProviderWithVars.d.mts +7 -7
  36. package/styles/ThemeProviderWithVars.d.ts +7 -7
  37. package/styles/createGetSelector.d.mts +2 -2
  38. package/styles/createGetSelector.d.ts +2 -2
  39. package/styles/identifier.d.mts +1 -1
  40. package/styles/identifier.d.ts +1 -1
  41. package/useAutocomplete/useAutocomplete.js +10 -9
  42. package/useAutocomplete/useAutocomplete.mjs +10 -9
  43. package/useScrollTrigger/useScrollTrigger.js +1 -0
  44. package/useScrollTrigger/useScrollTrigger.mjs +1 -0
  45. package/utils/memoTheme.d.mts +1 -1
  46. package/utils/memoTheme.d.ts +1 -1
  47. package/utils/useSlot.d.mts +1 -1
  48. package/utils/useSlot.d.ts +1 -1
  49. package/version/index.js +2 -2
  50. package/version/index.mjs +2 -2
@@ -171,7 +171,11 @@ export interface AutocompleteProps<Value, Multiple extends boolean | undefined,
171
171
  */
172
172
  forcePopupIcon?: true | false | 'auto' | undefined;
173
173
  /**
174
- * If `true`, the input will take up the full width of its container.
174
+ * If `true`, the input takes up the full width of its container.
175
+ *
176
+ * `Autocomplete` treats `undefined` and `false` differently.
177
+ * If `undefined`, the inner input takes up the full width of its container.
178
+ * If `false`, the inner input is restricted to its intrinsic width.
175
179
  * @default false
176
180
  */
177
181
  fullWidth?: boolean | undefined;
@@ -171,7 +171,11 @@ export interface AutocompleteProps<Value, Multiple extends boolean | undefined,
171
171
  */
172
172
  forcePopupIcon?: true | false | 'auto' | undefined;
173
173
  /**
174
- * If `true`, the input will take up the full width of its container.
174
+ * If `true`, the input takes up the full width of its container.
175
+ *
176
+ * `Autocomplete` treats `undefined` and `false` differently.
177
+ * If `undefined`, the inner input takes up the full width of its container.
178
+ * If `false`, the inner input is restricted to its intrinsic width.
175
179
  * @default false
176
180
  */
177
181
  fullWidth?: boolean | undefined;
@@ -944,7 +944,11 @@ process.env.NODE_ENV !== "production" ? Autocomplete.propTypes /* remove-proptyp
944
944
  */
945
945
  freeSolo: _propTypes.default.bool,
946
946
  /**
947
- * If `true`, the input will take up the full width of its container.
947
+ * If `true`, the input takes up the full width of its container.
948
+ *
949
+ * `Autocomplete` treats `undefined` and `false` differently.
950
+ * If `undefined`, the inner input takes up the full width of its container.
951
+ * If `false`, the inner input is restricted to its intrinsic width.
948
952
  * @default false
949
953
  */
950
954
  fullWidth: _propTypes.default.bool,
@@ -932,7 +932,11 @@ process.env.NODE_ENV !== "production" ? Autocomplete.propTypes /* remove-proptyp
932
932
  */
933
933
  freeSolo: PropTypes.bool,
934
934
  /**
935
- * If `true`, the input will take up the full width of its container.
935
+ * If `true`, the input takes up the full width of its container.
936
+ *
937
+ * `Autocomplete` treats `undefined` and `false` differently.
938
+ * If `undefined`, the inner input takes up the full width of its container.
939
+ * If `false`, the inner input is restricted to its intrinsic width.
936
940
  * @default false
937
941
  */
938
942
  fullWidth: PropTypes.bool,
package/Avatar/Avatar.js CHANGED
@@ -118,6 +118,8 @@ function useLoaded(src, srcSet, crossOrigin, referrerPolicy) {
118
118
  if (!src && !srcSet) {
119
119
  return undefined;
120
120
  }
121
+
122
+ // eslint-disable-next-line react-hooks/set-state-in-effect
121
123
  setLoaded(false);
122
124
  let active = true;
123
125
  const image = new Image();
package/Avatar/Avatar.mjs CHANGED
@@ -111,6 +111,8 @@ function useLoaded(src, srcSet, crossOrigin, referrerPolicy) {
111
111
  if (!src && !srcSet) {
112
112
  return undefined;
113
113
  }
114
+
115
+ // eslint-disable-next-line react-hooks/set-state-in-effect
114
116
  setLoaded(false);
115
117
  let active = true;
116
118
  const image = new Image();
@@ -212,6 +212,23 @@ const TouchRippleRipple = exports.TouchRippleRipple = (0, _zeroStyled.styled)(_R
212
212
  transform: scale(1);
213
213
  }
214
214
 
215
+ /*
216
+ * Order matters: 'child', 'childLeaving' and 'childPulsate' apply to the same
217
+ * element with equal specificity, so the later rule wins. 'child' must come
218
+ * before 'childLeaving' so the leaving 'opacity: 0' takes precedence. A focus
219
+ * (pulsate) ripple keeps 'pulsateKeyframe' (no opacity animation) on exit, so
220
+ * it relies on this static 'opacity: 0' to disappear on blur instead of
221
+ * lingering until removal.
222
+ */
223
+ & .${_touchRippleClasses.default.child} {
224
+ opacity: 1;
225
+ display: block;
226
+ width: 100%;
227
+ height: 100%;
228
+ border-radius: 50%;
229
+ background-color: currentColor;
230
+ }
231
+
215
232
  & .${_touchRippleClasses.default.childLeaving} {
216
233
  opacity: 0;
217
234
  }
@@ -226,15 +243,6 @@ const TouchRippleRipple = exports.TouchRippleRipple = (0, _zeroStyled.styled)(_R
226
243
  ${({
227
244
  theme
228
245
  }) => getAnimationStyles(theme)}
229
-
230
- & .${_touchRippleClasses.default.child} {
231
- opacity: 1;
232
- display: block;
233
- width: 100%;
234
- height: 100%;
235
- border-radius: 50%;
236
- background-color: currentColor;
237
- }
238
246
  `;
239
247
 
240
248
  /**
@@ -205,6 +205,23 @@ export const TouchRippleRipple = styled(Ripple, {
205
205
  transform: scale(1);
206
206
  }
207
207
 
208
+ /*
209
+ * Order matters: 'child', 'childLeaving' and 'childPulsate' apply to the same
210
+ * element with equal specificity, so the later rule wins. 'child' must come
211
+ * before 'childLeaving' so the leaving 'opacity: 0' takes precedence. A focus
212
+ * (pulsate) ripple keeps 'pulsateKeyframe' (no opacity animation) on exit, so
213
+ * it relies on this static 'opacity: 0' to disappear on blur instead of
214
+ * lingering until removal.
215
+ */
216
+ & .${touchRippleClasses.child} {
217
+ opacity: 1;
218
+ display: block;
219
+ width: 100%;
220
+ height: 100%;
221
+ border-radius: 50%;
222
+ background-color: currentColor;
223
+ }
224
+
208
225
  & .${touchRippleClasses.childLeaving} {
209
226
  opacity: 0;
210
227
  }
@@ -219,15 +236,6 @@ export const TouchRippleRipple = styled(Ripple, {
219
236
  ${({
220
237
  theme
221
238
  }) => getAnimationStyles(theme)}
222
-
223
- & .${touchRippleClasses.child} {
224
- opacity: 1;
225
- display: block;
226
- width: 100%;
227
- height: 100%;
228
- border-radius: 50%;
229
- background-color: currentColor;
230
- }
231
239
  `;
232
240
 
233
241
  /**
package/CHANGELOG.md CHANGED
@@ -1,5 +1,79 @@
1
1
  # [Versions](https://mui.com/material-ui/getting-started/versions/)
2
2
 
3
+ ## 9.1.2
4
+
5
+ <!-- generated comparing v9.1.1..master -->
6
+
7
+ _Jun 23, 2026_
8
+
9
+ A big thanks to the 5 contributors who made this release possible.
10
+
11
+ ### `@mui/material@9.1.2`
12
+
13
+ - [autocomplete] Don't submit forms when committing `freeSolo` value with Enter key (#48679) @mj12albert
14
+ - [transitions] Fix RTG import in ESM (#48645) @mj12albert
15
+
16
+ ### `@mui/system@9.1.2`
17
+
18
+ - [InitColorSchemeScript] Fix script tag warning in Next.js 16 dev mode (#48671) @siriwatknp
19
+
20
+ ### Docs
21
+
22
+ - Fix typos in release instructions (#48687) @brijeshb42
23
+ - Update @mui/x-* packages to latest (#48661) @Janpot
24
+
25
+ ### Core
26
+
27
+ - [code-infra] Convert leaf @mui/system .js+.d.ts pairs to TypeScript (part 1) (#48578) @Janpot
28
+ - [code-infra] Bump to latest code-infra packages (#48672) @brijeshb42
29
+ - [code-infra] Resolve remaining minimatch advisory (#48662) @Janpot
30
+ - [code-infra] Bump nx to resolve minimatch advisory (#48658) @Janpot
31
+ - [core] Drop @babel/* pnpm overrides (#48710) @Janpot
32
+ - [docs-infra] Revert "Pin StackBlitz demo vite to v7 and plugin-react to v5" (#48709) @Janpot
33
+ - [docs-infra] Fix code-block copy button broken on direct page load (#48653) @brijeshb42
34
+ - [test] Stabilize Data Grid demo data in Argos screenshots (#48654) @LukasTy
35
+
36
+
37
+ All contributors of this release in alphabetical order: @brijeshb42, @Janpot, @LukasTy, @mj12albert, @siriwatknp
38
+
39
+ ## 9.1.1
40
+
41
+ <!-- generated comparing v9.1.0..master -->
42
+
43
+ _Jun 11, 2026_
44
+
45
+ A big thanks to the 9 contributors who made this release possible.
46
+
47
+ ### `@mui/material@9.1.1`
48
+
49
+ - [Autocomplete] Update fullWidth prop documentation (#48626) @vipin8797
50
+ - [ButtonBase] Fix focus ripple lingering after blur (#48650) @siriwatknp
51
+ - [InitColorSchemeScript] Server-render in tests for React 19.3 (#48604) @Janpot
52
+ - [Transition] Mount child in same commit when opening from unmounted (#48649) @siriwatknp
53
+
54
+ ### `@mui/styled-engine@9.1.1`
55
+
56
+ - [styled-engine] Prevent enableCssLayer styles from being overridden by unlayered styles (#48603) @Janpot
57
+
58
+ ### Docs
59
+
60
+ - Send SOURCE to Brevo on newsletter subscribe (#48633) @aemartos
61
+ - fix TypeScript heading capitalization (#48619) @ifer47
62
+ - Remove outdated security section (#48628) @oliviertassinari
63
+ - [legal] Update EULA links on website (#48642) @rluzists1
64
+
65
+ ### Core
66
+
67
+ - Update dependencies to resolve Dependabot security alerts (#48641) @Janpot
68
+ - [core-docs] Pin StackBlitz demo vite to v7 and plugin-react to v5 (#48643) @Janpot
69
+ - [code-infra] Port codebase to use tsgo (#48616) @brijeshb42
70
+ - [docs-infra] Fix immutable cache headers for /\_next/static assets (#48655) @brijeshb42
71
+ - [docs-infra] Run link checker during docs build instead of as separate CI step (#48634) @Janpot
72
+ - [docs-infra] Support turbopack for docs (#48569) @brijeshb42
73
+ - [test] Cover docs landing-page composites with Argos (#48589) @LukasTy
74
+
75
+ All contributors of this release in alphabetical order: @aemartos, @brijeshb42, @ifer47, @Janpot, @LukasTy, @oliviertassinari, @rluzists1, @siriwatknp, @vipin8797
76
+
3
77
  ## 9.1.0
4
78
 
5
79
  <!-- generated comparing v9.0.1..master -->
@@ -1,9 +1,9 @@
1
1
  export declare const defaultConfig: {
2
- readonly attribute: "data-mui-color-scheme";
3
- readonly colorSchemeStorageKey: "mui-color-scheme";
4
- readonly defaultLightColorScheme: "light";
5
- readonly defaultDarkColorScheme: "dark";
6
- readonly modeStorageKey: "mui-mode";
2
+ readonly attribute: 'data-mui-color-scheme';
3
+ readonly colorSchemeStorageKey: 'mui-color-scheme';
4
+ readonly defaultLightColorScheme: 'light';
5
+ readonly defaultDarkColorScheme: 'dark';
6
+ readonly modeStorageKey: 'mui-mode';
7
7
  };
8
8
  export interface InitColorSchemeScriptProps {
9
9
  /**
@@ -1,9 +1,9 @@
1
1
  export declare const defaultConfig: {
2
- readonly attribute: "data-mui-color-scheme";
3
- readonly colorSchemeStorageKey: "mui-color-scheme";
4
- readonly defaultLightColorScheme: "light";
5
- readonly defaultDarkColorScheme: "dark";
6
- readonly modeStorageKey: "mui-mode";
2
+ readonly attribute: 'data-mui-color-scheme';
3
+ readonly colorSchemeStorageKey: 'mui-color-scheme';
4
+ readonly defaultLightColorScheme: 'light';
5
+ readonly defaultDarkColorScheme: 'dark';
6
+ readonly modeStorageKey: 'mui-mode';
7
7
  };
8
8
  export interface InitColorSchemeScriptProps {
9
9
  /**
@@ -330,6 +330,7 @@ const InputBase = /*#__PURE__*/React.forwardRef(function InputBase(inProps, ref)
330
330
  // We need to book keep the focused state manually.
331
331
  React.useEffect(() => {
332
332
  if (!muiFormControl && disabled && focused) {
333
+ // eslint-disable-next-line react-hooks/set-state-in-effect
333
334
  setFocused(false);
334
335
  if (onBlur) {
335
336
  onBlur();
@@ -321,6 +321,7 @@ const InputBase = /*#__PURE__*/React.forwardRef(function InputBase(inProps, ref)
321
321
  // We need to book keep the focused state manually.
322
322
  React.useEffect(() => {
323
323
  if (!muiFormControl && disabled && focused) {
324
+ // eslint-disable-next-line react-hooks/set-state-in-effect
324
325
  setFocused(false);
325
326
  if (onBlur) {
326
327
  onBlur();
package/NoSsr/NoSsr.js CHANGED
@@ -43,6 +43,7 @@ function NoSsr(props) {
43
43
  }, [defer]);
44
44
  React.useEffect(() => {
45
45
  if (defer) {
46
+ // eslint-disable-next-line react-hooks/set-state-in-effect
46
47
  setMountedState(true);
47
48
  }
48
49
  }, [defer]);
package/NoSsr/NoSsr.mjs CHANGED
@@ -36,6 +36,7 @@ function NoSsr(props) {
36
36
  }, [defer]);
37
37
  React.useEffect(() => {
38
38
  if (defer) {
39
+ // eslint-disable-next-line react-hooks/set-state-in-effect
39
40
  setMountedState(true);
40
41
  }
41
42
  }, [defer]);
@@ -92,17 +92,12 @@ const PopperTooltip = /*#__PURE__*/React.forwardRef(function PopperTooltip(props
92
92
  * modifiers.flip is essentially a flip for controlled/uncontrolled behavior
93
93
  */
94
94
  const [placement, setPlacement] = React.useState(rtlPlacement);
95
- const [resolvedAnchorElement, setResolvedAnchorElement] = React.useState(resolveAnchorEl(anchorEl));
95
+ const resolvedAnchorElement = React.useMemo(() => resolveAnchorEl(anchorEl), [anchorEl]);
96
96
  React.useEffect(() => {
97
97
  if (popperRef.current) {
98
98
  popperRef.current.forceUpdate();
99
99
  }
100
100
  });
101
- React.useEffect(() => {
102
- if (anchorEl) {
103
- setResolvedAnchorElement(resolveAnchorEl(anchorEl));
104
- }
105
- }, [anchorEl]);
106
101
  (0, _useEnhancedEffect.default)(() => {
107
102
  if (!resolvedAnchorElement || !open) {
108
103
  return undefined;
@@ -85,17 +85,12 @@ const PopperTooltip = /*#__PURE__*/React.forwardRef(function PopperTooltip(props
85
85
  * modifiers.flip is essentially a flip for controlled/uncontrolled behavior
86
86
  */
87
87
  const [placement, setPlacement] = React.useState(rtlPlacement);
88
- const [resolvedAnchorElement, setResolvedAnchorElement] = React.useState(resolveAnchorEl(anchorEl));
88
+ const resolvedAnchorElement = React.useMemo(() => resolveAnchorEl(anchorEl), [anchorEl]);
89
89
  React.useEffect(() => {
90
90
  if (popperRef.current) {
91
91
  popperRef.current.forceUpdate();
92
92
  }
93
93
  });
94
- React.useEffect(() => {
95
- if (anchorEl) {
96
- setResolvedAnchorElement(resolveAnchorEl(anchorEl));
97
- }
98
- }, [anchorEl]);
99
94
  useEnhancedEffect(() => {
100
95
  if (!resolvedAnchorElement || !open) {
101
96
  return undefined;
@@ -1,4 +1,4 @@
1
1
  import * as React from 'react';
2
- declare function useSelectFocusSource(): "touch" | "mouse" | "keyboard" | null;
3
- declare const SelectFocusSourceProvider: React.Provider<"touch" | "mouse" | "keyboard" | null>;
2
+ declare function useSelectFocusSource(): "keyboard" | "mouse" | "touch" | null;
3
+ declare const SelectFocusSourceProvider: React.Provider<"keyboard" | "mouse" | "touch" | null>;
4
4
  export { useSelectFocusSource, SelectFocusSourceProvider };
@@ -1,4 +1,4 @@
1
1
  import * as React from 'react';
2
- declare function useSelectFocusSource(): "touch" | "mouse" | "keyboard" | null;
3
- declare const SelectFocusSourceProvider: React.Provider<"touch" | "mouse" | "keyboard" | null>;
2
+ declare function useSelectFocusSource(): "keyboard" | "mouse" | "touch" | null;
3
+ declare const SelectFocusSourceProvider: React.Provider<"keyboard" | "mouse" | "touch" | null>;
4
4
  export { useSelectFocusSource, SelectFocusSourceProvider };
@@ -7,7 +7,7 @@ declare function SliderValueLabel(props: SliderValueLabelProps): React.ReactElem
7
7
  className?: string | undefined;
8
8
  children?: React.ReactNode;
9
9
  }, string | React.JSXElementConstructor<any>> | null;
10
+ export default SliderValueLabel;
10
11
  declare namespace SliderValueLabel {
11
12
  var propTypes: any;
12
- }
13
- export default SliderValueLabel;
13
+ }
@@ -7,7 +7,7 @@ declare function SliderValueLabel(props: SliderValueLabelProps): React.ReactElem
7
7
  className?: string | undefined;
8
8
  children?: React.ReactNode;
9
9
  }, string | React.JSXElementConstructor<any>> | null;
10
+ export default SliderValueLabel;
10
11
  declare namespace SliderValueLabel {
11
12
  var propTypes: any;
12
- }
13
- export default SliderValueLabel;
13
+ }
@@ -11,7 +11,7 @@ export interface StepContextType {
11
11
  /**
12
12
  * Provides information about the current step in Stepper.
13
13
  */
14
- declare const StepContext: React.Context<{} | StepContextType>;
14
+ declare const StepContext: React.Context<StepContextType | {}>;
15
15
  /**
16
16
  * Returns the current StepContext or an empty object if no StepContext
17
17
  * has been defined in the component tree.
@@ -11,7 +11,7 @@ export interface StepContextType {
11
11
  /**
12
12
  * Provides information about the current step in Stepper.
13
13
  */
14
- declare const StepContext: React.Context<{} | StepContextType>;
14
+ declare const StepContext: React.Context<StepContextType | {}>;
15
15
  /**
16
16
  * Returns the current StepContext or an empty object if no StepContext
17
17
  * has been defined in the component tree.
@@ -11,7 +11,7 @@ export interface StepperContextType {
11
11
  /**
12
12
  * Provides information about the current step in Stepper.
13
13
  */
14
- declare const StepperContext: React.Context<{} | StepperContextType>;
14
+ declare const StepperContext: React.Context<StepperContextType | {}>;
15
15
  /**
16
16
  * Returns the current StepperContext or an empty object if no StepperContext
17
17
  * has been defined in the component tree.
@@ -11,7 +11,7 @@ export interface StepperContextType {
11
11
  /**
12
12
  * Provides information about the current step in Stepper.
13
13
  */
14
- declare const StepperContext: React.Context<{} | StepperContextType>;
14
+ declare const StepperContext: React.Context<StepperContextType | {}>;
15
15
  /**
16
16
  * Returns the current StepperContext or an empty object if no StepperContext
17
17
  * has been defined in the component tree.
package/Tabs/Tabs.js CHANGED
@@ -615,6 +615,7 @@ const Tabs = /*#__PURE__*/React.forwardRef(function Tabs(inProps, ref) {
615
615
  return undefined;
616
616
  }, [scrollable, scrollButtons, updateScrollObserver, childrenProp?.length]);
617
617
  React.useEffect(() => {
618
+ // eslint-disable-next-line react-hooks/set-state-in-effect
618
619
  setMounted(true);
619
620
  }, []);
620
621
  React.useEffect(() => {
package/Tabs/Tabs.mjs CHANGED
@@ -608,6 +608,7 @@ const Tabs = /*#__PURE__*/React.forwardRef(function Tabs(inProps, ref) {
608
608
  return undefined;
609
609
  }, [scrollable, scrollButtons, updateScrollObserver, childrenProp?.length]);
610
610
  React.useEffect(() => {
611
+ // eslint-disable-next-line react-hooks/set-state-in-effect
611
612
  setMounted(true);
612
613
  }, []);
613
614
  React.useEffect(() => {
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/material v9.1.0
2
+ * @mui/material v9.1.2
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
package/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/material v9.1.0
2
+ * @mui/material v9.1.2
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -12,11 +12,14 @@ var React = _interopRequireWildcard(require("react"));
12
12
  var _propTypes = _interopRequireDefault(require("prop-types"));
13
13
  var _useEnhancedEffect = _interopRequireDefault(require("@mui/utils/useEnhancedEffect"));
14
14
  var _useValueAsRef = _interopRequireDefault(require("@mui/utils/useValueAsRef"));
15
- var _TransitionGroupContext = _interopRequireDefault(require("react-transition-group/TransitionGroupContext"));
15
+ var _TransitionGroupContext = _interopRequireDefault(require("react-transition-group/cjs/TransitionGroupContext.js"));
16
16
  var _utils = require("../transitions/utils");
17
17
  var _jsxRuntime = require("react/jsx-runtime");
18
18
  // Material UI transitions must still work inside react-transition-group's TransitionGroup.
19
19
  // Import only its context module; do not import its Transition or TransitionGroup components.
20
+ // Use RTG's explicit CJS file for Node ESM/SSR; package.json's `browser` field redirects
21
+ // browser bundles to RTG's ESM file.
22
+ // eslint-disable-next-line import/extensions -- Node ESM needs the explicit .js extension.
20
23
 
21
24
  function resolveTimeouts(timeout) {
22
25
  if (timeout == null) {
@@ -100,6 +103,16 @@ function Transition(props) {
100
103
  });
101
104
  const statusRef = React.useRef(status);
102
105
  statusRef.current = status;
106
+
107
+ // Opening from `unmounted`: mount the child in the same commit that `in` turns
108
+ // true so its ref is attached before effects run. react-transition-group did
109
+ // this by deriving the status from props during render; handling it in a
110
+ // layout effect instead would add a commit where the child is still null,
111
+ // breaking consumers that read the ref right after `in` flips.
112
+ if (inProp && status === 'unmounted') {
113
+ statusRef.current = 'exited';
114
+ setStatus('exited');
115
+ }
103
116
  const shouldAppearOnMountRef = React.useRef(inProp && shouldEnterOnMount);
104
117
  const mountedRef = React.useRef(false);
105
118
  const nextCallbackRef = React.useRef(null);
@@ -284,7 +297,8 @@ function Transition(props) {
284
297
  }, [cancelPendingCallback, updateStatus]);
285
298
 
286
299
  // Reconcile the rendered status after `in` or status changes:
287
- // - opening from unmounted first renders the child as exited so refs exist.
300
+ // - opening from unmounted is handled during render (see above) so the child
301
+ // is committed as exited with its ref attached before this effect runs.
288
302
  // - unmountOnExit removes the child after the exited state commits.
289
303
  // This matches react-transition-group's observable status steps without
290
304
  // running work after unrelated commits.
@@ -294,12 +308,7 @@ function Transition(props) {
294
308
  }
295
309
  const current = statusRef.current;
296
310
  if (inProp) {
297
- if (current === 'unmounted') {
298
- // Opening from unmounted needs one render with the child present so
299
- // refs are attached before the enter animation starts.
300
- statusRef.current = 'exited';
301
- setStatus('exited');
302
- } else if (current !== 'entering' && current !== 'entered') {
311
+ if (current !== 'entering' && current !== 'entered') {
303
312
  updateStatus(false, 'entering');
304
313
  }
305
314
  } else if (current === 'entering' || current === 'entered') {
@@ -7,7 +7,10 @@ import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
7
7
  import useValueAsRef from '@mui/utils/useValueAsRef';
8
8
  // Material UI transitions must still work inside react-transition-group's TransitionGroup.
9
9
  // Import only its context module; do not import its Transition or TransitionGroup components.
10
- import TransitionGroupContext from 'react-transition-group/TransitionGroupContext';
10
+ // Use RTG's explicit CJS file for Node ESM/SSR; package.json's `browser` field redirects
11
+ // browser bundles to RTG's ESM file.
12
+ // eslint-disable-next-line import/extensions -- Node ESM needs the explicit .js extension.
13
+ import TransitionGroupContext from 'react-transition-group/cjs/TransitionGroupContext.js';
11
14
  import { reflow } from "../transitions/utils.mjs";
12
15
  import { jsx as _jsx } from "react/jsx-runtime";
13
16
  function resolveTimeouts(timeout) {
@@ -92,6 +95,16 @@ function Transition(props) {
92
95
  });
93
96
  const statusRef = React.useRef(status);
94
97
  statusRef.current = status;
98
+
99
+ // Opening from `unmounted`: mount the child in the same commit that `in` turns
100
+ // true so its ref is attached before effects run. react-transition-group did
101
+ // this by deriving the status from props during render; handling it in a
102
+ // layout effect instead would add a commit where the child is still null,
103
+ // breaking consumers that read the ref right after `in` flips.
104
+ if (inProp && status === 'unmounted') {
105
+ statusRef.current = 'exited';
106
+ setStatus('exited');
107
+ }
95
108
  const shouldAppearOnMountRef = React.useRef(inProp && shouldEnterOnMount);
96
109
  const mountedRef = React.useRef(false);
97
110
  const nextCallbackRef = React.useRef(null);
@@ -276,7 +289,8 @@ function Transition(props) {
276
289
  }, [cancelPendingCallback, updateStatus]);
277
290
 
278
291
  // Reconcile the rendered status after `in` or status changes:
279
- // - opening from unmounted first renders the child as exited so refs exist.
292
+ // - opening from unmounted is handled during render (see above) so the child
293
+ // is committed as exited with its ref attached before this effect runs.
280
294
  // - unmountOnExit removes the child after the exited state commits.
281
295
  // This matches react-transition-group's observable status steps without
282
296
  // running work after unrelated commits.
@@ -286,12 +300,7 @@ function Transition(props) {
286
300
  }
287
301
  const current = statusRef.current;
288
302
  if (inProp) {
289
- if (current === 'unmounted') {
290
- // Opening from unmounted needs one render with the child present so
291
- // refs are attached before the enter animation starts.
292
- statusRef.current = 'exited';
293
- setStatus('exited');
294
- } else if (current !== 'entering' && current !== 'entered') {
303
+ if (current !== 'entering' && current !== 'entered') {
295
304
  updateStatus(false, 'entering');
296
305
  }
297
306
  } else if (current === 'entering' || current === 'entered') {
@@ -5,4 +5,12 @@ declare module 'react-transition-group/TransitionGroupContext' {
5
5
  }
6
6
  const TransitionGroupContext: React.Context<TransitionGroupContextValue | null>;
7
7
  export default TransitionGroupContext;
8
+ }
9
+ declare module 'react-transition-group/cjs/TransitionGroupContext.js' {
10
+ import * as React from 'react';
11
+ interface TransitionGroupContextValue {
12
+ isMounting: boolean;
13
+ }
14
+ const TransitionGroupContext: React.Context<TransitionGroupContextValue | null>;
15
+ export default TransitionGroupContext;
8
16
  }
@@ -5,4 +5,12 @@ declare module 'react-transition-group/TransitionGroupContext' {
5
5
  }
6
6
  const TransitionGroupContext: React.Context<TransitionGroupContextValue | null>;
7
7
  export default TransitionGroupContext;
8
+ }
9
+ declare module 'react-transition-group/cjs/TransitionGroupContext.js' {
10
+ import * as React from 'react';
11
+ interface TransitionGroupContextValue {
12
+ isMounting: boolean;
13
+ }
14
+ const TransitionGroupContext: React.Context<TransitionGroupContextValue | null>;
15
+ export default TransitionGroupContext;
8
16
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/material",
3
- "version": "9.1.0",
3
+ "version": "9.1.2",
4
4
  "author": "MUI Team",
5
5
  "description": "Material UI is an open-source React component library that implements Google's Material Design. It's comprehensive and can be used in production out of the box.",
6
6
  "license": "MIT",
@@ -33,10 +33,10 @@
33
33
  "prop-types": "^15.8.1",
34
34
  "react-is": "^19.2.6",
35
35
  "react-transition-group": "^4.4.5",
36
- "@mui/core-downloads-tracker": "^9.1.0",
37
- "@mui/types": "^9.0.0",
38
- "@mui/utils": "^9.1.0",
39
- "@mui/system": "^9.1.0"
36
+ "@mui/system": "^9.1.2",
37
+ "@mui/core-downloads-tracker": "^9.1.2",
38
+ "@mui/types": "^9.1.1",
39
+ "@mui/utils": "^9.1.1"
40
40
  },
41
41
  "peerDependencies": {
42
42
  "@emotion/react": "^11.5.0",
@@ -44,7 +44,7 @@
44
44
  "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
45
45
  "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
46
46
  "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0",
47
- "@mui/material-pigment-css": "^9.1.0"
47
+ "@mui/material-pigment-css": "^9.1.1"
48
48
  },
49
49
  "peerDependenciesMeta": {
50
50
  "@types/react": {
@@ -67,6 +67,9 @@
67
67
  "engines": {
68
68
  "node": ">=14.0.0"
69
69
  },
70
+ "browser": {
71
+ "react-transition-group/cjs/TransitionGroupContext.js": "react-transition-group/esm/TransitionGroupContext.js"
72
+ },
70
73
  "pigment-css": {
71
74
  "vite": {
72
75
  "include": [
@@ -27,19 +27,19 @@ declare const getInitColorSchemeScript: typeof deprecatedGetInitColorSchemeScrip
27
27
  */
28
28
  export declare const CssVarsProvider: (props: import("react").PropsWithChildren<Partial<import("@mui/system").CssVarsProviderConfig<SupportedColorScheme>> & {
29
29
  theme?: {
30
- cssVariables?: false | undefined;
31
- cssVarPrefix?: string | undefined;
32
- colorSchemes: Partial<Record<SupportedColorScheme, any>>;
33
- colorSchemeSelector?: "media" | "class" | "data" | string | undefined;
34
- } | {
35
30
  $$material: {
36
31
  cssVariables?: false | undefined;
37
32
  cssVarPrefix?: string | undefined;
38
33
  colorSchemes: Partial<Record<SupportedColorScheme, any>>;
39
- colorSchemeSelector?: "media" | "class" | "data" | string | undefined;
34
+ colorSchemeSelector?: 'media' | 'class' | 'data' | string | undefined;
40
35
  };
36
+ } | {
37
+ cssVariables?: false | undefined;
38
+ cssVarPrefix?: string | undefined;
39
+ colorSchemes: Partial<Record<SupportedColorScheme, any>>;
40
+ colorSchemeSelector?: 'media' | 'class' | 'data' | string | undefined;
41
41
  } | undefined;
42
- defaultMode?: "light" | "dark" | "system" | undefined;
42
+ defaultMode?: 'light' | 'dark' | 'system' | undefined;
43
43
  documentNode?: Document | null | undefined;
44
44
  colorSchemeNode?: Element | null | undefined;
45
45
  storageManager?: import("@mui/system").StorageManager | null | undefined;
@@ -27,19 +27,19 @@ declare const getInitColorSchemeScript: typeof deprecatedGetInitColorSchemeScrip
27
27
  */
28
28
  export declare const CssVarsProvider: (props: import("react").PropsWithChildren<Partial<import("@mui/system").CssVarsProviderConfig<SupportedColorScheme>> & {
29
29
  theme?: {
30
- cssVariables?: false | undefined;
31
- cssVarPrefix?: string | undefined;
32
- colorSchemes: Partial<Record<SupportedColorScheme, any>>;
33
- colorSchemeSelector?: "media" | "class" | "data" | string | undefined;
34
- } | {
35
30
  $$material: {
36
31
  cssVariables?: false | undefined;
37
32
  cssVarPrefix?: string | undefined;
38
33
  colorSchemes: Partial<Record<SupportedColorScheme, any>>;
39
- colorSchemeSelector?: "media" | "class" | "data" | string | undefined;
34
+ colorSchemeSelector?: 'media' | 'class' | 'data' | string | undefined;
40
35
  };
36
+ } | {
37
+ cssVariables?: false | undefined;
38
+ cssVarPrefix?: string | undefined;
39
+ colorSchemes: Partial<Record<SupportedColorScheme, any>>;
40
+ colorSchemeSelector?: 'media' | 'class' | 'data' | string | undefined;
41
41
  } | undefined;
42
- defaultMode?: "light" | "dark" | "system" | undefined;
42
+ defaultMode?: 'light' | 'dark' | 'system' | undefined;
43
43
  documentNode?: Document | null | undefined;
44
44
  colorSchemeNode?: Element | null | undefined;
45
45
  storageManager?: import("@mui/system").StorageManager | null | undefined;
@@ -1,10 +1,10 @@
1
1
  declare const _default: <T extends {
2
2
  rootSelector?: string | undefined;
3
- colorSchemeSelector?: "media" | "class" | "data" | string | undefined;
3
+ colorSchemeSelector?: 'media' | 'class' | 'data' | string | undefined;
4
4
  colorSchemes?: Record<string, any> | undefined;
5
5
  defaultColorScheme?: string | undefined;
6
6
  cssVarPrefix?: string | undefined;
7
- }>(theme: T) => (colorScheme: keyof T["colorSchemes"] | undefined, css: Record<string, any>) => string | {
7
+ }>(theme: T) => (colorScheme: keyof T['colorSchemes'] | undefined, css: Record<string, any>) => string | {
8
8
  [x: string]: Record<string, any>;
9
9
  "@media (prefers-color-scheme: dark)": {
10
10
  [x: string]: Record<string, any>;
@@ -1,10 +1,10 @@
1
1
  declare const _default: <T extends {
2
2
  rootSelector?: string | undefined;
3
- colorSchemeSelector?: "media" | "class" | "data" | string | undefined;
3
+ colorSchemeSelector?: 'media' | 'class' | 'data' | string | undefined;
4
4
  colorSchemes?: Record<string, any> | undefined;
5
5
  defaultColorScheme?: string | undefined;
6
6
  cssVarPrefix?: string | undefined;
7
- }>(theme: T) => (colorScheme: keyof T["colorSchemes"] | undefined, css: Record<string, any>) => string | {
7
+ }>(theme: T) => (colorScheme: keyof T['colorSchemes'] | undefined, css: Record<string, any>) => string | {
8
8
  [x: string]: Record<string, any>;
9
9
  "@media (prefers-color-scheme: dark)": {
10
10
  [x: string]: Record<string, any>;
@@ -1,2 +1,2 @@
1
- declare const _default: "$$material";
1
+ declare const _default = "$$material";
2
2
  export default _default;
@@ -1,2 +1,2 @@
1
- declare const _default: "$$material";
1
+ declare const _default = "$$material";
2
2
  export default _default;
@@ -267,6 +267,7 @@ function useAutocomplete(props) {
267
267
  // Ensure the focusedItem is never inconsistent
268
268
  React.useEffect(() => {
269
269
  if (multiple && focusedItem > value.length - 1) {
270
+ // eslint-disable-next-line react-hooks/set-state-in-effect
270
271
  setFocusedItem(-1);
271
272
  focusItem(-1);
272
273
  }
@@ -853,13 +854,13 @@ function useAutocomplete(props) {
853
854
  break;
854
855
  case 'Enter':
855
856
  {
856
- // In freeSolo, only select the highlighted option if the user hasn't
857
- // typed new text (inputPristine) or explicitly interacted with an option
858
- // (keyboard, mouse, or touch any non-null reason). This lets typed
859
- // text win over a programmatic highlight (reason=null, e.g. from
860
- // syncHighlightedIndex matching a previous value) while still honoring
861
- // deliberate user interactions like hovering a suggestion then pressing Enter.
862
- const shouldSelectHighlighted = !freeSolo || inputPristine || highlightReasonRef.current !== null;
857
+ // In freeSolo, once the user has typed new text, Enter should commit that text instead
858
+ // of treating a programmatic highlight as an intentional selection. Programmatic
859
+ // highlights include autoHighlight and syncHighlightedIndex matching a previous value.
860
+ const hasProgrammaticHighlight = popupOpen && highlightedIndexRef.current !== -1 && highlightReasonRef.current === null;
861
+ const shouldCommitFreeSoloOverProgrammaticHighlight = freeSolo && !inputPristine && hasProgrammaticHighlight;
862
+ const shouldSelectHighlighted = !freeSolo || inputPristine || !hasProgrammaticHighlight;
863
+ const shouldPreventSubmitAfterFreeSoloCommit = shouldCommitFreeSoloOverProgrammaticHighlight && !touchScrolledRef.current;
863
864
  if (highlightedIndexRef.current !== -1 && popupOpen && shouldSelectHighlighted &&
864
865
  // After a touch-scroll the highlight is stale (the user scrolled
865
866
  // past it), so skip selection until the next deliberate interaction.
@@ -879,8 +880,8 @@ function useAutocomplete(props) {
879
880
  inputRef.current.setSelectionRange(inputRef.current.value.length, inputRef.current.value.length);
880
881
  }
881
882
  } else if (freeSolo && inputValue !== '' && inputValueIsSelectedValue === false) {
882
- if (multiple) {
883
- // Allow people to add new values before they submit the form.
883
+ if (multiple || shouldPreventSubmitAfterFreeSoloCommit) {
884
+ // Allow people to commit the freeSolo value before they submit the form.
884
885
  event.preventDefault();
885
886
  }
886
887
  selectNewValue(event, inputValue, 'createOption', 'freeSolo');
@@ -259,6 +259,7 @@ function useAutocomplete(props) {
259
259
  // Ensure the focusedItem is never inconsistent
260
260
  React.useEffect(() => {
261
261
  if (multiple && focusedItem > value.length - 1) {
262
+ // eslint-disable-next-line react-hooks/set-state-in-effect
262
263
  setFocusedItem(-1);
263
264
  focusItem(-1);
264
265
  }
@@ -845,13 +846,13 @@ function useAutocomplete(props) {
845
846
  break;
846
847
  case 'Enter':
847
848
  {
848
- // In freeSolo, only select the highlighted option if the user hasn't
849
- // typed new text (inputPristine) or explicitly interacted with an option
850
- // (keyboard, mouse, or touch any non-null reason). This lets typed
851
- // text win over a programmatic highlight (reason=null, e.g. from
852
- // syncHighlightedIndex matching a previous value) while still honoring
853
- // deliberate user interactions like hovering a suggestion then pressing Enter.
854
- const shouldSelectHighlighted = !freeSolo || inputPristine || highlightReasonRef.current !== null;
849
+ // In freeSolo, once the user has typed new text, Enter should commit that text instead
850
+ // of treating a programmatic highlight as an intentional selection. Programmatic
851
+ // highlights include autoHighlight and syncHighlightedIndex matching a previous value.
852
+ const hasProgrammaticHighlight = popupOpen && highlightedIndexRef.current !== -1 && highlightReasonRef.current === null;
853
+ const shouldCommitFreeSoloOverProgrammaticHighlight = freeSolo && !inputPristine && hasProgrammaticHighlight;
854
+ const shouldSelectHighlighted = !freeSolo || inputPristine || !hasProgrammaticHighlight;
855
+ const shouldPreventSubmitAfterFreeSoloCommit = shouldCommitFreeSoloOverProgrammaticHighlight && !touchScrolledRef.current;
855
856
  if (highlightedIndexRef.current !== -1 && popupOpen && shouldSelectHighlighted &&
856
857
  // After a touch-scroll the highlight is stale (the user scrolled
857
858
  // past it), so skip selection until the next deliberate interaction.
@@ -871,8 +872,8 @@ function useAutocomplete(props) {
871
872
  inputRef.current.setSelectionRange(inputRef.current.value.length, inputRef.current.value.length);
872
873
  }
873
874
  } else if (freeSolo && inputValue !== '' && inputValueIsSelectedValue === false) {
874
- if (multiple) {
875
- // Allow people to add new values before they submit the form.
875
+ if (multiple || shouldPreventSubmitAfterFreeSoloCommit) {
876
+ // Allow people to commit the freeSolo value before they submit the form.
876
877
  event.preventDefault();
877
878
  }
878
879
  selectNewValue(event, inputValue, 'createOption', 'freeSolo');
@@ -36,6 +36,7 @@ function useScrollTrigger(options = {}) {
36
36
  const [trigger, setTrigger] = React.useState(() => getTrigger(store, other));
37
37
  React.useEffect(() => {
38
38
  if (target === null) {
39
+ // eslint-disable-next-line react-hooks/set-state-in-effect
39
40
  return setTrigger(false);
40
41
  }
41
42
  const handleScroll = () => {
@@ -30,6 +30,7 @@ export default function useScrollTrigger(options = {}) {
30
30
  const [trigger, setTrigger] = React.useState(() => getTrigger(store, other));
31
31
  React.useEffect(() => {
32
32
  if (target === null) {
33
+ // eslint-disable-next-line react-hooks/set-state-in-effect
33
34
  return setTrigger(false);
34
35
  }
35
36
  const handleScroll = () => {
@@ -3,5 +3,5 @@ declare const memoTheme: (styleFn: (props: {
3
3
  theme: Theme;
4
4
  }) => import("@mui/styled-engine").CSSInterpolation) => (props: {
5
5
  theme: Theme;
6
- }) => string | number | boolean | import("@mui/styled-engine").ComponentSelector | import("@mui/styled-engine").Keyframes | import("@mui/styled-engine").SerializedStyles | import("@mui/styled-engine").CSSObject | import("@mui/styled-engine").ArrayCSSInterpolation | null;
6
+ }) => string | number | boolean | import("@mui/styled-engine").ArrayCSSInterpolation | import("@mui/styled-engine").CSSObject | import("@mui/styled-engine").ComponentSelector | import("@mui/styled-engine").SerializedStyles | import("@mui/styled-engine").Keyframes | null;
7
7
  export default memoTheme;
@@ -3,5 +3,5 @@ declare const memoTheme: (styleFn: (props: {
3
3
  theme: Theme;
4
4
  }) => import("@mui/styled-engine").CSSInterpolation) => (props: {
5
5
  theme: Theme;
6
- }) => string | number | boolean | import("@mui/styled-engine").ComponentSelector | import("@mui/styled-engine").Keyframes | import("@mui/styled-engine").SerializedStyles | import("@mui/styled-engine").CSSObject | import("@mui/styled-engine").ArrayCSSInterpolation | null;
6
+ }) => string | number | boolean | import("@mui/styled-engine").ArrayCSSInterpolation | import("@mui/styled-engine").CSSObject | import("@mui/styled-engine").ComponentSelector | import("@mui/styled-engine").SerializedStyles | import("@mui/styled-engine").Keyframes | null;
7
7
  export default memoTheme;
@@ -77,5 +77,5 @@ name: T, parameters: (T extends 'root' ? {
77
77
  }): [ElementType, {
78
78
  className: string;
79
79
  ownerState: OwnerState & SlotOwnerState;
80
- } & AdditionalProps & SlotProps & ExternalSlotProps & ExtractComponentProps<Exclude<Exclude<ExternalForwardedProps["slotProps"], undefined>[T], undefined>>];
80
+ } & AdditionalProps & SlotProps & ExternalSlotProps & ExtractComponentProps<Exclude<Exclude<ExternalForwardedProps['slotProps'], undefined>[T], undefined>>];
81
81
  export {};
@@ -77,5 +77,5 @@ name: T, parameters: (T extends 'root' ? {
77
77
  }): [ElementType, {
78
78
  className: string;
79
79
  ownerState: OwnerState & SlotOwnerState;
80
- } & AdditionalProps & SlotProps & ExternalSlotProps & ExtractComponentProps<Exclude<Exclude<ExternalForwardedProps["slotProps"], undefined>[T], undefined>>];
80
+ } & AdditionalProps & SlotProps & ExternalSlotProps & ExtractComponentProps<Exclude<Exclude<ExternalForwardedProps['slotProps'], undefined>[T], undefined>>];
81
81
  export {};
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 = "9.1.0";
7
+ const version = exports.version = "9.1.2";
8
8
  const major = exports.major = Number("9");
9
9
  const minor = exports.minor = Number("1");
10
- const patch = exports.patch = Number("0");
10
+ const patch = exports.patch = Number("2");
11
11
  const prerelease = exports.prerelease = undefined;
12
12
  var _default = exports.default = version;
package/version/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
- export const version = "9.1.0";
1
+ export const version = "9.1.2";
2
2
  export const major = Number("9");
3
3
  export const minor = Number("1");
4
- export const patch = Number("0");
4
+ export const patch = Number("2");
5
5
  export const prerelease = undefined;
6
6
  export default version;