diff --git a/docs/data/base/components/button/UseButton.js b/docs/data/base/components/button/UseButton.js index 081adb4019c822..24e1d25505a7e3 100644 --- a/docs/data/base/components/button/UseButton.js +++ b/docs/data/base/components/button/UseButton.js @@ -7,10 +7,10 @@ import { styled } from '@mui/system'; import Stack from '@mui/material/Stack'; const CustomButton = React.forwardRef(function CustomButton(props, ref) { - const { children } = props; - const { active, disabled, focusVisible, getRootProps } = useButton({ + const { children, disabled } = props; + const { active, focusVisible, getRootProps } = useButton({ ...props, - ref, + rootRef: ref, }); const classes = { @@ -28,6 +28,11 @@ const CustomButton = React.forwardRef(function CustomButton(props, ref) { CustomButton.propTypes = { children: PropTypes.node, + /** + * If `true`, the component is disabled. + * @default false + */ + disabled: PropTypes.bool, }; export default function UseButton() { diff --git a/docs/data/base/components/button/UseButton.tsx b/docs/data/base/components/button/UseButton.tsx index f904efc19def92..2ecbc2ede1130b 100644 --- a/docs/data/base/components/button/UseButton.tsx +++ b/docs/data/base/components/button/UseButton.tsx @@ -9,10 +9,10 @@ const CustomButton = React.forwardRef(function CustomButton( props: ButtonProps, ref: React.ForwardedRef, ) { - const { children } = props; - const { active, disabled, focusVisible, getRootProps } = useButton({ + const { children, disabled } = props; + const { active, focusVisible, getRootProps } = useButton({ ...props, - ref, + rootRef: ref, }); const classes = { diff --git a/docs/data/base/components/menu/UseMenu.js b/docs/data/base/components/menu/UseMenu.js index 42bb0797728083..79fe2fe00b1e6d 100644 --- a/docs/data/base/components/menu/UseMenu.js +++ b/docs/data/base/components/menu/UseMenu.js @@ -31,7 +31,7 @@ Menu.propTypes = { const MenuItem = React.forwardRef(function MenuItem(props, ref) { const { children, onClick, ...other } = props; - const { getRootProps, disabled, focusVisible } = useMenuItem({ ref }); + const { getRootProps, disabled, focusVisible } = useMenuItem({ rootRef: ref }); const classes = { 'focus-visible': focusVisible, diff --git a/docs/data/base/components/menu/UseMenu.tsx b/docs/data/base/components/menu/UseMenu.tsx index 61a70d5a6d527e..ec5822adae19fd 100644 --- a/docs/data/base/components/menu/UseMenu.tsx +++ b/docs/data/base/components/menu/UseMenu.tsx @@ -33,7 +33,7 @@ const MenuItem = React.forwardRef(function MenuItem( ) { const { children, onClick, ...other } = props; - const { getRootProps, disabled, focusVisible } = useMenuItem({ ref }); + const { getRootProps, disabled, focusVisible } = useMenuItem({ rootRef: ref }); const classes = { 'focus-visible': focusVisible, diff --git a/docs/pages/base/api/use-button.json b/docs/pages/base/api/use-button.json index c30c89d3b09b68..ce6d38c8ba087e 100644 --- a/docs/pages/base/api/use-button.json +++ b/docs/pages/base/api/use-button.json @@ -9,7 +9,9 @@ "onFocusVisible": { "type": { "name": "React.FocusEventHandler", "description": "React.FocusEventHandler" } }, - "ref": { "type": { "name": "React.Ref<any>", "description": "React.Ref<any>" } }, + "rootRef": { + "type": { "name": "React.Ref<Element>", "description": "React.Ref<Element>" } + }, "tabIndex": { "type": { "name": "NonNullable<React.HTMLAttributes<any>['tabIndex']>", @@ -31,11 +33,6 @@ "default": "false", "required": true }, - "disabled": { - "type": { "name": "boolean", "description": "boolean" }, - "default": "false", - "required": true - }, "focusVisible": { "type": { "name": "boolean", "description": "boolean" }, "default": "false", @@ -48,10 +45,10 @@ }, "required": true }, - "ref": { + "rootRef": { "type": { - "name": "((instance: unknown) => void) | null", - "description": "((instance: unknown) => void) | null" + "name": "React.RefCallback<Element> | null", + "description": "React.RefCallback<Element> | null" }, "required": true }, diff --git a/docs/pages/base/api/use-input.json b/docs/pages/base/api/use-input.json index cabf8d6c864f36..adccff25df884e 100644 --- a/docs/pages/base/api/use-input.json +++ b/docs/pages/base/api/use-input.json @@ -64,6 +64,13 @@ }, "required": true }, + "inputRef": { + "type": { + "name": "React.RefCallback<HTMLInputElement> | null", + "description": "React.RefCallback<HTMLInputElement> | null" + }, + "required": true + }, "required": { "type": { "name": "boolean", "description": "boolean" }, "default": "false", diff --git a/docs/pages/base/api/use-menu-item.json b/docs/pages/base/api/use-menu-item.json index f41adb366e962c..2cbe11387ee4aa 100644 --- a/docs/pages/base/api/use-menu-item.json +++ b/docs/pages/base/api/use-menu-item.json @@ -1,7 +1,7 @@ { "parameters": { - "ref": { - "type": { "name": "React.Ref<any>", "description": "React.Ref<any>" }, + "rootRef": { + "type": { "name": "React.Ref<Element>", "description": "React.Ref<Element>" }, "required": true }, "disabled": { "type": { "name": "boolean", "description": "boolean" } }, @@ -26,10 +26,10 @@ }, "highlighted": { "type": { "name": "boolean", "description": "boolean" }, "required": true }, "index": { "type": { "name": "number", "description": "number" }, "required": true }, - "ref": { + "rootRef": { "type": { - "name": "((instance: unknown) => void) | null", - "description": "((instance: unknown) => void) | null" + "name": "React.RefCallback<Element> | null", + "description": "React.RefCallback<Element> | null" }, "required": true }, diff --git a/docs/pages/base/api/use-menu.json b/docs/pages/base/api/use-menu.json index 33d2a27671dfd7..90ff035c0a2ff7 100644 --- a/docs/pages/base/api/use-menu.json +++ b/docs/pages/base/api/use-menu.json @@ -3,7 +3,7 @@ "defaultOpen": { "type": { "name": "boolean", "description": "boolean" }, "default": "false" }, "listboxId": { "type": { "name": "string", "description": "string" } }, "listboxRef": { - "type": { "name": "React.Ref<any>", "description": "React.Ref<any>" } + "type": { "name": "React.Ref<Element>", "description": "React.Ref<Element>" } }, "onOpenChange": { "type": { "name": "(open: boolean) => void", "description": "(open: boolean) => void" } @@ -33,6 +33,13 @@ "type": { "name": "string | null", "description": "string | null" }, "required": true }, + "listboxRef": { + "type": { + "name": "React.RefCallback<Element> | null", + "description": "React.RefCallback<Element> | null" + }, + "required": true + }, "menuItems": { "type": { "name": "Map<string, MenuItemMetadata>", diff --git a/docs/pages/base/api/use-option.json b/docs/pages/base/api/use-option.json index ec04df35c47a9f..6a1602953b6fa3 100644 --- a/docs/pages/base/api/use-option.json +++ b/docs/pages/base/api/use-option.json @@ -7,11 +7,8 @@ }, "value": { "type": { "name": "Value", "description": "Value" }, "required": true }, "id": { "type": { "name": "string", "description": "string" } }, - "optionRef": { - "type": { - "name": "React.Ref<HTMLElement>", - "description": "React.Ref<HTMLElement>" - } + "rootRef": { + "type": { "name": "React.Ref<Element>", "description": "React.Ref<Element>" } } }, "returnValue": { @@ -24,10 +21,10 @@ }, "highlighted": { "type": { "name": "boolean", "description": "boolean" }, "required": true }, "index": { "type": { "name": "number", "description": "number" }, "required": true }, - "ref": { + "rootRef": { "type": { - "name": "React.RefCallback<HTMLElement>", - "description": "React.RefCallback<HTMLElement>" + "name": "React.RefCallback<Element> | null", + "description": "React.RefCallback<Element> | null" }, "required": true }, diff --git a/docs/pages/base/api/use-select.json b/docs/pages/base/api/use-select.json index dffa49027b8985..c3cfcd10f69cb2 100644 --- a/docs/pages/base/api/use-select.json +++ b/docs/pages/base/api/use-select.json @@ -58,6 +58,13 @@ "type": { "name": "boolean", "description": "boolean" }, "required": true }, + "buttonRef": { + "type": { + "name": "React.RefCallback<Element> | null", + "description": "React.RefCallback<Element> | null" + }, + "required": true + }, "contextValue": { "type": { "name": "SelectProviderValue<Value>", @@ -98,6 +105,13 @@ "type": { "name": "Value | null", "description": "Value | null" }, "required": true }, + "listboxRef": { + "type": { + "name": "React.RefCallback<Element> | null", + "description": "React.RefCallback<Element> | null" + }, + "required": true + }, "open": { "type": { "name": "boolean", "description": "boolean" }, "required": true }, "options": { "type": { "name": "Value[]", "description": "Value[]" }, "required": true }, "value": { diff --git a/docs/pages/base/api/use-slider.json b/docs/pages/base/api/use-slider.json index e24d391711bd39..5f75a73d74aefc 100644 --- a/docs/pages/base/api/use-slider.json +++ b/docs/pages/base/api/use-slider.json @@ -1,9 +1,5 @@ { "parameters": { - "ref": { - "type": { "name": "React.Ref<any>", "description": "React.Ref<any>" }, - "required": true - }, "aria-labelledby": { "type": { "name": "string", "description": "string" } }, "defaultValue": { "type": { "name": "number | number[]", "description": "number | number[]" } }, "disabled": { "type": { "name": "boolean", "description": "boolean" }, "default": "false" }, @@ -35,6 +31,9 @@ }, "default": "'horizontal'" }, + "rootRef": { + "type": { "name": "React.Ref<Element>", "description": "React.Ref<Element>" } + }, "scale": { "type": { "name": "(value: number) => number", @@ -101,6 +100,13 @@ "required": true }, "range": { "type": { "name": "boolean", "description": "boolean" }, "required": true }, + "rootRef": { + "type": { + "name": "React.RefCallback<Element> | null", + "description": "React.RefCallback<Element> | null" + }, + "required": true + }, "trackLeap": { "type": { "name": "number", "description": "number" }, "required": true }, "trackOffset": { "type": { "name": "number", "description": "number" }, "required": true }, "values": { "type": { "name": "number[]", "description": "number[]" }, "required": true } diff --git a/docs/pages/base/api/use-snackbar.json b/docs/pages/base/api/use-snackbar.json index 1e5ffd07f9e5d7..dc8c24a848908f 100644 --- a/docs/pages/base/api/use-snackbar.json +++ b/docs/pages/base/api/use-snackbar.json @@ -15,7 +15,6 @@ } }, "open": { "type": { "name": "boolean", "description": "boolean" } }, - "ref": { "type": { "name": "React.Ref<any>", "description": "React.Ref<any>" } }, "resumeHideDuration": { "type": { "name": "number", "description": "number" } } }, "returnValue": { diff --git a/docs/pages/base/api/use-switch.json b/docs/pages/base/api/use-switch.json index cf70cb05986d1f..20626c2aef1f32 100644 --- a/docs/pages/base/api/use-switch.json +++ b/docs/pages/base/api/use-switch.json @@ -36,6 +36,13 @@ }, "required": true }, + "inputRef": { + "type": { + "name": "React.RefCallback<HTMLInputElement> | null", + "description": "React.RefCallback<HTMLInputElement> | null" + }, + "required": true + }, "readOnly": { "type": { "name": "boolean", "description": "boolean" }, "required": true } }, "name": "useSwitch", diff --git a/docs/pages/base/api/use-tab.json b/docs/pages/base/api/use-tab.json index 656dad09fbbe91..58c50846fc64c0 100644 --- a/docs/pages/base/api/use-tab.json +++ b/docs/pages/base/api/use-tab.json @@ -11,7 +11,9 @@ "onClick": { "type": { "name": "React.MouseEventHandler", "description": "React.MouseEventHandler" } }, - "ref": { "type": { "name": "React.Ref<any>", "description": "React.Ref<any>" } }, + "rootRef": { + "type": { "name": "React.Ref<Element>", "description": "React.Ref<Element>" } + }, "value": { "type": { "name": "number | string", "description": "number | string" } } }, "returnValue": { @@ -26,6 +28,13 @@ }, "highlighted": { "type": { "name": "boolean", "description": "boolean" }, "required": true }, "index": { "type": { "name": "number", "description": "number" }, "required": true }, + "rootRef": { + "type": { + "name": "React.RefCallback<Element> | null", + "description": "React.RefCallback<Element> | null" + }, + "required": true + }, "selected": { "type": { "name": "boolean", "description": "boolean" }, "required": true }, "setFocusVisible": { "type": { diff --git a/docs/pages/base/api/use-tabs-list.json b/docs/pages/base/api/use-tabs-list.json index bc7931dddcc7f2..b5e453af6f8a3e 100644 --- a/docs/pages/base/api/use-tabs-list.json +++ b/docs/pages/base/api/use-tabs-list.json @@ -1,7 +1,7 @@ { "parameters": { - "ref": { - "type": { "name": "React.Ref<unknown>", "description": "React.Ref<unknown>" }, + "rootRef": { + "type": { "name": "React.Ref<Element>", "description": "React.Ref<Element>" }, "required": true } }, @@ -41,6 +41,13 @@ "default": "'horizontal'", "required": true }, + "rootRef": { + "type": { + "name": "React.RefCallback<Element> | null", + "description": "React.RefCallback<Element> | null" + }, + "required": true + }, "selectedValue": { "type": { "name": "string | number | null", "description": "string | number | null" }, "required": true diff --git a/docs/pages/experiments/base/listbox.tsx b/docs/pages/experiments/base/listbox.tsx index 3d87ee935df0c9..47dcd768043cbe 100644 --- a/docs/pages/experiments/base/listbox.tsx +++ b/docs/pages/experiments/base/listbox.tsx @@ -93,7 +93,7 @@ const Item = React.forwardRef(function Item( ref: React.Ref, ) { const { value: item, id } = props; - const { getRootProps, selected, highlighted } = useListItem({ item, ref }); + const { getRootProps, selected, highlighted } = useListItem({ item, rootRef: ref }); const itemProps = getRootProps(); diff --git a/docs/translations/api-docs/use-button/use-button.json b/docs/translations/api-docs/use-button/use-button.json index 15688c68bc0ed6..b4dbbae1765c6b 100644 --- a/docs/translations/api-docs/use-button/use-button.json +++ b/docs/translations/api-docs/use-button/use-button.json @@ -7,10 +7,9 @@ }, "returnValueDescriptions": { "active": "If true, the component is active (pressed).", - "disabled": "If true, the component is disabled.", "focusVisible": "If true, the component is being focused using keyboard.", "getRootProps": "Resolver for the root slot's props.", - "ref": "A ref to the component's root DOM element.", + "rootRef": "A ref to the component's root DOM element.", "setFocusVisible": "Callback for setting the focusVisible param." } } diff --git a/docs/translations/api-docs/use-menu-item/use-menu-item.json b/docs/translations/api-docs/use-menu-item/use-menu-item.json index 5c2971b849e460..1b3d173e4923ee 100644 --- a/docs/translations/api-docs/use-menu-item/use-menu-item.json +++ b/docs/translations/api-docs/use-menu-item/use-menu-item.json @@ -7,7 +7,7 @@ "getRootProps": "Resolver for the root slot's props.", "highlighted": "If true, the component is being highlighted.", "index": "0-based index of the item in the menu.", - "ref": "The ref to the component's root DOM element.", + "rootRef": "The ref to the component's root DOM element.", "totalItemCount": "Total number of items in the menu." } } diff --git a/docs/translations/api-docs/use-menu/use-menu.json b/docs/translations/api-docs/use-menu/use-menu.json index 28fc5be0ea60b0..24966d2a171183 100644 --- a/docs/translations/api-docs/use-menu/use-menu.json +++ b/docs/translations/api-docs/use-menu/use-menu.json @@ -12,6 +12,7 @@ "dispatch": "Action dispatcher for the menu component.\nAllows to programmatically control the menu.", "getListboxProps": "Resolver for the listbox component's props.", "highlightedValue": "The highlighted option in the menu listbox.", + "listboxRef": "The ref to the listbox DOM node.", "menuItems": "Items in the menu listbox.", "open": "If true, the menu is open." } diff --git a/docs/translations/api-docs/use-select/use-select.json b/docs/translations/api-docs/use-select/use-select.json index c9822f6fbf031f..ec626227399f64 100644 --- a/docs/translations/api-docs/use-select/use-select.json +++ b/docs/translations/api-docs/use-select/use-select.json @@ -19,6 +19,7 @@ "returnValueDescriptions": { "buttonActive": "If true, the trigger button is active (pressed).", "buttonFocusVisible": "If true, the trigger button has a visible focus.", + "buttonRef": "Ref to the button slot DOM node.", "contextValue": "A value to be passed to the SelectProvider component.", "disabled": "If true, the select is disabled.", "dispatch": "Action dispatcher for the select component.\nAllows to programmatically control the select.", @@ -26,6 +27,7 @@ "getListboxProps": "Resolver for the listbox slot's props.", "getOptionMetadata": "A function that returns the metadata of an option with a given value.", "highlightedOption": "The value of the highlighted option.", + "listboxRef": "Ref to the listbox slot DOM node.", "open": "If true, the listbox is open.", "options": "Values of all the registered options.", "value": "The value of the selected option(s)." diff --git a/docs/translations/api-docs/use-slider/use-slider.json b/docs/translations/api-docs/use-slider/use-slider.json index 0ed11afef95b15..6125d7226b96b9 100644 --- a/docs/translations/api-docs/use-slider/use-slider.json +++ b/docs/translations/api-docs/use-slider/use-slider.json @@ -13,7 +13,7 @@ "onChange": "Callback function that is fired when the slider's value changed.", "onChangeCommitted": "Callback function that is fired when the mouseup is triggered.", "orientation": "The component orientation.", - "ref": "The ref attached to the root of the Slider.", + "rootRef": "The ref attached to the root of the Slider.", "scale": "A transformation function, to change the scale of the slider.", "step": "The granularity with which the slider can step through values. (A \"discrete\" slider.)\nThe min prop serves as the origin for the valid values.\nWe recommend (max - min) to be evenly divisible by the step.\n\nWhen step is null, the thumb can only be slid onto marks provided with the marks prop.", "tabIndex": "Tab index attribute of the hidden input element.", @@ -31,6 +31,7 @@ "marks": "The marks of the slider. Marks indicate predetermined values to which the user can move the slider.", "open": "The thumb index for the current value when in hover state.", "range": "If true, the slider is a range slider when the value prop passed is an array.", + "rootRef": "Ref to the root slot's DOM node.", "trackLeap": "The track leap for the current value of the slider.", "trackOffset": "The track offset for the current value of the slider.", "values": "The possible values of the slider." diff --git a/docs/translations/api-docs/use-switch/use-switch.json b/docs/translations/api-docs/use-switch/use-switch.json index 2858315d56d30c..16f137be40b835 100644 --- a/docs/translations/api-docs/use-switch/use-switch.json +++ b/docs/translations/api-docs/use-switch/use-switch.json @@ -13,6 +13,7 @@ "disabled": "If true, the component will be disabled.", "focusVisible": "If true, it indicates that the component is being focused using keyboard.", "getInputProps": "Resolver for the input slot's props.", + "inputRef": "Ref to the input slot's DOM node.", "readOnly": "If true, the component will be read only." } } diff --git a/docs/translations/api-docs/use-tab/use-tab.json b/docs/translations/api-docs/use-tab/use-tab.json index 0f4fd4712898e2..84dde04e8b49cc 100644 --- a/docs/translations/api-docs/use-tab/use-tab.json +++ b/docs/translations/api-docs/use-tab/use-tab.json @@ -5,7 +5,7 @@ "id": "The id of the tab.\nIf not provided, it will be automatically generated.", "onChange": "If true, the tab will be disabled.", "onClick": "Callback fired when the tab is clicked.", - "ref": "Ref to the DOM element associated with the tab.", + "rootRef": "Ref to the root slot's DOM element.", "value": "The value of the tab.\nIt's used to associate the tab with a tab panel(s) with the same value.\nIf the value is not provided, it falls back to the position index." }, "returnValueDescriptions": { @@ -14,6 +14,7 @@ "getRootProps": "Resolver for the root slot's props.", "highlighted": "If true, the tab is highlighted.", "index": "0-based index of the tab in the list of tabs.", + "rootRef": "Ref to the root slot's DOM element.", "selected": "If true, the tab is selected.", "setFocusVisible": "Sets the focus-visible state of the tab.\nThis is a workaround for browsers that do not support this feature natively.", "totalTabsCount": "Total number of tabs in the nearest parent TabsList.\nThis can be used to determine if the tab is the last one to style it accordingly." diff --git a/docs/translations/api-docs/use-tabs-list/use-tabs-list.json b/docs/translations/api-docs/use-tabs-list/use-tabs-list.json index eb1cbcd966bb1a..9cba356151ab91 100644 --- a/docs/translations/api-docs/use-tabs-list/use-tabs-list.json +++ b/docs/translations/api-docs/use-tabs-list/use-tabs-list.json @@ -1,6 +1,6 @@ { "hookDescription": "", - "parametersDescriptions": { "ref": "Ref to the root element." }, + "parametersDescriptions": { "rootRef": "Ref to the root element." }, "returnValueDescriptions": { "contextValue": "The value to be passed to the TabListProvider above all the tabs.", "dispatch": "Action dispatcher for the tabs list component.\nAllows to programmatically control the tabs list.", diff --git a/packages/mui-base/src/Badge/Badge.tsx b/packages/mui-base/src/Badge/Badge.tsx index 4f35db7bbf7ef9..3936c21e8c4b3d 100644 --- a/packages/mui-base/src/Badge/Badge.tsx +++ b/packages/mui-base/src/Badge/Badge.tsx @@ -34,7 +34,10 @@ const useUtilityClasses = (ownerState: BadgeOwnerState) => { * * - [Badge API](https://mui.com/base/react-badge/components-api/#badge) */ -const Badge = React.forwardRef(function Badge(props: BadgeProps, ref) { +const Badge = React.forwardRef(function Badge( + props: BadgeProps, + forwardedRef: React.ForwardedRef, +) { const { badgeContent: badgeContentProp, component, @@ -68,7 +71,7 @@ const Badge = React.forwardRef(function Badge(props: BadgeProps, ref) { externalSlotProps: slotProps.root, externalForwardedProps: other, additionalProps: { - ref, + ref: forwardedRef, }, ownerState, className: classes.root, diff --git a/packages/mui-base/src/Badge/Badge.types.ts b/packages/mui-base/src/Badge/Badge.types.ts index 0e49314d5da09c..8bf9d3756ed9e7 100644 --- a/packages/mui-base/src/Badge/Badge.types.ts +++ b/packages/mui-base/src/Badge/Badge.types.ts @@ -1,16 +1,18 @@ import * as React from 'react'; -import { OverrideProps, OverridableTypeMap, OverridableComponent } from '@mui/types'; +import { OverrideProps, OverridableTypeMap, OverridableComponent, Simplify } from '@mui/types'; import { SlotComponentProps } from '../utils'; export interface BadgeRootSlotPropsOverrides {} export interface BadgeBadgeSlotPropsOverrides {} -export type BadgeOwnerState = BadgeProps & { - badgeContent: React.ReactNode; - invisible: boolean; - max: number; - showZero: boolean; -}; +export type BadgeOwnerState = Simplify< + BadgeOwnProps & { + badgeContent: React.ReactNode; + invisible: boolean; + max: number; + showZero: boolean; + } +>; export interface BadgeOwnProps { /** @@ -65,9 +67,12 @@ export interface BadgeSlots { badge?: React.ElementType; } -export interface BadgeTypeMap

{ - props: P & BadgeOwnProps; - defaultComponent: D; +export interface BadgeTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'span', +> { + props: BadgeOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } /** @@ -80,10 +85,11 @@ export interface ExtendBadgeTypeMap { export type ExtendBadge = OverridableComponent>; -export type BadgeProps = - OverrideProps, D> & { - component?: D; - }; +export type BadgeProps< + RootComponentType extends React.ElementType = BadgeTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType> & { + component?: RootComponentType; +}; export type BadgeRootSlotProps = { children?: React.ReactNode; diff --git a/packages/mui-base/src/Button/Button.tsx b/packages/mui-base/src/Button/Button.tsx index c4186d15517465..013c3fb78e56e1 100644 --- a/packages/mui-base/src/Button/Button.tsx +++ b/packages/mui-base/src/Button/Button.tsx @@ -3,17 +3,12 @@ import PropTypes from 'prop-types'; import { OverridableComponent } from '@mui/types'; import composeClasses from '../composeClasses'; import { getButtonUtilityClass } from './buttonClasses'; -import { ButtonProps, ButtonOwnProps, ButtonTypeMap, ButtonRootSlotProps } from './Button.types'; +import { ButtonProps, ButtonTypeMap, ButtonRootSlotProps, ButtonOwnerState } from './Button.types'; import useButton from '../useButton'; import { WithOptionalOwnerState } from '../utils/types'; import { useSlotProps } from '../utils'; import { useClassNamesOverride } from '../utils/ClassNameConfigurator'; -export interface ButtonOwnerState extends ButtonOwnProps { - focusVisible: boolean; - active: boolean; -} - const useUtilityClasses = (ownerState: ButtonOwnerState) => { const { active, disabled, focusVisible } = ownerState; @@ -34,9 +29,10 @@ const useUtilityClasses = (ownerState: ButtonOwnerState) => { * * - [Button API](https://mui.com/base/react-button/components-api/#button) */ -const Button = React.forwardRef(function Button< - BaseComponentType extends React.ElementType = ButtonTypeMap['defaultComponent'], ->(props: ButtonProps, forwardedRef: React.ForwardedRef) { +const Button = React.forwardRef(function Button( + props: ButtonProps, + forwardedRef: React.ForwardedRef, +) { const { action, children, diff --git a/packages/mui-base/src/Button/Button.types.ts b/packages/mui-base/src/Button/Button.types.ts index 54c35764b4f68b..c873aa0f89eb5d 100644 --- a/packages/mui-base/src/Button/Button.types.ts +++ b/packages/mui-base/src/Button/Button.types.ts @@ -39,20 +39,26 @@ export interface ButtonSlots { root?: React.ElementType; } -export type ButtonProps = - OverrideProps, D> & { - component?: D; - }; +export type ButtonProps< + RootComponentType extends React.ElementType = ButtonTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType> & { + component?: RootComponentType; +}; -export interface ButtonTypeMap

{ - props: P & ButtonOwnProps; - defaultComponent: D; +export interface ButtonTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'button', +> { + props: ButtonOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } -export type ButtonOwnerState = ButtonOwnProps & { - active: boolean; - focusVisible: boolean; -}; +export type ButtonOwnerState = Simplify< + ButtonOwnProps & { + active: boolean; + focusVisible: boolean; + } +>; export type ButtonRootSlotProps = Simplify< UseButtonRootSlotProps & { diff --git a/packages/mui-base/src/FormControl/FormControl.tsx b/packages/mui-base/src/FormControl/FormControl.tsx index a6d362c85e65ab..f79f77647eaa2b 100644 --- a/packages/mui-base/src/FormControl/FormControl.tsx +++ b/packages/mui-base/src/FormControl/FormControl.tsx @@ -75,8 +75,8 @@ function useUtilityClasses(ownerState: FormControlOwnerState) { * - [FormControl API](https://mui.com/base/react-form-control/components-api/#form-control) */ const FormControl = React.forwardRef(function FormControl< - D extends React.ElementType = FormControlTypeMap['defaultComponent'], ->(props: FormControlProps, ref: React.ForwardedRef) { + RootComponentType extends React.ElementType, +>(props: FormControlProps, forwardedRef: React.ForwardedRef) { const { defaultValue, children, @@ -151,7 +151,7 @@ const FormControl = React.forwardRef(function FormControl< externalSlotProps: slotProps.root, externalForwardedProps: other, additionalProps: { - ref, + ref: forwardedRef, children: renderChildren(), }, ownerState, diff --git a/packages/mui-base/src/FormControl/FormControl.types.ts b/packages/mui-base/src/FormControl/FormControl.types.ts index a1b4b8e6f675a6..faa33734da2979 100644 --- a/packages/mui-base/src/FormControl/FormControl.types.ts +++ b/packages/mui-base/src/FormControl/FormControl.types.ts @@ -62,16 +62,18 @@ export interface FormControlSlots { root?: React.ElementType; } -export interface FormControlTypeMap

{ - props: P & FormControlOwnProps; - defaultComponent: D; +export interface FormControlTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'div', +> { + props: FormControlOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } export type FormControlProps< - D extends React.ElementType = FormControlTypeMap['defaultComponent'], - P = {}, -> = OverrideProps, D> & { - component?: D; + RootComponentType extends React.ElementType = FormControlTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType> & { + component?: RootComponentType; }; type NonOptionalOwnerState = 'disabled' | 'error' | 'required'; diff --git a/packages/mui-base/src/Input/Input.tsx b/packages/mui-base/src/Input/Input.tsx index 7a709d2b71f9ec..2ce2cad7adc565 100644 --- a/packages/mui-base/src/Input/Input.tsx +++ b/packages/mui-base/src/Input/Input.tsx @@ -46,9 +46,9 @@ const useUtilityClasses = (ownerState: InputOwnerState) => { * * - [Input API](https://mui.com/base/react-input/components-api/#input) */ -const Input = React.forwardRef(function Input( - props: InputProps, - forwardedRef: React.ForwardedRef, +const Input = React.forwardRef(function Input( + props: InputProps, + forwardedRef: React.ForwardedRef, ) { const { 'aria-describedby': ariaDescribedby, diff --git a/packages/mui-base/src/Input/Input.types.ts b/packages/mui-base/src/Input/Input.types.ts index dc4262134007c2..71d142d22defe5 100644 --- a/packages/mui-base/src/Input/Input.types.ts +++ b/packages/mui-base/src/Input/Input.types.ts @@ -146,20 +146,22 @@ export interface InputSlots { textarea?: React.ElementType; } -export interface InputTypeMap

{ - props: P & InputOwnProps; - defaultComponent: D; +export interface InputTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'div', +> { + props: InputOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } export type InputProps< - D extends React.ElementType = InputTypeMap['defaultComponent'], - P = {}, -> = OverrideProps, D> & { - component?: D; + RootComponentType extends React.ElementType = InputTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType> & { + component?: RootComponentType; }; export type InputOwnerState = Simplify< - Omit & { + InputOwnProps & { formControlContext: FormControlState | undefined; focused: boolean; type: React.InputHTMLAttributes['type'] | undefined; diff --git a/packages/mui-base/src/Menu/Menu.tsx b/packages/mui-base/src/Menu/Menu.tsx index 6f9ee7f707fc6e..41c463e4da7976 100644 --- a/packages/mui-base/src/Menu/Menu.tsx +++ b/packages/mui-base/src/Menu/Menu.tsx @@ -31,9 +31,10 @@ function useUtilityClasses(ownerState: MenuOwnerState) { * * - [Menu API](https://mui.com/base/react-menu/components-api/#menu) */ -const Menu = React.forwardRef(function Menu< - BaseComponentType extends React.ElementType = MenuTypeMap['defaultComponent'], ->(props: MenuProps, forwardedRef: React.Ref) { +const Menu = React.forwardRef(function Menu( + props: MenuProps, + forwardedRef: React.ForwardedRef, +) { const { actions, anchorEl, diff --git a/packages/mui-base/src/Menu/Menu.types.ts b/packages/mui-base/src/Menu/Menu.types.ts index 87262a72b64450..fa8ccca77518c8 100644 --- a/packages/mui-base/src/Menu/Menu.types.ts +++ b/packages/mui-base/src/Menu/Menu.types.ts @@ -1,5 +1,5 @@ -import { OverrideProps } from '@mui/types'; import * as React from 'react'; +import { OverrideProps, Simplify } from '@mui/types'; import Popper, { PopperProps } from '../Popper'; import { SlotComponentProps } from '../utils'; import { UseMenuListboxSlotProps } from '../useMenu'; @@ -66,19 +66,25 @@ export interface MenuSlots { listbox?: React.ElementType; } -export interface MenuTypeMap

{ - props: P & MenuOwnProps; - defaultComponent: D; +export interface MenuTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'ul', +> { + props: MenuOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } -export type MenuProps = - OverrideProps, D> & { - component?: D; - }; +export type MenuProps< + RootComponentType extends React.ElementType = MenuTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType> & { + component?: RootComponentType; +}; -export interface MenuOwnerState extends MenuOwnProps { - open: boolean; -} +export type MenuOwnerState = Simplify< + MenuOwnProps & { + open: boolean; + } +>; export type MenuRootSlotProps = { anchorEl: PopperProps['anchorEl']; diff --git a/packages/mui-base/src/MenuItem/MenuItem.tsx b/packages/mui-base/src/MenuItem/MenuItem.tsx index 625a98e786d95f..7786d99a7251cb 100644 --- a/packages/mui-base/src/MenuItem/MenuItem.tsx +++ b/packages/mui-base/src/MenuItem/MenuItem.tsx @@ -28,9 +28,10 @@ function useUtilityClasses(ownerState: MenuItemOwnerState) { * * - [MenuItem API](https://mui.com/base/react-menu/components-api/#menu-item) */ -const MenuItem = React.forwardRef(function MenuItem< - BaseComponentType extends React.ElementType = MenuItemTypeMap['defaultComponent'], ->(props: MenuItemProps, ref: React.Ref) { +const MenuItem = React.forwardRef(function MenuItem( + props: MenuItemProps, + forwardedRef: React.ForwardedRef, +) { const { children, disabled: disabledProp = false, @@ -43,7 +44,7 @@ const MenuItem = React.forwardRef(function MenuItem< const { getRootProps, disabled, focusVisible, highlighted } = useMenuItem({ disabled: disabledProp, - ref, + rootRef: forwardedRef, label, }); diff --git a/packages/mui-base/src/MenuItem/MenuItem.types.ts b/packages/mui-base/src/MenuItem/MenuItem.types.ts index 8979b3d598962a..43f9454a7357aa 100644 --- a/packages/mui-base/src/MenuItem/MenuItem.types.ts +++ b/packages/mui-base/src/MenuItem/MenuItem.types.ts @@ -1,14 +1,16 @@ -import { OverrideProps } from '@mui/types'; import * as React from 'react'; +import { OverrideProps, Simplify } from '@mui/types'; import { SlotComponentProps } from '../utils'; export interface MenuItemRootSlotPropsOverrides {} -export interface MenuItemOwnerState extends MenuItemOwnProps { - disabled: boolean; - focusVisible: boolean; - highlighted: boolean; -} +export type MenuItemOwnerState = Simplify< + MenuItemOwnProps & { + disabled: boolean; + focusVisible: boolean; + highlighted: boolean; + } +>; export interface MenuItemOwnProps { children?: React.ReactNode; @@ -47,15 +49,19 @@ export interface MenuItemSlots { root?: React.ElementType; } -export interface MenuItemTypeMap

{ - props: P & MenuItemOwnProps; - defaultComponent: D; +export interface MenuItemTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'li', +> { + props: MenuItemOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } -export type MenuItemProps = - OverrideProps, D> & { - component?: D; - }; +export type MenuItemProps< + RootComponentType extends React.ElementType = MenuItemTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType> & { + component?: RootComponentType; +}; export interface MenuItemState { disabled: boolean; diff --git a/packages/mui-base/src/Modal/Modal.tsx b/packages/mui-base/src/Modal/Modal.tsx index b16b8b6f80844d..c2e95b3b85e416 100644 --- a/packages/mui-base/src/Modal/Modal.tsx +++ b/packages/mui-base/src/Modal/Modal.tsx @@ -62,9 +62,10 @@ const defaultManager = new ModalManager(); * * - [Modal API](https://mui.com/base/react-modal/components-api/#modal) */ -const Modal = React.forwardRef(function Modal< - BaseComponentType extends React.ElementType = ModalTypeMap['defaultComponent'], ->(props: ModalProps, forwardedRef: React.Ref | undefined) { +const Modal = React.forwardRef(function Modal( + props: ModalProps, + forwardedRef: React.ForwardedRef, +) { const { children, closeAfterTransition = false, diff --git a/packages/mui-base/src/Modal/Modal.types.ts b/packages/mui-base/src/Modal/Modal.types.ts index 4ba580e8f213e0..586d49124f4a3c 100644 --- a/packages/mui-base/src/Modal/Modal.types.ts +++ b/packages/mui-base/src/Modal/Modal.types.ts @@ -1,5 +1,5 @@ -import { OverridableComponent, OverridableTypeMap, OverrideProps } from '@mui/types'; import * as React from 'react'; +import { OverridableComponent, OverridableTypeMap, OverrideProps, Simplify } from '@mui/types'; import { PortalProps } from '../Portal'; import { SlotComponentProps } from '../utils'; @@ -122,9 +122,12 @@ export interface ModalSlots { backdrop?: React.ElementType; } -export interface ModalTypeMap

{ - props: P & ModalOwnProps; - defaultComponent: D; +export interface ModalTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'div', +> { + props: ModalOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } /** @@ -138,25 +141,23 @@ export interface ExtendModalTypeMap { export type ExtendModal = OverridableComponent>; export type ModalProps< - D extends React.ElementType = ModalTypeMap['defaultComponent'], - P = { - component?: React.ElementType; - focusVisible?: boolean; - }, -> = OverrideProps, D>; + RootComponentType extends React.ElementType = ModalTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType>; -export type ModalOwnerState = ModalProps & { - closeAfterTransition: boolean; - disableAutoFocus: boolean; - disableEnforceFocus: boolean; - disableEscapeKeyDown: boolean; - disablePortal: boolean; - disableRestoreFocus: boolean; - disableScrollLock: boolean; - exited: boolean; - hideBackdrop: boolean; - keepMounted: boolean; -}; +export type ModalOwnerState = Simplify< + ModalOwnProps & { + closeAfterTransition: boolean; + disableAutoFocus: boolean; + disableEnforceFocus: boolean; + disableEscapeKeyDown: boolean; + disablePortal: boolean; + disableRestoreFocus: boolean; + disableScrollLock: boolean; + exited: boolean; + hideBackdrop: boolean; + keepMounted: boolean; + } +>; export interface ModalRootSlotProps { children: React.ReactNode; diff --git a/packages/mui-base/src/Option/Option.tsx b/packages/mui-base/src/Option/Option.tsx index b36585e371741a..7ecb1ef8091662 100644 --- a/packages/mui-base/src/Option/Option.tsx +++ b/packages/mui-base/src/Option/Option.tsx @@ -21,10 +21,10 @@ function useUtilityClasses(ownerState: OptionOwnerState( - props: OptionProps, - ref: React.ForwardedRef, -) { +const Option = React.forwardRef(function Option< + OptionValue, + RootComponentType extends React.ElementType, +>(props: OptionProps, forwardedRef: React.ForwardedRef) { const { children, component, @@ -38,8 +38,8 @@ const Option = React.forwardRef(function Option( const Root = component || slots.root || 'li'; - const optionRef = React.useRef(null); - const combinedRef = useForkRef(optionRef, ref); + const optionRef = React.useRef(null); + const combinedRef = useForkRef(optionRef, forwardedRef); // If `label` is not explicitly provided, the `children` are used for convenience. // This is used to populate the select's trigger with the selected option's label. @@ -49,7 +49,7 @@ const Option = React.forwardRef(function Option( const { getRootProps, selected, highlighted, index } = useOption({ disabled, label: computedLabel, - optionRef: combinedRef, + rootRef: combinedRef, value, }); diff --git a/packages/mui-base/src/Option/Option.types.ts b/packages/mui-base/src/Option/Option.types.ts index 2ea4769164e200..c87e9f911d39be 100644 --- a/packages/mui-base/src/Option/Option.types.ts +++ b/packages/mui-base/src/Option/Option.types.ts @@ -45,27 +45,31 @@ export interface OptionSlots { root?: React.ElementType; } -export interface OptionTypeMap { - props: P & OptionOwnProps; - defaultComponent: D; +export interface OptionTypeMap< + OptionValue, + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'li', +> { + props: OptionOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } export type OptionProps< OptionValue, - D extends React.ElementType = OptionTypeMap['defaultComponent'], -> = OverrideProps, D> & { - component?: D; + RootComponentType extends React.ElementType = OptionTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType> & { + component?: RootComponentType; }; export interface OptionType { - ( + ( props: { /** * The component used for the root node. * Either a string to use a HTML element or a component. */ - component: C; - } & OverrideProps, C>, + component: RootComponentType; + } & OverrideProps, RootComponentType>, ): JSX.Element | null; (props: DefaultComponentProps>): JSX.Element | null; propTypes?: any; diff --git a/packages/mui-base/src/OptionGroup/OptionGroup.tsx b/packages/mui-base/src/OptionGroup/OptionGroup.tsx index bc1166785e9bff..8f4d8ebf8b2c8d 100644 --- a/packages/mui-base/src/OptionGroup/OptionGroup.tsx +++ b/packages/mui-base/src/OptionGroup/OptionGroup.tsx @@ -35,8 +35,8 @@ function useUtilityClasses(disabled: boolean) { * - [OptionGroup API](https://mui.com/base/react-select/components-api/#option-group) */ const OptionGroup = React.forwardRef(function OptionGroup< - BaseComponentType extends React.ElementType = OptionGroupTypeMap['defaultComponent'], ->(props: OptionGroupProps, ref: React.ForwardedRef) { + RootComponentType extends React.ElementType, +>(props: OptionGroupProps, forwardedRef: React.ForwardedRef) { const { component, disabled = false, slotProps = {}, slots = {}, ...other } = props; const Root = component || slots?.root || 'li'; @@ -50,7 +50,7 @@ const OptionGroup = React.forwardRef(function OptionGroup< externalSlotProps: slotProps.root, externalForwardedProps: other, additionalProps: { - ref, + ref: forwardedRef, }, ownerState: props, className: classes.root, diff --git a/packages/mui-base/src/OptionGroup/OptionGroup.types.ts b/packages/mui-base/src/OptionGroup/OptionGroup.types.ts index 8a9517cf734a96..709d3c7c512b32 100644 --- a/packages/mui-base/src/OptionGroup/OptionGroup.types.ts +++ b/packages/mui-base/src/OptionGroup/OptionGroup.types.ts @@ -53,15 +53,19 @@ export interface OptionGroupSlots { list?: React.ElementType; } -export interface OptionGroupTypeMap

{ - props: P & OptionGroupOwnProps; - defaultComponent: D; +export interface OptionGroupTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'li', +> { + props: OptionGroupOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } -export type OptionGroupProps = - OverrideProps, D> & { - component?: D; - }; +export type OptionGroupProps< + RootComponentType extends React.ElementType = OptionGroupTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType> & { + component?: RootComponentType; +}; export type OptionGroupOwnerState = OptionGroupOwnProps; diff --git a/packages/mui-base/src/Popper/Popper.tsx b/packages/mui-base/src/Popper/Popper.tsx index 797dc9258ac8b8..95208a0e67771d 100644 --- a/packages/mui-base/src/Popper/Popper.tsx +++ b/packages/mui-base/src/Popper/Popper.tsx @@ -75,10 +75,9 @@ const useUtilityClasses = () => { const defaultPopperOptions = {}; -const PopperTooltip = React.forwardRef(function PopperTooltip( - props: PopperTooltipProps, - ref: React.ForwardedRef, -) { +const PopperTooltip = React.forwardRef(function PopperTooltip< + RootComponentType extends React.ElementType, +>(props: PopperTooltipProps, forwardedRef: React.ForwardedRef) { const { anchorEl, children, @@ -99,7 +98,7 @@ const PopperTooltip = React.forwardRef(function PopperTooltip( } = props; const tooltipRef = React.useRef(null); - const ownRef = useForkRef(tooltipRef, ref); + const ownRef = useForkRef(tooltipRef, forwardedRef); const popperRef = React.useRef(null); const handlePopperRef = useForkRef(popperRef, popperRefProp); @@ -247,9 +246,9 @@ const PopperTooltip = React.forwardRef(function PopperTooltip( * * - [Popper API](https://mui.com/base/react-popper/components-api/#popper) */ -const Popper = React.forwardRef(function Popper( - props: PopperProps, - ref: React.ForwardedRef, +const Popper = React.forwardRef(function Popper( + props: PopperProps, + forwardedRef: React.ForwardedRef, ) { const { anchorEl, @@ -313,7 +312,7 @@ const Popper = React.forwardRef(function Popper( direction={direction} disablePortal={disablePortal} modifiers={modifiers} - ref={ref} + ref={forwardedRef} open={transition ? !exited : open} placement={placement} popperOptions={popperOptions} diff --git a/packages/mui-base/src/Popper/Popper.types.ts b/packages/mui-base/src/Popper/Popper.types.ts index cce150f69cd0ea..9a7e1df513b8f7 100644 --- a/packages/mui-base/src/Popper/Popper.types.ts +++ b/packages/mui-base/src/Popper/Popper.types.ts @@ -1,6 +1,6 @@ +import * as React from 'react'; import { OverrideProps } from '@mui/types'; import { Instance, Options, OptionsGeneric, VirtualElement } from '@popperjs/core'; -import * as React from 'react'; import { PortalProps } from '../Portal'; import { SlotComponentProps } from '../utils'; @@ -114,16 +114,18 @@ export interface PopperSlots { export type PopperOwnerState = PopperOwnProps; -export interface PopperTypeMap

{ - props: P & PopperOwnProps; - defaultComponent: D; +export interface PopperTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'div', +> { + props: PopperOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } export type PopperProps< - D extends React.ElementType = PopperTypeMap['defaultComponent'], - P = {}, -> = OverrideProps, D> & { - component?: D; + RootComponentType extends React.ElementType = PopperTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType> & { + component?: RootComponentType; }; export type PopperTooltipOwnProps = Omit< @@ -133,16 +135,18 @@ export type PopperTooltipOwnProps = Omit< TransitionProps?: PopperTransitionProps; }; -export interface PopperTooltipTypeMap

{ - props: P & PopperTooltipOwnProps; - defaultComponent: D; +export interface PopperTooltipTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'div', +> { + props: PopperTooltipOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } export type PopperTooltipProps< - D extends React.ElementType = PopperTooltipTypeMap['defaultComponent'], - P = {}, -> = OverrideProps, D> & { - component?: D; + RootComponentType extends React.ElementType = PopperTooltipTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType> & { + component?: RootComponentType; }; export interface PopperRootSlotProps { diff --git a/packages/mui-base/src/Portal/Portal.tsx b/packages/mui-base/src/Portal/Portal.tsx index 64a23f78e8d7de..4042ab8b341d83 100644 --- a/packages/mui-base/src/Portal/Portal.tsx +++ b/packages/mui-base/src/Portal/Portal.tsx @@ -28,12 +28,12 @@ function getContainer(container: PortalProps['container']) { */ const Portal = React.forwardRef(function Portal( props: PortalProps, - ref: React.ForwardedRef, + forwardedRef: React.ForwardedRef, ) { const { children, container, disablePortal = false } = props; const [mountNode, setMountNode] = React.useState>(null); // @ts-expect-error TODO upstream fix - const handleRef = useForkRef(React.isValidElement(children) ? children.ref : null, ref); + const handleRef = useForkRef(React.isValidElement(children) ? children.ref : null, forwardedRef); useEnhancedEffect(() => { if (!disablePortal) { @@ -43,14 +43,14 @@ const Portal = React.forwardRef(function Portal( useEnhancedEffect(() => { if (mountNode && !disablePortal) { - setRef(ref, mountNode); + setRef(forwardedRef, mountNode); return () => { - setRef(ref, null); + setRef(forwardedRef, null); }; } return undefined; - }, [ref, mountNode, disablePortal]); + }, [forwardedRef, mountNode, disablePortal]); if (disablePortal) { if (React.isValidElement(children)) { diff --git a/packages/mui-base/src/Select/Select.tsx b/packages/mui-base/src/Select/Select.tsx index 66ba7666f8ac7d..1bd7e94f4fd99f 100644 --- a/packages/mui-base/src/Select/Select.tsx +++ b/packages/mui-base/src/Select/Select.tsx @@ -62,7 +62,9 @@ function defaultFormValueProvider( return JSON.stringify(selectedOption.value); } -function useUtilityClasses(ownerState: SelectOwnerState) { +function useUtilityClasses( + ownerState: SelectOwnerState, +) { const { active, disabled, open, focusVisible } = ownerState; const slots = { @@ -91,9 +93,13 @@ function useUtilityClasses(ownerState: SelectOwnerState) { * * - [Select API](https://mui.com/base/react-select/components-api/#select) */ -const Select = React.forwardRef(function Select( - props: SelectProps, - forwardedRef: React.ForwardedRef, +const Select = React.forwardRef(function Select< + OptionValue extends {}, + Multiple extends boolean, + RootComponentType extends React.ElementType, +>( + props: SelectProps, + forwardedRef: React.ForwardedRef, ) { const { autoFocus, diff --git a/packages/mui-base/src/Select/Select.types.ts b/packages/mui-base/src/Select/Select.types.ts index e4dad740da409d..e7d6aea61f2bb5 100644 --- a/packages/mui-base/src/Select/Select.types.ts +++ b/packages/mui-base/src/Select/Select.types.ts @@ -141,31 +141,41 @@ export interface SelectSlots { export interface SelectTypeMap< OptionValue extends {}, Multiple extends boolean, - P = {}, - D extends React.ElementType = 'button', + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'button', > { - props: P & SelectOwnProps; - defaultComponent: D; + props: SelectOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } export type SelectProps< OptionValue extends {}, Multiple extends boolean, - D extends React.ElementType = SelectTypeMap['defaultComponent'], -> = OverrideProps, D> & { - component?: D; + RootComponentType extends React.ElementType = SelectTypeMap< + OptionValue, + Multiple + >['defaultComponent'], +> = OverrideProps< + SelectTypeMap, + RootComponentType +> & { + component?: RootComponentType; }; // OverridableComponent cannot be used below as Select's props are generic. export interface SelectType { - ( + < + OptionValue extends {}, + RootComponentType extends React.ElementType, + Multiple extends boolean = false, + >( props: { /** * The component used for the root node. * Either a string to use a HTML element or a component. */ - component: C; - } & OverrideProps, C>, + component: RootComponentType; + } & OverrideProps, RootComponentType>, ): JSX.Element | null; ( props: DefaultComponentProps>, @@ -173,13 +183,14 @@ export interface SelectType { propTypes?: any; } -export interface SelectOwnerState - extends SelectOwnProps { - active: boolean; - disabled: boolean; - focusVisible: boolean; - open: boolean; -} +export type SelectOwnerState = Simplify< + SelectOwnProps & { + active: boolean; + disabled: boolean; + focusVisible: boolean; + open: boolean; + } +>; export type SelectRootSlotProps = Simplify< UseSelectButtonSlotProps & { diff --git a/packages/mui-base/src/Slider/Slider.tsx b/packages/mui-base/src/Slider/Slider.tsx index d1e7ff36371dcc..b64edc34e442d7 100644 --- a/packages/mui-base/src/Slider/Slider.tsx +++ b/packages/mui-base/src/Slider/Slider.tsx @@ -55,9 +55,10 @@ const useUtilityClasses = (ownerState: SliderOwnerState) => { * * - [Slider API](https://mui.com/base/react-slider/components-api/#slider) */ -const Slider = React.forwardRef(function Slider< - BaseComponentType extends React.ElementType = SliderTypeMap['defaultComponent'], ->(props: SliderProps, ref: React.ForwardedRef) { +const Slider = React.forwardRef(function Slider( + props: SliderProps, + forwardedRef: React.ForwardedRef, +) { const { 'aria-label': ariaLabel, 'aria-valuetext': ariaValuetext, @@ -119,7 +120,7 @@ const Slider = React.forwardRef(function Slider< values, trackOffset, trackLeap, - } = useSlider({ ...partialOwnerState, ref }); + } = useSlider({ ...partialOwnerState, rootRef: forwardedRef }); const ownerState: SliderOwnerState = { ...partialOwnerState, diff --git a/packages/mui-base/src/Slider/Slider.types.ts b/packages/mui-base/src/Slider/Slider.types.ts index 95542a46bfb9ca..a95ecc53533f9e 100644 --- a/packages/mui-base/src/Slider/Slider.types.ts +++ b/packages/mui-base/src/Slider/Slider.types.ts @@ -1,4 +1,4 @@ -import { OverridableComponent, OverridableTypeMap, OverrideProps } from '@mui/types'; +import { OverridableComponent, OverridableTypeMap, OverrideProps, Simplify } from '@mui/types'; import * as React from 'react'; import { SlotComponentProps } from '../utils'; import { @@ -8,20 +8,22 @@ import { UseSliderThumbSlotProps, } from '../useSlider'; -export interface SliderOwnerState extends SliderOwnProps { - disabled: boolean; - focusedThumbIndex: number; - isRtl: boolean; - max: number; - min: number; - dragging: boolean; - marked: boolean; - orientation: 'horizontal' | 'vertical'; - scale: (value: number) => number; - step: number | null; - track: 'normal' | false | 'inverted'; - valueLabelFormat: string | ((value: number, index: number) => React.ReactNode); -} +export type SliderOwnerState = Simplify< + SliderOwnProps & { + disabled: boolean; + focusedThumbIndex: number; + isRtl: boolean; + max: number; + min: number; + dragging: boolean; + marked: boolean; + orientation: 'horizontal' | 'vertical'; + scale: (value: number) => number; + step: number | null; + track: 'normal' | false | 'inverted'; + valueLabelFormat: string | ((value: number, index: number) => React.ReactNode); + } +>; export interface SliderRootSlotPropsOverrides {} export interface SliderTrackSlotPropsOverrides {} @@ -147,9 +149,12 @@ export interface SliderSlots { input?: React.ElementType; } -export interface SliderTypeMap

{ - props: P & SliderOwnProps; - defaultComponent: D; +export interface SliderTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'span', +> { + props: SliderOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } /** @@ -164,10 +169,11 @@ export type ExtendSlider = OverridableComponent< ExtendSliderTypeMap >; -export type SliderProps = - OverrideProps, D> & { - component?: D; - }; +export type SliderProps< + RootComponentType extends React.ElementType = SliderTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType> & { + component?: RootComponentType; +}; export type SliderRootSlotProps = UseSliderRootSlotProps & { children: React.ReactNode; diff --git a/packages/mui-base/src/Snackbar/Snackbar.tsx b/packages/mui-base/src/Snackbar/Snackbar.tsx index acd987066b9496..2d3e3d03964fe1 100644 --- a/packages/mui-base/src/Snackbar/Snackbar.tsx +++ b/packages/mui-base/src/Snackbar/Snackbar.tsx @@ -33,9 +33,9 @@ const useUtilityClasses = () => { * * - [Snackbar API](https://mui.com/base/react-snackbar/components-api/#snackbar) */ -const Snackbar = React.forwardRef(function Snackbar( - props: SnackbarProps, - ref: React.ForwardedRef, +const Snackbar = React.forwardRef(function Snackbar( + props: SnackbarProps, + forwardedRef: React.ForwardedRef, ) { const { autoHideDuration = null, @@ -64,7 +64,6 @@ const Snackbar = React.forwardRef(function Snackbar( onClose, open, resumeHideDuration, - ref, }); const ownerState: SnackbarOwnerState = props; @@ -77,7 +76,7 @@ const Snackbar = React.forwardRef(function Snackbar( externalForwardedProps: other, externalSlotProps: slotProps.root, additionalProps: { - ref, + ref: forwardedRef, }, ownerState, className: classes.root, diff --git a/packages/mui-base/src/Snackbar/Snackbar.types.ts b/packages/mui-base/src/Snackbar/Snackbar.types.ts index 36346c24ec6885..eac50b9f1eb636 100644 --- a/packages/mui-base/src/Snackbar/Snackbar.types.ts +++ b/packages/mui-base/src/Snackbar/Snackbar.types.ts @@ -42,19 +42,21 @@ export interface SnackbarSlots { root?: React.ElementType; } -export interface SnackbarTypeMap

{ - props: P & SnackbarOwnProps; - defaultComponent: D; +export interface SnackbarTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'div', +> { + props: SnackbarOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } export type SnackbarProps< - D extends React.ElementType = SnackbarTypeMap['defaultComponent'], - P = {}, -> = OverrideProps, D> & { - component?: D; + RootComponentType extends React.ElementType = SnackbarTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType> & { + component?: RootComponentType; }; -export type SnackbarOwnerState = SnackbarProps; +export type SnackbarOwnerState = SnackbarOwnProps; export type SnackbarRootSlotProps = { ownerState: SnackbarOwnerState; diff --git a/packages/mui-base/src/Switch/Switch.tsx b/packages/mui-base/src/Switch/Switch.tsx index 2d8a646b226811..754fc0e7b85b67 100644 --- a/packages/mui-base/src/Switch/Switch.tsx +++ b/packages/mui-base/src/Switch/Switch.tsx @@ -46,9 +46,10 @@ const useUtilityClasses = (ownerState: SwitchOwnerState) => { * * - [Switch API](https://mui.com/base/react-switch/components-api/#switch) */ -const Switch = React.forwardRef(function Switch< - BaseComponentType extends React.ElementType = SwitchTypeMap['defaultComponent'], ->(props: SwitchProps, ref: React.ForwardedRef) { +const Switch = React.forwardRef(function Switch( + props: SwitchProps, + forwardedRef: React.ForwardedRef, +) { const { checked: checkedProp, component, @@ -94,7 +95,7 @@ const Switch = React.forwardRef(function Switch< externalSlotProps: slotProps.root, externalForwardedProps: other, additionalProps: { - ref, + ref: forwardedRef, }, ownerState, className: classes.root, diff --git a/packages/mui-base/src/Switch/Switch.types.ts b/packages/mui-base/src/Switch/Switch.types.ts index a09d087d8ae21b..ef6fd19c34aa26 100644 --- a/packages/mui-base/src/Switch/Switch.types.ts +++ b/packages/mui-base/src/Switch/Switch.types.ts @@ -53,15 +53,19 @@ export interface SwitchSlots { track?: React.ElementType | null; } -export interface SwitchTypeMap

{ - props: P & SwitchOwnProps; - defaultComponent: D; +export interface SwitchTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'span', +> { + props: SwitchOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } -export type SwitchProps = - OverrideProps, D> & { - component?: D; - }; +export type SwitchProps< + RootComponentType extends React.ElementType = SwitchTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType> & { + component?: RootComponentType; +}; export type SwitchOwnerState = Simplify< SwitchOwnProps & { diff --git a/packages/mui-base/src/Tab/Tab.tsx b/packages/mui-base/src/Tab/Tab.tsx index 735dbf5c35c4e7..b1abb62b4dbd38 100644 --- a/packages/mui-base/src/Tab/Tab.tsx +++ b/packages/mui-base/src/Tab/Tab.tsx @@ -28,7 +28,10 @@ const useUtilityClasses = (ownerState: TabOwnerState) => { * * - [Tab API](https://mui.com/base/react-tabs/components-api/#tab) */ -const Tab = React.forwardRef(function Tab(props, ref) { +const Tab = React.forwardRef(function Tab( + props: TabProps, + forwardedRef: React.ForwardedRef, +) { const { action, children, @@ -44,14 +47,14 @@ const Tab = React.forwardRef(function Tab(props, ref) { } = props; const tabRef = React.useRef(); - const handleRef = useForkRef(tabRef, ref); + const handleRef = useForkRef(tabRef, forwardedRef); const { active, highlighted, selected, getRootProps } = useTab({ ...props, - ref: handleRef, + rootRef: handleRef, }); - const ownerState = { + const ownerState: TabOwnerState = { ...props, active, disabled, @@ -68,7 +71,7 @@ const Tab = React.forwardRef(function Tab(props, ref) { externalSlotProps: slotProps.root, externalForwardedProps: other, additionalProps: { - ref, + ref: forwardedRef, }, ownerState, className: classes.root, diff --git a/packages/mui-base/src/Tab/Tab.types.ts b/packages/mui-base/src/Tab/Tab.types.ts index 314bbe16fa247e..226e7ef6b0d898 100644 --- a/packages/mui-base/src/Tab/Tab.types.ts +++ b/packages/mui-base/src/Tab/Tab.types.ts @@ -38,24 +38,27 @@ export interface TabSlots { root?: React.ElementType; } -export type TabProps< - D extends React.ElementType = TabTypeMap['defaultComponent'], - P = {}, -> = OverrideProps, D> & { - component?: D; -}; +export type TabProps = + OverrideProps, RootComponentType> & { + component?: RootComponentType; + }; -export interface TabTypeMap

{ - props: P & TabOwnProps; - defaultComponent: D; +export interface TabTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'button', +> { + props: TabOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } -export type TabOwnerState = TabProps & { - active: boolean; - disabled: boolean; - highlighted: boolean; - selected: boolean; -}; +export type TabOwnerState = Simplify< + TabOwnProps & { + active: boolean; + disabled: boolean; + highlighted: boolean; + selected: boolean; + } +>; export type TabRootSlotProps = Simplify< UseTabRootSlotProps & { diff --git a/packages/mui-base/src/TabPanel/TabPanel.tsx b/packages/mui-base/src/TabPanel/TabPanel.tsx index e30838039ca92a..594081404bbf1f 100644 --- a/packages/mui-base/src/TabPanel/TabPanel.tsx +++ b/packages/mui-base/src/TabPanel/TabPanel.tsx @@ -5,7 +5,12 @@ import { useSlotProps, WithOptionalOwnerState } from '../utils'; import composeClasses from '../composeClasses'; import { getTabPanelUtilityClass } from './tabPanelClasses'; import useTabPanel from '../useTabPanel/useTabPanel'; -import { TabPanelProps, TabPanelRootSlotProps, TabPanelTypeMap } from './TabPanel.types'; +import { + TabPanelOwnerState, + TabPanelProps, + TabPanelRootSlotProps, + TabPanelTypeMap, +} from './TabPanel.types'; import { useClassNamesOverride } from '../utils/ClassNameConfigurator'; const useUtilityClasses = (ownerState: { hidden: boolean }) => { @@ -27,12 +32,15 @@ const useUtilityClasses = (ownerState: { hidden: boolean }) => { * * - [TabPanel API](https://mui.com/base/react-tabs/components-api/#tab-panel) */ -const TabPanel = React.forwardRef(function TabPanel(props, ref) { +const TabPanel = React.forwardRef(function TabPanel( + props: TabPanelProps, + forwardedRef: React.ForwardedRef, +) { const { children, component, value, slotProps = {}, slots = {}, ...other } = props; const { hidden, getRootProps } = useTabPanel(props); - const ownerState = { + const ownerState: TabPanelOwnerState = { ...props, hidden, }; @@ -47,7 +55,7 @@ const TabPanel = React.forwardRef(function TabPanel(prop externalForwardedProps: other, additionalProps: { role: 'tabpanel', - ref, + ref: forwardedRef, }, ownerState, className: classes.root, diff --git a/packages/mui-base/src/TabPanel/TabPanel.types.ts b/packages/mui-base/src/TabPanel/TabPanel.types.ts index 371d006cc6ac9a..6aeb60db779310 100644 --- a/packages/mui-base/src/TabPanel/TabPanel.types.ts +++ b/packages/mui-base/src/TabPanel/TabPanel.types.ts @@ -1,5 +1,5 @@ import * as React from 'react'; -import { OverrideProps } from '@mui/types'; +import { OverrideProps, Simplify } from '@mui/types'; import { UseTabPanelRootSlotProps } from '../useTabPanel'; import { SlotComponentProps } from '../utils'; @@ -40,21 +40,25 @@ export interface TabPanelSlots { root?: React.ElementType; } -export interface TabPanelTypeMap

{ - props: P & TabPanelOwnProps; - defaultComponent: D; +export interface TabPanelTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'div', +> { + props: TabPanelOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } export type TabPanelProps< - D extends React.ElementType = TabPanelTypeMap['defaultComponent'], - P = {}, -> = OverrideProps, D> & { - component?: D; + RootComponentType extends React.ElementType = TabPanelTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType> & { + component?: RootComponentType; }; -export type TabPanelOwnerState = TabPanelProps & { - hidden: boolean; -}; +export type TabPanelOwnerState = Simplify< + TabPanelOwnProps & { + hidden: boolean; + } +>; export type TabPanelRootSlotProps = UseTabPanelRootSlotProps & { children?: React.ReactNode; diff --git a/packages/mui-base/src/TablePagination/TablePagination.tsx b/packages/mui-base/src/TablePagination/TablePagination.tsx index e403e04998a54d..a233ebb085f289 100644 --- a/packages/mui-base/src/TablePagination/TablePagination.tsx +++ b/packages/mui-base/src/TablePagination/TablePagination.tsx @@ -59,10 +59,9 @@ const useUtilityClasses = () => { * * - [TablePagination API](https://mui.com/base/react-table-pagination/components-api/#table-pagination) */ -const TablePagination = React.forwardRef(function TablePagination( - props, - ref, -) { +const TablePagination = React.forwardRef(function TablePagination< + RootComponentType extends React.ElementType, +>(props: TablePaginationProps, forwardedRef: React.ForwardedRef) { const { component, colSpan: colSpanProp, @@ -107,7 +106,7 @@ const TablePagination = React.forwardRef(function externalForwardedProps: other, additionalProps: { colSpan, - ref, + ref: forwardedRef, }, ownerState, className: classes.root, diff --git a/packages/mui-base/src/TablePagination/TablePagination.types.ts b/packages/mui-base/src/TablePagination/TablePagination.types.ts index dae470f0e51ec7..537c185a560bda 100644 --- a/packages/mui-base/src/TablePagination/TablePagination.types.ts +++ b/packages/mui-base/src/TablePagination/TablePagination.types.ts @@ -195,19 +195,21 @@ export interface TablePaginationSlots { spacer?: React.ElementType; } -export interface TablePaginationTypeMap

{ - props: P & TablePaginationOwnProps; - defaultComponent: D; +export interface TablePaginationTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'td', +> { + props: TablePaginationOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } export type TablePaginationProps< - D extends React.ElementType = TablePaginationTypeMap['defaultComponent'], - P = {}, -> = OverrideProps, D> & { - component?: D; + RootComponentType extends React.ElementType = TablePaginationTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType> & { + component?: RootComponentType; }; -export type TablePaginationOwnerState = TablePaginationProps; +export type TablePaginationOwnerState = TablePaginationOwnProps; export type TablePaginationRootSlotProps = { children?: React.ReactNode; diff --git a/packages/mui-base/src/TablePagination/TablePaginationActions.tsx b/packages/mui-base/src/TablePagination/TablePaginationActions.tsx index ec5fc9e9007430..de43160147baee 100644 --- a/packages/mui-base/src/TablePagination/TablePaginationActions.tsx +++ b/packages/mui-base/src/TablePagination/TablePaginationActions.tsx @@ -29,134 +29,137 @@ function defaultGetAriaLabel(type: ItemAriaLabelType) { /** * @ignore - internal component. */ -const TablePaginationActions = React.forwardRef( - function TablePaginationActions(props, ref) { - const { - component, - count, - getItemAriaLabel = defaultGetAriaLabel, - onPageChange, - page, - rowsPerPage, - showFirstButton = false, - showLastButton = false, - direction, - // @ts-ignore - ownerState: ownerStateProp, - slotProps = {}, - slots = {}, - ...other - } = props; - - const ownerState = props; - - const handleFirstPageButtonClick = (event: React.MouseEvent) => { - onPageChange(event, 0); - }; - - const handleBackButtonClick = (event: React.MouseEvent) => { - onPageChange(event, page - 1); - }; - - const handleNextButtonClick = (event: React.MouseEvent) => { - onPageChange(event, page + 1); - }; - - const handleLastPageButtonClick = (event: React.MouseEvent) => { - onPageChange(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1)); - }; - - const Root = slots.root ?? component ?? 'div'; - const rootProps: WithOptionalOwnerState = useSlotProps({ - elementType: Root, - externalSlotProps: slotProps.root, - externalForwardedProps: other, - additionalProps: { ref }, +const TablePaginationActions = React.forwardRef(function TablePaginationActions< + RootComponentType extends React.ElementType, +>( + props: TablePaginationActionsProps, + forwardedRef: React.ForwardedRef, +) { + const { + component, + count, + getItemAriaLabel = defaultGetAriaLabel, + onPageChange, + page, + rowsPerPage, + showFirstButton = false, + showLastButton = false, + direction, + // @ts-ignore + ownerState: ownerStateProp, + slotProps = {}, + slots = {}, + ...other + } = props; + + const ownerState = props; + + const handleFirstPageButtonClick = (event: React.MouseEvent) => { + onPageChange(event, 0); + }; + + const handleBackButtonClick = (event: React.MouseEvent) => { + onPageChange(event, page - 1); + }; + + const handleNextButtonClick = (event: React.MouseEvent) => { + onPageChange(event, page + 1); + }; + + const handleLastPageButtonClick = (event: React.MouseEvent) => { + onPageChange(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1)); + }; + + const Root = slots.root ?? component ?? 'div'; + const rootProps: WithOptionalOwnerState = useSlotProps({ + elementType: Root, + externalSlotProps: slotProps.root, + externalForwardedProps: other, + additionalProps: { ref: forwardedRef }, + ownerState, + }); + + const FirstButton = slots.firstButton ?? 'button'; + const firstButtonProps: WithOptionalOwnerState = + useSlotProps({ + elementType: FirstButton, + externalSlotProps: slotProps.firstButton, + additionalProps: { + onClick: handleFirstPageButtonClick, + disabled: page === 0, + 'aria-label': getItemAriaLabel('first', page), + title: getItemAriaLabel('first', page), + }, ownerState, }); - const FirstButton = slots.firstButton ?? 'button'; - const firstButtonProps: WithOptionalOwnerState = - useSlotProps({ - elementType: FirstButton, - externalSlotProps: slotProps.firstButton, - additionalProps: { - onClick: handleFirstPageButtonClick, - disabled: page === 0, - 'aria-label': getItemAriaLabel('first', page), - title: getItemAriaLabel('first', page), - }, - ownerState, - }); - - const LastButton = slots.lastButton ?? 'button'; - const lastButtonProps: WithOptionalOwnerState = - useSlotProps({ - elementType: LastButton, - externalSlotProps: slotProps.lastButton, - additionalProps: { - onClick: handleLastPageButtonClick, - disabled: page >= Math.ceil(count / rowsPerPage) - 1, - 'aria-label': getItemAriaLabel('last', page), - title: getItemAriaLabel('last', page), - }, - ownerState, - }); - - const NextButton = slots.nextButton ?? 'button'; - const nextButtonProps: WithOptionalOwnerState = - useSlotProps({ - elementType: NextButton, - externalSlotProps: slotProps.nextButton, - additionalProps: { - onClick: handleNextButtonClick, - disabled: count !== -1 ? page >= Math.ceil(count / rowsPerPage) - 1 : false, - 'aria-label': getItemAriaLabel('next', page), - title: getItemAriaLabel('next', page), - }, - ownerState, - }); - - const BackButton = slots.backButton ?? 'button'; - const backButtonProps: WithOptionalOwnerState = - useSlotProps({ - elementType: BackButton, - externalSlotProps: slotProps.backButton, - additionalProps: { - onClick: handleBackButtonClick, - disabled: page === 0, - 'aria-label': getItemAriaLabel('previous', page), - title: getItemAriaLabel('previous', page), - }, - ownerState, - }); - - const LastPageIcon = slots.lastPageIcon ?? LastPageIconDefault; - const FirstPageIcon = slots.firstPageIcon ?? FirstPageIconDefault; - const NextPageIcon = slots.nextPageIcon ?? NextPageIconDefault; - const BackPageIcon = slots.backPageIcon ?? BackPageIconDefault; - - return ( - - {showFirstButton && ( - - {direction === 'rtl' ? : } - - )} - - {direction === 'rtl' ? : } - - - {direction === 'rtl' ? : } - - {showLastButton && ( - - {direction === 'rtl' ? : } - - )} - - ); - }, -) as OverridableComponent; + const LastButton = slots.lastButton ?? 'button'; + const lastButtonProps: WithOptionalOwnerState = + useSlotProps({ + elementType: LastButton, + externalSlotProps: slotProps.lastButton, + additionalProps: { + onClick: handleLastPageButtonClick, + disabled: page >= Math.ceil(count / rowsPerPage) - 1, + 'aria-label': getItemAriaLabel('last', page), + title: getItemAriaLabel('last', page), + }, + ownerState, + }); + + const NextButton = slots.nextButton ?? 'button'; + const nextButtonProps: WithOptionalOwnerState = + useSlotProps({ + elementType: NextButton, + externalSlotProps: slotProps.nextButton, + additionalProps: { + onClick: handleNextButtonClick, + disabled: count !== -1 ? page >= Math.ceil(count / rowsPerPage) - 1 : false, + 'aria-label': getItemAriaLabel('next', page), + title: getItemAriaLabel('next', page), + }, + ownerState, + }); + + const BackButton = slots.backButton ?? 'button'; + const backButtonProps: WithOptionalOwnerState = + useSlotProps({ + elementType: BackButton, + externalSlotProps: slotProps.backButton, + additionalProps: { + onClick: handleBackButtonClick, + disabled: page === 0, + 'aria-label': getItemAriaLabel('previous', page), + title: getItemAriaLabel('previous', page), + }, + ownerState, + }); + + const LastPageIcon = slots.lastPageIcon ?? LastPageIconDefault; + const FirstPageIcon = slots.firstPageIcon ?? FirstPageIconDefault; + const NextPageIcon = slots.nextPageIcon ?? NextPageIconDefault; + const BackPageIcon = slots.backPageIcon ?? BackPageIconDefault; + + return ( + + {showFirstButton && ( + + {direction === 'rtl' ? : } + + )} + + {direction === 'rtl' ? : } + + + {direction === 'rtl' ? : } + + {showLastButton && ( + + {direction === 'rtl' ? : } + + )} + + ); +}) as OverridableComponent; export default TablePaginationActions; diff --git a/packages/mui-base/src/TablePagination/TablePaginationActions.types.ts b/packages/mui-base/src/TablePagination/TablePaginationActions.types.ts index 90536b9f395005..2297c8112bfbaf 100644 --- a/packages/mui-base/src/TablePagination/TablePaginationActions.types.ts +++ b/packages/mui-base/src/TablePagination/TablePaginationActions.types.ts @@ -117,18 +117,20 @@ export interface TablePaginationActionsSlots { } export type TablePaginationActionsProps< - D extends React.ElementType = TablePaginationActionsTypeMap['defaultComponent'], - P = {}, -> = OverrideProps, D> & { - component?: D; + RootComponentType extends React.ElementType = TablePaginationActionsTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType> & { + component?: RootComponentType; }; -export interface TablePaginationActionsTypeMap

{ - props: P & TablePaginationActionsOwnProps; - defaultComponent: D; +export interface TablePaginationActionsTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'button', +> { + props: TablePaginationActionsOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } -export type TablePaginationActionsOwnerState = TablePaginationActionsProps; +export type TablePaginationActionsOwnerState = TablePaginationActionsOwnProps; export type TablePaginationActionsRootSlotProps = { children?: React.ReactNode; diff --git a/packages/mui-base/src/Tabs/Tabs.tsx b/packages/mui-base/src/Tabs/Tabs.tsx index ea0d05cde6f7c1..ac9ae86635c95f 100644 --- a/packages/mui-base/src/Tabs/Tabs.tsx +++ b/packages/mui-base/src/Tabs/Tabs.tsx @@ -4,7 +4,7 @@ import { OverridableComponent } from '@mui/types'; import { useSlotProps, WithOptionalOwnerState } from '../utils'; import composeClasses from '../composeClasses'; import { getTabsUtilityClass } from './tabsClasses'; -import { TabsProps, TabsRootSlotProps, TabsTypeMap } from './Tabs.types'; +import { TabsOwnerState, TabsProps, TabsRootSlotProps, TabsTypeMap } from './Tabs.types'; import useTabs from '../useTabs'; import TabsProvider from '../useTabs/TabsProvider'; import { useClassNamesOverride } from '../utils/ClassNameConfigurator'; @@ -29,7 +29,10 @@ const useUtilityClasses = (ownerState: { orientation: 'horizontal' | 'vertical' * * - [Tabs API](https://mui.com/base/react-tabs/components-api/#tabs) */ -const Tabs = React.forwardRef(function Tabs(props, ref) { +const Tabs = React.forwardRef(function Tabs( + props: TabsProps, + forwardedRef: React.ForwardedRef, +) { const { children, value: valueProp, @@ -46,7 +49,7 @@ const Tabs = React.forwardRef(function Tabs(props, ref) { const { contextValue } = useTabs(props); - const ownerState = { + const ownerState: TabsOwnerState = { ...props, orientation, direction, @@ -60,7 +63,7 @@ const Tabs = React.forwardRef(function Tabs(props, ref) { externalSlotProps: slotProps.root, externalForwardedProps: other, additionalProps: { - ref, + ref: forwardedRef, }, ownerState, className: classes.root, diff --git a/packages/mui-base/src/Tabs/Tabs.types.ts b/packages/mui-base/src/Tabs/Tabs.types.ts index 1abd353b5d4a78..56cea3e0b3e7ec 100644 --- a/packages/mui-base/src/Tabs/Tabs.types.ts +++ b/packages/mui-base/src/Tabs/Tabs.types.ts @@ -1,5 +1,5 @@ import * as React from 'react'; -import { OverrideProps } from '@mui/types'; +import { OverrideProps, Simplify } from '@mui/types'; import { SlotComponentProps } from '../utils'; export interface TabsRootSlotPropsOverrides {} @@ -65,22 +65,26 @@ export interface TabsSlots { root?: React.ElementType; } -export interface TabsTypeMap

{ - props: P & TabsOwnProps; - defaultComponent: D; +export interface TabsTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'div', +> { + props: TabsOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } export type TabsProps< - D extends React.ElementType = TabsTypeMap['defaultComponent'], - P = {}, -> = OverrideProps, D> & { - component?: D; + RootComponentType extends React.ElementType = TabsTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType> & { + component?: RootComponentType; }; -export type TabsOwnerState = TabsProps & { - orientation: TabsOrientation; - direction: TabsDirection; -}; +export type TabsOwnerState = Simplify< + TabsOwnProps & { + orientation: TabsOrientation; + direction: TabsDirection; + } +>; export type TabsRootSlotProps = { ownerState: TabsOwnerState; diff --git a/packages/mui-base/src/TabsList/TabsList.tsx b/packages/mui-base/src/TabsList/TabsList.tsx index bbdd5df8e365ce..b49e0b7eb63d41 100644 --- a/packages/mui-base/src/TabsList/TabsList.tsx +++ b/packages/mui-base/src/TabsList/TabsList.tsx @@ -4,7 +4,12 @@ import { OverridableComponent } from '@mui/types'; import composeClasses from '../composeClasses'; import { useSlotProps, WithOptionalOwnerState } from '../utils'; import { getTabsListUtilityClass } from './tabsListClasses'; -import { TabsListProps, TabsListRootSlotProps, TabsListTypeMap } from './TabsList.types'; +import { + TabsListOwnerState, + TabsListProps, + TabsListRootSlotProps, + TabsListTypeMap, +} from './TabsList.types'; import useTabsList from '../useTabsList'; import { useClassNamesOverride } from '../utils/ClassNameConfigurator'; import TabsListProvider from '../useTabsList/TabsListProvider'; @@ -29,14 +34,17 @@ const useUtilityClasses = (ownerState: { orientation: 'horizontal' | 'vertical' * * - [TabsList API](https://mui.com/base/react-tabs/components-api/#tabs-list) */ -const TabsList = React.forwardRef(function TabsList(props, ref) { +const TabsList = React.forwardRef(function TabsList( + props: TabsListProps, + forwardedRef: React.ForwardedRef, +) { const { children, component, slotProps = {}, slots = {}, ...other } = props; const { isRtl, orientation, getRootProps, contextValue } = useTabsList({ - ref, + rootRef: forwardedRef, }); - const ownerState = { + const ownerState: TabsListOwnerState = { ...props, isRtl, orientation, diff --git a/packages/mui-base/src/TabsList/TabsList.types.ts b/packages/mui-base/src/TabsList/TabsList.types.ts index 5abbe181d4cd9c..8b1e4a4475b67b 100644 --- a/packages/mui-base/src/TabsList/TabsList.types.ts +++ b/packages/mui-base/src/TabsList/TabsList.types.ts @@ -1,5 +1,5 @@ import * as React from 'react'; -import { OverrideProps } from '@mui/types'; +import { OverrideProps, Simplify } from '@mui/types'; import { UseTabsListRootSlotProps } from '../useTabsList'; import { SlotComponentProps } from '../utils'; @@ -34,22 +34,26 @@ export interface TabsListSlots { root?: React.ElementType; } -export interface TabsListTypeMap

{ - props: P & TabsListOwnProps; - defaultComponent: D; +export interface TabsListTypeMap< + AdditionalProps = {}, + RootComponentType extends React.ElementType = 'div', +> { + props: TabsListOwnProps & AdditionalProps; + defaultComponent: RootComponentType; } export type TabsListProps< - D extends React.ElementType = TabsListTypeMap['defaultComponent'], - P = {}, -> = OverrideProps, D> & { - component?: D; + RootComponentType extends React.ElementType = TabsListTypeMap['defaultComponent'], +> = OverrideProps, RootComponentType> & { + component?: RootComponentType; }; -export type TabsListOwnerState = TabsListProps & { - isRtl: boolean; - orientation: 'horizontal' | 'vertical'; -}; +export type TabsListOwnerState = Simplify< + TabsListOwnProps & { + isRtl: boolean; + orientation: 'horizontal' | 'vertical'; + } +>; export type TabsListRootSlotProps = UseTabsListRootSlotProps & { className?: string; diff --git a/packages/mui-base/src/TextareaAutosize/TextareaAutosize.tsx b/packages/mui-base/src/TextareaAutosize/TextareaAutosize.tsx index 47b499792a6af1..79ae353361001b 100644 --- a/packages/mui-base/src/TextareaAutosize/TextareaAutosize.tsx +++ b/packages/mui-base/src/TextareaAutosize/TextareaAutosize.tsx @@ -58,13 +58,13 @@ function isEmpty(obj: State) { */ const TextareaAutosize = React.forwardRef(function TextareaAutosize( props: TextareaAutosizeProps, - ref: React.ForwardedRef, + forwardedRef: React.ForwardedRef, ) { const { onChange, maxRows, minRows = 1, style, value, ...other } = props; const { current: isControlled } = React.useRef(value != null); const inputRef = React.useRef(null); - const handleRef = useForkRef(ref, inputRef); + const handleRef = useForkRef(forwardedRef, inputRef); const shadowRef = React.useRef(null); const renders = React.useRef(0); const [state, setState] = React.useState({ diff --git a/packages/mui-base/src/useButton/useButton.test.tsx b/packages/mui-base/src/useButton/useButton.test.tsx index 8150b84bff0328..2ab557bd3e27d0 100644 --- a/packages/mui-base/src/useButton/useButton.test.tsx +++ b/packages/mui-base/src/useButton/useButton.test.tsx @@ -12,7 +12,7 @@ describe('useButton', () => { it('is set when triggered by mouse', () => { function TestComponent() { const buttonRef = React.useRef(null); - const { active, getRootProps } = useButton({ ref: buttonRef }); + const { active, getRootProps } = useButton({ rootRef: buttonRef }); return