@massds/mayflower-react
Version:
React versions of Mayflower design system UI components
134 lines (133 loc) • 5.07 kB
JavaScript
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
/**
* TypeAheadDropdown module.
* @module @massds/mayflower-react/TypeAheadDropdown
* @requires module:@massds/mayflower-assets/scss/01-atoms/button-with-icon
* @requires module:@massds/mayflower-assets/scss/01-atoms/button-search
* @requires module:@massds/mayflower-assets/scss/01-atoms/input-typeahead
* @requires module:@massds/mayflower-assets/scss/01-atoms/svg-icons
* @requires module:@massds/mayflower-assets/scss/01-atoms/svg-loc-icons
*/
import React from "react";
import PropTypes from "prop-types";
import ButtonWithIcon from "../ButtonWithIcon/index.mjs";
import InputTextFuzzy from "../InputTextFuzzy/index.mjs";
// eslint-disable-next-line import/no-unresolved
import IconCaretDown from "../Icon/IconCaretDown.mjs";
const TypeAheadDropdown = props => {
const _React$useState = React.useState(false),
buttonExpand = _React$useState[0],
setButtonExpand = _React$useState[1];
const _React$useState2 = React.useState(props.dropdownButton.text),
buttonText = _React$useState2[0],
setButtonText = _React$useState2[1];
const _React$useState3 = React.useState(),
buttonClicked = _React$useState3[0],
setButtonClicked = _React$useState3[1];
const buttonRef = React.useRef();
const wrapperRef = React.useRef();
const handleRefMouseDown = () => {
setButtonClicked(true);
};
const handleClick = () => {
setButtonExpand(!buttonExpand);
};
const handleKeyDown = event => {
// If the user pressed escape, or pressed enter with nothing selected close
// the panel.
if (event.key === 'Escape' || event.key === 'Enter' && event.target.value === '') {
closeDropdown();
}
if (event.key === 'Escape' && buttonRef) {
buttonRef.focus();
}
if (typeof props.onKeyDown === 'function') {
props.onKeyDown(event);
}
};
const handleInputBlur = () => {
if (buttonClicked) {
closeDropdown();
}
};
const handleSelect = (event, _ref) => {
let suggestion = _ref.suggestion;
// Stop the filters form submission if enter is pressed in the selector.
event.preventDefault();
// Update this component state and pass the event out to the calling code.
const text = suggestion.item.text;
if (text.length > 0) {
setButtonText(text);
setButtonExpand(false);
if (typeof props.inputText.onSuggestionClick === 'function') {
props.inputText.onSuggestionClick(event, {
suggestion: suggestion
});
}
}
};
const handleClickOutside = event => {
// Close the panel if the user clicks outside the component.
const node = wrapperRef.current;
if (node && !node.contains(event.target)) {
if (buttonExpand) {
setButtonExpand(false);
}
}
};
const closeDropdown = () => {
setButtonExpand(false);
};
// update state from prop
React.useEffect(() => {
const defaultValue = props.defaultValue;
if (defaultValue !== undefined) {
setButtonText(defaultValue);
setButtonExpand(false);
}
}, [props.defaultValue]);
React.useEffect(() => {
setButtonClicked(false);
document.addEventListener('mousedown', handleClickOutside);
buttonRef.current.addEventListener('mousedown', handleRefMouseDown);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
if (buttonRef && buttonRef.current) {
buttonRef.current.removeEventListener('mousedown', handleRefMouseDown);
}
};
});
const dropdownButton = _extends({
onClick: handleClick,
setButtonRef: buttonRef,
expanded: buttonExpand,
icon: /*#__PURE__*/React.createElement(IconCaretDown, {
height: 20,
width: 20
}),
size: ''
}, props.dropdownButton);
dropdownButton.text = buttonText || dropdownButton.text;
const inputTextFuzzyProps = _extends({}, props.inputText, {
onKeyDown: handleKeyDown,
onSuggestionClick: handleSelect,
onBlur: handleInputBlur,
autoFocusInput: true
});
return /*#__PURE__*/React.createElement("div", {
ref: wrapperRef
}, /*#__PURE__*/React.createElement(ButtonWithIcon, dropdownButton), buttonExpand && /*#__PURE__*/React.createElement(InputTextFuzzy, inputTextFuzzyProps));
};
TypeAheadDropdown.propTypes = process.env.NODE_ENV !== "production" ? {
/** The props to set up the dropdown button */
dropdownButton: PropTypes.shape(ButtonWithIcon.propTypes).isRequired,
/** The props to set up the inputTextFuzzy */
inputText: PropTypes.shape(InputTextFuzzy.propTypes).isRequired,
/** Default text value for the selection */
defaultValue: PropTypes.string,
/** Custom keydown callback */
onKeyDown: PropTypes.func,
/** Custom suggestion onClick callback */
onSuggestionClick: PropTypes.func
} : {};
export default TypeAheadDropdown;