UNPKG

@s-ui/react-molecule-autosuggest

Version:

`MoleculeAutosuggest` is an input that will display a list of suggestions while values are entered It allows Single and Multiple Selection

207 lines 8.83 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose"; var _excluded = ["autoClose", "children", "disabled", "errorState", "id", "isOpen", "keysCloseList", "keysSelection", "multiselection", "onBlur", "onChange", "onClear", "onEnter", "onFocus", "onSelect", "onToggle", "refMoleculeAutosuggest", "refMoleculeAutosuggestInput", "state"]; import { Children, cloneElement, createRef, useRef, useState } from 'react'; import cx from 'classnames'; import PropTypes from 'prop-types'; import { getCurrentElementFocused } from '@s-ui/js/lib/dom'; import { getTarget } from '@s-ui/js/lib/react'; import { inputShapes, inputTypes } from '@s-ui/react-atom-input'; import useControlledState from '@s-ui/react-hooks/lib/useControlledState'; import useMergeRefs from '@s-ui/react-hooks/lib/useMergeRefs'; import { moleculeDropdownListSizes as SIZES } from '@s-ui/react-molecule-dropdown-list'; import MoleculeAutosuggestMultipleSelection from './components/MultipleSelection/index.js'; import MoleculeAutosuggestSingleSelection from './components/SingleSelection/index.js'; import { AUTOSUGGEST_STATES, BASE_CLASS, CLASS_DISABLED, CLOSE_KEYS_LIST, getIsTypeableKey, SELECT_KEYS_LIST } from './config.js'; import { jsx as _jsx } from "react/jsx-runtime"; var MoleculeAutosuggest = function MoleculeAutosuggest(_ref) { var _cx; var _ref$autoClose = _ref.autoClose, autoClose = _ref$autoClose === void 0 ? true : _ref$autoClose, children = _ref.children, disabled = _ref.disabled, errorState = _ref.errorState, _ref$id = _ref.id, id = _ref$id === void 0 ? '' : _ref$id, isOpen = _ref.isOpen, _ref$keysCloseList = _ref.keysCloseList, keysCloseList = _ref$keysCloseList === void 0 ? CLOSE_KEYS_LIST : _ref$keysCloseList, _ref$keysSelection = _ref.keysSelection, keysSelection = _ref$keysSelection === void 0 ? SELECT_KEYS_LIST : _ref$keysSelection, multiselection = _ref.multiselection, onBlur = _ref.onBlur, onChange = _ref.onChange, onClear = _ref.onClear, onEnter = _ref.onEnter, onFocus = _ref.onFocus, onSelect = _ref.onSelect, onToggle = _ref.onToggle, _ref$refMoleculeAutos = _ref.refMoleculeAutosuggest, refMoleculeAutosuggestFromProps = _ref$refMoleculeAutos === void 0 ? {} : _ref$refMoleculeAutos, _ref$refMoleculeAutos2 = _ref.refMoleculeAutosuggestInput, refMoleculeAutosuggestInputFromProps = _ref$refMoleculeAutos2 === void 0 ? {} : _ref$refMoleculeAutos2, state = _ref.state, restProps = _objectWithoutPropertiesLoose(_ref, _excluded); var innerRefMoleculeAutosuggest = useRef(); var refMoleculeAutosuggest = useMergeRefs(innerRefMoleculeAutosuggest, refMoleculeAutosuggestFromProps); var _useControlledState = useControlledState(isOpen, !!isOpen), isOpenState = _useControlledState[0], setIsOpenState = _useControlledState[1], isControlled = _useControlledState[2]; var refsMoleculeAutosuggestOptions = useRef([]); var innerRefMoleculeAutosuggestInput = useRef(); var refMoleculeAutosuggestInput = useMergeRefs(innerRefMoleculeAutosuggestInput, refMoleculeAutosuggestInputFromProps); var _useState = useState(false), focus = _useState[0], setFocus = _useState[1]; var handleToggle = function handleToggle(ev, _ref2) { var nextIsOpenState = _ref2.isOpen; var type = ev.type; if (type !== 'change') { setIsOpenState(nextIsOpenState, autoClose !== false); } else if (!isOpenState) { setIsOpenState(nextIsOpenState, nextIsOpenState && isOpen !== false); } typeof onToggle === 'function' && onToggle(ev, { isOpen: nextIsOpenState }); }; var extendedChildren = Children.toArray(children).filter(Boolean).map(function (child, index) { refsMoleculeAutosuggestOptions.current[index] = /*#__PURE__*/createRef(); return /*#__PURE__*/cloneElement(child, { innerRef: refsMoleculeAutosuggestOptions.current[index], selectKey: keysSelection }); }); var className = cx(BASE_CLASS, errorState && BASE_CLASS + "--" + AUTOSUGGEST_STATES.ERROR, errorState === false && BASE_CLASS + "--" + AUTOSUGGEST_STATES.SUCCESS, state && BASE_CLASS + "--" + state, (_cx = {}, _cx[CLASS_DISABLED] = disabled, _cx)); var closeList = function closeList(ev) { var domMoleculeAutosuggest = innerRefMoleculeAutosuggest.current; handleToggle(ev, { isOpen: false }); if (multiselection && typeof onChange === 'function') { onChange(ev, { value: '' }); } domMoleculeAutosuggest && !focus && domMoleculeAutosuggest.focus(); setFocus(false); ev.preventDefault(); ev.stopPropagation(); }; var focusFirstOption = function focusFirstOption(ev, _ref3) { var options = _ref3.options; if (options[0]) options[0].focus(); ev.preventDefault(); ev.stopPropagation(); }; var handleKeyDown = function handleKeyDown(ev) { ev.persist(); var domInnerInput = refMoleculeAutosuggestInput.current; var optionsFromRef = refsMoleculeAutosuggestOptions.current; var key = ev.key; var options = optionsFromRef.map(getTarget); var isTypeableKey = getIsTypeableKey(key); var isSelectionKey = keysSelection.includes(key); if (isTypeableKey) { if (!isSelectionKey && domInnerInput) domInnerInput.focus(); } if (isOpenState) { var currentElementFocused = getCurrentElementFocused(); var isSomeOptionFocused = [].concat(options).includes(currentElementFocused); if (keysCloseList.includes(key)) closeList(ev);else if (key === 'ArrowDown' && !isSomeOptionFocused) focusFirstOption(ev, { options: options });else if (isSomeOptionFocused) handleFocusIn(ev); if (key === 'Enter') { typeof onEnter === 'function' && onEnter(ev); handleFocusInput(); } } }; var handleFocusIn = function handleFocusIn(ev) { typeof onFocus === 'function' && onFocus(ev); setFocus(true); }; var handleFocusOut = function handleFocusOut(ev) { ev.persist(); var domContainer = innerRefMoleculeAutosuggest.current; var domInnerInput = innerRefMoleculeAutosuggestInput.current; var optionsFromRef = refsMoleculeAutosuggestOptions.current; var options = optionsFromRef.map(getTarget); setTimeout(function () { var currentElementFocused = getCurrentElementFocused(); var focusOutFromOutside = ![domInnerInput].concat(options).includes(currentElementFocused) && !domContainer.contains(currentElementFocused); if (focusOutFromOutside) { if (autoClose && isOpenState) { closeList(ev); } else { setFocus(false); } typeof onBlur === 'function' && onBlur(); } }, 1); setFocus(true); }; var handleInputKeyDown = function handleInputKeyDown(ev) { var key = ev.key; if (key === 'Enter') { typeof onEnter === 'function' && onEnter(ev); onEnter && typeof onEnter === 'function' && autoClose && closeList(ev); } }; var handleClick = function handleClick() { handleFocusInput(); }; var handleFocusInput = function handleFocusInput() { var innerRefInput = innerRefMoleculeAutosuggestInput.current; if (innerRefInput && (!isControlled || autoClose)) { innerRefInput.focus(); } }; var handleClear = function handleClear(ev) { ev.stopPropagation(); handleFocusInput(); if (onClear) { onClear(ev); } }; var autosuggestSelectionProps = _extends({ autoClose: autoClose, children: extendedChildren, disabled: disabled, errorState: errorState, id: id, innerRefInput: refMoleculeAutosuggestInput, isOpen: isOpenState, keysCloseList: keysCloseList, keysSelection: keysSelection, onBlur: onBlur, onChange: onChange, onClear: handleClear, onEnter: onEnter, onFocus: onFocus, onInputKeyDown: handleInputKeyDown, onKeyDown: handleKeyDown, onSelect: onSelect, onToggle: handleToggle, state: state }, restProps); var AutosuggestSelection = multiselection ? MoleculeAutosuggestMultipleSelection : MoleculeAutosuggestSingleSelection; return /*#__PURE__*/_jsx("div", { ref: refMoleculeAutosuggest, tabIndex: "0", className: className, onKeyDown: handleKeyDown, onFocus: handleFocusIn, onBlur: handleFocusOut, onClick: handleClick, role: "combobox", "aria-controls": id, "aria-expanded": isOpenState, children: /*#__PURE__*/_jsx(AutosuggestSelection, _extends({}, autosuggestSelectionProps)) }); }; MoleculeAutosuggest.displayName = 'MoleculeAutosuggest'; export { SIZES as MoleculeAutosuggestDropdownListSizes }; export { AUTOSUGGEST_STATES as MoleculeAutosuggestStates }; export default MoleculeAutosuggest;