UNPKG

@primer/components

Version:
140 lines (119 loc) • 6.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireWildcard(require("react")); var _AutocompleteContext = require("./AutocompleteContext"); var _TextInput = _interopRequireDefault(require("../TextInput")); var _useCombinedRefs = require("../hooks/useCombinedRefs"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } const AutocompleteInput = /*#__PURE__*/_react.default.forwardRef(({ as: Component = _TextInput.default, onFocus, onBlur, onChange, onKeyDown, onKeyPress, value, ...props }, forwardedRef) => { const { activeDescendantRef, autocompleteSuggestion = '', id, inputRef, inputValue = '', isMenuDirectlyActivated, setInputValue, setShowMenu, showMenu } = (0, _react.useContext)(_AutocompleteContext.AutocompleteContext); const combinedInputRef = (0, _useCombinedRefs.useCombinedRefs)(inputRef, forwardedRef); const [highlightRemainingText, setHighlightRemainingText] = (0, _react.useState)(true); const handleInputFocus = (0, _react.useCallback)(e => { onFocus && onFocus(e); setShowMenu && setShowMenu(true); }, [onFocus, setShowMenu]); const handleInputBlur = (0, _react.useCallback)(e => { onBlur && onBlur(e); // HACK: wait a tick and check the focused element before hiding the autocomplete menu // this prevents the menu from hiding when the user is clicking an option in the Autoselect.Menu, // but still hides the menu when the user blurs the input by tabbing out or clicking somewhere else on the page setTimeout(() => { if (document.activeElement !== combinedInputRef.current) { setShowMenu && setShowMenu(false); } }, 0); }, [onBlur, setShowMenu]); const handleInputChange = (0, _react.useCallback)(e => { onChange && onChange(e); setInputValue && setInputValue(e.currentTarget.value); if (!showMenu) { setShowMenu && setShowMenu(true); } }, [onChange, setInputValue, setShowMenu, showMenu]); const handleInputKeyDown = (0, _react.useCallback)(e => { var _inputRef$current; if (e.key === 'Backspace') { setHighlightRemainingText(false); } if (e.key === 'Escape' && inputRef !== null && inputRef !== void 0 && (_inputRef$current = inputRef.current) !== null && _inputRef$current !== void 0 && _inputRef$current.value) { setInputValue && setInputValue(''); inputRef.current.value = ''; } }, [inputRef, setInputValue, setHighlightRemainingText]); const handleInputKeyUp = (0, _react.useCallback)(e => { if (e.key === 'Backspace') { setHighlightRemainingText(true); } }, [setHighlightRemainingText]); const onInputKeyPress = (0, _react.useCallback)(event => { if (activeDescendantRef && event.key === 'Enter' && activeDescendantRef.current) { event.preventDefault(); event.nativeEvent.stopImmediatePropagation(); // Forward Enter key press to active descendant so that item gets activated const activeDescendantEvent = new KeyboardEvent(event.type, event.nativeEvent); activeDescendantRef.current.dispatchEvent(activeDescendantEvent); } }, [activeDescendantRef]); (0, _react.useEffect)(() => { if (!(inputRef !== null && inputRef !== void 0 && inputRef.current)) { return; } // resets input value to being empty after a selection has been made if (!autocompleteSuggestion) { inputRef.current.value = inputValue; } // TODO: fix bug where this function prevents `onChange` from being triggered if the highlighted item text // is the same as what I'm typing // e.g.: typing 'tw' highights 'two', but when I 'two', the text input change does not get triggered if (highlightRemainingText && autocompleteSuggestion && (inputValue || isMenuDirectlyActivated)) { inputRef.current.value = autocompleteSuggestion; if (autocompleteSuggestion.toLowerCase().indexOf(inputValue.toLowerCase()) === 0) { inputRef.current.setSelectionRange(inputValue.length, autocompleteSuggestion.length); } } }, [autocompleteSuggestion, inputValue]); (0, _react.useEffect)(() => { if (value) { setInputValue && setInputValue(value.toString()); } }, [value]); return /*#__PURE__*/_react.default.createElement(Component, _extends({ onFocus: handleInputFocus, onBlur: handleInputBlur, onChange: handleInputChange, onKeyDown: handleInputKeyDown, onKeyPress: onInputKeyPress, onKeyUp: handleInputKeyUp, ref: combinedInputRef, "aria-controls": `${id}-listbox`, "aria-autocomplete": "both", role: "combobox", "aria-expanded": showMenu, "aria-haspopup": "listbox", "aria-owns": `${id}-listbox` }, props)); }); var _default = AutocompleteInput; exports.default = _default;