import { FC, useCallback } from 'react' import { EdgeById, NodeById, useGraphSearch, GraphSearchInputProps, GraphSearchContextProvider, GraphSearchContextProviderProps } from '@react-sigma/graph-search' import { AsyncSelect } from '@/components/ui/AsyncSelect' import { searchResultLimit } from '@/lib/constants' interface OptionItem { id: string type: 'nodes' | 'edges' | 'message' message?: string } function OptionComponent(item: OptionItem) { return (
{item.type === 'nodes' && } {item.type === 'edges' && } {item.type === 'message' &&
{item.message}
}
) } const messageId = '__message_item' /** * Component thats display the search input. */ export const GraphSearchInput = ({ onChange, onFocus, type, value }: { onChange: GraphSearchInputProps['onChange'] onFocus?: GraphSearchInputProps['onFocus'] type?: GraphSearchInputProps['type'] value?: GraphSearchInputProps['value'] }) => { const { search } = useGraphSearch() /** * Loading the options while the user is typing. */ const loadOptions = useCallback( async (query?: string): Promise => { if (onFocus) onFocus(null) if (!query) return [] const result = (await search(query, type)) as OptionItem[] // prettier-ignore return result.length <= searchResultLimit ? result : [ ...result.slice(0, searchResultLimit), { type: 'message', id: messageId, message: `And ${result.length - searchResultLimit} others` } ] }, [type, search, onFocus] ) return ( item.id} value={value && value.type !== 'message' ? value.id : null} onChange={(id) => { if (id !== messageId && type) onChange(id ? { id, type } : null) }} onFocus={(id) => { if (id !== messageId && onFocus && type) onFocus(id ? { id, type } : null) }} label={'item'} preload={false} placeholder="Type search here..." /> ) } /** * Component that display the search. */ const GraphSearch: FC = ({ minisearchOptions, ...props }) => ( ) export default GraphSearch