110 lines
2.3 KiB
JavaScript

import CloseIcon from '@mui/icons-material/Close';
import { IconButton, InputAdornment, TextField } from '@mui/material';
import { memo, useEffect, useRef, useState } from 'react';
import { Search } from './icons/icons';
function SearchComponent({
placeholder = 'Поиск...',
value = '',
onChange,
onClear,
clearable = false,
debounceMs = 0,
height = '2rem',
sx: sxProp,
...rest
}) {
const [inputValue, setInputValue] = useState(value);
const onChangeRef = useRef(onChange);
useEffect(() => {
onChangeRef.current = onChange;
}, [onChange]);
useEffect(() => {
setInputValue(value);
}, [value]);
useEffect(() => {
if (!debounceMs) return;
const timer = setTimeout(() => {
if (inputValue !== value) {
onChangeRef.current(inputValue);
}
}, debounceMs);
return () => clearTimeout(timer);
}, [inputValue, debounceMs, value]);
const handleChange = (e) => {
const next = e.target.value;
setInputValue(next);
if (!debounceMs) {
onChange(next);
}
};
const handleClear = () => {
setInputValue('');
(onClear ?? onChange)('');
};
return (
<TextField
{...rest}
size='small'
placeholder={placeholder}
value={inputValue}
onChange={handleChange}
sx={{
minWidth: '20rem',
maxWidth: '100%',
width: '100%',
flex: 1,
...sxProp,
'& .MuiOutlinedInput-root': {
height: height,
maxHeight: '5rem',
borderRadius: '0.5rem',
backgroundColor: '#fff',
padding: '0.25rem 0.75rem',
'& fieldset': {
border: '0.06rem solid rgba(0, 0, 0, 0.1)',
},
'&.Mui-focused fieldset': {
borderWidth: '0.1rem',
},
},
'& .MuiOutlinedInput-input': {
padding: 0,
},
}}
slotProps={{
input: {
startAdornment: (
<InputAdornment position='start'>
<Search />
</InputAdornment>
),
...(clearable && inputValue
? {
endAdornment: (
<InputAdornment position='end'>
<IconButton
aria-label='Очистить поиск'
size='small'
onMouseDown={(event) => event.preventDefault()}
onClick={handleClear}>
<CloseIcon fontSize='small' />
</IconButton>
</InputAdornment>
),
}
: {}),
},
}}
/>
);
}
export default memo(SearchComponent);