@helpscout/hsds-react
Version:
React component library for Help Scout's Design System
500 lines (403 loc) • 16.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = exports.Select = 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 _getValidProps = _interopRequireDefault(require("@helpscout/react-utils/dist/getValidProps"));
var _Context = _interopRequireDefault(require("../FormLabel/Context"));
var _Input = _interopRequireDefault(require("../Input/Input.BackdropV2"));
var _HelpText = _interopRequireDefault(require("../HelpText"));
var _Label = _interopRequireDefault(require("../Label"));
var _Icon = _interopRequireDefault(require("../Icon"));
var _Tooltip = _interopRequireDefault(require("../Tooltip"));
var _Select = _interopRequireDefault(require("./Select.Arrows"));
var _constants = require("../../constants");
var _classnames = _interopRequireDefault(require("classnames"));
var _id = require("../../utilities/id");
var _lodash = _interopRequireDefault(require("lodash.isstring"));
var _Input2 = require("../Input/Input.css");
var _Select2 = require("./Select.css");
var _jsxRuntime = require("react/jsx-runtime");
/* istanbul ignore file */
/**
***DEPRECATED COMPONENT***
***DEPRECATED COMPONENT***
***DEPRECATED COMPONENT***
*/
function noop() {}
var PLACEHOLDER_VALUE = '__placeholder__';
var uniqueID = (0, _id.createUniqueIDFactory)('Select');
var Select = /*#__PURE__*/function (_React$PureComponent) {
(0, _inheritsLoose2.default)(Select, _React$PureComponent);
function Select(_props) {
var _this;
_this = _React$PureComponent.call(this, _props) || this;
_this.optionClassName = 'c-Select__option';
_this.handleOnChange = function (event) {
var value = event.currentTarget.value;
_this.props.onChange(value);
_this.setState({
value: value
});
};
_this.handleOnBlur = function (event) {
_this.setState({
isFocused: false
});
_this.props.onBlur(event);
};
_this.handleOnFocus = function (event) {
var _this$props = _this.props,
onFocus = _this$props.onFocus,
removeStateStylesOnFocus = _this$props.removeStateStylesOnFocus;
var state = _this.state.state;
if (removeStateStylesOnFocus && state) {
_this.setState({
state: null
});
}
_this.setState({
isFocused: true
});
onFocus(event);
};
_this.getHelpTextMarkup = function () {
var helpText = _this.props.helpText;
return helpText && /*#__PURE__*/(0, _jsxRuntime.jsx)(_HelpText.default, {
className: "c-Select__helpText",
children: helpText
});
};
_this.getHintTextMarkup = function () {
var hintText = _this.props.hintText;
return hintText && /*#__PURE__*/(0, _jsxRuntime.jsx)(_HelpText.default, {
className: "c-Select__hintText",
isCompact: true,
children: hintText
});
};
_this.getLabelMarkup = function () {
var _this$props2 = _this.props,
id = _this$props2.id,
label = _this$props2.label;
return label && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Label.default, {
className: "c-Select__label",
for: id,
children: label
});
};
_this.getPrefixMarkup = function () {
var prefix = _this.props.prefix;
return prefix && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Select2.InlinePrefixSuffixUI, {
className: _this.getInlinePrefixSuffixClassName({
type: 'prefix'
}),
children: prefix
});
};
_this.getErrorMarkup = function () {
var _this$props3 = _this.props,
errorIcon = _this$props3.errorIcon,
errorMessage = _this$props3.errorMessage,
state = _this$props3.state,
_this$props3$tabIndex = _this$props3.tabIndex,
tabIndex = _this$props3$tabIndex === void 0 ? 0 : _this$props3$tabIndex;
var shouldRenderError = state === _constants.STATES.error;
if (!shouldRenderError) return null;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Select2.ItemUI, {
className: (0, _classnames.default)('c-Select__item', 'c-Select__suffix', 'is-icon'),
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
display: "block",
placement: "top-end",
title: errorMessage,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
name: errorIcon,
state: _constants.STATES.error,
className: "c-Select__errorIcon",
tabIndex: tabIndex
})
})
});
};
_this.getPlaceholderMarkup = function () {
var placeholder = _this.props.placeholder;
return placeholder && /*#__PURE__*/(0, _jsxRuntime.jsx)("option", {
className: _this.optionClassName,
label: placeholder,
value: PLACEHOLDER_VALUE,
disabled: true,
children: placeholder
});
};
_this.renderOptions = function (option) {
// HTML <optgroup> only allows for single level nesting
var hasOptions = option.hasOwnProperty('value') && Array.isArray(option.value); // Group
if (!(0, _lodash.default)(option) && hasOptions) {
// Recursion!
return /*#__PURE__*/(0, _jsxRuntime.jsx)("optgroup", {
className: "c-Select__optGroup",
label: option.label,
children: option.value.map(_this.renderOptions)
}, option.label);
} // Option
if ((0, _lodash.default)(option)) {
return /*#__PURE__*/(0, _jsxRuntime.jsx)("option", {
className: _this.optionClassName,
value: option,
children: option
}, option);
} else {
return /*#__PURE__*/(0, _jsxRuntime.jsx)("option", {
className: _this.optionClassName,
value: option.value,
disabled: option.disabled,
children: option.label
}, option.value);
}
};
_this.setSelectNode = function (node) {
_this.selectNode = node;
_this.props.innerRef(node);
};
_this.getSelectMarkup = function (props) {
var _this$props4 = _this.props,
children = _this$props4.children,
className = _this$props4.className,
disabled = _this$props4.disabled,
errorIcon = _this$props4.errorIcon,
errorMessage = _this$props4.errorMessage,
forceAutoFocusTimeout = _this$props4.forceAutoFocusTimeout,
helpText = _this$props4.helpText,
hintText = _this$props4.hintText,
innerRef = _this$props4.innerRef,
isFocused = _this$props4.isFocused,
isFirst = _this$props4.isFirst,
isNotOnly = _this$props4.isNotOnly,
isLast = _this$props4.isLast,
label = _this$props4.label,
onChange = _this$props4.onChange,
onFocus = _this$props4.onFocus,
options = _this$props4.options,
placeholder = _this$props4.placeholder,
prefix = _this$props4.prefix,
removeStateStylesOnFocus = _this$props4.removeStateStylesOnFocus,
seamless = _this$props4.seamless,
size = _this$props4.size,
stateProp = _this$props4.state,
styleProp = _this$props4.style,
success = _this$props4.success,
tabIndex = _this$props4.tabIndex,
value = _this$props4.value,
rest = (0, _objectWithoutPropertiesLoose2.default)(_this$props4, ["children", "className", "disabled", "errorIcon", "errorMessage", "forceAutoFocusTimeout", "helpText", "hintText", "innerRef", "isFocused", "isFirst", "isNotOnly", "isLast", "label", "onChange", "onFocus", "options", "placeholder", "prefix", "removeStateStylesOnFocus", "seamless", "size", "state", "style", "success", "tabIndex", "value"]);
var fieldClassName = (0, _classnames.default)('c-Select__inputField', 'c-InputField', _this.hasPlaceholder() && 'has-placeholder', size && "is-" + size);
var placeholderMarkup = _this.getPlaceholderMarkup();
var optionsMarkup = children || (Array.isArray(options) ? options.map(_this.renderOptions) : _this.renderOptions(options));
var hasPlaceholder = _this.hasPlaceholder();
var id = props.id || _this.state.id;
var selectedValue = hasPlaceholder ? PLACEHOLDER_VALUE : _this.state.value;
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Select2.FieldUI, (0, _extends2.default)({}, (0, _getValidProps.default)(rest), {
className: fieldClassName,
disabled: disabled,
id: id,
onBlur: _this.handleOnBlur,
onChange: _this.handleOnChange,
onFocus: _this.handleOnFocus,
ref: _this.setSelectNode,
value: selectedValue,
children: [placeholderMarkup, optionsMarkup]
}));
};
_this.state = {
id: _props.id || uniqueID(),
isFocused: _props.isFocused,
state: _props.state,
value: _props.value
};
return _this;
}
var _proto = Select.prototype;
_proto.componentDidMount = function componentDidMount() {
this.autoFocus();
};
_proto.UNSAFE_componentWillReceiveProps = function UNSAFE_componentWillReceiveProps(nextProps) {
var isFocused = nextProps.isFocused,
state = nextProps.state;
var prevState = this.state.state;
if (state !== prevState) {
this.setState({
state: state
});
}
if (isFocused) {
this.forceAutoFocus();
}
};
_proto.componentWillUnmount = function componentWillUnmount() {
this.selectNode = null;
};
_proto.autoFocus = function autoFocus() {
var _this$props5 = this.props,
autoFocus = _this$props5.autoFocus,
isFocused = _this$props5.isFocused;
if (autoFocus || isFocused) {
this.forceAutoFocus();
}
};
_proto.forceAutoFocus = function forceAutoFocus() {
var _this2 = this;
var forceAutoFocusTimeout = this.props.forceAutoFocusTimeout;
this.setState({
isFocused: true
});
setTimeout(function () {
if (_this2.selectNode) {
_this2.selectNode.focus();
}
}, forceAutoFocusTimeout);
};
_proto.hasPlaceholder = function hasPlaceholder() {
return this.state.value === '' && this.props.placeholder;
};
_proto.getInlinePrefixSuffixClassName = function getInlinePrefixSuffixClassName(_ref) {
var type = _ref.type,
icon = _ref.icon;
var _this$props6 = this.props,
seamless = _this$props6.seamless,
state = _this$props6.state;
return (0, _classnames.default)('c-Select__item', type && "is-" + type, icon && 'is-icon', seamless && 'is-seamless', state && "is-" + state);
};
_proto.render = function render() {
var _this3 = this;
var _this$props7 = this.props,
className = _this$props7.className,
disabled = _this$props7.disabled,
isFirst = _this$props7.isFirst,
isNotOnly = _this$props7.isNotOnly,
isLast = _this$props7.isLast,
seamless = _this$props7.seamless,
styleProp = _this$props7.style,
width = _this$props7.width;
var _this$state = this.state,
isFocused = _this$state.isFocused,
state = _this$state.state;
var componentClassName = (0, _classnames.default)('c-Select', disabled && 'is-disabled', isFocused && 'is-focused', this.hasPlaceholder() && 'has-placeholder', seamless && 'is-seamless', state && "is-" + state, className);
var helpTextMarkup = this.getHelpTextMarkup();
var hintTextMarkup = this.getHintTextMarkup();
var labelMarkup = this.getLabelMarkup();
var prefixMarkup = this.getPrefixMarkup();
var errorMarkup = this.getErrorMarkup();
var style = (0, _extends2.default)({}, styleProp, {
maxWidth: width
});
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Context.default.Consumer, {
children: function children(props) {
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Input2.InputWrapperUI, {
className: "c-InputWrapper",
style: style,
children: [labelMarkup, hintTextMarkup, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Select2.SelectUI, {
className: componentClassName,
children: [prefixMarkup, _this3.getSelectMarkup(props), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Select.default, {
className: "c-SelectIcon",
state: state
}), errorMarkup, /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input.default, {
className: "c-Select__backdrop",
disabled: disabled,
isFirst: isFirst,
isFocused: isFocused,
isNotOnly: isNotOnly,
isLast: isLast,
isSeamless: seamless,
state: state
})]
}), helpTextMarkup]
});
}
});
};
return Select;
}(_react.default.PureComponent);
exports.Select = Select;
Select.Arrows = _Select.default;
Select.defaultProps = {
autoFocus: false,
'data-cy': 'Select',
disabled: false,
errorIcon: 'alert',
innerRef: noop,
forceAutoFocusTimeout: 120,
onBlur: noop,
onChange: noop,
onFocus: noop,
options: [],
removeStateStylesOnFocus: false,
seamless: false,
value: ''
};
Select.propTypes = {
/** Data attr for Cypress tests. */
'data-cy': _propTypes.default.string,
/** Automatically focuses the select. */
autoFocus: _propTypes.default.bool,
/** Custom class names to be added to the component. */
className: _propTypes.default.string,
/** Disable the select. */
disabled: _propTypes.default.bool,
/** Icon that renders when the state is `error`. */
errorIcon: _propTypes.default.string,
/** Error message that renders into a Tooltip. */
errorMessage: _propTypes.default.string,
/** Determines the amount of time (`ms`) for the component to focus on mount. */
forceAutoFocusTimeout: _propTypes.default.number,
/** Displays text underneath select. */
helpText: _propTypes.default.any,
/** Displays text above select. */
hintText: _propTypes.default.any,
/** ID for the select. */
id: _propTypes.default.string,
/** Retrieves the `input` DOM node. */
innerRef: _propTypes.default.func,
/** Determines if the component is focused. */
isFocused: _propTypes.default.bool,
isNotOnly: _propTypes.default.bool,
isLast: _propTypes.default.bool,
isFirst: _propTypes.default.bool,
/** Label for the select. */
label: _propTypes.default.any,
/** Name for the select. */
name: _propTypes.default.string,
/** Callback when select is blurred. */
onBlur: _propTypes.default.func,
/** Callback when select value is changed. */
onChange: _propTypes.default.func,
/** Callback when select is focused. */
onFocus: _propTypes.default.func,
/** Array of options with the shape: { disabled: PropTypes.bool, label: PropTypes.string, value: PropTypes.string } */
options: _propTypes.default.oneOfType([_propTypes.default.arrayOf(_propTypes.default.any), _propTypes.default.object, _propTypes.default.string, _propTypes.default.number]),
/** Placeholder text for the select. */
placeholder: _propTypes.default.string,
/** Text to appear before the select. */
prefix: _propTypes.default.string,
/** Disable editing of the select. */
readOnly: _propTypes.default.bool,
/** Removes the `state` styles on input focus. Default `false`. */
removeStateStylesOnFocus: _propTypes.default.bool,
/** Removes the border around the select. */
seamless: _propTypes.default.bool,
/** Determines the size of the select. */
size: _propTypes.default.oneOf(['xs', 'xssm', 'sm', 'md', 'lg', '', null]),
/** Change select to state color. */
state: _propTypes.default.oneOf(['error', 'info', 'success', 'warning', '', null]),
/** Text to appear after the select. */
suffix: _propTypes.default.string,
/** Initial value of the select. */
value: _propTypes.default.string,
success: _propTypes.default.bool,
tabIndex: _propTypes.default.number,
width: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string])
};
var _default = Select;
exports.default = _default;