@massds/mayflower-react
Version:
React versions of Mayflower design system UI components
307 lines (254 loc) • 10.2 kB
JavaScript
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
/**
* MultiSelectDropDown module.
* @module @massds/mayflower-react/MultiSelectDropDown
* @requires module:@massds/mayflower-assets/scss/02-molecules/multiselect-dropdown
* @requires module:@massds/mayflower-assets/scss/01-atoms/input-checkbox
* @requires module:@massds/mayflower-assets/scss/02-molecules/tags
* @requires module:@massds/mayflower-assets/scss/01-atoms/button-tag
* @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 classNames from "classnames";
import InputCheckBox from "../InputCheckBox/index.mjs";
import Tags from "../Tags/index.mjs";
export const getObjByValue = (arr, value, key) => {
let i = 0;
const arrayMax = arr.length;
for (; i < arrayMax; i += 1) {
const item = arr[i];
if (item[key] === value) {
return item;
}
}
return undefined;
};
let MultiSelectDropDown = /*#__PURE__*/function (_React$Component) {
_inheritsLoose(MultiSelectDropDown, _React$Component);
function MultiSelectDropDown(props) {
var _this;
_this = _React$Component.call(this, props) || this;
_defineProperty(_assertThisInitialized(_this), "_timeoutID", void 0);
_defineProperty(_assertThisInitialized(_this), "onBlur", () => {
// Time out to wait for React processing delay on activeElement
_this._timeoutID = setTimeout(() => {
if (document.activeElement !== null) {
if (!_this.wrapperRef.contains(document.activeElement)) {
_this.setState({
dropwDownExpand: false
});
}
}
}, 0);
});
_defineProperty(_assertThisInitialized(_this), "handleTagClick", (target, e) => {
e.stopPropagation();
const val = target.getAttribute('data-ma-filter-value');
const values = _this.state.values;
values.splice(values.indexOf(val), 1);
_this.setState({
values: values,
dropwDownExpand: true
});
});
_defineProperty(_assertThisInitialized(_this), "handleClearAll", () => {
_this.setState({
values: []
});
_this.focusOnComboBox();
});
_defineProperty(_assertThisInitialized(_this), "handleClickOutside", event => {
// Close the panel if the user clicks outside the component.
const node = _this.wrapperRef;
if (node && !node.contains(event.target)) {
if (_this.state.dropwDownExpand) {
_this.closeDropDown();
}
}
});
_defineProperty(_assertThisInitialized(_this), "handleDropDownKeyDown", event => {
if (event.key === 'Enter') {
_this.handleSelect(event);
}
});
_defineProperty(_assertThisInitialized(_this), "handleSelect", event => {
const value = event.target.value;
const values = _this.state.values;
if (values.indexOf(value) > -1) {
values.splice(values.indexOf(value), 1);
} else {
values.push(value);
}
_this.setState({
values: values
});
});
_defineProperty(_assertThisInitialized(_this), "handleKeyDown", event => {
// Detect onBlur using tab key
if (event.key === 'Tab') {
_this.onBlur();
} // If the user pressed escape collapse list.
if (event.key === 'Escape') {
_this.closeDropDown();
_this.focusOnComboBox();
}
let index = -1;
const tagName = event.target.tagName;
if (tagName === 'INPUT') {
const targetId = event.target.id;
index = Number(targetId.split('-').pop());
}
const nextIndex = index + 1;
const prevIndex = index - 1;
if (event.key === 'ArrowUp') {
if (prevIndex === -1) {
_this.focusOnComboBox();
}
if (prevIndex >= 0) {
const prevItem = document.getElementById("input-checkbox-" + prevIndex);
if (prevItem) {
prevItem.focus();
}
}
}
if (event.key === 'ArrowDown' && nextIndex < _this.props.dropdownItems.length) {
const nextItem = document.getElementById("input-checkbox-" + nextIndex);
if (nextItem) {
nextItem.focus();
}
}
});
_defineProperty(_assertThisInitialized(_this), "focusOnComboBox", () => {
const comboBox = document.getElementById(_this.props.fieldName + "-multiselect-combobox");
comboBox.focus();
});
_defineProperty(_assertThisInitialized(_this), "handleClick", () => {
_this.toggleDropDown();
});
_defineProperty(_assertThisInitialized(_this), "handleComboBoxKeyDown", event => {
event.stopPropagation();
if (event.key === 'Enter') {
_this.toggleDropDown();
}
});
_defineProperty(_assertThisInitialized(_this), "toggleDropDown", () => {
_this.setState(prevState => ({
dropwDownExpand: !prevState.dropwDownExpand
}));
});
_defineProperty(_assertThisInitialized(_this), "closeDropDown", () => {
_this.setState({
dropwDownExpand: false
});
});
_this.state = {
values: [],
dropwDownExpand: false
};
return _this;
}
var _proto = MultiSelectDropDown.prototype;
_proto.componentDidMount = function componentDidMount() {
this.buttonClicked = false;
document.addEventListener('mousedown', e => this.handleClickOutside(e));
this.wrapperRef.addEventListener('keydown', e => this.handleKeyDown(e));
};
_proto.componentWillUnmount = function componentWillUnmount() {
document.removeEventListener('mousedown', () => this.handleClickOutside());
this.wrapperRef.removeEventListener('keydown', () => this.handleKeyDown());
this.wrapperRef.removeEventListener('onblur', e => this.handleKeyDown(e));
};
_proto.render = function render() {
var _classNames;
const _this$props = this.props,
dropdownItems = _this$props.dropdownItems,
fieldName = _this$props.fieldName,
title = _this$props.title,
titleClasses = _this$props.titleClasses,
defaultText = _this$props.defaultText;
const _this$state = this.state,
values = _this$state.values,
dropwDownExpand = _this$state.dropwDownExpand;
const tags = values.map(val => getObjByValue(dropdownItems, val, 'value'));
const tagsProps = {
tags: tags.map(tag => ({
value: tag.value,
text: tag.label,
type: fieldName
})),
onClearThisCallback: this.handleTagClick,
onClearCallback: this.handleClearAll
};
const titleCls = classNames((_classNames = {}, _classNames[titleClasses.join(' ')] = true, _classNames));
return /*#__PURE__*/React.createElement("div", {
className: "ma__multiselect-dropdown",
ref: node => {
this.wrapperRef = node;
}
}, /*#__PURE__*/React.createElement("fieldset", {
className: "group"
}, /*#__PURE__*/React.createElement("legend", {
className: titleClasses.length > 0 ? titleCls : null
}, title), /*#__PURE__*/React.createElement("div", {
role: "combobox",
tabIndex: 0,
"aria-expanded": dropwDownExpand,
"aria-controls": fieldName + "-multiselect",
id: fieldName + "-multiselect-combobox",
"aria-haspopup": true,
className: "ma__select-box__field",
onClick: this.handleClick,
onKeyDown: this.handleComboBoxKeyDown
}, /*#__PURE__*/React.createElement("div", {
className: "ma__select-box__link"
}, /*#__PURE__*/React.createElement("span", {
className: "js-dropdown-link"
}, values.length > 0 ? /*#__PURE__*/React.createElement(Tags, tagsProps) : defaultText), /*#__PURE__*/React.createElement("span", {
className: "ma__select-box__icon"
}))), dropwDownExpand && /*#__PURE__*/React.createElement("div", {
id: fieldName + "-multiselect",
className: "ma__multiselect-dropdown-menu ma__multiselect-dropdown-menu--expanded"
}, dropdownItems.map((item, i) => /*#__PURE__*/React.createElement(InputCheckBox, {
id: "input-checkbox-" + i
/* eslint-disable-next-line react/no-array-index-key */
,
key: "input-checkbox-" + i,
name: fieldName,
value: item.value,
label: item.label,
onChange: this.handleSelect,
onKeyDown: this.handleDropDownKeyDown,
classes: ['ma__multiselect-dropdown-item'],
defaultValue: values.indexOf(item.value) > -1 ? item.value : false,
tabIndex: -1
})))));
};
return MultiSelectDropDown;
}(React.Component);
MultiSelectDropDown.propTypes = process.env.NODE_ENV !== "production" ? {
/** The legend title of the multiple select dropdown, can be a string, an element or a React component. */
title: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
/** Legend classes. */
titleClasses: PropTypes.arrayOf(PropTypes.string),
/** Default display in dropdown field. */
defaultText: PropTypes.string,
/** Custom callback on dropdown item selection. */
onItemSelect: PropTypes.func,
/** Custom callback on dropdown click. */
onDropDownClick: PropTypes.func,
/** An array of dropdown multiselect items */
dropdownItems: PropTypes.arrayOf(PropTypes.shape({
text: PropTypes.string,
href: PropTypes.string
})),
/** Field name attribute that is used for grouping DOM submission and identify tags type */
fieldName: PropTypes.string
} : {};
MultiSelectDropDown.defaultProps = {
titleClasses: []
};
export default MultiSelectDropDown;