UNPKG

@helpscout/hsds-react

Version:

React component library for Help Scout's Design System

500 lines (403 loc) 16.5 kB
"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;