@helpscout/hsds-react
Version:
React component library for Help Scout's Design System
300 lines (233 loc) • 10.1 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose"));
var _react = _interopRequireDefault(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _classnames = _interopRequireDefault(require("classnames"));
var _lodash = _interopRequireDefault(require("lodash.isnil"));
var _lodash2 = _interopRequireDefault(require("lodash.get"));
var _getValidProps = _interopRequireDefault(require("@helpscout/react-utils/dist/getValidProps"));
var _ChoiceGroup = _interopRequireDefault(require("./ChoiceGroup.Context"));
var _FormGroup = _interopRequireDefault(require("../FormGroup"));
var _Context = _interopRequireDefault(require("../FormLabel/Context"));
var _id = require("../../utilities/id");
var _ChoiceGroup2 = require("./ChoiceGroup.css");
var _jsxRuntime = require("react/jsx-runtime");
function noop() {}
var uniqueID = (0, _id.createUniqueIDFactory)('ChoiceGroup');
var ChoiceGroup = /*#__PURE__*/function (_React$Component) {
(0, _inheritsLoose2.default)(ChoiceGroup, _React$Component);
function ChoiceGroup(_props) {
var _this;
_this = _React$Component.call(this, _props) || this;
_this.getMultiSelectValue = function (value, checked) {
var selectedValue = _this.state.selectedValue;
var valueIndex = selectedValue.indexOf(value);
if (valueIndex < 0 && checked) {
return selectedValue.concat(value);
}
return selectedValue.filter(function (v) {
return v !== value;
});
};
_this.getSingleSelectValue = function (value, checked) {
return checked ? value : [];
};
_this.getSelectLimitState = function (props, selectedValue) {
var multiSelect = props.multiSelect,
multiSelectLimit = props.multiSelectLimit;
return multiSelect && !(0, _lodash.default)(multiSelectLimit) && multiSelectLimit > 0 && selectedValue.length === multiSelectLimit;
};
_this.handleOnChange = function (value, checked) {
var _this$props = _this.props,
multiSelect = _this$props.multiSelect,
onChange = _this$props.onChange;
var selectedValue = multiSelect ? _this.getMultiSelectValue(value, checked) : _this.getSingleSelectValue(value, checked);
var limitReached = _this.getSelectLimitState(_this.props, selectedValue);
_this.setState({
selectedValue: selectedValue,
limitReached: limitReached
});
onChange(selectedValue);
};
_this.handleOnEnter = function (value, checked) {
var _this$props2 = _this.props,
multiSelect = _this$props2.multiSelect,
onEnter = _this$props2.onEnter,
onChange = _this$props2.onChange;
var selectedValue = multiSelect ? _this.getMultiSelectValue(value, checked) : _this.getSingleSelectValue(value, checked);
var limitReached = _this.getSelectLimitState(_this.props, selectedValue);
_this.setState({
selectedValue: selectedValue,
limitReached: limitReached
});
onEnter(selectedValue);
onChange(selectedValue);
};
_this.getContextProps = function () {
var _this$props3 = _this.props,
onBlur = _this$props3.onBlur,
onFocus = _this$props3.onFocus,
name = _this$props3.name;
var selectedValue = _this.state.selectedValue;
return {
onBlur: onBlur,
onChange: _this.handleOnChange,
onEnter: _this.handleOnEnter,
onFocus: onFocus,
name: name,
selectedValue: selectedValue
};
};
_this.getChildrenMarkup = function () {
var _this$props4 = _this.props,
isResponsive = _this$props4.isResponsive,
choiceMaxWidth = _this$props4.choiceMaxWidth,
choiceHeight = _this$props4.choiceHeight,
children = _this$props4.children;
var _this$state = _this.state,
id = _this$state.id,
selectedValue = _this$state.selectedValue,
limitReached = _this$state.limitReached;
return children && _react.default.Children.map(children, function (child, index) {
var key = (0, _lodash2.default)(child, 'props.id') || id + "-" + index;
var isSelected = selectedValue.includes(child.props.value);
var disabled = (0, _lodash2.default)(child, 'props.disabled') || limitReached && !isSelected;
var clone = /*#__PURE__*/_react.default.isValidElement(child) ? /*#__PURE__*/_react.default.cloneElement(child, {
checked: isSelected,
disabled: disabled,
maxWidth: choiceMaxWidth,
height: choiceHeight
}) : child;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_FormGroup.default.Choice, {
isResponsive: isResponsive,
children: clone
}, key);
});
};
_this.getIdFromContextProps = function (props) {
return props.id || _this.state.id;
};
var _selectedValue = _this.getInitialSelectedValue(_props);
_this.state = {
id: uniqueID(),
selectedValue: _selectedValue,
limitReached: _this.getSelectLimitState(_props, _selectedValue)
};
return _this;
}
var _proto = ChoiceGroup.prototype;
_proto.UNSAFE_componentWillReceiveProps = function UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.value !== this.props.value) {
this.setState({
selectedValue: this.getInitialSelectedValue(nextProps)
});
}
};
_proto.getInitialSelectedValue = function getInitialSelectedValue(props) {
var value = props.value,
multiSelect = props.multiSelect,
multiSelectLimit = props.multiSelectLimit;
var selectedValue = value ? [].concat(value) : [];
/** When multiSelect is not enabled and we get a value prop with more
* than one item, take the first and ignore the rest
*/
if (!multiSelect && selectedValue.length > 1) {
selectedValue = selectedValue[0];
}
/** When multiselec is enabled and we have a limit, make sure
* we return a selectedValue array with no more items than said limit
*/
if (!(0, _lodash.default)(multiSelectLimit) && multiSelectLimit > 0) {
selectedValue = selectedValue.slice(0, multiSelectLimit);
}
return selectedValue;
};
_proto.render = function render() {
var _this2 = this;
var _this$props5 = this.props,
align = _this$props5.align,
className = _this$props5.className,
children = _this$props5.children,
isResponsive = _this$props5.isResponsive,
onBlur = _this$props5.onBlur,
onChange = _this$props5.onChange,
onFocus = _this$props5.onFocus,
onEnter = _this$props5.onEnter,
multiSelect = _this$props5.multiSelect,
name = _this$props5.name,
rest = (0, _objectWithoutPropertiesLoose2.default)(_this$props5, ["align", "className", "children", "isResponsive", "onBlur", "onChange", "onFocus", "onEnter", "multiSelect", "name"]);
var _this$state2 = this.state,
limitReached = _this$state2.limitReached,
selectedValue = _this$state2.selectedValue;
var componentClassName = (0, _classnames.default)('c-ChoiceGroup', align && "is-align-" + align, multiSelect && 'is-multi-select', isResponsive && 'is-responsive', limitReached && 'limit-reached', hasSelectedValue(selectedValue) && 'has-selected-value', className);
var childrenMarkup = this.getChildrenMarkup();
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Context.default.Consumer, {
children: function children(props) {
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ChoiceGroup.default.Provider, {
value: _this2.getContextProps(),
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ChoiceGroup2.ChoiceGroupUI, (0, _extends2.default)({}, (0, _getValidProps.default)(rest), {
className: componentClassName,
id: _this2.getIdFromContextProps(props),
children: childrenMarkup
}))
});
}
});
};
return ChoiceGroup;
}(_react.default.Component);
function hasSelectedValue(value) {
if (Array.isArray(value)) {
return value.length > 0;
}
if (!(0, _lodash.default)(value)) {
return true;
}
return false;
}
ChoiceGroup.defaultProps = {
align: 'vertical',
'data-cy': 'ChoiceGroup',
isResponsive: false,
onBlur: noop,
onChange: noop,
onFocus: noop,
onEnter: noop,
multiSelect: true
};
ChoiceGroup.propTypes = {
align: _propTypes.default.oneOf(['horizontal', 'vertical']),
/** Custom class names to be added to the component. */
className: _propTypes.default.string,
/** Set the max-width for the child `Choice` components. */
choiceMaxWidth: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
/** Disable the input. */
disabled: _propTypes.default.bool,
/** Enables responsive styling. */
isResponsive: _propTypes.default.bool,
/** Allow multiple choice selection */
multiSelect: _propTypes.default.bool,
/** Limit of selections allowed when multiSelect enabled */
multiSelectLimit: _propTypes.default.number,
/** Name for the inputs. */
name: _propTypes.default.string,
/** Callback when an input is blurred. */
onBlur: _propTypes.default.func,
/** Callback when an input value is changed. */
onChange: _propTypes.default.func,
/** Callback when an input is focused. */
onFocus: _propTypes.default.func,
/** Callback when an enter or espace is pressed. */
onEnter: _propTypes.default.func,
/** The default value of input group. */
value: _propTypes.default.any,
/** Data attr for Cypress tests. */
'data-cy': _propTypes.default.string
};
var _default = ChoiceGroup;
exports.default = _default;