diff --git a/packages/grafana-ui/src/components/Combobox/Combobox.tsx b/packages/grafana-ui/src/components/Combobox/Combobox.tsx index 6a338006b08..6a18da04294 100644 --- a/packages/grafana-ui/src/components/Combobox/Combobox.tsx +++ b/packages/grafana-ui/src/components/Combobox/Combobox.tsx @@ -15,6 +15,7 @@ import { Stack } from '../Layout/Stack/Stack'; import { Portal } from '../Portal/Portal'; import { ScrollContainer } from '../ScrollContainer/ScrollContainer'; +import { itemFilter, itemToString } from './filter'; import { getComboboxStyles, MENU_OPTION_HEIGHT, MENU_OPTION_HEIGHT_DESCRIPTION } from './getComboboxStyles'; import { useComboboxFloat } from './useComboboxFloat'; import { StaleResultError, useLatestAsyncCall } from './useLatestAsyncCall'; @@ -86,28 +87,6 @@ export type AutoSizeConditionals = type ComboboxProps = ComboboxBaseProps & AutoSizeConditionals & ClearableConditionals; -export function itemToString(item?: ComboboxOption | null) { - if (!item) { - return ''; - } - if (item.label?.includes('Custom value: ')) { - return item.value.toString(); - } - return item.label ?? item.value.toString(); -} - -function itemFilter(inputValue: string) { - const lowerCasedInputValue = inputValue.toLowerCase(); - - return (item: ComboboxOption) => { - return ( - !inputValue || - item.label?.toLowerCase().includes(lowerCasedInputValue) || - item.value?.toString().toLowerCase().includes(lowerCasedInputValue) - ); - }; -} - const noop = () => {}; const asyncNoop = () => Promise.resolve([]); diff --git a/packages/grafana-ui/src/components/Combobox/MultiCombobox.tsx b/packages/grafana-ui/src/components/Combobox/MultiCombobox.tsx index 0af00d221e2..81abe9f6a00 100644 --- a/packages/grafana-ui/src/components/Combobox/MultiCombobox.tsx +++ b/packages/grafana-ui/src/components/Combobox/MultiCombobox.tsx @@ -13,15 +13,10 @@ import { Spinner } from '../Spinner/Spinner'; import { Text } from '../Text/Text'; import { Tooltip } from '../Tooltip'; -import { - ComboboxOption, - ComboboxBaseProps, - AutoSizeConditionals, - itemToString, - VIRTUAL_OVERSCAN_ITEMS, -} from './Combobox'; +import { ComboboxOption, ComboboxBaseProps, AutoSizeConditionals, VIRTUAL_OVERSCAN_ITEMS } from './Combobox'; import { OptionListItem } from './OptionListItem'; import { ValuePill } from './ValuePill'; +import { itemFilter, itemToString } from './filter'; import { getComboboxStyles, MENU_OPTION_HEIGHT, MENU_OPTION_HEIGHT_DESCRIPTION } from './getComboboxStyles'; import { getMultiComboboxStyles } from './getMultiComboboxStyles'; import { useComboboxFloat } from './useComboboxFloat'; @@ -48,8 +43,11 @@ export const MultiCombobox = (props: MultiComboboxPro }, [value, options, isAsync]); const styles = useStyles2(getComboboxStyles); + const [inputValue, setInputValue] = useState(''); - const [items, baseSetItems] = useState(isAsync ? [] : options); + const [baseItems, baseSetItems] = useState(isAsync ? [] : options); + + const items = useMemo(() => baseItems.filter(itemFilter(inputValue)), [baseItems, inputValue]); // TODO: Improve this with async useEffect(() => { @@ -73,8 +71,6 @@ export const MultiCombobox = (props: MultiComboboxPro [selectedItems] ); - const [inputValue, setInputValue] = useState(''); - const { getSelectedItemProps, getDropdownProps, removeSelectedItem } = useMultipleSelection({ selectedItems, //initally selected items, onStateChange: ({ type, selectedItems: newSelectedItems }) => { @@ -120,7 +116,6 @@ export const MultiCombobox = (props: MultiComboboxPro case useCombobox.stateChangeTypes.InputBlur: setInputValue(''); setIsOpen(false); - return changes; default: return changes; } diff --git a/packages/grafana-ui/src/components/Combobox/filter.ts b/packages/grafana-ui/src/components/Combobox/filter.ts new file mode 100644 index 00000000000..09ab4653051 --- /dev/null +++ b/packages/grafana-ui/src/components/Combobox/filter.ts @@ -0,0 +1,23 @@ +import { ComboboxOption } from './Combobox'; + +export function itemToString(item?: ComboboxOption | null) { + if (!item) { + return ''; + } + if (item.label?.includes('Custom value: ')) { + return item.value.toString(); + } + return item.label ?? item.value.toString(); +} + +export function itemFilter(inputValue: string) { + const lowerCasedInputValue = inputValue.toLowerCase(); + + return (item: ComboboxOption) => { + return ( + !inputValue || + item.label?.toLowerCase().includes(lowerCasedInputValue) || + item.value?.toString().toLowerCase().includes(lowerCasedInputValue) + ); + }; +}