Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ export interface MultiTypeaheadSelectProps extends Omit<SelectProps, 'toggle' |
onToggle?: (nextIsOpen: boolean) => void;
/** Callback triggered when the text in the input field changes. */
onInputChange?: (newValue: string) => void;
/** Custom callback triggered when the input field has focus and a keyboard event is triggered.
* This will override the default keydown behavior for the input field.
*/
onInputKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void;
/** Placeholder text for the select input. */
placeholder?: string;
/** Message to display when no options match the filter. */
Expand All @@ -55,6 +59,7 @@ export const MultiTypeaheadSelectBase: React.FunctionComponent<MultiTypeaheadSel
onSelectionChange,
onToggle,
onInputChange,
onInputKeyDown: onInputKeyDownProp,
placeholder = 'Select an option',
noOptionsFoundMessage = (filter) => `No results found for "${filter}"`,
isDisabled,
Expand Down Expand Up @@ -219,11 +224,12 @@ export const MultiTypeaheadSelectBase: React.FunctionComponent<MultiTypeaheadSel
setActiveAndFocusedItem(indexToFocus);
};

const onInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
const defaultOnInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
const focusedItem = focusedItemIndex !== null ? selectOptions[focusedItemIndex] : null;

switch (event.key) {
case 'Enter':
event.preventDefault();
if (isOpen && focusedItem && focusedItem.value !== NO_RESULTS && !focusedItem.isAriaDisabled) {
selectOption(event, focusedItem?.value);
}
Expand All @@ -242,6 +248,14 @@ export const MultiTypeaheadSelectBase: React.FunctionComponent<MultiTypeaheadSel
}
};

const onInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (onInputKeyDownProp) {
onInputKeyDownProp(event);
} else {
defaultOnInputKeyDown(event);
}
};

const onToggleClick = () => {
onToggle && onToggle(!isOpen);
setIsOpen(!isOpen);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export interface TypeaheadSelectProps extends Omit<SelectProps, 'toggle' | 'onSe
onToggle?: (nextIsOpen: boolean) => void;
/** Callback triggered when the text in the input field changes. */
onInputChange?: (newValue: string) => void;
/** Custom callback triggered when the input field has focus and a keyboard event is triggered.
* This will override the default keydown behavior for the input field.
*/
onInputKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void;
/** Callback triggered when the clear button is selected */
onClearSelection?: () => void;
/** Placeholder text for the select input. */
Expand Down Expand Up @@ -67,6 +71,7 @@ export const TypeaheadSelectBase: React.FunctionComponent<TypeaheadSelectProps>
onSelect,
onToggle,
onInputChange,
onInputKeyDown: onInputKeyDownProp,
onClearSelection,
placeholder = 'Select an option',
noOptionsAvailableMessage = 'No options are available',
Expand Down Expand Up @@ -273,11 +278,12 @@ export const TypeaheadSelectBase: React.FunctionComponent<TypeaheadSelectProps>
setActiveAndFocusedItem(indexToFocus);
};

const onInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
const defaultOnInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
const focusedItem = focusedItemIndex !== null ? selectOptions[focusedItemIndex] : null;

switch (event.key) {
case 'Enter':
event.preventDefault();
if (isOpen && focusedItem && focusedItem.value !== NO_RESULTS && !focusedItem.isAriaDisabled) {
selectOption(event, focusedItem);
}
Expand All @@ -293,6 +299,14 @@ export const TypeaheadSelectBase: React.FunctionComponent<TypeaheadSelectProps>
}
};

const onInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (onInputKeyDownProp) {
onInputKeyDownProp(event);
} else {
defaultOnInputKeyDown(event);
}
};

const onToggleClick = () => {
onToggle && onToggle(!isOpen);
setIsOpen(!isOpen);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,25 @@ describe('MultiTypeaheadSelect', () => {
expect(onInputChangeMock).toHaveBeenCalledWith('1');
});

it('calls the onInputKeyDown callback only when keydown event occurs', async () => {
const initialOptions = [
{ content: 'Option 1', value: 'option1' },
{ content: 'Option 2', value: 'option2' },
{ content: 'Option 3', value: 'option3' }
];

const user = userEvent.setup();
const onInputKeyDownMock = jest.fn();

render(<MultiTypeaheadSelect initialOptions={initialOptions} onInputKeyDown={onInputKeyDownMock} />);

const input = screen.getByRole('combobox');
await user.click(input);
expect(onInputKeyDownMock).not.toHaveBeenCalled();
await user.keyboard('{Enter}');
expect(onInputKeyDownMock).toHaveBeenCalledTimes(1);
});

it('Matches snapshot', async () => {
const initialOptions = [
{ content: 'Option 1', value: 'option1' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,25 @@ test('typing in input triggers onInputChange callback', async () => {
expect(onInputChangeMock).toHaveBeenCalledWith('1');
});

it('calls the onInputKeyDown callback only when keydown event occurs', async () => {
const initialOptions = [
{ content: 'Option 1', value: 'option1' },
{ content: 'Option 2', value: 'option2' },
{ content: 'Option 3', value: 'option3' }
];

const user = userEvent.setup();
const onInputKeyDownMock = jest.fn();

render(<TypeaheadSelect initialOptions={initialOptions} onInputKeyDown={onInputKeyDownMock} />);

const input = screen.getByRole('combobox');
await user.click(input);
expect(onInputKeyDownMock).not.toHaveBeenCalled();
await user.keyboard('{Enter}');
expect(onInputKeyDownMock).toHaveBeenCalledTimes(1);
});

test('Matches snapshot', async () => {
const initialOptions = [
{ content: 'Option 1', value: 'option1' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ exports[`MultiTypeaheadSelect Matches snapshot 1`] = `
<button
aria-label="Clear input value"
class="pf-v6-c-button pf-m-plain"
data-ouia-component-id="OUIA-Generated-Button-plain-17"
data-ouia-component-id="OUIA-Generated-Button-plain-18"
data-ouia-component-type="PF6/Button"
data-ouia-safe="true"
type="button"
Expand Down Expand Up @@ -63,7 +63,7 @@ exports[`MultiTypeaheadSelect Matches snapshot 1`] = `
aria-expanded="true"
aria-label="Multi select Typeahead menu toggle"
class="pf-v6-c-menu-toggle__button"
data-ouia-component-id="OUIA-Generated-MenuToggle-typeahead-17"
data-ouia-component-id="OUIA-Generated-MenuToggle-typeahead-18"
data-ouia-component-type="PF6/MenuToggle"
data-ouia-safe="true"
tabindex="-1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ exports[`Matches snapshot 1`] = `
<button
aria-label="Clear input value"
class="pf-v6-c-button pf-m-plain"
data-ouia-component-id="OUIA-Generated-Button-plain-17"
data-ouia-component-id="OUIA-Generated-Button-plain-18"
data-ouia-component-type="PF6/Button"
data-ouia-safe="true"
type="button"
Expand Down Expand Up @@ -63,7 +63,7 @@ exports[`Matches snapshot 1`] = `
aria-expanded="true"
aria-label="Typeahead menu toggle"
class="pf-v6-c-menu-toggle__button"
data-ouia-component-id="OUIA-Generated-MenuToggle-typeahead-17"
data-ouia-component-id="OUIA-Generated-MenuToggle-typeahead-18"
data-ouia-component-type="PF6/MenuToggle"
data-ouia-safe="true"
tabindex="-1"
Expand Down
Loading