Skip to main content
Glama
SearchableSelect.tsx2.55 kB
// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors // SPDX-License-Identifier: Apache-2.0 import type { InputBaseProps, PolymorphicComponentProps } from '@mantine/core'; import { Combobox, InputBase, useCombobox } from '@mantine/core'; import type { JSX } from 'react'; import { useMemo, useState } from 'react'; const MAX_DISPLAYED_OPTIONS = 8; interface SearchableSelectProps { readonly inputProps?: PolymorphicComponentProps<'input', InputBaseProps>; readonly data: string[]; readonly onChange?: (value: string) => void; } export function SearchableSelect({ inputProps, data, onChange }: SearchableSelectProps): JSX.Element { const combobox = useCombobox({ onDropdownClose: () => combobox.resetSelectedOption(), }); const [value, setValue] = useState<string | null>(null); const [search, setSearch] = useState(''); const filteredOptions = useMemo(() => { return data.filter((item) => item.toLowerCase().includes(search.toLowerCase().trim())); }, [data, search]); const displayedOptions = useMemo(() => { const result: JSX.Element[] = new Array(Math.min(filteredOptions.length, MAX_DISPLAYED_OPTIONS)); for (let i = 0; i < result.length; i++) { const item = filteredOptions[i]; result[i] = ( <Combobox.Option value={item} key={item}> {item} </Combobox.Option> ); } return result; }, [filteredOptions]); return ( <Combobox store={combobox} withinPortal={false} onOptionSubmit={(val) => { if (onChange) { onChange(val); } setValue(val); setSearch(val); combobox.closeDropdown(); }} > <Combobox.Target> <InputBase rightSection={<Combobox.Chevron />} value={search} onChange={(event) => { combobox.openDropdown(); combobox.updateSelectedOptionIndex(); setSearch(event.currentTarget.value); }} onClick={() => combobox.openDropdown()} onFocus={() => combobox.openDropdown()} onBlur={() => { combobox.closeDropdown(); setSearch(value || ''); }} rightSectionPointerEvents="none" {...inputProps} /> </Combobox.Target> <Combobox.Dropdown> <Combobox.Options> {displayedOptions.length > 0 ? displayedOptions : <Combobox.Empty>Nothing found</Combobox.Empty>} </Combobox.Options> </Combobox.Dropdown> </Combobox> ); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/medplum/medplum'

If you have feedback or need assistance with the MCP directory API, please join our Discord server