import PropTypes from "prop-types"; import { Box, ListItem, Autocomplete, TextField, Stack, Typography } from "@mui/material"; import { useTheme } from "@emotion/react"; import SearchIcon from "../../../assets/icons/search.svg?react"; /** * Search component using Material UI's Autocomplete. * * @param {Object} props * @param {string} props.id - Unique identifier for the Autocomplete component * @param {Array} props.options - Options to display in the Autocomplete dropdown * @param {string} props.filteredBy - Key to access the option label from the options * @param {string} props.value - Current input value for the Autocomplete * @param {Function} props.handleChange - Function to call when the input changes * @param {Function} Prop.onBlur - Function to call when the input is blured * @param {Object} props.sx - Additional styles to apply to the component * @returns {JSX.Element} The rendered Search component */ const SearchAdornment = () => { const theme = useTheme(); return ( ); }; //TODO keep search state inside of component const Search = ({ label, id, options, filteredBy, secondaryLabel, value, inputValue, handleInputChange, handleChange, sx, multiple = false, isAdorned = true, error, disabled, startAdornment, endAdornment, onBlur, }) => { const theme = useTheme(); return ( { handleInputChange(newValue); }} onChange={(_, newValue) => { handleChange(newValue); }} fullWidth freeSolo disabled={disabled} disableClearable options={options} getOptionLabel={(option) => option[filteredBy]} isOptionEqualToValue={(option, value) => option._id === value._id} // Compare by unique identifier renderInput={(params) => ( {label} }), ...(startAdornment && { startAdornment: startAdornment }), ...(endAdornment && { endAdornment: endAdornment }), }, }} sx={{ "& fieldset": { borderColor: theme.palette.primary.lowContrast, borderRadius: theme.shape.borderRadius, }, "& .MuiOutlinedInput-root:hover:not(:has(input:focus)):not(:has(textarea:focus)) fieldset": { borderColor: theme.palette.primary.lowContrast, }, "& .MuiOutlinedInput-root": { paddingY: 0, }, "& .MuiAutocomplete-tag": { // CAIO_REVIEW color: theme.palette.primary.contrastText, backgroundColor: theme.palette.primary.lowContrast, }, "& .MuiChip-deleteIcon": { color: theme.palette.primary.contrastText, // CAIO_REVIEW }, }} /> {error && ( {error} )} )} filterOptions={(options, { inputValue }) => { const filtered = options.filter((option) => option[filteredBy].toLowerCase().includes(inputValue.toLowerCase()) ); if (filtered.length === 0) { return [{ [filteredBy]: "No monitors found", noOptions: true }]; } return filtered; }} getOptionKey={(option) => { return option._id; }} renderOption={(props, option) => { const { key, ...optionProps } = props; const hasSecondaryLabel = secondaryLabel && option[secondaryLabel] !== undefined; return ( {option[filteredBy] + (hasSecondaryLabel ? ` (${option[secondaryLabel]})` : "")} ); }} slotProps={{ popper: { keepMounted: true, sx: { "& ul": { p: 2, backgroundColor: theme.palette.primary.main }, "& li.MuiAutocomplete-option": { color: theme.palette.primary.contrastTextSecondary, 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.primary.lowContrast, color: "red", }, "& li.MuiAutocomplete-option:hover:not([aria-selected='true'])": { color: theme.palette.secondary.contrastText, backgroundColor: theme.palette.secondary.main, }, "& .MuiAutocomplete-noOptions": { px: theme.spacing(6), py: theme.spacing(5), }, }, }, }} sx={{ /* height: 34,*/ "&.MuiAutocomplete-root .MuiAutocomplete-input": { p: 0 }, ...sx, }} /> ); }; Search.propTypes = { label: PropTypes.string, id: PropTypes.string, multiple: PropTypes.bool, options: PropTypes.array.isRequired, filteredBy: PropTypes.string.isRequired, secondaryLabel: PropTypes.string, value: PropTypes.array, inputValue: PropTypes.string.isRequired, handleInputChange: PropTypes.func.isRequired, handleChange: PropTypes.func, isAdorned: PropTypes.bool, sx: PropTypes.object, error: PropTypes.string, disabled: PropTypes.bool, startAdornment: PropTypes.object, endAdornment: PropTypes.object, onBlur: PropTypes.func, }; export default Search;