Files
Checkmate/Client/src/Components/Inputs/Search/index.jsx
T

153 lines
4.6 KiB
React
Raw Normal View History

2024-09-18 17:14:03 -04:00
import PropTypes from "prop-types";
import { Box, ListItem, Autocomplete, TextField } from "@mui/material";
import { useTheme } from "@emotion/react";
import SearchIcon from "../../../assets/icons/search.svg?react";
2024-09-18 17:24:36 -04:00
/**
* Search component using Material UI's Autocomplete.
*
* @param {Object} props
* @param {string} props.id - Unique identifier for the Autocomplete component
* @param {Array<Object>} props.options - Options to display in the Autocomplete dropdown
2024-09-18 20:27:55 -04:00
* @param {string} props.filteredBy - Key to access the option label from the options
2024-09-18 17:24:36 -04:00
* @param {string} props.value - Current input value for the Autocomplete
* @param {Function} props.handleChange - Function to call when the input changes
* @param {Object} props.sx - Additional styles to apply to the component
* @returns {JSX.Element} The rendered Search component
*/
2024-09-19 11:07:38 +08:00
const Search = ({
id,
options,
filteredBy,
secondaryLabel,
2024-09-19 11:07:38 +08:00
value,
handleInputChange,
handleChange,
sx,
}) => {
2024-09-18 17:14:03 -04:00
const theme = useTheme();
return (
<Autocomplete
id={id}
2024-09-18 17:22:58 -04:00
inputValue={value}
2024-09-19 11:07:38 +08:00
onInputChange={(_, newValue) => {
handleInputChange(newValue);
}}
onChange={(_, newValue) => {
handleChange && handleChange(newValue);
2024-09-18 17:22:58 -04:00
}}
2024-09-18 17:14:03 -04:00
fullWidth
// freeSolo
2024-09-18 17:14:03 -04:00
disableClearable
options={options}
2024-09-18 20:27:55 -04:00
getOptionLabel={(option) => option[filteredBy]}
2024-09-18 17:14:03 -04:00
renderInput={(params) => (
<TextField
{...params}
placeholder="Type to search"
InputProps={{
...params.InputProps,
startAdornment: (
<Box
mr={theme.spacing(4)}
height={16}
sx={{
"& svg": {
width: 16,
height: 16,
"& path": {
stroke: theme.palette.text.tertiary,
strokeWidth: 1.2,
},
},
}}
>
<SearchIcon />
</Box>
),
}}
sx={{
"& fieldset": {
borderColor: theme.palette.border.light,
borderRadius: theme.shape.borderRadius,
},
"& .MuiOutlinedInput-root:hover:not(:has(input:focus)):not(:has(textarea:focus)) fieldset":
{
borderColor: theme.palette.border.light,
},
}}
/>
)}
filterOptions={(options, { inputValue }) => {
const filtered = options.filter((option) =>
2024-09-18 20:27:55 -04:00
option[filteredBy].toLowerCase().includes(inputValue.toLowerCase())
2024-09-18 17:14:03 -04:00
);
if (filtered.length === 0) {
2024-09-18 20:27:55 -04:00
return [{ [filteredBy]: "No monitors found", noOptions: true }];
2024-09-18 17:14:03 -04:00
}
return filtered;
}}
renderOption={(props, option) => {
const { key, ...optionProps } = props;
return (
<ListItem
key={key}
{...optionProps}
sx={
option.noOptions
? {
pointerEvents: "none",
backgroundColor: theme.palette.background.main,
}
: {}
}
>
{option[filteredBy] +
(secondaryLabel ? ` (${option[secondaryLabel]})` : "")}
2024-09-18 17:14:03 -04:00
</ListItem>
);
}}
slotProps={{
popper: {
keepMounted: true,
sx: {
"& ul": { p: 2 },
"& li.MuiAutocomplete-option": {
color: theme.palette.text.secondary,
px: 4,
borderRadius: theme.shape.borderRadius,
},
"& .MuiAutocomplete-listbox .MuiAutocomplete-option[aria-selected='true'], & .MuiAutocomplete-listbox .MuiAutocomplete-option[aria-selected='true'].Mui-focused, & .MuiAutocomplete-listbox .MuiAutocomplete-option[aria-selected='true']:hover":
{
backgroundColor: theme.palette.background.fill,
},
"& .MuiAutocomplete-noOptions": {
px: theme.spacing(6),
py: theme.spacing(5),
},
},
},
}}
sx={{
height: 34,
"&.MuiAutocomplete-root .MuiAutocomplete-input": { p: 0 },
...sx,
}}
/>
);
};
2024-09-18 17:24:36 -04:00
Search.propTypes = {
id: PropTypes.string,
2024-09-18 20:27:55 -04:00
options: PropTypes.array.isRequired,
filteredBy: PropTypes.string.isRequired,
secondaryLabel: PropTypes.string,
2024-09-18 17:24:36 -04:00
value: PropTypes.string.isRequired,
2024-09-19 11:07:38 +08:00
handleInputChange: PropTypes.func.isRequired,
handleChange: PropTypes.func,
2024-09-18 17:24:36 -04:00
sx: PropTypes.object,
};
2024-09-18 17:14:03 -04:00
export default Search;