@mui/material 9.1.1 → 9.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.
Files changed (48) hide show
  1. package/Avatar/Avatar.js +2 -0
  2. package/Avatar/Avatar.mjs +2 -0
  3. package/ButtonBase/ButtonBase.js +1 -1
  4. package/ButtonBase/ButtonBase.mjs +1 -1
  5. package/CHANGELOG.md +74 -0
  6. package/ClickAwayListener/ClickAwayListener.js +1 -1
  7. package/ClickAwayListener/ClickAwayListener.mjs +1 -1
  8. package/InputBase/InputBase.js +1 -0
  9. package/InputBase/InputBase.mjs +1 -0
  10. package/ListItem/ListItem.d.mts +2 -1
  11. package/ListItem/ListItem.d.ts +2 -1
  12. package/ListItem/ListItem.js +1 -1
  13. package/ListItem/ListItem.mjs +1 -1
  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/Rating/Rating.js +2 -2
  19. package/Rating/Rating.mjs +2 -2
  20. package/Select/SelectInput.js +3 -0
  21. package/Select/SelectInput.mjs +3 -0
  22. package/Stack/Stack.d.mts +1 -1
  23. package/Stack/Stack.d.ts +1 -1
  24. package/Stack/Stack.js +1 -1
  25. package/Stack/Stack.mjs +1 -1
  26. package/Tabs/Tabs.js +1 -0
  27. package/Tabs/Tabs.mjs +1 -0
  28. package/Tooltip/Tooltip.js +2 -2
  29. package/Tooltip/Tooltip.mjs +2 -2
  30. package/index.js +1 -1
  31. package/index.mjs +1 -1
  32. package/internal/SwitchBase.js +1 -1
  33. package/internal/SwitchBase.mjs +1 -1
  34. package/internal/Transition.js +4 -1
  35. package/internal/Transition.mjs +4 -1
  36. package/internal/react-transition-group.d.mts +8 -0
  37. package/internal/react-transition-group.d.ts +8 -0
  38. package/locale/zhCN.js +21 -0
  39. package/locale/zhCN.mjs +21 -0
  40. package/package.json +8 -5
  41. package/useAutocomplete/useAutocomplete.js +10 -9
  42. package/useAutocomplete/useAutocomplete.mjs +10 -9
  43. package/useScrollTrigger/useScrollTrigger.js +2 -1
  44. package/useScrollTrigger/useScrollTrigger.mjs +2 -1
  45. package/utils/types.d.mts +1 -1
  46. package/utils/types.d.ts +1 -1
  47. package/version/index.js +3 -3
  48. package/version/index.mjs +3 -3
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();
@@ -227,7 +227,7 @@ const ButtonBase = /*#__PURE__*/React.forwardRef(function ButtonBase(inProps, re
227
227
  }
228
228
  }, false);
229
229
  const handleFocus = (0, _useEventCallback.default)(event => {
230
- // Fix for https://github.com/facebook/react/issues/7769
230
+ // Fix for https://github.com/react/react/issues/7769
231
231
  if (!buttonRef.current) {
232
232
  buttonRef.current = event.currentTarget;
233
233
  }
@@ -220,7 +220,7 @@ const ButtonBase = /*#__PURE__*/React.forwardRef(function ButtonBase(inProps, re
220
220
  }
221
221
  }, false);
222
222
  const handleFocus = useEventCallback(event => {
223
- // Fix for https://github.com/facebook/react/issues/7769
223
+ // Fix for https://github.com/react/react/issues/7769
224
224
  if (!buttonRef.current) {
225
225
  buttonRef.current = event.currentTarget;
226
226
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,79 @@
1
1
  # [Versions](https://mui.com/material-ui/getting-started/versions/)
2
2
 
3
+ ## 9.2.0
4
+
5
+ <!-- generated comparing v9.1.2..master -->
6
+
7
+ _Jul 2, 2026_
8
+
9
+ A big thanks to the 9 contributors who made this release possible.
10
+
11
+ - ⚙️ Add support for [`data-*` attributes on `slotProps`](https://mui.com/material-ui/guides/typescript/#allowing-data-attributes-on-slotprops).
12
+
13
+ ### `@mui/material@9.1.3`
14
+
15
+ - [l10n] Add missing MuiPagination localization to zh-CN locale (#48741) @greymoth-jp
16
+ - [select] Guard display ref during mouse down (#48744) @michelengelen
17
+
18
+ ### `@mui/utils@9.1.3`
19
+
20
+ - [utils] Add opt-in `DataAttributesOverrides` augmentation for slot props (#48554) @LukasTy
21
+
22
+ ### Docs
23
+
24
+ - [docs] Improve Icon Dialog responsiveness on small screens (#48639) @Prakash1185
25
+ - [docs] Fix invalid UTF-8 in skill references (#48739) @mturac
26
+
27
+ ### Core
28
+
29
+ - [code-infra] Resolve Renovate dashboard warnings (#48700) @Sushantplive
30
+ - [code-infra] Validate npm publishing through dry run (#48691) @brijeshb42
31
+ - [code-infra] Run prettier after renovate update (#48754) @Janpot
32
+ - [code-infra] Fix 'A11y results committed?' check on react-pinned nightly jobs (#48740) @Janpot
33
+ - [core] Remove leftover Joy UI references (#48719) @siriwatknp
34
+ - [code-infra] Bump react-router to 7.15.1 (#48725) @Janpot
35
+ - [docs-infra] Drive docs analytics IDs via ANALYTICS_ENV (#48694) @Janpot
36
+ - [docs-infra] Pre-render API page descriptions (#48693) @brijeshb42
37
+ - [code-infra][icons-material] Build lib/package.json with code-infra --no-expand (#48689) @Janpot
38
+ - [code-infra] Fix react@18/next nightly workflow (#48635) @Janpot
39
+
40
+ All contributors of this release in alphabetical order: @brijeshb42, @greymoth-jp, @Janpot, @LukasTy, @michelengelen, @mturac, @Prakash1185, @siriwatknp, @Sushantplive
41
+
42
+ ## 9.1.2
43
+
44
+ <!-- generated comparing v9.1.1..master -->
45
+
46
+ _Jun 23, 2026_
47
+
48
+ A big thanks to the 5 contributors who made this release possible.
49
+
50
+ ### `@mui/material@9.1.2`
51
+
52
+ - [autocomplete] Don't submit forms when committing `freeSolo` value with Enter key (#48679) @mj12albert
53
+ - [transitions] Fix RTG import in ESM (#48645) @mj12albert
54
+
55
+ ### `@mui/system@9.1.2`
56
+
57
+ - [InitColorSchemeScript] Fix script tag warning in Next.js 16 dev mode (#48671) @siriwatknp
58
+
59
+ ### Docs
60
+
61
+ - Fix typos in release instructions (#48687) @brijeshb42
62
+ - Update @mui/x-\* packages to latest (#48661) @Janpot
63
+
64
+ ### Core
65
+
66
+ - [code-infra] Convert leaf @mui/system .js+.d.ts pairs to TypeScript (part 1) (#48578) @Janpot
67
+ - [code-infra] Bump to latest code-infra packages (#48672) @brijeshb42
68
+ - [code-infra] Resolve remaining minimatch advisory (#48662) @Janpot
69
+ - [code-infra] Bump nx to resolve minimatch advisory (#48658) @Janpot
70
+ - [core] Drop @babel/\* pnpm overrides (#48710) @Janpot
71
+ - [docs-infra] Revert "Pin StackBlitz demo vite to v7 and plugin-react to v5" (#48709) @Janpot
72
+ - [docs-infra] Fix code-block copy button broken on direct page load (#48653) @brijeshb42
73
+ - [test] Stabilize Data Grid demo data in Argos screenshots (#48654) @LukasTy
74
+
75
+ All contributors of this release in alphabetical order: @brijeshb42, @Janpot, @LukasTy, @mj12albert, @siriwatknp
76
+
3
77
  ## 9.1.1
4
78
 
5
79
  <!-- generated comparing v9.1.0..master -->
@@ -50,7 +50,7 @@ function ClickAwayListener(props) {
50
50
  const syntheticEventRef = React.useRef(false);
51
51
  React.useEffect(() => {
52
52
  // Ensure that this component is not "activated" synchronously.
53
- // https://github.com/facebook/react/issues/20074
53
+ // https://github.com/react/react/issues/20074
54
54
  setTimeout(() => {
55
55
  activatedRef.current = true;
56
56
  }, 0);
@@ -44,7 +44,7 @@ function ClickAwayListener(props) {
44
44
  const syntheticEventRef = React.useRef(false);
45
45
  React.useEffect(() => {
46
46
  // Ensure that this component is not "activated" synchronously.
47
- // https://github.com/facebook/react/issues/20074
47
+ // https://github.com/react/react/issues/20074
48
48
  setTimeout(() => {
49
49
  activatedRef.current = true;
50
50
  }, 0);
@@ -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();
@@ -4,6 +4,7 @@ import { Theme } from "../styles/index.mjs";
4
4
  import { OverridableComponent, OverrideProps } from "../OverridableComponent/index.mjs";
5
5
  import { ListItemClasses } from "./listItemClasses.mjs";
6
6
  import { SlotProps } from "../utils/types.mjs";
7
+ export interface ListItemRootSlotPropsOverrides {}
7
8
  export interface ListItemSecondaryActionSlotPropsOverrides {}
8
9
 
9
10
  /**
@@ -62,7 +63,7 @@ export interface ListItemOwnProps extends ListItemBaseProps {
62
63
  * @default {}
63
64
  */
64
65
  slotProps?: {
65
- root?: React.HTMLAttributes<HTMLDivElement> | undefined;
66
+ root?: SlotProps<React.ElementType<React.HTMLAttributes<HTMLDivElement>>, ListItemRootSlotPropsOverrides, ListItemOwnerState> | undefined;
66
67
  secondaryAction?: SlotProps<React.ElementType<React.HTMLAttributes<HTMLDivElement>>, ListItemSecondaryActionSlotPropsOverrides, ListItemOwnerState> | undefined;
67
68
  } | undefined;
68
69
  /**
@@ -4,6 +4,7 @@ import { Theme } from "../styles/index.js";
4
4
  import { OverridableComponent, OverrideProps } from "../OverridableComponent/index.js";
5
5
  import { ListItemClasses } from "./listItemClasses.js";
6
6
  import { SlotProps } from "../utils/types.js";
7
+ export interface ListItemRootSlotPropsOverrides {}
7
8
  export interface ListItemSecondaryActionSlotPropsOverrides {}
8
9
 
9
10
  /**
@@ -62,7 +63,7 @@ export interface ListItemOwnProps extends ListItemBaseProps {
62
63
  * @default {}
63
64
  */
64
65
  slotProps?: {
65
- root?: React.HTMLAttributes<HTMLDivElement> | undefined;
66
+ root?: SlotProps<React.ElementType<React.HTMLAttributes<HTMLDivElement>>, ListItemRootSlotPropsOverrides, ListItemOwnerState> | undefined;
66
67
  secondaryAction?: SlotProps<React.ElementType<React.HTMLAttributes<HTMLDivElement>>, ListItemSecondaryActionSlotPropsOverrides, ListItemOwnerState> | undefined;
67
68
  } | undefined;
68
69
  /**
@@ -265,7 +265,7 @@ process.env.NODE_ENV !== "production" ? ListItem.propTypes /* remove-proptypes *
265
265
  * @default {}
266
266
  */
267
267
  slotProps: _propTypes.default.shape({
268
- root: _propTypes.default.object,
268
+ root: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object]),
269
269
  secondaryAction: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object])
270
270
  }),
271
271
  /**
@@ -257,7 +257,7 @@ process.env.NODE_ENV !== "production" ? ListItem.propTypes /* remove-proptypes *
257
257
  * @default {}
258
258
  */
259
259
  slotProps: PropTypes.shape({
260
- root: PropTypes.object,
260
+ root: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
261
261
  secondaryAction: PropTypes.oneOfType([PropTypes.func, PropTypes.object])
262
262
  }),
263
263
  /**
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;
package/Rating/Rating.js CHANGED
@@ -157,7 +157,7 @@ const RatingIcon = (0, _zeroStyled.styled)('span', {
157
157
  duration: theme.transitions.duration.shortest
158
158
  }),
159
159
  // Fix mouseLeave issue.
160
- // https://github.com/facebook/react/issues/4492
160
+ // https://github.com/react/react/issues/4492
161
161
  pointerEvents: 'none',
162
162
  variants: [{
163
163
  props: ({
@@ -452,7 +452,7 @@ const Rating = /*#__PURE__*/React.forwardRef(function Rating(inProps, ref) {
452
452
  };
453
453
  const handleClear = event => {
454
454
  // Ignore keyboard events
455
- // https://github.com/facebook/react/issues/7407
455
+ // https://github.com/react/react/issues/7407
456
456
  if (event.clientX === 0 && event.clientY === 0) {
457
457
  return;
458
458
  }
package/Rating/Rating.mjs CHANGED
@@ -150,7 +150,7 @@ const RatingIcon = styled('span', {
150
150
  duration: theme.transitions.duration.shortest
151
151
  }),
152
152
  // Fix mouseLeave issue.
153
- // https://github.com/facebook/react/issues/4492
153
+ // https://github.com/react/react/issues/4492
154
154
  pointerEvents: 'none',
155
155
  variants: [{
156
156
  props: ({
@@ -445,7 +445,7 @@ const Rating = /*#__PURE__*/React.forwardRef(function Rating(inProps, ref) {
445
445
  };
446
446
  const handleClear = event => {
447
447
  // Ignore keyboard events
448
- // https://github.com/facebook/react/issues/7407
448
+ // https://github.com/react/react/issues/7407
449
449
  if (event.clientX === 0 && event.clientY === 0) {
450
450
  return;
451
451
  }
@@ -383,6 +383,9 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
383
383
  }
384
384
  // Hijack the default focus behavior.
385
385
  event.preventDefault();
386
+ if (!displayRef.current) {
387
+ return;
388
+ }
386
389
  displayRef.current.focus();
387
390
  const doc = (0, _ownerDocument.default)(event.currentTarget);
388
391
  scheduleMouseUpSelection();
@@ -376,6 +376,9 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
376
376
  }
377
377
  // Hijack the default focus behavior.
378
378
  event.preventDefault();
379
+ if (!displayRef.current) {
380
+ return;
381
+ }
379
382
  displayRef.current.focus();
380
383
  const doc = ownerDocument(event.currentTarget);
381
384
  scheduleMouseUpSelection();
package/Stack/Stack.d.mts CHANGED
@@ -25,7 +25,7 @@ export interface StackOwnProps {
25
25
  /**
26
26
  * If `true`, the CSS flexbox `gap` is used instead of applying `margin` to children.
27
27
  *
28
- * While CSS `gap` removes the [known limitations](https://mui.com/joy-ui/react-stack/#limitations),
28
+ * While CSS `gap` removes the known limitations,
29
29
  * it is not fully supported in some browsers. We recommend checking https://caniuse.com/?search=flex%20gap before using this flag.
30
30
  *
31
31
  * To enable this flag globally, follow the [theme's default props](https://mui.com/material-ui/customization/theme-components/#default-props) configuration.
package/Stack/Stack.d.ts CHANGED
@@ -25,7 +25,7 @@ export interface StackOwnProps {
25
25
  /**
26
26
  * If `true`, the CSS flexbox `gap` is used instead of applying `margin` to children.
27
27
  *
28
- * While CSS `gap` removes the [known limitations](https://mui.com/joy-ui/react-stack/#limitations),
28
+ * While CSS `gap` removes the known limitations,
29
29
  * it is not fully supported in some browsers. We recommend checking https://caniuse.com/?search=flex%20gap before using this flag.
30
30
  *
31
31
  * To enable this flag globally, follow the [theme's default props](https://mui.com/material-ui/customization/theme-components/#default-props) configuration.
package/Stack/Stack.js CHANGED
@@ -56,7 +56,7 @@ process.env.NODE_ENV !== "production" ? Stack.propTypes /* remove-proptypes */ =
56
56
  /**
57
57
  * If `true`, the CSS flexbox `gap` is used instead of applying `margin` to children.
58
58
  *
59
- * While CSS `gap` removes the [known limitations](https://mui.com/joy-ui/react-stack/#limitations),
59
+ * While CSS `gap` removes the known limitations,
60
60
  * it is not fully supported in some browsers. We recommend checking https://caniuse.com/?search=flex%20gap before using this flag.
61
61
  *
62
62
  * To enable this flag globally, follow the [theme's default props](https://mui.com/material-ui/customization/theme-components/#default-props) configuration.
package/Stack/Stack.mjs CHANGED
@@ -50,7 +50,7 @@ process.env.NODE_ENV !== "production" ? Stack.propTypes /* remove-proptypes */ =
50
50
  /**
51
51
  * If `true`, the CSS flexbox `gap` is used instead of applying `margin` to children.
52
52
  *
53
- * While CSS `gap` removes the [known limitations](https://mui.com/joy-ui/react-stack/#limitations),
53
+ * While CSS `gap` removes the known limitations,
54
54
  * it is not fully supported in some browsers. We recommend checking https://caniuse.com/?search=flex%20gap before using this flag.
55
55
  *
56
56
  * To enable this flag globally, follow the [theme's default props](https://mui.com/material-ui/customization/theme-components/#default-props) configuration.
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(() => {
@@ -384,14 +384,14 @@ const Tooltip = /*#__PURE__*/React.forwardRef(function Tooltip(inProps, ref) {
384
384
  }
385
385
  };
386
386
  const handleFocus = event => {
387
- // Workaround for https://github.com/facebook/react/issues/7769
387
+ // Workaround for https://github.com/react/react/issues/7769
388
388
  // The autoFocus of React might trigger the event before the componentDidMount.
389
389
  // We need to account for this eventuality.
390
390
  if (!childNode) {
391
391
  setChildNode(event.currentTarget);
392
392
  }
393
393
  if ((0, _isFocusVisible.default)(event.target)) {
394
- // Workaround for https://github.com/facebook/react/issues/9142.
394
+ // Workaround for https://github.com/react/react/issues/9142.
395
395
  // React does not fire blur when a focused element becomes disabled.
396
396
  const handleNativeBlur = blurEvent => {
397
397
  if (blurEvent.target.disabled) {
@@ -376,14 +376,14 @@ const Tooltip = /*#__PURE__*/React.forwardRef(function Tooltip(inProps, ref) {
376
376
  }
377
377
  };
378
378
  const handleFocus = event => {
379
- // Workaround for https://github.com/facebook/react/issues/7769
379
+ // Workaround for https://github.com/react/react/issues/7769
380
380
  // The autoFocus of React might trigger the event before the componentDidMount.
381
381
  // We need to account for this eventuality.
382
382
  if (!childNode) {
383
383
  setChildNode(event.currentTarget);
384
384
  }
385
385
  if (isFocusVisible(event.target)) {
386
- // Workaround for https://github.com/facebook/react/issues/9142.
386
+ // Workaround for https://github.com/react/react/issues/9142.
387
387
  // React does not fire blur when a focused element becomes disabled.
388
388
  const handleNativeBlur = blurEvent => {
389
389
  if (blurEvent.target.disabled) {
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/material v9.1.1
2
+ * @mui/material v9.2.0
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.1
2
+ * @mui/material v9.2.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -142,7 +142,7 @@ const SwitchBase = /*#__PURE__*/React.forwardRef(function SwitchBase(props, ref)
142
142
  }
143
143
  };
144
144
  const handleInputChange = event => {
145
- // Workaround for https://github.com/facebook/react/issues/9023
145
+ // Workaround for https://github.com/react/react/issues/9023
146
146
  if (event.nativeEvent.defaultPrevented || readOnly) {
147
147
  return;
148
148
  }
@@ -135,7 +135,7 @@ const SwitchBase = /*#__PURE__*/React.forwardRef(function SwitchBase(props, ref)
135
135
  }
136
136
  };
137
137
  const handleInputChange = event => {
138
- // Workaround for https://github.com/facebook/react/issues/9023
138
+ // Workaround for https://github.com/react/react/issues/9023
139
139
  if (event.nativeEvent.defaultPrevented || readOnly) {
140
140
  return;
141
141
  }
@@ -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) {
@@ -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) {
@@ -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/locale/zhCN.js CHANGED
@@ -55,6 +55,27 @@ const zhCN = exports.zhCN = {
55
55
  defaultProps: {
56
56
  closeText: '关闭'
57
57
  }
58
+ },
59
+ MuiPagination: {
60
+ defaultProps: {
61
+ 'aria-label': '分页导航',
62
+ getItemAriaLabel: (type, page, selected) => {
63
+ if (type === 'page') {
64
+ return `${selected ? '' : '转到'}第 ${page} 页`;
65
+ }
66
+ if (type === 'first') {
67
+ return '转到第一页';
68
+ }
69
+ if (type === 'last') {
70
+ return '转到最后一页';
71
+ }
72
+ if (type === 'next') {
73
+ return '转到下一页';
74
+ }
75
+ // if (type === 'previous')
76
+ return '转到上一页';
77
+ }
78
+ }
58
79
  }
59
80
  }
60
81
  };
package/locale/zhCN.mjs CHANGED
@@ -48,6 +48,27 @@ export const zhCN = {
48
48
  defaultProps: {
49
49
  closeText: '关闭'
50
50
  }
51
+ },
52
+ MuiPagination: {
53
+ defaultProps: {
54
+ 'aria-label': '分页导航',
55
+ getItemAriaLabel: (type, page, selected) => {
56
+ if (type === 'page') {
57
+ return `${selected ? '' : '转到'}第 ${page} 页`;
58
+ }
59
+ if (type === 'first') {
60
+ return '转到第一页';
61
+ }
62
+ if (type === 'last') {
63
+ return '转到最后一页';
64
+ }
65
+ if (type === 'next') {
66
+ return '转到下一页';
67
+ }
68
+ // if (type === 'previous')
69
+ return '转到上一页';
70
+ }
71
+ }
51
72
  }
52
73
  }
53
74
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/material",
3
- "version": "9.1.1",
3
+ "version": "9.2.0",
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.1",
37
- "@mui/system": "^9.1.1",
36
+ "@mui/core-downloads-tracker": "^9.2.0",
38
37
  "@mui/types": "^9.1.1",
39
- "@mui/utils": "^9.1.1"
38
+ "@mui/system": "^9.2.0",
39
+ "@mui/utils": "^9.2.0"
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.1"
47
+ "@mui/material-pigment-css": "^9.2.0"
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": [
@@ -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 = () => {
@@ -53,7 +54,7 @@ function useScrollTrigger(options = {}) {
53
54
  passive: true
54
55
  });
55
56
  };
56
- // See Option 3. https://github.com/facebook/react/issues/14476#issuecomment-471199055
57
+ // See Option 3. https://github.com/react/react/issues/14476#issuecomment-471199055
57
58
  // TODO: uncomment once we enable eslint-plugin-react-compiler // eslint-disable-next-line react-compiler/react-compiler
58
59
  // eslint-disable-next-line react-hooks/exhaustive-deps
59
60
  }, [target, getTrigger, JSON.stringify(other)]);
@@ -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 = () => {
@@ -47,7 +48,7 @@ export default function useScrollTrigger(options = {}) {
47
48
  passive: true
48
49
  });
49
50
  };
50
- // See Option 3. https://github.com/facebook/react/issues/14476#issuecomment-471199055
51
+ // See Option 3. https://github.com/react/react/issues/14476#issuecomment-471199055
51
52
  // TODO: uncomment once we enable eslint-plugin-react-compiler // eslint-disable-next-line react-compiler/react-compiler
52
53
  // eslint-disable-next-line react-hooks/exhaustive-deps
53
54
  }, [target, getTrigger, JSON.stringify(other)]);
package/utils/types.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { SxProps } from '@mui/system';
2
2
  import { SlotComponentProps } from '@mui/utils/types';
3
3
  import { Theme } from "../styles/index.mjs";
4
- export type { EventHandlers, WithOptionalOwnerState, SlotComponentProps, SlotComponentPropsWithSlotState } from '@mui/utils/types';
4
+ export type { EventHandlers, WithOptionalOwnerState, SlotComponentProps, SlotComponentPropsWithSlotState, DataAttributesOverrides, WithDataAttributes } from '@mui/utils/types';
5
5
  export type SlotCommonProps = {
6
6
  component?: React.ElementType | undefined;
7
7
  sx?: SxProps<Theme> | undefined;
package/utils/types.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { SxProps } from '@mui/system';
2
2
  import { SlotComponentProps } from '@mui/utils/types';
3
3
  import { Theme } from "../styles/index.js";
4
- export type { EventHandlers, WithOptionalOwnerState, SlotComponentProps, SlotComponentPropsWithSlotState } from '@mui/utils/types';
4
+ export type { EventHandlers, WithOptionalOwnerState, SlotComponentProps, SlotComponentPropsWithSlotState, DataAttributesOverrides, WithDataAttributes } from '@mui/utils/types';
5
5
  export type SlotCommonProps = {
6
6
  component?: React.ElementType | undefined;
7
7
  sx?: SxProps<Theme> | undefined;
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.1";
7
+ const version = exports.version = "9.2.0";
8
8
  const major = exports.major = Number("9");
9
- const minor = exports.minor = Number("1");
10
- const patch = exports.patch = Number("1");
9
+ const minor = exports.minor = Number("2");
10
+ const patch = exports.patch = Number("0");
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.1";
1
+ export const version = "9.2.0";
2
2
  export const major = Number("9");
3
- export const minor = Number("1");
4
- export const patch = Number("1");
3
+ export const minor = Number("2");
4
+ export const patch = Number("0");
5
5
  export const prerelease = undefined;
6
6
  export default version;