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; }; const SearchBar = forwardRef((props: SearchBarProps, ref: Ref) => { const localize = useLocalize(); const location = useLocation(); const queryClient = useQueryClient(); const { 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 setIsSearchTyping = useSetRecoilState(store.isSearchTyping); const clearSearch = useCallback(() => { if (location.pathname.includes('/search')) { newConversation({ disableFocus: true }); } }, [newConversation, 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], ); const debouncedSendRequest = useMemo( () => debounce((value: string) => { sendRequest(value); }, 350), [sendRequest, setIsSearchTyping], ); const onChange = (e: React.ChangeEvent) => { const value = e.target.value; setShowClearIcon(value.length > 0); setText(value); setSearchQuery(value); setIsSearchTyping(true); // debounce only the API call debouncedSendRequest(value); }; 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;