@mui/material 6.4.5 → 6.4.7

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 (80) hide show
  1. package/Accordion/Accordion.d.ts +14 -12
  2. package/Alert/Alert.d.ts +3 -15
  3. package/Backdrop/Backdrop.d.ts +14 -12
  4. package/CHANGELOG.md +58 -0
  5. package/CardHeader/CardHeader.d.ts +4 -20
  6. package/Checkbox/Checkbox.d.ts +45 -9
  7. package/Checkbox/Checkbox.js +51 -21
  8. package/Dialog/Dialog.d.ts +4 -4
  9. package/Drawer/Drawer.d.ts +92 -1
  10. package/Drawer/Drawer.js +108 -36
  11. package/InputBase/inputBaseClasses.d.ts +15 -6
  12. package/Menu/Menu.d.ts +88 -1
  13. package/Menu/Menu.js +58 -19
  14. package/Modal/Modal.js +9 -10
  15. package/Popover/Popover.d.ts +60 -6
  16. package/Popover/Popover.js +78 -51
  17. package/Radio/Radio.d.ts +45 -1
  18. package/Radio/Radio.js +61 -16
  19. package/Rating/Rating.d.ts +59 -1
  20. package/Rating/Rating.js +131 -45
  21. package/Select/SelectInput.js +8 -8
  22. package/Snackbar/Snackbar.d.ts +79 -2
  23. package/Snackbar/Snackbar.js +110 -32
  24. package/SpeedDial/SpeedDial.d.ts +8 -6
  25. package/SpeedDialAction/SpeedDialAction.d.ts +82 -1
  26. package/SpeedDialAction/SpeedDialAction.js +108 -30
  27. package/StepContent/StepContent.d.ts +2 -2
  28. package/SwipeableDrawer/SwipeableDrawer.d.ts +28 -2
  29. package/SwipeableDrawer/SwipeableDrawer.js +60 -13
  30. package/Switch/Switch.js +2 -0
  31. package/Tabs/Tabs.d.ts +129 -29
  32. package/Tabs/Tabs.js +120 -52
  33. package/Tabs/tabsClasses.d.ts +4 -0
  34. package/Tabs/tabsClasses.js +1 -1
  35. package/Tooltip/Tooltip.d.ts +20 -12
  36. package/index.js +1 -1
  37. package/internal/SwitchBase.d.ts +35 -1
  38. package/internal/SwitchBase.js +84 -30
  39. package/modern/Checkbox/Checkbox.js +51 -21
  40. package/modern/Drawer/Drawer.js +108 -36
  41. package/modern/Menu/Menu.js +58 -19
  42. package/modern/Modal/Modal.js +9 -10
  43. package/modern/Popover/Popover.js +78 -51
  44. package/modern/Radio/Radio.js +61 -16
  45. package/modern/Rating/Rating.js +131 -45
  46. package/modern/Select/SelectInput.js +8 -8
  47. package/modern/Snackbar/Snackbar.js +110 -32
  48. package/modern/SpeedDialAction/SpeedDialAction.js +108 -30
  49. package/modern/SwipeableDrawer/SwipeableDrawer.js +60 -13
  50. package/modern/Switch/Switch.js +2 -0
  51. package/modern/Tabs/Tabs.js +120 -52
  52. package/modern/Tabs/tabsClasses.js +1 -1
  53. package/modern/index.js +1 -1
  54. package/modern/internal/SwitchBase.js +84 -30
  55. package/modern/styles/createThemeNoVars.js +7 -2
  56. package/modern/version/index.js +2 -2
  57. package/node/Checkbox/Checkbox.js +51 -21
  58. package/node/Drawer/Drawer.js +108 -36
  59. package/node/Menu/Menu.js +58 -19
  60. package/node/Modal/Modal.js +9 -10
  61. package/node/Popover/Popover.js +78 -51
  62. package/node/Radio/Radio.js +61 -16
  63. package/node/Rating/Rating.js +132 -46
  64. package/node/Select/SelectInput.js +8 -8
  65. package/node/Snackbar/Snackbar.js +110 -32
  66. package/node/SpeedDialAction/SpeedDialAction.js +108 -30
  67. package/node/SwipeableDrawer/SwipeableDrawer.js +60 -13
  68. package/node/Switch/Switch.js +2 -0
  69. package/node/Tabs/Tabs.js +120 -52
  70. package/node/Tabs/tabsClasses.js +1 -1
  71. package/node/index.js +1 -1
  72. package/node/internal/SwitchBase.js +84 -30
  73. package/node/styles/createThemeNoVars.js +7 -2
  74. package/node/version/index.js +2 -2
  75. package/package.json +5 -5
  76. package/styles/ThemeProvider.d.ts +6 -0
  77. package/styles/ThemeProviderWithVars.d.ts +1 -0
  78. package/styles/createThemeNoVars.js +7 -2
  79. package/styles/index.d.ts +1 -0
  80. package/version/index.js +2 -2
@@ -15,12 +15,12 @@ import { useDefaultProps } from "../DefaultPropsProvider/index.js";
15
15
  import debounce from "../utils/debounce.js";
16
16
  import ownerDocument from "../utils/ownerDocument.js";
17
17
  import ownerWindow from "../utils/ownerWindow.js";
18
- import useForkRef from "../utils/useForkRef.js";
19
18
  import Grow from "../Grow/index.js";
20
19
  import Modal from "../Modal/index.js";
21
20
  import PaperBase from "../Paper/index.js";
22
21
  import { getPopoverUtilityClass } from "./popoverClasses.js";
23
22
  import useSlot from "../utils/useSlot.js";
23
+ import { mergeSlotProps } from "../utils/index.js";
24
24
  import { jsx as _jsx } from "react/jsx-runtime";
25
25
  export function getOffsetTop(rect, vertical) {
26
26
  let offset = 0;
@@ -103,22 +103,21 @@ const Popover = /*#__PURE__*/React.forwardRef(function Popover(inProps, ref) {
103
103
  marginThreshold = 16,
104
104
  open,
105
105
  PaperProps: PaperPropsProp = {},
106
+ // TODO: remove in v7
106
107
  slots = {},
107
108
  slotProps = {},
108
109
  transformOrigin = {
109
110
  vertical: 'top',
110
111
  horizontal: 'left'
111
112
  },
112
- TransitionComponent = Grow,
113
+ TransitionComponent,
114
+ // TODO: remove in v7
113
115
  transitionDuration: transitionDurationProp = 'auto',
114
- TransitionProps: {
115
- onEntering,
116
- ...TransitionProps
117
- } = {},
116
+ TransitionProps = {},
117
+ // TODO: remove in v7
118
118
  disableScrollLock = false,
119
119
  ...other
120
120
  } = props;
121
- const externalPaperSlotProps = slotProps?.paper ?? PaperPropsProp;
122
121
  const paperRef = React.useRef();
123
122
  const ownerState = {
124
123
  ...props,
@@ -126,7 +125,6 @@ const Popover = /*#__PURE__*/React.forwardRef(function Popover(inProps, ref) {
126
125
  anchorReference,
127
126
  elevation,
128
127
  marginThreshold,
129
- externalPaperSlotProps,
130
128
  transformOrigin,
131
129
  TransitionComponent,
132
130
  transitionDuration: transitionDurationProp,
@@ -255,10 +253,7 @@ const Popover = /*#__PURE__*/React.forwardRef(function Popover(inProps, ref) {
255
253
  }
256
254
  return () => window.removeEventListener('scroll', setPositioningStyles);
257
255
  }, [anchorEl, disableScrollLock, setPositioningStyles]);
258
- const handleEntering = (element, isAppearing) => {
259
- if (onEntering) {
260
- onEntering(element, isAppearing);
261
- }
256
+ const handleEntering = () => {
262
257
  setPositioningStyles();
263
258
  };
264
259
  const handleExited = () => {
@@ -289,45 +284,65 @@ const Popover = /*#__PURE__*/React.forwardRef(function Popover(inProps, ref) {
289
284
  };
290
285
  }, [anchorEl, open, setPositioningStyles]);
291
286
  let transitionDuration = transitionDurationProp;
292
- if (transitionDurationProp === 'auto' && !TransitionComponent.muiSupportAuto) {
293
- transitionDuration = undefined;
294
- }
295
-
296
- // If the container prop is provided, use that
297
- // If the anchorEl prop is provided, use its parent body element as the container
298
- // If neither are provided let the Modal take care of choosing the container
299
- const container = containerProp || (anchorEl ? ownerDocument(resolveAnchorEl(anchorEl)).body : undefined);
300
287
  const externalForwardedProps = {
301
- slots,
288
+ slots: {
289
+ transition: TransitionComponent,
290
+ ...slots
291
+ },
302
292
  slotProps: {
303
- ...slotProps,
304
- paper: externalPaperSlotProps
293
+ transition: TransitionProps,
294
+ paper: PaperPropsProp,
295
+ ...slotProps
305
296
  }
306
297
  };
307
- const [PaperSlot, paperProps] = useSlot('paper', {
308
- elementType: PopoverPaper,
298
+ const [TransitionSlot, transitionSlotProps] = useSlot('transition', {
299
+ elementType: Grow,
309
300
  externalForwardedProps,
310
- additionalProps: {
311
- elevation,
312
- className: clsx(classes.paper, externalPaperSlotProps?.className),
313
- style: isPositioned ? externalPaperSlotProps.style : {
314
- ...externalPaperSlotProps.style,
315
- opacity: 0
301
+ ownerState,
302
+ getSlotProps: handlers => ({
303
+ ...handlers,
304
+ onEntering: (element, isAppearing) => {
305
+ handlers.onEntering?.(element, isAppearing);
306
+ handleEntering();
307
+ },
308
+ onExited: element => {
309
+ handlers.onExited?.(element);
310
+ handleExited();
316
311
  }
317
- },
318
- ownerState
312
+ }),
313
+ additionalProps: {
314
+ appear: true,
315
+ in: open
316
+ }
319
317
  });
318
+ if (transitionDurationProp === 'auto' && !TransitionSlot.muiSupportAuto) {
319
+ transitionDuration = undefined;
320
+ }
321
+
322
+ // If the container prop is provided, use that
323
+ // If the anchorEl prop is provided, use its parent body element as the container
324
+ // If neither are provided let the Modal take care of choosing the container
325
+ const container = containerProp || (anchorEl ? ownerDocument(resolveAnchorEl(anchorEl)).body : undefined);
320
326
  const [RootSlot, {
327
+ slots: rootSlotsProp,
321
328
  slotProps: rootSlotPropsProp,
322
329
  ...rootProps
323
330
  }] = useSlot('root', {
331
+ ref,
324
332
  elementType: PopoverRoot,
325
- externalForwardedProps,
333
+ externalForwardedProps: {
334
+ ...externalForwardedProps,
335
+ ...other
336
+ },
337
+ shouldForwardComponentProp: true,
326
338
  additionalProps: {
339
+ slots: {
340
+ backdrop: slots.backdrop
341
+ },
327
342
  slotProps: {
328
- backdrop: {
343
+ backdrop: mergeSlotProps(typeof slotProps.backdrop === 'function' ? slotProps.backdrop(ownerState) : slotProps.backdrop, {
329
344
  invisible: true
330
- }
345
+ })
331
346
  },
332
347
  container,
333
348
  open
@@ -335,25 +350,32 @@ const Popover = /*#__PURE__*/React.forwardRef(function Popover(inProps, ref) {
335
350
  ownerState,
336
351
  className: clsx(classes.root, className)
337
352
  });
338
- const handlePaperRef = useForkRef(paperRef, paperProps.ref);
353
+ const [PaperSlot, paperProps] = useSlot('paper', {
354
+ ref: paperRef,
355
+ className: classes.paper,
356
+ elementType: PopoverPaper,
357
+ externalForwardedProps,
358
+ shouldForwardComponentProp: true,
359
+ additionalProps: {
360
+ elevation,
361
+ style: isPositioned ? undefined : {
362
+ opacity: 0
363
+ }
364
+ },
365
+ ownerState
366
+ });
339
367
  return /*#__PURE__*/_jsx(RootSlot, {
340
368
  ...rootProps,
341
369
  ...(!isHostComponent(RootSlot) && {
370
+ slots: rootSlotsProp,
342
371
  slotProps: rootSlotPropsProp,
343
372
  disableScrollLock
344
373
  }),
345
- ...other,
346
- ref: ref,
347
- children: /*#__PURE__*/_jsx(TransitionComponent, {
348
- appear: true,
349
- in: open,
350
- onEntering: handleEntering,
351
- onExited: handleExited,
374
+ children: /*#__PURE__*/_jsx(TransitionSlot, {
375
+ ...transitionSlotProps,
352
376
  timeout: transitionDuration,
353
- ...TransitionProps,
354
377
  children: /*#__PURE__*/_jsx(PaperSlot, {
355
378
  ...paperProps,
356
- ref: handlePaperRef,
357
379
  children: children
358
380
  })
359
381
  })
@@ -421,8 +443,7 @@ process.env.NODE_ENV !== "production" ? Popover.propTypes /* remove-proptypes */
421
443
  anchorReference: PropTypes.oneOf(['anchorEl', 'anchorPosition', 'none']),
422
444
  /**
423
445
  * A backdrop component. This prop enables custom backdrop rendering.
424
- * @deprecated Use `slotProps.root.slots.backdrop` instead. While this prop currently works, it will be removed in the next major version.
425
- * Use the `slotProps.root.slots.backdrop` prop to make your application ready for the next version of Material UI.
446
+ * @deprecated Use `slots.backdrop` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details.
426
447
  * @default styled(Backdrop, {
427
448
  * name: 'MuiModal',
428
449
  * slot: 'Backdrop',
@@ -436,7 +457,7 @@ process.env.NODE_ENV !== "production" ? Popover.propTypes /* remove-proptypes */
436
457
  BackdropComponent: PropTypes.elementType,
437
458
  /**
438
459
  * Props applied to the [`Backdrop`](/material-ui/api/backdrop/) element.
439
- * @deprecated Use `slotProps.root.slotProps.backdrop` instead.
460
+ * @deprecated Use `slotProps.backdrop` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details.
440
461
  */
441
462
  BackdropProps: PropTypes.object,
442
463
  /**
@@ -500,16 +521,20 @@ process.env.NODE_ENV !== "production" ? Popover.propTypes /* remove-proptypes */
500
521
  * @default {}
501
522
  */
502
523
  slotProps: PropTypes.shape({
524
+ backdrop: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
503
525
  paper: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
504
- root: PropTypes.oneOfType([PropTypes.func, PropTypes.object])
526
+ root: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
527
+ transition: PropTypes.oneOfType([PropTypes.func, PropTypes.object])
505
528
  }),
506
529
  /**
507
530
  * The components used for each slot inside.
508
531
  * @default {}
509
532
  */
510
533
  slots: PropTypes.shape({
534
+ backdrop: PropTypes.elementType,
511
535
  paper: PropTypes.elementType,
512
- root: PropTypes.elementType
536
+ root: PropTypes.elementType,
537
+ transition: PropTypes.elementType
513
538
  }),
514
539
  /**
515
540
  * The system prop that allows defining system overrides as well as additional CSS styles.
@@ -534,6 +559,7 @@ process.env.NODE_ENV !== "production" ? Popover.propTypes /* remove-proptypes */
534
559
  /**
535
560
  * The component used for the transition.
536
561
  * [Follow this guide](https://mui.com/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component.
562
+ * @deprecated use the `slots.transition` prop instead. This prop will be removed in v7. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details.
537
563
  * @default Grow
538
564
  */
539
565
  TransitionComponent: PropTypes.elementType,
@@ -549,6 +575,7 @@ process.env.NODE_ENV !== "production" ? Popover.propTypes /* remove-proptypes */
549
575
  /**
550
576
  * Props applied to the transition element.
551
577
  * By default, the element is based on this [`Transition`](https://reactcommunity.org/react-transition-group/transition/) component.
578
+ * @deprecated use the `slotProps.transition` prop instead. This prop will be removed in v7. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details.
552
579
  * @default {}
553
580
  */
554
581
  TransitionProps: PropTypes.object
@@ -17,6 +17,7 @@ import rootShouldForwardProp from "../styles/rootShouldForwardProp.js";
17
17
  import { styled } from "../zero-styled/index.js";
18
18
  import memoTheme from "../utils/memoTheme.js";
19
19
  import createSimplePaletteValueFilter from "../utils/createSimplePaletteValueFilter.js";
20
+ import useSlot from "../utils/useSlot.js";
20
21
  import { useDefaultProps } from "../DefaultPropsProvider/index.js";
21
22
  import { jsx as _jsx } from "react/jsx-runtime";
22
23
  const useUtilityClasses = ownerState => {
@@ -125,6 +126,9 @@ const Radio = /*#__PURE__*/React.forwardRef(function Radio(inProps, ref) {
125
126
  className,
126
127
  disabled: disabledProp,
127
128
  disableRipple = false,
129
+ slots = {},
130
+ slotProps = {},
131
+ inputProps,
128
132
  ...other
129
133
  } = props;
130
134
  const muiFormControl = useFormControl();
@@ -155,23 +159,46 @@ const Radio = /*#__PURE__*/React.forwardRef(function Radio(inProps, ref) {
155
159
  name = radioGroup.name;
156
160
  }
157
161
  }
158
- return /*#__PURE__*/_jsx(RadioRoot, {
159
- type: "radio",
160
- icon: /*#__PURE__*/React.cloneElement(icon, {
161
- fontSize: defaultIcon.props.fontSize ?? size
162
- }),
163
- checkedIcon: /*#__PURE__*/React.cloneElement(checkedIcon, {
164
- fontSize: defaultCheckedIcon.props.fontSize ?? size
165
- }),
166
- disabled: disabled,
167
- ownerState: ownerState,
168
- classes: classes,
169
- name: name,
170
- checked: checked,
171
- onChange: onChange,
172
- ref: ref,
162
+ const externalInputProps = slotProps.input ?? inputProps;
163
+ const [RootSlot, rootSlotProps] = useSlot('root', {
164
+ ref,
165
+ elementType: RadioRoot,
173
166
  className: clsx(classes.root, className),
174
- ...other
167
+ shouldForwardComponentProp: true,
168
+ externalForwardedProps: {
169
+ slots,
170
+ slotProps,
171
+ ...other
172
+ },
173
+ getSlotProps: handlers => ({
174
+ ...handlers,
175
+ onChange: (event, ...args) => {
176
+ handlers.onChange?.(event, ...args);
177
+ onChange(event, ...args);
178
+ }
179
+ }),
180
+ ownerState,
181
+ additionalProps: {
182
+ type: 'radio',
183
+ icon: /*#__PURE__*/React.cloneElement(icon, {
184
+ fontSize: icon.props.fontSize ?? size
185
+ }),
186
+ checkedIcon: /*#__PURE__*/React.cloneElement(checkedIcon, {
187
+ fontSize: checkedIcon.props.fontSize ?? size
188
+ }),
189
+ disabled,
190
+ name,
191
+ checked,
192
+ slots,
193
+ slotProps: {
194
+ // Do not forward `slotProps.root` again because it's already handled by the `RootSlot` in this file.
195
+ input: typeof externalInputProps === 'function' ? externalInputProps(ownerState) : externalInputProps
196
+ }
197
+ }
198
+ });
199
+ return /*#__PURE__*/_jsx(RootSlot, {
200
+ ...rootSlotProps,
201
+ classes: classes
175
202
  });
176
203
  });
177
204
  process.env.NODE_ENV !== "production" ? Radio.propTypes /* remove-proptypes */ = {
@@ -223,10 +250,12 @@ process.env.NODE_ENV !== "production" ? Radio.propTypes /* remove-proptypes */ =
223
250
  id: PropTypes.string,
224
251
  /**
225
252
  * [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Attributes) applied to the `input` element.
253
+ * @deprecated Use `slotProps.input` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details.
226
254
  */
227
255
  inputProps: PropTypes.object,
228
256
  /**
229
257
  * Pass a ref to the `input` element.
258
+ * @deprecated Use `slotProps.input.ref` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details.
230
259
  */
231
260
  inputRef: refType,
232
261
  /**
@@ -252,6 +281,22 @@ process.env.NODE_ENV !== "production" ? Radio.propTypes /* remove-proptypes */ =
252
281
  * @default 'medium'
253
282
  */
254
283
  size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['medium', 'small']), PropTypes.string]),
284
+ /**
285
+ * The props used for each slot inside.
286
+ * @default {}
287
+ */
288
+ slotProps: PropTypes.shape({
289
+ input: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
290
+ root: PropTypes.oneOfType([PropTypes.func, PropTypes.object])
291
+ }),
292
+ /**
293
+ * The components used for each slot inside.
294
+ * @default {}
295
+ */
296
+ slots: PropTypes.shape({
297
+ input: PropTypes.elementType,
298
+ root: PropTypes.elementType
299
+ }),
255
300
  /**
256
301
  * The system prop that allows defining system overrides as well as additional CSS styles.
257
302
  */
@@ -17,7 +17,9 @@ import memoTheme from "../utils/memoTheme.js";
17
17
  import { useDefaultProps } from "../DefaultPropsProvider/index.js";
18
18
  import slotShouldForwardProp from "../styles/slotShouldForwardProp.js";
19
19
  import ratingClasses, { getRatingUtilityClass } from "./ratingClasses.js";
20
+ import useSlot from "../utils/useSlot.js";
20
21
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
22
+ import { createElement as _createElement } from "react";
21
23
  function getDecimalPrecision(num) {
22
24
  const decimalPart = num.toString().split('.')[1];
23
25
  return decimalPart ? decimalPart.length : 0;
@@ -220,7 +222,9 @@ function RatingItem(props) {
220
222
  readOnly,
221
223
  ownerState,
222
224
  ratingValue,
223
- ratingValueRounded
225
+ ratingValueRounded,
226
+ slots = {},
227
+ slotProps = {}
224
228
  } = props;
225
229
  const isFilled = highlightSelectedOnly ? itemValue === ratingValue : itemValue <= ratingValue;
226
230
  const isHovered = itemValue <= hover;
@@ -232,10 +236,14 @@ function RatingItem(props) {
232
236
  // Update to const id = useId(); when React 17 support is dropped.
233
237
  // More details: https://github.com/mui/material-ui/issues/40997
234
238
  const id = `${name}-${useId()}`;
235
- const container = /*#__PURE__*/_jsx(RatingIcon, {
236
- as: IconContainerComponent,
237
- value: itemValue,
239
+ const externalForwardedProps = {
240
+ slots,
241
+ slotProps
242
+ };
243
+ const [IconSlot, iconSlotProps] = useSlot('icon', {
244
+ elementType: RatingIcon,
238
245
  className: clsx(classes.icon, isFilled ? classes.iconFilled : classes.iconEmpty, isHovered && classes.iconHover, isFocused && classes.iconFocus, isActive && classes.iconActive),
246
+ externalForwardedProps,
239
247
  ownerState: {
240
248
  ...ownerState,
241
249
  iconEmpty: !isFilled,
@@ -244,6 +252,29 @@ function RatingItem(props) {
244
252
  iconFocus: isFocused,
245
253
  iconActive: isActive
246
254
  },
255
+ additionalProps: {
256
+ value: itemValue
257
+ },
258
+ internalForwardedProps: {
259
+ // TODO: remove this in v7 because `IconContainerComponent` is deprecated
260
+ // only forward if `slots.icon` is NOT provided
261
+ as: IconContainerComponent
262
+ }
263
+ });
264
+ const [LabelSlot, labelSlotProps] = useSlot('label', {
265
+ elementType: RatingLabel,
266
+ externalForwardedProps,
267
+ ownerState: {
268
+ ...ownerState,
269
+ emptyValueFocused: undefined
270
+ },
271
+ additionalProps: {
272
+ style: labelProps?.style,
273
+ htmlFor: id
274
+ }
275
+ });
276
+ const container = /*#__PURE__*/_jsx(IconSlot, {
277
+ ...iconSlotProps,
247
278
  children: emptyIcon && !isFilled ? emptyIcon : icon
248
279
  });
249
280
  if (readOnly) {
@@ -253,13 +284,8 @@ function RatingItem(props) {
253
284
  });
254
285
  }
255
286
  return /*#__PURE__*/_jsxs(React.Fragment, {
256
- children: [/*#__PURE__*/_jsxs(RatingLabel, {
257
- ownerState: {
258
- ...ownerState,
259
- emptyValueFocused: undefined
260
- },
261
- htmlFor: id,
262
- ...labelProps,
287
+ children: [/*#__PURE__*/_jsxs(LabelSlot, {
288
+ ...labelSlotProps,
263
289
  children: [container, /*#__PURE__*/_jsx("span", {
264
290
  className: classes.visuallyHidden,
265
291
  children: getLabelText(itemValue)
@@ -300,7 +326,9 @@ process.env.NODE_ENV !== "production" ? RatingItem.propTypes = {
300
326
  ownerState: PropTypes.object.isRequired,
301
327
  ratingValue: PropTypes.number,
302
328
  ratingValueRounded: PropTypes.number,
303
- readOnly: PropTypes.bool.isRequired
329
+ readOnly: PropTypes.bool.isRequired,
330
+ slotProps: PropTypes.object,
331
+ slots: PropTypes.object
304
332
  } : void 0;
305
333
  const defaultIcon = /*#__PURE__*/_jsx(Star, {
306
334
  fontSize: "inherit"
@@ -337,6 +365,8 @@ const Rating = /*#__PURE__*/React.forwardRef(function Rating(inProps, ref) {
337
365
  readOnly = false,
338
366
  size = 'medium',
339
367
  value: valueProp,
368
+ slots = {},
369
+ slotProps = {},
340
370
  ...other
341
371
  } = props;
342
372
  const name = useId(nameProp);
@@ -474,16 +504,50 @@ const Rating = /*#__PURE__*/React.forwardRef(function Rating(inProps, ref) {
474
504
  size
475
505
  };
476
506
  const classes = useUtilityClasses(ownerState);
477
- return /*#__PURE__*/_jsxs(RatingRoot, {
478
- as: component,
507
+ const externalForwardedProps = {
508
+ slots,
509
+ slotProps
510
+ };
511
+ const [RootSlot, rootSlotProps] = useSlot('root', {
479
512
  ref: handleRef,
480
- onMouseMove: handleMouseMove,
481
- onMouseLeave: handleMouseLeave,
482
- className: clsx(classes.root, className, readOnly && 'MuiRating-readOnly'),
483
- ownerState: ownerState,
484
- role: readOnly ? 'img' : null,
485
- "aria-label": readOnly ? getLabelText(value) : null,
486
- ...other,
513
+ className: clsx(classes.root, className),
514
+ elementType: RatingRoot,
515
+ externalForwardedProps: {
516
+ ...externalForwardedProps,
517
+ ...other,
518
+ component
519
+ },
520
+ getSlotProps: handlers => ({
521
+ ...handlers,
522
+ onMouseMove: event => {
523
+ handleMouseMove(event);
524
+ handlers.onMouseMove?.(event);
525
+ },
526
+ onMouseLeave: event => {
527
+ handleMouseLeave(event);
528
+ handlers.onMouseLeave?.(event);
529
+ }
530
+ }),
531
+ ownerState,
532
+ additionalProps: {
533
+ role: readOnly ? 'img' : null,
534
+ 'aria-label': readOnly ? getLabelText(value) : null
535
+ }
536
+ });
537
+ const [LabelSlot, labelSlotProps] = useSlot('label', {
538
+ className: clsx(classes.label, classes.labelEmptyValue),
539
+ elementType: RatingLabel,
540
+ externalForwardedProps,
541
+ ownerState
542
+ });
543
+ const [DecimalSlot, decimalSlotProps] = useSlot('decimal', {
544
+ className: classes.decimal,
545
+ elementType: RatingDecimal,
546
+ externalForwardedProps,
547
+ ownerState
548
+ });
549
+ return /*#__PURE__*/_jsxs(RootSlot, {
550
+ ...rootSlotProps,
487
551
  children: [Array.from(new Array(max)).map((_, index) => {
488
552
  const itemValue = index + 1;
489
553
  const ratingItemProps = {
@@ -504,41 +568,42 @@ const Rating = /*#__PURE__*/React.forwardRef(function Rating(inProps, ref) {
504
568
  ratingValue: value,
505
569
  ratingValueRounded: valueRounded,
506
570
  readOnly,
507
- ownerState
571
+ ownerState,
572
+ slots,
573
+ slotProps
508
574
  };
509
575
  const isActive = itemValue === Math.ceil(value) && (hover !== -1 || focus !== -1);
510
576
  if (precision < 1) {
511
577
  const items = Array.from(new Array(1 / precision));
512
- return /*#__PURE__*/_jsx(RatingDecimal, {
513
- className: clsx(classes.decimal, isActive && classes.iconActive),
514
- ownerState: ownerState,
515
- iconActive: isActive,
516
- children: items.map(($, indexDecimal) => {
517
- const itemDecimalValue = roundValueToPrecision(itemValue - 1 + (indexDecimal + 1) * precision, precision);
518
- return /*#__PURE__*/_jsx(RatingItem, {
519
- ...ratingItemProps,
520
- // The icon is already displayed as active
521
- isActive: false,
522
- itemValue: itemDecimalValue,
523
- labelProps: {
524
- style: items.length - 1 === indexDecimal ? {} : {
525
- width: itemDecimalValue === value ? `${(indexDecimal + 1) * precision * 100}%` : '0%',
526
- overflow: 'hidden',
527
- position: 'absolute'
528
- }
578
+ return /*#__PURE__*/_createElement(DecimalSlot, {
579
+ ...decimalSlotProps,
580
+ key: itemValue,
581
+ className: clsx(decimalSlotProps.className, isActive && classes.iconActive),
582
+ iconActive: isActive
583
+ }, items.map(($, indexDecimal) => {
584
+ const itemDecimalValue = roundValueToPrecision(itemValue - 1 + (indexDecimal + 1) * precision, precision);
585
+ return /*#__PURE__*/_jsx(RatingItem, {
586
+ ...ratingItemProps,
587
+ // The icon is already displayed as active
588
+ isActive: false,
589
+ itemValue: itemDecimalValue,
590
+ labelProps: {
591
+ style: items.length - 1 === indexDecimal ? {} : {
592
+ width: itemDecimalValue === value ? `${(indexDecimal + 1) * precision * 100}%` : '0%',
593
+ overflow: 'hidden',
594
+ position: 'absolute'
529
595
  }
530
- }, itemDecimalValue);
531
- })
532
- }, itemValue);
596
+ }
597
+ }, itemDecimalValue);
598
+ }));
533
599
  }
534
600
  return /*#__PURE__*/_jsx(RatingItem, {
535
601
  ...ratingItemProps,
536
602
  isActive: isActive,
537
603
  itemValue: itemValue
538
604
  }, itemValue);
539
- }), !readOnly && !disabled && /*#__PURE__*/_jsxs(RatingLabel, {
540
- className: clsx(classes.label, classes.labelEmptyValue),
541
- ownerState: ownerState,
605
+ }), !readOnly && !disabled && /*#__PURE__*/_jsxs(LabelSlot, {
606
+ ...labelSlotProps,
542
607
  children: [/*#__PURE__*/_jsx("input", {
543
608
  className: classes.visuallyHidden,
544
609
  value: "",
@@ -622,6 +687,7 @@ process.env.NODE_ENV !== "production" ? Rating.propTypes /* remove-proptypes */
622
687
  icon: PropTypes.node,
623
688
  /**
624
689
  * The component containing the icon.
690
+ * @deprecated Use `slotProps.icon.component` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details.
625
691
  * @default function IconContainer(props) {
626
692
  * const { value, ...other } = props;
627
693
  * return <span {...other} />;
@@ -679,6 +745,26 @@ process.env.NODE_ENV !== "production" ? Rating.propTypes /* remove-proptypes */
679
745
  * @default 'medium'
680
746
  */
681
747
  size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['small', 'medium', 'large']), PropTypes.string]),
748
+ /**
749
+ * The props used for each slot inside.
750
+ * @default {}
751
+ */
752
+ slotProps: PropTypes.shape({
753
+ decimal: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
754
+ icon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
755
+ label: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
756
+ root: PropTypes.oneOfType([PropTypes.func, PropTypes.object])
757
+ }),
758
+ /**
759
+ * The components used for each slot inside.
760
+ * @default {}
761
+ */
762
+ slots: PropTypes.shape({
763
+ decimal: PropTypes.elementType,
764
+ icon: PropTypes.elementType,
765
+ label: PropTypes.elementType,
766
+ root: PropTypes.elementType
767
+ }),
682
768
  /**
683
769
  * The system prop that allows defining system overrides as well as additional CSS styles.
684
770
  */
@@ -500,16 +500,16 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
500
500
  horizontal: 'center'
501
501
  },
502
502
  ...MenuProps,
503
- MenuListProps: {
504
- 'aria-labelledby': labelId,
505
- role: 'listbox',
506
- 'aria-multiselectable': multiple ? 'true' : undefined,
507
- disableListWrap: true,
508
- id: listboxId,
509
- ...MenuProps.MenuListProps
510
- },
511
503
  slotProps: {
512
504
  ...MenuProps.slotProps,
505
+ list: {
506
+ 'aria-labelledby': labelId,
507
+ role: 'listbox',
508
+ 'aria-multiselectable': multiple ? 'true' : undefined,
509
+ disableListWrap: true,
510
+ id: listboxId,
511
+ ...MenuProps.MenuListProps
512
+ },
513
513
  paper: {
514
514
  ...paperProps,
515
515
  style: {