|
import { forwardRef, useState, useCallback, useMemo, Ref } from 'react'; |
|
import { Search, X } from 'lucide-react'; |
|
import { useSetRecoilState } from 'recoil'; |
|
import debounce from 'lodash/debounce'; |
|
import { useLocalize } from '~/hooks'; |
|
import store from '~/store'; |
|
|
|
type SearchBarProps = { |
|
clearSearch: () => void; |
|
}; |
|
|
|
const SearchBar = forwardRef((props: SearchBarProps, ref: Ref<HTMLDivElement>) => { |
|
const { clearSearch } = props; |
|
const setSearchQuery = useSetRecoilState(store.searchQuery); |
|
const [showClearIcon, setShowClearIcon] = useState(false); |
|
const [text, setText] = useState(''); |
|
const localize = useLocalize(); |
|
|
|
const clearText = useCallback(() => { |
|
setShowClearIcon(false); |
|
setSearchQuery(''); |
|
clearSearch(); |
|
setText(''); |
|
}, [setSearchQuery, clearSearch]); |
|
|
|
const handleKeyUp = (e: React.KeyboardEvent<HTMLInputElement>) => { |
|
const { value } = e.target as HTMLInputElement; |
|
if (e.key === 'Backspace' && value === '') { |
|
clearText(); |
|
} |
|
}; |
|
|
|
const sendRequest = useCallback((value: string) => setSearchQuery(value), [setSearchQuery]); |
|
const debouncedSendRequest = useMemo(() => debounce(sendRequest, 350), [sendRequest]); |
|
|
|
const onChange = (e: React.FormEvent<HTMLInputElement>) => { |
|
const { value } = e.target as HTMLInputElement; |
|
setShowClearIcon(value.length > 0); |
|
setText(value); |
|
debouncedSendRequest(value); |
|
}; |
|
|
|
return ( |
|
<div |
|
ref={ref} |
|
className="relative flex w-full cursor-pointer items-center gap-3 rounded-md border border-white/20 px-3 py-3 text-sm text-white transition-colors duration-200 hover:bg-gray-500/10" |
|
> |
|
{<Search className="absolute left-3 h-4 w-4" />} |
|
<input |
|
type="text" |
|
className="m-0 mr-0 w-full border-none bg-transparent p-0 pl-7 text-sm leading-tight outline-none" |
|
value={text} |
|
onChange={onChange} |
|
onKeyDown={(e) => { |
|
e.code === 'Space' ? e.stopPropagation() : null; |
|
}} |
|
placeholder={localize('com_nav_search_placeholder')} |
|
onKeyUp={handleKeyUp} |
|
/> |
|
<X |
|
className={`absolute right-3 h-5 w-5 cursor-pointer ${ |
|
showClearIcon ? 'opacity-100' : 'opacity-0' |
|
} transition-opacity duration-1000`} |
|
onClick={clearText} |
|
/> |
|
</div> |
|
); |
|
}); |
|
|
|
export default SearchBar; |
|
|