import PropTypes from 'prop-types'; import ExpandLess from '@mui/icons-material/ExpandLess'; import ExpandMore from '@mui/icons-material/ExpandMore'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; import Collapse from '@mui/material/Collapse'; import List from '@mui/material/List'; import ListItemButton from '@mui/material/ListItemButton'; import ListItemText from '@mui/material/ListItemText'; import Paper from '@mui/material/Paper'; import Typography from '@mui/material/Typography'; import throttle from 'lodash/throttle'; import * as React from 'react'; import { FixedSizeList } from 'react-window'; import SearchInput from 'components/SearchInput'; import useFormatMessage from 'hooks/useFormatMessage'; import SuggestionItem from './SuggestionItem'; const SHORT_LIST_LENGTH = 4; const LIST_ITEM_HEIGHT = 64; const computeListHeight = (currentLength) => { const numberOfRenderedItems = Math.min(SHORT_LIST_LENGTH, currentLength); return LIST_ITEM_HEIGHT * numberOfRenderedItems; }; const getPartialArray = (array, length = array.length) => { return array.slice(0, length); }; const renderItemFactory = ({ onSuggestionClick }) => (props) => ( ); const Suggestions = (props) => { const formatMessage = useFormatMessage(); const { data, onSuggestionClick = () => null } = props; const [current, setCurrent] = React.useState(0); const [listLength, setListLength] = React.useState(SHORT_LIST_LENGTH); const [filteredData, setFilteredData] = React.useState(data); React.useEffect( function syncOptions() { setFilteredData((filteredData) => { if (filteredData.length === 0 && filteredData.length !== data.length) { return data; } return filteredData; }); }, [data], ); const renderItem = React.useMemo( () => renderItemFactory({ onSuggestionClick, }), [onSuggestionClick], ); const expandList = () => { setListLength(Infinity); }; const collapseList = () => { setListLength(SHORT_LIST_LENGTH); }; React.useEffect(() => { setListLength(SHORT_LIST_LENGTH); }, [current]); const onSearchChange = React.useMemo( () => throttle((event) => { const search = event.target.value.toLowerCase(); if (!search) { setFilteredData(data); return; } const newFilteredData = data .map((stepWithOutput) => { return { id: stepWithOutput.id, name: stepWithOutput.name, output: stepWithOutput.output.filter((option) => `${option.label}\n${option.sampleValue}` .toLowerCase() .includes(search.toLowerCase()), ), }; }) .filter((stepWithOutput) => stepWithOutput.output.length); setFilteredData(newFilteredData); }, 400), [data], ); return ( {filteredData.length > 0 && ( {filteredData.map((option, index) => ( setCurrent((currentIndex) => currentIndex === index ? null : index, ) } sx={{ py: 0.5 }} > {!!option.output?.length && (current === index ? : )} {renderItem} {(option.output?.length || 0) > listLength && ( )} {listLength === Infinity && ( )} ))} )} {filteredData.length === 0 && ( theme.spacing(0, 0, 2, 2) }}> {formatMessage('powerInputSuggestions.noOptions')} )} ); }; Suggestions.propTypes = { data: PropTypes.arrayOf( PropTypes.shape({ id: PropTypes.string.isRequired, name: PropTypes.string.isRequired, output: PropTypes.arrayOf(PropTypes.object).isRequired, }), ).isRequired, onSuggestionClick: PropTypes.func, }; export default Suggestions;