From afbb22cbb709c36e5d7d6eaa1bdc3bf1a67548f5 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Thu, 7 Sep 2023 13:47:10 +0800 Subject: [PATCH] Accept arbitrary external props and forward to root --- packages/mui-base/src/useList/useList.test.tsx | 16 ++++++++++++++++ packages/mui-base/src/useList/useList.ts | 15 ++++++++------- packages/mui-base/src/useList/useList.types.ts | 15 ++++++++++----- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/packages/mui-base/src/useList/useList.test.tsx b/packages/mui-base/src/useList/useList.test.tsx index 02b12be6f39bb6..6d5cb0f6285a2d 100644 --- a/packages/mui-base/src/useList/useList.test.tsx +++ b/packages/mui-base/src/useList/useList.test.tsx @@ -85,4 +85,20 @@ describe('useList', () => { }), ); }); + + describe('external props', () => { + it('should pass arbitrary props to the root slot', () => { + function Listbox() { + const { getRootProps } = useList({ + items: [], + getItemId: () => undefined, + }); + return
; + } + + const { getByRole } = render(); + + expect(getByRole('listbox')).to.have.attribute('data-testid', 'test-listbox'); + }); + }); }); diff --git a/packages/mui-base/src/useList/useList.ts b/packages/mui-base/src/useList/useList.ts index 8451d1bb4b8023..351760058872c5 100644 --- a/packages/mui-base/src/useList/useList.ts +++ b/packages/mui-base/src/useList/useList.ts @@ -20,10 +20,10 @@ import { StateComparers, } from '../utils/useControllableReducer.types'; import { areArraysEqual } from '../utils/areArraysEqual'; -import { EventHandlers } from '../utils/types'; import { useLatest } from '../utils/useLatest'; import { useTextNavigation } from '../utils/useTextNavigation'; import { MuiCancellableEvent } from '../utils/MuiCancellableEvent'; +import { extractEventHandlers } from '../utils/extractEventHandlers'; const EMPTY_OBJECT = {}; const NOOP = () => {}; @@ -333,17 +333,18 @@ function useList< }); }; - const getRootProps = ( - otherHandlers: TOther = {} as TOther, - ): UseListRootSlotProps => { + const getRootProps = = {}>( + externalProps: ExternalProps = {} as ExternalProps, + ): UseListRootSlotProps => { + const externalEventHandlers = extractEventHandlers(externalProps); return { - ...otherHandlers, + ...externalProps, 'aria-activedescendant': focusManagement === 'activeDescendant' && highlightedValue != null ? getItemId!(highlightedValue) : undefined, - onBlur: createHandleBlur(otherHandlers), - onKeyDown: createHandleKeyDown(otherHandlers), + onBlur: createHandleBlur(externalEventHandlers), + onKeyDown: createHandleKeyDown(externalEventHandlers), tabIndex: focusManagement === 'DOM' ? -1 : 0, ref: handleRef, }; diff --git a/packages/mui-base/src/useList/useList.types.ts b/packages/mui-base/src/useList/useList.types.ts index 83285651a3119a..b28853b3e7886a 100644 --- a/packages/mui-base/src/useList/useList.types.ts +++ b/packages/mui-base/src/useList/useList.types.ts @@ -6,7 +6,6 @@ import { ControllableReducerAction, StateChangeCallback, } from '../utils/useControllableReducer.types'; -import { EventHandlers } from '../utils'; import type { ListContextValue } from './ListContext'; import { MuiCancellableEventHandler } from '../utils/MuiCancellableEvent'; @@ -106,6 +105,7 @@ export interface UseListParameters< /** * The focus management strategy used by the list. * Controls the attributes used to set focus on the list items. + * @default 'activeDescendant' */ focusManagement?: FocusManagementType; /** @@ -248,7 +248,7 @@ interface UseListRootSlotOwnProps { ref: React.RefCallback | null; } -export type UseListRootSlotProps = TOther & UseListRootSlotOwnProps; +export type UseListRootSlotProps = ExternalProps & UseListRootSlotOwnProps; export interface UseListReturnValue< ItemValue, @@ -257,9 +257,14 @@ export interface UseListReturnValue< > { contextValue: ListContextValue; dispatch: (action: CustomAction | ListAction) => void; - getRootProps: ( - otherHandlers?: TOther, - ) => UseListRootSlotProps; + /** + * Resolver for the root slot's props. + * @param externalProps additional props for the root slot + * @returns props that should be spread on the root slot + */ + getRootProps: = {}>( + externalProps?: ExternalProps, + ) => UseListRootSlotProps; rootRef: React.RefCallback | null; state: State; }