@massds/mayflower-react
Version:
React versions of Mayflower design system UI components
256 lines • 10.1 kB
JavaScript
function _inheritsLoose(t, o) { t.prototype = Object.create(o.prototype), t.prototype.constructor = t, _setPrototypeOf(t, o); }
function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
/**
* 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) {
function MultiSelectDropDown(props) {
var _this;
_this = _React$Component.call(this, props) || this;
_defineProperty(_this, "_timeoutID", void 0);
_defineProperty(_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(_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(_this, "handleClearAll", () => {
_this.setState({
values: []
});
_this.focusOnComboBox();
});
_defineProperty(_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(_this, "handleDropDownKeyDown", event => {
if (event.key === 'Enter') {
_this.handleSelect(event);
}
});
_defineProperty(_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(_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(_this, "focusOnComboBox", () => {
const comboBox = document.getElementById(_this.props.fieldName + "-multiselect-combobox");
comboBox.focus();
});
_defineProperty(_this, "handleClick", () => {
_this.toggleDropDown();
});
_defineProperty(_this, "handleComboBoxKeyDown", event => {
event.stopPropagation();
if (event.key === 'Enter') {
_this.toggleDropDown();
}
});
_defineProperty(_this, "toggleDropDown", () => {
_this.setState(prevState => ({
dropwDownExpand: !prevState.dropwDownExpand
}));
});
_defineProperty(_this, "closeDropDown", () => {
_this.setState({
dropwDownExpand: false
});
});
_this.state = {
values: [],
dropwDownExpand: false
};
return _this;
}
_inheritsLoose(MultiSelectDropDown, _React$Component);
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;