/ src / components / SearchInput.tsx
SearchInput.tsx
 1  import { SearchIcon } from '@heroicons/react/outline';
 2  import { XCircleIcon } from '@heroicons/react/solid';
 3  import { Box, BoxProps, IconButton, InputBase, useMediaQuery, useTheme } from '@mui/material';
 4  import debounce from 'lodash/debounce';
 5  import { useMemo, useRef, useState } from 'react';
 6  
 7  interface SearchInputProps {
 8    onSearchTermChange: (value: string) => void;
 9    wrapperSx?: BoxProps;
10    placeholder: string;
11    disableFocus?: boolean;
12  }
13  
14  export const SearchInput = ({
15    onSearchTermChange,
16    wrapperSx,
17    placeholder,
18    disableFocus,
19  }: SearchInputProps) => {
20    const inputEl = useRef<HTMLInputElement>(null);
21    const [searchTerm, setSearchTerm] = useState('');
22  
23    const { breakpoints } = useTheme();
24    const sm = useMediaQuery(breakpoints.down('sm'));
25  
26    const handleClear = () => {
27      setSearchTerm('');
28      onSearchTermChange('');
29      inputEl.current?.focus();
30    };
31  
32    const debounchedChangeHandler = useMemo(() => {
33      return debounce((value: string) => {
34        onSearchTermChange(value);
35      }, 300);
36    }, [onSearchTermChange]);
37    return (
38      <Box
39        sx={(theme) => ({
40          display: 'flex',
41          alignItems: 'center',
42          gap: 2,
43          border: `1px solid ${theme.palette.divider}`,
44          borderRadius: '6px',
45          height: '36px',
46          ...wrapperSx,
47        })}
48      >
49        <Box sx={{ ml: 2, mt: 1 }}>
50          <SearchIcon height={16} />
51        </Box>
52        <InputBase
53          autoFocus={sm}
54          inputRef={inputEl}
55          sx={{ width: '100%', fontSize: { xs: 16, sm: 14 } }}
56          placeholder={placeholder}
57          value={searchTerm}
58          onChange={(e) => {
59            setSearchTerm(e.target.value);
60            debounchedChangeHandler(e.target.value);
61          }}
62          onKeyDown={(event) => {
63            if (disableFocus) event.stopPropagation();
64          }}
65        />
66        <IconButton
67          sx={{ p: 0, mr: 2, visibility: searchTerm ? 'visible' : 'hidden' }}
68          onClick={() => handleClear()}
69        >
70          <XCircleIcon height={16} />
71        </IconButton>
72      </Box>
73    );
74  };