UNPKG

@vtex/styleguide

Version:

> VTEX Styleguide React components ([Docs](https://vtex.github.io/styleguide))

352 lines (287 loc) 12.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _classnames = require("classnames"); var _classnames2 = _interopRequireDefault(_classnames); var _react = require("react"); var _react2 = _interopRequireDefault(_react); var _propTypes = require("prop-types"); var _propTypes2 = _interopRequireDefault(_propTypes); var _withDeviceHoc = require("../utils/withDeviceHoc"); var _withDeviceHoc2 = _interopRequireDefault(_withDeviceHoc); var _ArrowDownIcon = require("./ArrowDownIcon"); var _ArrowDownIcon2 = _interopRequireDefault(_ArrowDownIcon); var _withForwardedRef = require("../../modules/withForwardedRef"); var _Dropdown = require("./Dropdown.css"); var _Dropdown2 = _interopRequireDefault(_Dropdown); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } var Dropdown = /*#__PURE__*/ function (_Component) { _inheritsLoose(Dropdown, _Component); function Dropdown(props) { var _this; _this = _Component.call(this, props) || this; // The initial value sent to the dropdown is kept in order to know // whether or not to create and keep a first disabled option. // If the initial value is invalid/empty, an empty option is kept // so the select will have an empty state. Otherwise, the first // value would automatically be chosen. // However, you can't select a null/undefined option, so nil values // are transformed to empty string. _this.handleChange = function (e) { var _this$props = _this.props, disabled = _this$props.disabled, onChange = _this$props.onChange; var value = e.target.value; !disabled && onChange && onChange(e, value); }; _this.getOptionFromValue = function (value) { var options = _this.props.options; var option = options.filter(function (option) { return option.value === value; })[0]; if (!option) return null; return option; }; _this.getDropdownIdentification = function () { var _this$props2 = _this.props, label = _this$props2.label, id = _this$props2.id, options = _this$props2.options; if (label) { return "Dropdown with the label \"" + label + "\""; } else if (id) { return "Dropdown #" + id; } return "Dropdown with the options " + options.map(function (option) { return option.label; }).join(', '); }; _this.getPlaceholder = function () { var _this$props3 = _this.props, placeholder = _this$props3.placeholder, label = _this$props3.label, helpText = _this$props3.helpText; var placeholderValue = placeholder || label || helpText || ''; if (placeholderValue === '' && !_this.sentPlaceholderWarning) { var identificationText = _this.getDropdownIdentification(); console.warn("The following dropdown has a placeholder option, but no placeholder text. Please use at least one of these props: placeholder, label, or helpText. " + identificationText); _this.sentPlaceholderWarning = true; } return placeholderValue; }; _this.getSelectedOption = function () { return _this.getOptionFromValue(_this.props.value); }; _this.handleFocus = function () { _this.setState({ active: true }); _this.props.onFocus && _this.props.onFocus(event); }; _this.handleBlur = function () { _this.setState({ active: false }); _this.props.onBlur && _this.props.onBlur(event); }; _this.initialValue = ''; _this.state = { active: false }; return _this; } var _proto = Dropdown.prototype; _proto.getValueLabel = function getValueLabel() { var selectedOption = this.getSelectedOption(); return selectedOption ? selectedOption.label : this.getPlaceholder(); }; _proto.componentDidMount = function componentDidMount() { if (this.props.size === 'x-large') { console.warn('Dropdown: The value "x-large" for the prop "size" is deprecated. In the next major version, it will be equivalent to "large", and removed altogether in future versions'); } }; _proto.render = function render() { var _classNames; var active = this.state.active; var _this$props4 = this.props, label = _this$props4.label, id = _this$props4.id, testId = _this$props4.testId, value = _this$props4.value, size = _this$props4.size, disabled = _this$props4.disabled, options = _this$props4.options, error = _this$props4.error, errorMessage = _this$props4.errorMessage, helpText = _this$props4.helpText, placeholder = _this$props4.placeholder, preventTruncate = _this$props4.preventTruncate, autoFocus = _this$props4.autoFocus, form = _this$props4.form, name = _this$props4.name, required = _this$props4.required, variation = _this$props4.variation, selectTestId = _this$props4.selectTestId, isMobile = _this$props4.isMobile; var hasValidInitialValue = this.getOptionFromValue(this.initialValue) !== null; var valueLabel = this.getValueLabel(); var showCaption = !valueLabel; var isPlaceholder = this.getSelectedOption() === null; var isInline = variation.toLowerCase() === 'inline'; var iconSize = size === 'x-large' ? 22 : 18; var color = isInline ? 'c-link' : 'c-on-base'; var buttonClasses = (0, _classnames2.default)('vtex-dropdown__button bg-transparent bn w-100 h-100', (_classNames = { pointer: !disabled, 'c-disabled': disabled || !valueLabel }, _classNames[color] = !disabled && valueLabel && !isPlaceholder, _classNames['c-muted-2'] = !disabled && valueLabel && isPlaceholder, _classNames.ph2 = isInline && size !== 'x-large', _classNames['pl5 pr3'] = !isInline && size !== 'x-large', _classNames['t-body pv5 ph5'] = size === 'x-large', _classNames)); var rootClasses = (0, _classnames2.default)(_Dropdown2.default.dropdown, 'vtex-dropdown', { 'vtex-dropdown--inline dib': isInline }); var containerClasses = (0, _classnames2.default)(_Dropdown2.default.container, 'vtex-dropdown__container br2 relative', { 'bg-base': !isInline, ba: !isInline, bw1: !isInline || disabled, 'b--disabled bg-disabled': disabled, 'b--danger hover-b--danger': (error || errorMessage) && !disabled, fw5: isInline && !error && !errorMessage && !disabled, 'b--muted-2': active && !isInline && !error && !errorMessage && !disabled, 'hover-b--muted-3 b--muted-4': !active && !isInline && !error && !errorMessage && !disabled, 't-body': size !== 'small' && size !== 'x-large', 'h-auto': isInline && size !== 'x-large', 'h-small': !isInline && size === 'small', 'h-large': !isInline && size === 'large', 'h-regular': !isInline && size !== 'small' && size !== 'large' && size !== 'x-large' }); var selectClasses = (0, _classnames2.default)('o-0 absolute top-0 left-0 h-100 w-100 bottom-0 t-body', { pointer: !disabled }); var labelClasses = (0, _classnames2.default)('vtex-dropdown__label db mb3 w-100 c-on-base', { 't-small': size !== 'large' && size !== 'x-large', 't-body': size === 'large' || size === 'x-large' }); return _react2.default.createElement("div", { className: rootClasses, "data-testid": testId }, _react2.default.createElement("label", { className: "h-100" }, label && _react2.default.createElement("span", { className: labelClasses }, label), _react2.default.createElement("div", { className: containerClasses }, _react2.default.createElement("div", { id: id, className: buttonClasses }, _react2.default.createElement("div", { className: "flex " + (isInline ? '' : 'h-100') }, _react2.default.createElement("div", { className: "vtex-dropdown__caption flex-auto tl truncate " + (isInline ? '' : 'h-100') }, _react2.default.createElement("div", { className: (isInline ? '' : 'h-100') + " flex items-center" }, showCaption ? placeholder : valueLabel)), _react2.default.createElement("div", { className: "vtex-dropdown__arrow flex-none flex items-center pl2 " + (disabled ? 'c-on-disabled' : 'c-action-primary') }, _react2.default.createElement(_ArrowDownIcon2.default, { size: iconSize })))), _react2.default.createElement("select", { "data-testid": selectTestId, disabled: disabled, className: selectClasses, onChange: this.handleChange, onFocus: this.handleFocus, onBlur: this.handleBlur, onMouseEnter: this.props.onMouseEnter, onMouseLeave: this.props.onMouseLeave, ref: this.props.forwardedRef // Check the comment on the constructor regarding nil values , value: value == null ? '' : value, autoFocus: autoFocus, form: form, name: name, required: required, style: { // safari select height fix WebkitAppearance: 'menulist-button' } }, preventTruncate && isMobile && _react2.default.createElement("optgroup", { label: label || helpText || '' }), (!hasValidInitialValue || placeholder) && _react2.default.createElement("option", { disabled: true, value: !hasValidInitialValue ? this.initialValue : null }, this.getPlaceholder()), options.map(function (option) { return _react2.default.createElement("option", { disabled: option.disabled, key: option.value, value: option.value }, option.label); })))), errorMessage && _react2.default.createElement("div", { className: "vtex-dropdown__error c-danger t-small mt3 lh-title" }, errorMessage), helpText && _react2.default.createElement("div", { className: "vtex-dropdown__help-text c-muted-1 t-small mt3 lh-title" }, helpText)); }; return Dropdown; }(_react.Component); Dropdown.defaultProps = { size: 'regular', options: [], variation: 'default' }; Dropdown.propTypes = { /** Error highlight */ error: _propTypes2.default.bool, /** Error message */ errorMessage: _propTypes2.default.node, /** @ignore Forwarded Ref */ forwardedRef: _withForwardedRef.refShape, /** Help text */ helpText: _propTypes2.default.node, /** Dropdown label */ label: _propTypes2.default.node, /** Dropdown placeholder value */ placeholder: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.number]), /** Dropdown size */ size: _propTypes2.default.oneOf(['small', 'regular', 'large']), /** Dropdown options list */ options: _propTypes2.default.arrayOf(_propTypes2.default.shape({ disabled: _propTypes2.default.bool, value: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.number]).isRequired, label: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.number]).isRequired })), /** Prevent truncating large options texts on some devices/browsers, such as iOS */ preventTruncate: _propTypes2.default.bool, /** Spec attribute */ id: _propTypes2.default.string, /** Data attribute */ testId: _propTypes2.default.string, /** Data attribute for select*/ selectTestId: _propTypes2.default.string, /** Spec attribute */ autoFocus: _propTypes2.default.bool, /** Spec attribute */ value: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.string]), /** Spec attribute */ disabled: _propTypes2.default.bool, /** Dropdown variation */ variation: _propTypes2.default.oneOf(['default', 'inline']), /** Spec attribute */ form: _propTypes2.default.string, /** Spec attribute */ name: _propTypes2.default.string, /** Spec attribute */ required: _propTypes2.default.bool, /** onChange event */ onChange: _propTypes2.default.func, /** onFocus event */ onFocus: _propTypes2.default.func, /** onBlur event */ onBlur: _propTypes2.default.func, /** onMouseEnter event */ onMouseEnter: _propTypes2.default.func, /** onMouseLeave event */ onMouseLeave: _propTypes2.default.func, /** @ignore */ isMobile: _propTypes2.default.bool }; exports.default = (0, _withForwardedRef.withForwardedRef)((0, _withDeviceHoc2.default)(Dropdown));