Skip to content

Commit

Permalink
Accept arbitrary external props and forward to root
Browse files Browse the repository at this point in the history
  • Loading branch information
mj12albert committed Sep 7, 2023
1 parent 6d765df commit afbb22c
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 12 deletions.
16 changes: 16 additions & 0 deletions packages/mui-base/src/useList/useList.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 <div role="listbox" {...getRootProps({ 'data-testid': 'test-listbox' })} />;
}

const { getByRole } = render(<Listbox />);

expect(getByRole('listbox')).to.have.attribute('data-testid', 'test-listbox');
});
});
});
15 changes: 8 additions & 7 deletions packages/mui-base/src/useList/useList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = () => {};
Expand Down Expand Up @@ -333,17 +333,18 @@ function useList<
});
};

const getRootProps = <TOther extends EventHandlers = {}>(
otherHandlers: TOther = {} as TOther,
): UseListRootSlotProps<TOther> => {
const getRootProps = <ExternalProps extends Record<string, any> = {}>(
externalProps: ExternalProps = {} as ExternalProps,
): UseListRootSlotProps<ExternalProps> => {
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,
};
Expand Down
15 changes: 10 additions & 5 deletions packages/mui-base/src/useList/useList.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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;
/**
Expand Down Expand Up @@ -248,7 +248,7 @@ interface UseListRootSlotOwnProps {
ref: React.RefCallback<Element> | null;
}

export type UseListRootSlotProps<TOther = {}> = TOther & UseListRootSlotOwnProps;
export type UseListRootSlotProps<ExternalProps = {}> = ExternalProps & UseListRootSlotOwnProps;

export interface UseListReturnValue<
ItemValue,
Expand All @@ -257,9 +257,14 @@ export interface UseListReturnValue<
> {
contextValue: ListContextValue<ItemValue>;
dispatch: (action: CustomAction | ListAction<ItemValue>) => void;
getRootProps: <TOther extends EventHandlers = {}>(
otherHandlers?: TOther,
) => UseListRootSlotProps<TOther>;
/**
* 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 extends Record<string, any> = {}>(
externalProps?: ExternalProps,
) => UseListRootSlotProps<ExternalProps>;
rootRef: React.RefCallback<Element> | null;
state: State;
}

0 comments on commit afbb22c

Please sign in to comment.