@shopgate/pwa-common
Version:
Common library for the Shopgate Connect PWA.
183 lines (180 loc) • 5.43 kB
JavaScript
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import find from 'lodash/find';
import Dropdown from "../Dropdown";
import I18n from "../I18n";
import SelectBoxItem from "./components/Item";
import styles from "./style";
/**
* The select box component.
*/
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
let SelectBox = /*#__PURE__*/function (_Component) {
/**
* Initializes the component.
* @param {Object} props The components props.
*/
function SelectBox(props) {
var _this;
_this = _Component.call(this, props) || this;
/**
* Handles any interaction the user does outside of the component.
* In this case the select gets closed.
* @param {Object} event The event object.
*/
_this.handleInteractionOutside = event => {
_this.setState({
isOpen: false
});
event.preventDefault();
event.stopPropagation();
};
/**
* Sets the open state to true
*/
_this.handleOpenList = () => {
if (_this.state.isOpen) {
return;
}
_this.setState({
isOpen: true
});
if (_this.firstItemRef) {
_this.firstItemRef.focus();
}
};
/**
* Sets the new active selection.
* @param {string} value Value of the selected item.
*/
_this.handleSelectionUpdate = value => {
const selection = find(_this.props.items, {
value
});
_this.setState({
selected: selection,
isOpen: false
});
// Delay the callback to make sure actions are fired after animations are done.
setTimeout(() => {
_this.props.handleSelectionUpdate(selection.value);
}, _this.props.duration);
if (_this.controlRef) {
_this.controlRef.focus();
}
};
/** @param {HTMLElement} ref The element */
_this.setControlRef = ref => {
_this.controlRef = ref;
};
/** @param {HTMLElement} ref The element */
_this.setFirstItemRef = ref => {
_this.firstItemRef = ref;
};
_this.state = {
isOpen: false,
selected: find(props.items, {
value: props.initialValue
})
};
return _this;
}
/**
* Reset selected when changing the initial value.
* @param {Object} nextProps The next props the component will receive.
*/
_inheritsLoose(SelectBox, _Component);
var _proto = SelectBox.prototype;
_proto.UNSAFE_componentWillReceiveProps = function UNSAFE_componentWillReceiveProps(nextProps) {
if (this.props.initialValue !== nextProps.initialValue) {
this.setState({
selected: find(nextProps.items, {
value: nextProps.initialValue
})
});
}
};
/**
* Renders the component
* @returns {JSX}
*/
_proto.render = function render() {
const Icon = this.props.icon;
const {
icon,
iconOpen = null,
selection,
button,
dropdown,
selectItem,
selectItemSelected
} = this.props.classNames;
const buttonLabel = this.state.selected ? this.state.selected.label : this.props.defaultText;
const iconClasses = classNames(icon, {
[iconOpen]: this.state.isOpen && iconOpen !== null
});
return /*#__PURE__*/_jsxs("div", {
className: `${this.props.className} common__select-box`,
"data-test-id": this.props.testId,
children: [/*#__PURE__*/_jsxs("button", {
className: button,
onClick: this.handleOpenList,
"data-test-id": buttonLabel,
type: "button",
"aria-haspopup": true,
"aria-expanded": this.state.isOpen ? true : null,
"aria-controls": buttonLabel,
ref: this.setControlRef,
children: [/*#__PURE__*/_jsx("span", {
className: selection,
children: /*#__PURE__*/_jsx(I18n.Text, {
string: buttonLabel
})
}), /*#__PURE__*/_jsx("div", {
className: iconClasses,
children: /*#__PURE__*/_jsx(Icon, {})
})]
}), /*#__PURE__*/_jsx(Dropdown, {
className: dropdown,
isOpen: this.state.isOpen,
duration: this.props.duration,
children: /*#__PURE__*/_jsx("ul", {
role: "menu",
id: buttonLabel,
tabIndex: "-1",
children: this.props.items.map(item => /*#__PURE__*/_jsx(SelectBoxItem, {
classNames: {
selectItem,
selectItemSelected
},
wrapper: this.props.item,
value: item.value,
label: item.label,
handleSelectionUpdate: this.handleSelectionUpdate,
isSelected: buttonLabel === item.label,
forwardedRef: buttonLabel === item.label ? this.setFirstItemRef : null
}, item.value))
})
}), this.state.isOpen && /*#__PURE__*/_jsx("button", {
className: styles.overlay,
onClick: this.handleInteractionOutside,
onTouchMove: this.handleInteractionOutside,
type: "button",
"aria-hidden": true
})]
});
};
return SelectBox;
}(Component);
SelectBox.defaultProps = {
className: '',
classNames: {},
duration: 225,
defaultText: 'filter.sort.default',
handleSelectionUpdate: () => {},
initialValue: null,
testId: null
};
export default SelectBox;