diff --git a/docs/pages/base-ui/api/use-option.json b/docs/pages/base-ui/api/use-option.json
index e71313c454812e..0db56f9c19f981 100644
--- a/docs/pages/base-ui/api/use-option.json
+++ b/docs/pages/base-ui/api/use-option.json
@@ -14,8 +14,8 @@
"returnValue": {
"getRootProps": {
"type": {
- "name": "<Other extends EventHandlers>(otherHandlers?: Other) => UseOptionRootSlotProps<Other>",
- "description": "<Other extends EventHandlers>(otherHandlers?: Other) => UseOptionRootSlotProps<Other>"
+ "name": "<ExternalProps extends Record<string, unknown>>(externalProps?: ExternalProps) => UseOptionRootSlotProps<ExternalProps>",
+ "description": "<ExternalProps extends Record<string, unknown>>(externalProps?: ExternalProps) => UseOptionRootSlotProps<ExternalProps>"
},
"required": true
},
diff --git a/docs/pages/base-ui/api/use-select.json b/docs/pages/base-ui/api/use-select.json
index e930c7a6758041..20af4c0a2f7de0 100644
--- a/docs/pages/base-ui/api/use-select.json
+++ b/docs/pages/base-ui/api/use-select.json
@@ -96,22 +96,22 @@
},
"getButtonProps": {
"type": {
- "name": "<OtherHandlers extends EventHandlers = {}>(otherHandlers?: OtherHandlers) => UseSelectButtonSlotProps<OtherHandlers>",
- "description": "<OtherHandlers extends EventHandlers = {}>(otherHandlers?: OtherHandlers) => UseSelectButtonSlotProps<OtherHandlers>"
+ "name": "<ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseSelectButtonSlotProps<ExternalProps>",
+ "description": "<ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseSelectButtonSlotProps<ExternalProps>"
},
"required": true
},
"getHiddenInputProps": {
"type": {
- "name": "<OtherHandlers extends EventHandlers = {}>(otherHandlers?: OtherHandlers) => UseSelectHiddenInputSlotProps<OtherHandlers>",
- "description": "<OtherHandlers extends EventHandlers = {}>(otherHandlers?: OtherHandlers) => UseSelectHiddenInputSlotProps<OtherHandlers>"
+ "name": "<ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseSelectHiddenInputSlotProps<ExternalProps>",
+ "description": "<ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseSelectHiddenInputSlotProps<ExternalProps>"
},
"required": true
},
"getListboxProps": {
"type": {
- "name": "<OtherHandlers extends EventHandlers = {}>(otherHandlers?: OtherHandlers) => UseSelectListboxSlotProps<OtherHandlers>",
- "description": "<OtherHandlers extends EventHandlers = {}>(otherHandlers?: OtherHandlers) => UseSelectListboxSlotProps<OtherHandlers>"
+ "name": "<ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseSelectListboxSlotProps<ExternalProps>",
+ "description": "<ExternalProps extends Record<string, unknown> = {}>(externalProps?: ExternalProps) => UseSelectListboxSlotProps<ExternalProps>"
},
"required": true
},
diff --git a/docs/translations/api-docs/use-option/use-option.json b/docs/translations/api-docs/use-option/use-option.json
index e3eb65c6e43006..07b5b62753ad2c 100644
--- a/docs/translations/api-docs/use-option/use-option.json
+++ b/docs/translations/api-docs/use-option/use-option.json
@@ -1 +1,10 @@
-{ "hookDescription": "", "parametersDescriptions": {}, "returnValueDescriptions": {} }
+{
+ "hookDescription": "",
+ "parametersDescriptions": {},
+ "returnValueDescriptions": {
+ "getRootProps": { "description": "Resolver for the root slot's props." },
+ "highlighted": { "description": "If true
, the option is highlighted." },
+ "rootRef": { "description": "Ref to the root slot DOM node." },
+ "selected": { "description": "If true
, the option is selected." }
+ }
+}
diff --git a/packages/mui-base/src/useOption/useOption.ts b/packages/mui-base/src/useOption/useOption.ts
index 556e82506e3344..87f9f02865ff88 100644
--- a/packages/mui-base/src/useOption/useOption.ts
+++ b/packages/mui-base/src/useOption/useOption.ts
@@ -2,7 +2,7 @@
import * as React from 'react';
import { unstable_useForkRef as useForkRef, unstable_useId as useId } from '@mui/utils';
import { SelectOption, UseOptionParameters, UseOptionReturnValue } from './useOption.types';
-import { EventHandlers } from '../utils';
+import { extractEventHandlers } from '../utils/extractEventHandlers';
import { useListItem } from '../useList';
import { useCompoundItem } from '../utils/useCompoundItem';
@@ -48,14 +48,19 @@ export function useOption(params: UseOptionParameters): UseOptionR
const handleRef = useForkRef(optionRefParam, optionRef, listItemRefHandler)!;
return {
- getRootProps: (otherHandlers: Other = {} as Other) => ({
- ...otherHandlers,
- ...getListItemProps(otherHandlers),
- id,
- ref: handleRef,
- role: 'option',
- 'aria-selected': selected,
- }),
+ getRootProps: = {}>(
+ externalProps: ExternalProps = {} as ExternalProps,
+ ) => {
+ const externalEventHandlers = extractEventHandlers(externalProps);
+ return {
+ ...externalProps,
+ ...getListItemProps(externalEventHandlers),
+ id,
+ ref: handleRef,
+ role: 'option',
+ 'aria-selected': selected,
+ };
+ },
highlighted,
index,
selected,
diff --git a/packages/mui-base/src/useOption/useOption.types.ts b/packages/mui-base/src/useOption/useOption.types.ts
index 7693a3c9fa40ef..32225dc0035728 100644
--- a/packages/mui-base/src/useOption/useOption.types.ts
+++ b/packages/mui-base/src/useOption/useOption.types.ts
@@ -1,5 +1,4 @@
import { UseListItemRootSlotProps } from '../useList';
-import { EventHandlers } from '../utils';
export interface SelectOption {
value: Value;
@@ -18,16 +17,30 @@ export interface UseOptionParameters {
}
export interface UseOptionReturnValue {
+ /**
+ * If `true`, the option is selected.
+ */
selected: boolean;
+ /**
+ * If `true`, the option is highlighted.
+ */
highlighted: boolean;
index: number;
- getRootProps: (
- otherHandlers?: Other,
- ) => UseOptionRootSlotProps;
+ /**
+ * Resolver for the root slot's props.
+ * @param externalProps props for the root slot
+ * @returns props that should be spread on the root slot
+ */
+ getRootProps: >(
+ externalProps?: ExternalProps,
+ ) => UseOptionRootSlotProps;
+ /**
+ * Ref to the root slot DOM node.
+ */
rootRef: React.RefCallback | null;
}
-export type UseOptionRootSlotProps =
- UseListItemRootSlotProps & {
+export type UseOptionRootSlotProps = {}> =
+ UseListItemRootSlotProps & {
ref?: React.RefCallback | null;
- } & Other;
+ } & ExternalProps;
diff --git a/packages/mui-base/src/useSelect/useSelect.ts b/packages/mui-base/src/useSelect/useSelect.ts
index 03fb06affc6a99..265b70099168fb 100644
--- a/packages/mui-base/src/useSelect/useSelect.ts
+++ b/packages/mui-base/src/useSelect/useSelect.ts
@@ -23,6 +23,7 @@ import { EventHandlers } from '../utils/types';
import { defaultOptionStringifier } from './defaultOptionStringifier';
import { SelectProviderValue } from './SelectProvider';
import { useCompoundParent } from '../utils/useCompound';
+import { extractEventHandlers } from '../utils/extractEventHandlers';
import { SelectOption } from '../useOption/useOption.types';
import { selectReducer } from './selectReducer';
import { combineHooksSlotProps } from '../utils/combineHooksSlotProps';
@@ -299,9 +300,8 @@ function useSelect(
} = useList(useListParameters);
const createHandleButtonMouseDown =
- (otherHandlers?: Record>) =>
- (event: React.MouseEvent & MuiCancellableEvent) => {
- otherHandlers?.onMouseDown?.(event);
+ (externalEventHandlers?: EventHandlers) => (event: React.MouseEvent & MuiCancellableEvent) => {
+ externalEventHandlers?.onMouseDown?.(event);
if (!event.defaultMuiPrevented) {
const action: ButtonClickAction = {
type: SelectActionTypes.buttonClick,
@@ -336,8 +336,8 @@ function useSelect(
[getOptionByValue],
);
- const getSelectTriggerProps = (
- otherHandlers: TOther = {} as TOther,
+ const getSelectTriggerProps = (
+ otherHandlers: OtherHandlers = {} as OtherHandlers,
) => {
return {
...otherHandlers,
@@ -349,19 +349,23 @@ function useSelect(
};
};
- const getButtonProps = (
- otherHandlers: TOther = {} as TOther,
- ): UseSelectButtonSlotProps => {
+ const getButtonProps = >(
+ externalProps: ExternalProps = {} as ExternalProps,
+ ): UseSelectButtonSlotProps => {
+ const externalEventHandlers = extractEventHandlers(externalProps);
const listboxAndButtonProps = combineHooksSlotProps(getButtonRootProps, getListboxRootProps);
const combinedProps = combineHooksSlotProps(listboxAndButtonProps, getSelectTriggerProps);
- return combinedProps(otherHandlers);
+ return {
+ ...externalProps,
+ ...combinedProps(externalEventHandlers),
+ };
};
- const getListboxProps = (
- otherHandlers: TOther = {} as TOther,
- ): UseSelectListboxSlotProps => {
+ const getListboxProps = >(
+ externalProps: ExternalProps = {} as ExternalProps,
+ ): UseSelectListboxSlotProps => {
return {
- ...otherHandlers,
+ ...externalProps,
id: listboxId,
role: 'listbox' as const,
'aria-multiselectable': multiple ? 'true' : undefined,
@@ -404,18 +408,20 @@ function useSelect(
null) as SelectValue, Multiple>;
}
- const getHiddenInputProps = (
- otherHandlers: TOther = {} as TOther,
- ): UseSelectHiddenInputSlotProps => ({
- name,
- tabIndex: -1,
- 'aria-hidden': true,
- required: required ? true : undefined,
- value: getSerializedValue(selectedOptionsMetadata),
- onChange: noop,
- style: visuallyHiddenStyle,
- ...otherHandlers,
- });
+ const getHiddenInputProps = >(
+ externalProps: ExternalProps = {} as ExternalProps,
+ ): UseSelectHiddenInputSlotProps => {
+ return {
+ name,
+ tabIndex: -1,
+ 'aria-hidden': true,
+ required: required ? true : undefined,
+ value: getSerializedValue(selectedOptionsMetadata),
+ onChange: noop,
+ style: visuallyHiddenStyle,
+ ...externalProps,
+ };
+ };
return {
buttonActive,
diff --git a/packages/mui-base/src/useSelect/useSelect.types.ts b/packages/mui-base/src/useSelect/useSelect.types.ts
index 762b922a13df84..33c7653608ae7f 100644
--- a/packages/mui-base/src/useSelect/useSelect.types.ts
+++ b/packages/mui-base/src/useSelect/useSelect.types.ts
@@ -1,7 +1,6 @@
import * as React from 'react';
import { ListAction, ListState, UseListRootSlotProps } from '../useList';
import { SelectOption } from '../useOption/useOption.types';
-import { EventHandlers } from '../utils/types';
import { SelectProviderValue } from './SelectProvider';
import { MuiCancellableEventHandler } from '../utils/MuiCancellableEvent';
@@ -182,27 +181,28 @@ export interface UseSelectReturnValue {
dispatch: (action: ListAction | SelectAction) => void;
/**
* Resolver for the button slot's props.
- * @param otherHandlers event handlers for the button slot
+ * @param externalProps event handlers for the button slot
* @returns props that should be spread on the button slot
*/
- getButtonProps: (
- otherHandlers?: OtherHandlers,
- ) => UseSelectButtonSlotProps;
+ getButtonProps: = {}>(
+ externalProps?: ExternalProps,
+ ) => UseSelectButtonSlotProps;
/**
* Resolver for the hidden input slot's props.
+ * @param externalProps event handlers for the hidden input slot
* @returns HTML input attributes that should be spread on the hidden input slot
*/
- getHiddenInputProps: (
- otherHandlers?: OtherHandlers,
- ) => UseSelectHiddenInputSlotProps;
+ getHiddenInputProps: = {}>(
+ externalProps?: ExternalProps,
+ ) => UseSelectHiddenInputSlotProps;
/**
* Resolver for the listbox slot's props.
- * @param otherHandlers event handlers for the listbox slot
+ * @param externalProps event handlers for the listbox slot
* @returns props that should be spread on the listbox slot
*/
- getListboxProps: (
- otherHandlers?: OtherHandlers,
- ) => UseSelectListboxSlotProps;
+ getListboxProps: = {}>(
+ externalProps?: ExternalProps,
+ ) => UseSelectListboxSlotProps;
/**
* A function that returns the metadata of an option with a given value.
*