@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
JavaScript
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;