✨(react) add onSearchInputChange callback to searchable select
We want to be able to notify an event when the search term of the searchable select gets updated.
This commit is contained in:
@@ -49,6 +49,9 @@ export type SelectProps = PropsWithChildren &
|
||||
monoline?: boolean;
|
||||
selectedItemsStyle?: "pills" | "text";
|
||||
menuOptionsStyle?: "plain" | "checkbox";
|
||||
onSearchInputChange?: (event: {
|
||||
target: { value: string | undefined };
|
||||
}) => void;
|
||||
};
|
||||
export const Select = forwardRef<SelectHandle, SelectProps>((props, ref) => {
|
||||
if (props.defaultValue && props.value) {
|
||||
|
||||
@@ -93,6 +93,10 @@ export const SelectMonoSearchable = forwardRef<SelectHandle, SubProps>(
|
||||
},
|
||||
}));
|
||||
|
||||
useEffect(() => {
|
||||
props.onSearchInputChange?.({ target: { value: inputFilter } });
|
||||
}, [inputFilter]);
|
||||
|
||||
const onInputBlur = () => {
|
||||
setHasInputFocused(false);
|
||||
if (downshiftReturn.selectedItem) {
|
||||
|
||||
@@ -40,6 +40,8 @@ You can enable the text live filtering simply by using the `searchable` props.
|
||||
<Story id="components-forms-select-mono--searchable-uncontrolled"/>
|
||||
</Canvas>
|
||||
|
||||
> You can use `onSearchInputChange` to get the value of the input when the user is typing.
|
||||
|
||||
## States
|
||||
|
||||
You can use the following props to change the state of the Select component by using the `state` props.
|
||||
|
||||
@@ -959,6 +959,64 @@ describe("<Select/>", () => {
|
||||
name: "Paris flag",
|
||||
});
|
||||
});
|
||||
|
||||
it("get the search term using onSearchInputChange", async () => {
|
||||
const user = userEvent.setup();
|
||||
let searchTerm: string | undefined;
|
||||
render(
|
||||
<CunninghamProvider>
|
||||
<Select
|
||||
label="City"
|
||||
options={[
|
||||
{
|
||||
label: "Paris",
|
||||
value: "paris",
|
||||
},
|
||||
{
|
||||
label: "Panama",
|
||||
value: "panama",
|
||||
},
|
||||
{
|
||||
label: "London",
|
||||
value: "london",
|
||||
},
|
||||
{
|
||||
label: "New York",
|
||||
value: "new_york",
|
||||
},
|
||||
{
|
||||
label: "Tokyo",
|
||||
value: "tokyo",
|
||||
},
|
||||
]}
|
||||
searchable={true}
|
||||
onSearchInputChange={(e) => {
|
||||
searchTerm = e.target.value;
|
||||
}}
|
||||
/>
|
||||
</CunninghamProvider>,
|
||||
);
|
||||
|
||||
const input = screen.getByRole("combobox", {
|
||||
name: "City",
|
||||
});
|
||||
|
||||
await user.click(input);
|
||||
expect(searchTerm).toBeUndefined();
|
||||
|
||||
await user.type(input, "Pa");
|
||||
expect(searchTerm).toEqual("Pa");
|
||||
|
||||
await user.type(input, "r", { skipClick: true });
|
||||
expect(searchTerm).toEqual("Par");
|
||||
|
||||
// Select option.
|
||||
const option: HTMLLIElement = screen.getByRole("option", {
|
||||
name: "Paris",
|
||||
});
|
||||
await user.click(option);
|
||||
expect(searchTerm).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Simple", () => {
|
||||
|
||||
@@ -16,7 +16,7 @@ import { SelectHandle } from ":/components/Forms/Select/index";
|
||||
|
||||
export const SelectMultiSearchable = forwardRef<SelectHandle, SubProps>(
|
||||
(props, ref) => {
|
||||
const [inputValue, setInputValue] = React.useState<string>("");
|
||||
const [inputValue, setInputValue] = React.useState<string>();
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const options = React.useMemo(
|
||||
() =>
|
||||
@@ -75,11 +75,11 @@ export const SelectMultiSearchable = forwardRef<SelectHandle, SubProps>(
|
||||
...props.selectedItems,
|
||||
newSelectedItem,
|
||||
]);
|
||||
setInputValue("");
|
||||
setInputValue(undefined);
|
||||
}
|
||||
break;
|
||||
case useCombobox.stateChangeTypes.InputChange:
|
||||
setInputValue(newInputValue ?? "");
|
||||
setInputValue(newInputValue);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -124,6 +124,10 @@ export const SelectMultiSearchable = forwardRef<SelectHandle, SubProps>(
|
||||
},
|
||||
}));
|
||||
|
||||
useEffect(() => {
|
||||
props.onSearchInputChange?.({ target: { value: inputValue } });
|
||||
}, [inputValue]);
|
||||
|
||||
return (
|
||||
<SelectMultiAux
|
||||
{...props}
|
||||
|
||||
@@ -26,6 +26,8 @@ You can enable the text live filtering simply by using the `searchable` props.
|
||||
<Story id="components-forms-select-multi--searchable-uncontrolled"/>
|
||||
</Canvas>
|
||||
|
||||
> You can use `onSearchInputChange` to get the value of the input when the user is typing.
|
||||
|
||||
## States
|
||||
|
||||
You can use the following props to change the state of the Multi-Select component by using the `state` props.
|
||||
|
||||
@@ -1193,6 +1193,67 @@ describe("<Select multi={true} />", () => {
|
||||
expectOptions(["Paris"]);
|
||||
});
|
||||
|
||||
it("get the search term using onSearchInputChange", async () => {
|
||||
const user = userEvent.setup();
|
||||
let searchTerm: string | undefined;
|
||||
render(
|
||||
<CunninghamProvider>
|
||||
<Select
|
||||
label="Cities"
|
||||
options={[
|
||||
{
|
||||
label: "Paris",
|
||||
value: "paris",
|
||||
},
|
||||
{
|
||||
label: "Panama",
|
||||
value: "panama",
|
||||
},
|
||||
{
|
||||
label: "London",
|
||||
value: "london",
|
||||
},
|
||||
{
|
||||
label: "New York",
|
||||
value: "new_york",
|
||||
},
|
||||
{
|
||||
label: "Tokyo",
|
||||
value: "tokyo",
|
||||
},
|
||||
]}
|
||||
searchable={true}
|
||||
multi={true}
|
||||
onSearchInputChange={(e) => {
|
||||
searchTerm = e.target.value;
|
||||
}}
|
||||
/>
|
||||
</CunninghamProvider>,
|
||||
);
|
||||
|
||||
const input = screen.getByRole("combobox", {
|
||||
name: "Cities",
|
||||
});
|
||||
expect(searchTerm).toBeUndefined();
|
||||
|
||||
await user.click(input);
|
||||
expect(searchTerm).toBeUndefined();
|
||||
|
||||
await user.type(input, "Pa");
|
||||
expect(searchTerm).toEqual("Pa");
|
||||
|
||||
await user.type(input, "r");
|
||||
expect(searchTerm).toEqual("Par");
|
||||
expectOptions(["Paris"]);
|
||||
|
||||
const option: HTMLLIElement = screen.getByRole("option", {
|
||||
name: "Paris",
|
||||
});
|
||||
await user.click(option);
|
||||
|
||||
expect(searchTerm).toBeUndefined();
|
||||
});
|
||||
|
||||
it("selects the option on enter", async () => {
|
||||
const user = userEvent.setup();
|
||||
render(
|
||||
|
||||
Reference in New Issue
Block a user