@mskcc/carbon-react
Version:
Carbon react components for the MSKCC DSM
94 lines (89 loc) • 2.63 kB
JavaScript
/**
* MSKCC 2021, 2024
*/
import React__default, { useContext, useState, useEffect, createContext } from 'react';
import { useCombobox } from 'downshift';
import debounce from 'lodash.debounce';
import PropTypes from 'prop-types';
import { AutocompleteInput } from './AutocompleteInput.js';
import { AutocompleteSuggestionList } from './AutocompleteSuggestionList.js';
const AutocompleteContext = /*#__PURE__*/createContext(null);
function useAutocomplete() {
const context = useContext(AutocompleteContext);
if (!context) {
throw new Error('useAutocomplete must be used within an Autocomplete provider');
}
return context;
}
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
const Autocomplete = _ref => {
let {
children,
handleInput,
min = 3,
...downshiftProps
} = _ref;
const [items, setItems] = useState([]);
const {
isOpen,
getMenuProps,
getInputProps,
highlightedIndex,
getItemProps,
reset,
inputValue
} = useCombobox({
items,
...downshiftProps
});
const clearInput = () => reset();
useEffect(() => {
const effectiveMin = Math.max(min, 1);
if (inputValue && inputValue.length >= effectiveMin) {
const debouncedHandleInput = debounce(() => {
const result = handleInput(inputValue);
if (result instanceof Promise) {
result.then(setItems);
} else {
setItems(result);
}
}, 300);
debouncedHandleInput();
return () => {
debouncedHandleInput.cancel();
};
}
}, [inputValue, handleInput]);
return /*#__PURE__*/React__default.createElement("div", {
className: "msk-autocomplete"
}, /*#__PURE__*/React__default.createElement(AutocompleteContext.Provider, {
value: {
isOpen,
getMenuProps,
getInputProps,
highlightedIndex,
getItemProps,
items,
clearInput
}
}, children));
};
Autocomplete.displayName = 'Autocomplete';
Autocomplete.Input = AutocompleteInput;
Autocomplete.SuggestionList = AutocompleteSuggestionList;
Autocomplete.propTypes = {
/**
* The children of the Autocomplete component.
*/
children: PropTypes.node.isRequired,
/**
* The function that will be called when the user types in the input.
* It should return an array of items or a promise that resolves to an array of items.
*/
handleInput: PropTypes.func.isRequired,
/**
* The minimum number of characters that must be typed before the handleInput function is called.
*/
min: PropTypes.number
};
export { Autocomplete, Autocomplete as default, useAutocomplete };