@vtex/styleguide
Version:
> VTEX Styleguide React components ([Docs](https://vtex.github.io/styleguide))
352 lines (287 loc) • 12.6 kB
JavaScript
"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));