UNPKG

@mskcc/carbon-react

Version:

Carbon react components for the MSKCC DSM

94 lines (89 loc) 2.63 kB
/** * 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 };