import debounce from 'lodash/debounce'; import { Search, X } from 'lucide-react'; import { useSetRecoilState } from 'recoil'; import { useLocation } from 'react-router-dom'; import { QueryKeys } from 'librechat-data-provider'; import { useQueryClient } from '@tanstack/react-query'; import { forwardRef, useState, useCallback, useMemo, Ref } from 'react'; import { useLocalize, useNewConvo } from '~/hooks'; import { cn } from '~/utils'; import store from '~/store'; type SearchBarProps = { isSmallScreen?: boolean; setPageNumber: React.Dispatch>; }; const SearchBar = forwardRef((props: SearchBarProps, ref: Ref) => { const localize = useLocalize(); const location = useLocation(); const queryClient = useQueryClient(); const { setPageNumber, isSmallScreen } = props; const [text, setText] = useState(''); const [showClearIcon, setShowClearIcon] = useState(false); const { newConversation } = useNewConvo(); const clearConvoState = store.useClearConvoState(); const setSearchQuery = useSetRecoilState(store.searchQuery); const setIsSearching = useSetRecoilState(store.isSearching); const clearSearch = useCallback(() => { setPageNumber(1); if (location.pathname.includes('/search')) { newConversation({ disableFocus: true }); } }, [newConversation, setPageNumber, location.pathname]); const clearText = useCallback(() => { setShowClearIcon(false); setSearchQuery(''); clearSearch(); setText(''); }, [setSearchQuery, clearSearch]); const handleKeyUp = (e: React.KeyboardEvent) => { const { value } = e.target as HTMLInputElement; if (e.key === 'Backspace' && value === '') { clearText(); } }; const sendRequest = useCallback( (value: string) => { setSearchQuery(value); if (!value) { return; } queryClient.invalidateQueries([QueryKeys.messages]); clearConvoState(); }, [queryClient, clearConvoState, setSearchQuery], ); // TODO: make the debounce time configurable via yaml const debouncedSendRequest = useMemo(() => debounce(sendRequest, 350), [sendRequest]); const onChange = (e: React.FormEvent) => { const { value } = e.target as HTMLInputElement; setShowClearIcon(value.length > 0); setText(value); debouncedSendRequest(value); setIsSearching(true); }; return (
{ } { e.code === 'Space' ? e.stopPropagation() : null; }} aria-label={localize('com_nav_search_placeholder')} placeholder={localize('com_nav_search_placeholder')} onKeyUp={handleKeyUp} onFocus={() => setIsSearching(true)} onBlur={() => setIsSearching(true)} autoComplete="off" dir="auto" />
); }); export default SearchBar;