wix-style-react
Version:
439 lines (332 loc) • 19.2 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _defaultTo = _interopRequireDefault(require("lodash/defaultTo"));
var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
var _sortBy = _interopRequireDefault(require("lodash/sortBy"));
var _propTypes = require("../utils/propTypes");
var _InputWithOptions2 = _interopRequireDefault(require("../InputWithOptions"));
var _DropdownSt = require("./Dropdown.st.css");
var _propTypes2 = _interopRequireDefault(require("prop-types"));
var _DropdownLayout = require("../DropdownLayout/DropdownLayout");
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
var NO_SELECTED_ID = null;
var Dropdown = /*#__PURE__*/function (_InputWithOptions) {
(0, _inherits2["default"])(Dropdown, _InputWithOptions);
var _super = _createSuper(Dropdown);
function Dropdown(props) {
var _this;
(0, _classCallCheck2["default"])(this, Dropdown);
_this = _super.call(this, props);
_this.state = _objectSpread({
value: '',
selectedId: NO_SELECTED_ID
}, Dropdown.getNextState(props, (0, _defaultTo["default"])(props.selectedId, props.initialSelectedId)));
return _this;
}
(0, _createClass2["default"])(Dropdown, [{
key: "isSelectedIdControlled",
value: function isSelectedIdControlled() {
return typeof this.props.selectedId !== 'undefined';
}
}, {
key: "getSelectedId",
value: function getSelectedId() {
return this.isSelectedIdControlled() ? this.props.selectedId : this.state.selectedId;
}
}, {
key: "_onInputClicked",
value: function _onInputClicked(event) {
if (this.props.onInputClicked) {
this.props.onInputClicked(event);
}
if (this.props.readOnly) {
return;
}
if (this.state.showOptions && Date.now() - this.state.lastOptionsShow > 200) {
this.hideOptions();
} else {
this.showOptions();
}
}
/**
* Updates the value by the selectedId.
* If selectedId is not found in options, then value is NOT changed.
*/
}, {
key: "UNSAFE_componentWillReceiveProps",
value: function UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.selectedId !== this.props.selectedId || !Dropdown.isOptionsEqual(this.props.options, nextProps.options)) {
this.setState(Dropdown.getNextState(nextProps, nextProps.selectedId, this.state.selectedId));
}
}
}, {
key: "inputClasses",
value: function inputClasses() {
var noBorder = this.props.noBorder;
return (0, _DropdownSt.st)(_DropdownSt.classes.showPointer, {
noBorder: noBorder
});
}
}, {
key: "dropdownAdditionalProps",
value: function dropdownAdditionalProps() {
return {
selectedId: this.getSelectedId(),
value: this.state.value,
tabIndex: -1,
withArrow: false
};
}
}, {
key: "inputAdditionalProps",
value: function inputAdditionalProps() {
return {
disableEditing: true,
value: this.state.value
};
}
}, {
key: "_onSelect",
value: function _onSelect(option) {
if (!this.isSelectedIdControlled()) {
this.setState({
value: this.props.valueParser(option),
selectedId: option.id
});
}
(0, _get2["default"])((0, _getPrototypeOf2["default"])(Dropdown.prototype), "_onSelect", this).call(this, option);
}
}, {
key: "_onChange",
value: function _onChange(event) {
this.setState({
value: event.target.value
});
(0, _get2["default"])((0, _getPrototypeOf2["default"])(Dropdown.prototype), "_onChange", this).call(this, event);
}
}], [{
key: "isOptionsEqual",
value: function isOptionsEqual(optionsA, optionsB) {
return (0, _isEqual["default"])((0, _sortBy["default"])(optionsA, 'id'), (0, _sortBy["default"])(optionsB, 'id'));
}
}, {
key: "getNextState",
value: function getNextState(props, selectedId) {
if (typeof selectedId !== 'undefined') {
var option = props.options.find(function (_option) {
return _option.id === selectedId;
});
if (option) {
var value = props.valueParser(option) || '';
return {
value: value,
selectedId: selectedId
};
}
}
return {
value: '',
selectedId: NO_SELECTED_ID
};
}
}]);
return Dropdown;
}(_InputWithOptions2["default"]);
Dropdown.propTypes = {
/** An initial selected option id. (Implies Uncontrolled mode) */
initialSelectedId: _propTypes2["default"].oneOfType([_propTypes2["default"].string, _propTypes2["default"].number]),
/** Associate a control with the regions that it controls. */
ariaControls: _propTypes2["default"].string,
/** Associate a region with its descriptions. Similar to aria-controls but instead associating descriptions to the region and description identifiers are separated with a space. */
ariaDescribedby: _propTypes2["default"].string,
/** Define a string that labels the current element in case where a text label is not visible on the screen. */
ariaLabel: _propTypes2["default"].string,
/** Focus the element on mount (standard React input autoFocus). */
autoFocus: _propTypes2["default"].bool,
/** Select the entire text of the element on focus (standard React input autoSelect). */
autoSelect: _propTypes2["default"].bool,
/** Control the border style of input. */
border: _propTypes2["default"].oneOf(['standard', 'round', 'bottomLine']),
/** Specifies a CSS class name to be appended to the component’s root element. */
className: _propTypes2["default"].string,
/** Displays clear button (X) on a non-empty input. */
clearButton: _propTypes2["default"].bool,
/** Closes DropdownLayout when option is selected. */
closeOnSelect: _propTypes2["default"].bool,
/** Render a custom input component instead of the default html input tag. */
customInput: _propTypes2["default"].node,
/** Applies a data-hook HTML attribute that can be used in the tests. */
dataHook: _propTypes2["default"].string,
/** Specifies whether input should be disabled or not. */
disabled: _propTypes2["default"].bool,
/** Restricts input editing. */
disableEditing: _propTypes2["default"].bool,
/** Sets the offset of the dropdown from the left in pixels. */
dropdownOffsetLeft: _propTypes2["default"].string,
/** Sets the width of the dropdown in pixels. */
dropdownWidth: _propTypes2["default"].string,
/** Adds a fixed footer container at the bottom of options list in `<DropdownLayout/>`. */
fixedFooter: _propTypes2["default"].node,
/** Adds a fixed header container at the top of options list in `<DropdownLayout/>`. */
fixedHeader: _propTypes2["default"].node,
/** Highlights and scrolls view to the specified option when dropdown layout is opened. It does not select the specified option. */
focusOnOption: _propTypes2["default"].oneOfType([_propTypes2["default"].string, _propTypes2["default"].number]),
/** Scrolls view to the selected option when dropdown layout is opened. */
focusOnSelectedOption: _propTypes2["default"].bool,
/** USED FOR TESTING. Forces focus state on the input. */
forceFocus: _propTypes2["default"].bool,
/** USED FOR TESTING. Forces hover state on the input. */
forceHover: _propTypes2["default"].bool,
/** Specifies whether there are more items to be loaded. */
hasMore: _propTypes2["default"].bool,
/** Specifies whether status suffix should be hidden. */
hideStatusSuffix: _propTypes2["default"].bool,
/** Assigns an unique identifier for the root element. */
id: _propTypes2["default"].string,
/** Specifies whether `<DropdownLayout/>` is in a container component. If true, some styles such as shadows, positioning and padding will be added to the component contentContainer. */
inContainer: _propTypes2["default"].bool,
/** Specifies whether lazy loading of the dropdown layout items is enabled. */
infiniteScroll: _propTypes2["default"].bool,
/** Allows to render a custom input component instead of the default `<Input/>`. */
inputElement: _propTypes2["default"].element,
/** Defines a callback function which is called on a request to render more list items. */
loadMore: _propTypes2["default"].func,
/** Sets the default hover behavior:
* - `false` - no initially hovered list item
* - `true` - hover first selectable option
* - any `number/string` specify the id of an option to be hovered
*/
markedOption: _propTypes2["default"].oneOfType([_propTypes2["default"].bool, _propTypes2["default"].string, _propTypes2["default"].number]),
/** Sets the maximum height of the dropdownLayout in pixels. */
maxHeightPixels: _propTypes2["default"].oneOfType([_propTypes2["default"].string, _propTypes2["default"].number]),
/** Specifies whether input should have a dropdown menu arrow on the right side. */
menuArrow: _propTypes2["default"].bool,
/** Sets a minimum value of an input. Similar to HTML5 min attribute. */
min: _propTypes2["default"].number,
/** Sets the minimum width of dropdownLayout in pixels. */
minWidthPixels: _propTypes2["default"].oneOfType([_propTypes2["default"].string, _propTypes2["default"].number]),
/** Reference element data when a form is submitted. */
name: _propTypes2["default"].string,
/** Render options list via native select element. */
"native": _propTypes2["default"].bool,
/** Specifies whether input shouldn’t have rounded corners on its left. */
noLeftBorderRadius: _propTypes2["default"].bool,
/** Specifies whether input shouldn’t have rounded corners on its right. */
noRightBorderRadius: _propTypes2["default"].bool,
/** Defines a standard input onBlur callback */
onBlur: _propTypes2["default"].func,
/** Displays clear button (X) on a non-empty input and calls a callback function with no arguments. */
onClear: _propTypes2["default"].func,
/** Defines a callback function which is called whenever the user presses the escape key. */
onClose: _propTypes2["default"].func,
/** Defines a standard input onChange callback. */
onChange: _propTypes2["default"].func,
/** Defines a callback function called on compositionstart/compositionend events. */
onCompositionChange: _propTypes2["default"].func,
/** Defines a callback handler that is called when user presses -enter-. */
onEnterPressed: _propTypes2["default"].func,
/** Defines a callback handler that is called when user presses -escape- */
onEscapePressed: _propTypes2["default"].func,
/** Defines a standard input onFocus callback. */
onFocus: _propTypes2["default"].func,
/** Defines a standard input onClick callback. */
onInputClicked: _propTypes2["default"].func,
/** Defines a standard input onKeyDown callback. */
onKeyDown: _propTypes2["default"].func,
/** Defines a standard input onKeyUp callback. */
onKeyUp: _propTypes2["default"].func,
/** Defines a callback function which is called when user performs a submit action. Submit action triggers are:
* "Enter", "Tab", [typing any defined delimiters], paste action.
* `onManuallyInput(values: Array<string>): void - The array of strings is the result of splitting the input value by the given delimiters */
onManuallyInput: _propTypes2["default"].func,
/** Defines a callback function which is called whenever the user enters dropdown layout with the mouse cursor. */
onMouseEnter: _propTypes2["default"].func,
/** Defines a callback function which is called whenever the user exits from dropdown layout with a mouse cursor. */
onMouseLeave: _propTypes2["default"].func,
/** Defines a callback function which is called whenever an option becomes focused (hovered/active). Receives the relevant option object from the original props.options array. */
onOptionMarked: _propTypes2["default"].func,
/** Defines a callback function which is called when options dropdown is hidden. */
onOptionsHide: _propTypes2["default"].func,
/** Defines a callback function which is called when options dropdown is shown. */
onOptionsShow: _propTypes2["default"].func,
/** Defines a callback function which is called whenever user selects a different option in the list. */
onSelect: _propTypes2["default"].func,
/** Array of objects:
* - `id <string / number>` *required*: the id of the option, should be unique;
* - value `<function / string / node>` *required*: can be a string, react element or a builder function;
* - disabled `<bool>` *default value- false*: whether this option is disabled or not;
* - linkTo `<string>`: when provided the option will be an anchor to the given value;
* - title `<bool>` *default value- false* **deprecated**: please use `listItemSectionBuilder` for rendering a title;
* - overrideStyle `<bool>` *default value- false* **deprecated**: please use `overrideOptionStyle` for override option styles;
* - overrideOptionStyle `<bool>` *default value- false* - when set to `true`, the option will be responsible to its own styles. No styles will be applied from the DropdownLayout itself;
* - label `<string>`: the string displayed within an input when the option is selected. This is used when using `<DropdownLayout/>` with an `<Input/>`.
*/
options: _propTypes2["default"].arrayOf(_DropdownLayout.optionValidator),
/** Handles container overflow. */
overflow: _propTypes2["default"].string,
/** Sets a placeholder message to display. */
placeholder: _propTypes2["default"].string,
/** Allows to pass all common popover props. */
popoverProps: _propTypes2["default"].shape({
appendTo: _propTypes2["default"].oneOf(['window', 'scrollParent', 'parent', 'viewport']),
maxWidth: _propTypes2["default"].oneOfType([_propTypes2["default"].string, _propTypes2["default"].number]),
minWidth: _propTypes2["default"].oneOfType([_propTypes2["default"].string, _propTypes2["default"].number]),
flip: _propTypes2["default"].bool,
fixed: _propTypes2["default"].bool,
placement: _propTypes2["default"].oneOf(['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start']),
dynamicWidth: _propTypes2["default"].bool
}),
/** Pass a component you want to show as the prefix of the input, e.g., text string, icon. */
prefix: _propTypes2["default"].node,
/** Specifies whether input is read only. */
readOnly: _propTypes2["default"].bool,
/** Flip component horizontally so it would be more suitable to RTL. */
rtl: _propTypes2["default"].bool,
/** Specifies whether selected option will be highlighted when dropdown is reopened. */
selectedHighlight: _propTypes2["default"].bool,
/** Specifies selected option by its id. */
selectedId: _propTypes2["default"].oneOfType([_propTypes2["default"].string, _propTypes2["default"].number]),
/** Controls whether to show options if input is empty. */
showOptionsIfEmptyInput: _propTypes2["default"].bool,
/** Controls the size of the input */
size: _propTypes2["default"].oneOf(['small', 'medium', 'large']),
/** Specify the status of a field. */
status: _propTypes2["default"].oneOf(['error', 'warning', 'loading']),
/** Defines the message to display on status icon hover. If not given or empty there will be no tooltip. */
statusMessage: _propTypes2["default"].node,
/** Pass a component you want to show as the suffix of the input, e.g., text string, icon. */
suffix: _propTypes2["default"].node,
/** Indicates that element can be focused and where it participates in sequential keyboard navigation. */
tabIndex: _propTypes2["default"].number,
/** Handles text overflow behavior. It can either clip (default) or display ellipsis. */
textOverflow: _propTypes2["default"].string,
/** Controls placement of a status tooltip. */
tooltipPlacement: _propTypes2["default"].string,
/** Specifies whether component should be shown or hidden. */
visible: _propTypes2["default"].bool
};
(0, _propTypes.extendPropTypes)(Dropdown, {
selectedId: (0, _propTypes.allValidators)(_propTypes2["default"].oneOfType([_propTypes2["default"].string, _propTypes2["default"].number]), function (props, propName) {
if (props[propName] !== undefined && props['initialSelectedId'] !== undefined) {
return new Error("'selectedId' and 'initialSelectedId' cannot both be used at the same time.");
}
})
});
Dropdown.defaultProps = _InputWithOptions2["default"].defaultProps;
Dropdown.displayName = 'Dropdown';
var _default = Dropdown;
exports["default"] = _default;