wix-style-react
Version:
605 lines (484 loc) • 25.7 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
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 _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireWildcard(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _InputSt = require("./Input.st.css");
var _InputContext = require("./InputContext");
var _constants = require("./constants");
var _constants2 = require("../StatusIndicator/constants.js");
var _Ticker = _interopRequireDefault(require("./Ticker"));
var _IconAffix = _interopRequireDefault(require("./IconAffix"));
var _Affix = _interopRequireDefault(require("./Affix"));
var _Group = _interopRequireDefault(require("./Group"));
var _InputSuffix = _interopRequireWildcard(require("./InputSuffix"));
var _deprecationLog = _interopRequireDefault(require("../utils/deprecationLog"));
var _excluded = ["customInput", "ref"],
_excluded2 = ["className"];
var _clearButtonSizeMap;
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
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 clearButtonSizeMap = (_clearButtonSizeMap = {}, (0, _defineProperty2["default"])(_clearButtonSizeMap, _constants.SIZES.small, 'small'), (0, _defineProperty2["default"])(_clearButtonSizeMap, _constants.SIZES.medium, 'medium'), (0, _defineProperty2["default"])(_clearButtonSizeMap, _constants.SIZES.large, 'medium'), _clearButtonSizeMap);
var Input = /*#__PURE__*/function (_Component) {
(0, _inherits2["default"])(Input, _Component);
var _super = _createSuper(Input);
function Input(_props) {
var _this;
(0, _classCallCheck2["default"])(this, Input);
_this = _super.call(this, _props);
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_onCompositionChange", function (isComposing) {
if (_this.props.onCompositionChange) {
_this.props.onCompositionChange(isComposing);
}
_this.isComposing = isComposing;
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_extractRef", function (ref) {
var inputRef = _this.props.inputRef;
_this.input = ref;
if (inputRef) {
inputRef(ref);
}
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_handleSuffixOnClear", function (event) {
var focusOnClearClick = _this.props.focusOnClearClick;
focusOnClearClick && _this.focus();
_this.clear(event);
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_onFocus", function (event) {
var onFocus = _this.props.onFocus;
_this._isMounted && _this.setState({
focus: true
});
onFocus && onFocus(event);
if (_this.props.autoSelect) {
// Set timeout is needed here since onFocus is called before react
// gets the reference for the input (specifically when autoFocus
// is on. So setTimeout ensures we have the ref.input needed in select)
setTimeout(function () {
/**
here we trying to cover edge case with chrome forms autofill,
after user will trigger chrome form autofill, onFocus will be called for each input,
each input will cause this.select, select may(mostly all time) cause new onFocus,
which will cause new this.select, ..., we have recursion which will all time randomly cause
inputs to become focused.
To prevent this, we check, that current input node is equal to focused node.
*/
if (document && document.activeElement === _this.input) {
_this.select();
}
}, 0);
}
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_onBlur", function (event) {
_this.setState({
focus: false
});
if (_this.props.onBlur) {
_this.props.onBlur(event);
}
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_onClick", function (event) {
_this.props.onInputClicked && _this.props.onInputClicked(event);
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_onKeyDown", function (event) {
if (_this.isComposing) {
return;
}
var _this$props = _this.props,
onKeyDown = _this$props.onKeyDown,
onEnterPressed = _this$props.onEnterPressed,
onEscapePressed = _this$props.onEscapePressed; // On key event
onKeyDown && onKeyDown(event); // Enter
if (event.key === 'Enter' || event.keyCode === 13) {
onEnterPressed && onEnterPressed(event);
} // Escape
if (event.key === 'Escape' || event.keyCode === 27) {
onEscapePressed && onEscapePressed(event);
}
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_isValidInput", function (value) {
var type = _this.props.type;
if (type === 'number') {
/*
* Limit our number input to contain only:
* - \d - digits
* - . - a dot
* - , - a comma
* - \- - a hyphen minus
* - + - a plus sign
*/
return /^[\d.,\-+]*$/.test(value);
}
return true;
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_onChange", function (event) {
var onChange = _this.props.onChange;
if (_this._isValidInput(event.target.value)) {
onChange && onChange(event);
}
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_onKeyPress", function (event) {
if (!_this._isValidInput(event.target.value + event.key)) {
event.preventDefault();
}
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "_renderInput", function (props) {
var CustomInputComponent = props.customInput,
ref = props.ref,
rest = (0, _objectWithoutProperties2["default"])(props, _excluded);
var inputProps = _objectSpread({}, CustomInputComponent ? _objectSpread(_objectSpread({
ref: ref
}, rest), {}, {
'data-hook': 'wsr-custom-input'
}) : _objectSpread({
ref: ref
}, rest));
return /*#__PURE__*/_react["default"].cloneElement(CustomInputComponent ? /*#__PURE__*/_react["default"].createElement(CustomInputComponent, null) : /*#__PURE__*/_react["default"].createElement("input", null), inputProps);
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "focus", function () {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_this.input && _this.input.focus(options);
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "blur", function () {
_this.input && _this.input.blur();
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "select", function () {
_this.input && _this.input.select();
});
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "clear", function (event) {
var onClear = _this.props.onClear;
if (!_this._isControlled) {
_this.input.value = '';
}
onClear && onClear(event);
});
_this._isMounted = false;
if (_props.size === 'normal') {
(0, _deprecationLog["default"])('<Input/> - change prop size="normal" to size="medium"');
} // TODO - deprecate (in a separate PR)
// if (props.roundInput) {
// deprecationLog(
// '<Input/> - roundInput prop is deprecated and will be removed in next major release, please use border prop instead',
// );
// }
_this.state = {
focus: false
};
return _this;
}
(0, _createClass2["default"])(Input, [{
key: "componentDidMount",
value: function componentDidMount() {
this._isMounted = true;
var _this$props2 = this.props,
autoFocus = _this$props2.autoFocus,
value = _this$props2.value;
autoFocus && this._onFocus();
/*
* autoFocus doesn't automatically selects text like focus do.
* Therefore we set the selection range, but in order to support prior implementation we set the start position as the end in order to place the cursor there.
*/
if (autoFocus && !!value) {
this.input.setSelectionRange(value.length, value.length);
}
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
this._isMounted = false;
}
}, {
key: "_isClearFeatureEnabled",
get: function get() {
var _this$props3 = this.props,
onClear = _this$props3.onClear,
clearButton = _this$props3.clearButton;
return !!onClear || !!clearButton;
}
}, {
key: "_isControlled",
get: function get() {
var value = this.props.value;
return value !== undefined;
}
}, {
key: "render",
value: function render() {
var _this2 = this;
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var _this$props4 = this.props,
id = _this$props4.id,
name = _this$props4.name,
value = _this$props4.value,
placeholder = _this$props4.placeholder,
menuArrow = _this$props4.menuArrow,
defaultValue = _this$props4.defaultValue,
tabIndex = _this$props4.tabIndex,
autoFocus = _this$props4.autoFocus,
onKeyUp = _this$props4.onKeyUp,
onPaste = _this$props4.onPaste,
disableEditing = _this$props4.disableEditing,
readOnly = _this$props4.readOnly,
prefix = _this$props4.prefix,
suffix = _this$props4.suffix,
type = _this$props4.type,
maxLength = _this$props4.maxLength,
textOverflow = _this$props4.textOverflow,
disabled = _this$props4.disabled,
status = _this$props4.status,
statusMessage = _this$props4.statusMessage,
tooltipPlacement = _this$props4.tooltipPlacement,
autocomplete = _this$props4.autocomplete,
min = _this$props4.min,
max = _this$props4.max,
step = _this$props4.step,
required = _this$props4.required,
hideStatusSuffix = _this$props4.hideStatusSuffix,
customInput = _this$props4.customInput,
pattern = _this$props4.pattern,
size = _this$props4.size;
var onIconClicked = function onIconClicked(event) {
if (!disabled) {
_this2.input && _this2.input.focus();
_this2._onClick(event);
}
}; // this doesn't work for uncontrolled, "value" refers only to controlled input
var isClearButtonVisible = this._isClearFeatureEnabled && !!value && !disabled;
var showSuffix = !hideStatusSuffix && Object.values(_constants2.STATUS).includes(status);
var visibleSuffixCount = (0, _InputSuffix.getVisibleSuffixCount)({
status: showSuffix,
statusMessage: statusMessage,
disabled: disabled,
isClearButtonVisible: isClearButtonVisible,
menuArrow: menuArrow,
suffix: suffix
}); // Aria Attributes
var ariaAttribute = {};
Object.keys(this.props).filter(function (key) {
return key.startsWith('aria');
}).map(function (key) {
return ariaAttribute['aria-' + key.substr(4).toLowerCase()] = _this2.props[key];
});
/* eslint-disable no-unused-vars */
var className = props.className,
inputElementProps = (0, _objectWithoutProperties2["default"])(props, _excluded2);
var inputElement = this._renderInput(_objectSpread(_objectSpread({
min: min,
max: max,
step: step,
'data-hook': 'wsr-input',
style: {
textOverflow: textOverflow
},
ref: this._extractRef,
className: _InputSt.classes.input,
id: id,
name: name,
disabled: disabled,
defaultValue: defaultValue,
value: value,
onChange: this._onChange,
onKeyPress: this._onKeyPress,
maxLength: maxLength,
onFocus: this._onFocus,
onBlur: this._onBlur,
onWheel: function onWheel() {
// Although it's opposed to the native behavior, we decided to blur an input type="number" on wheel event in order to prevent change in value.
if (type === 'number') _this2.blur();
},
onKeyDown: this._onKeyDown,
onPaste: onPaste,
placeholder: placeholder,
tabIndex: tabIndex,
autoFocus: autoFocus,
onClick: this._onClick,
onKeyUp: onKeyUp,
readOnly: readOnly || disableEditing,
type: type,
required: required,
autoComplete: autocomplete,
onCompositionStart: function onCompositionStart() {
return _this2._onCompositionChange(true);
},
onCompositionEnd: function onCompositionEnd() {
return _this2._onCompositionChange(false);
},
customInput: customInput,
pattern: pattern
}, ariaAttribute), inputElementProps));
return /*#__PURE__*/_react["default"].createElement("div", {
className: _InputSt.classes.wrapper
}, prefix && /*#__PURE__*/_react["default"].createElement(_InputContext.InputContext.Provider, {
value: _objectSpread(_objectSpread({}, this.props), {}, {
inPrefix: true
})
}, prefix), inputElement, /*#__PURE__*/_react["default"].createElement(_InputContext.InputContext.Provider, {
value: _objectSpread(_objectSpread({}, this.props), {}, {
inSuffix: true
})
}, visibleSuffixCount > 0 && /*#__PURE__*/_react["default"].createElement(_InputSuffix["default"], {
status: showSuffix ? status : undefined,
statusMessage: statusMessage,
disabled: disabled,
onIconClicked: onIconClicked,
isClearButtonVisible: isClearButtonVisible,
onClear: this._handleSuffixOnClear,
clearButtonSize: clearButtonSizeMap[size],
menuArrow: menuArrow,
suffix: suffix,
tooltipPlacement: tooltipPlacement
})));
}
}]);
return Input;
}(_react.Component);
(0, _defineProperty2["default"])(Input, "Ticker", _Ticker["default"]);
(0, _defineProperty2["default"])(Input, "IconAffix", _IconAffix["default"]);
(0, _defineProperty2["default"])(Input, "Affix", _Affix["default"]);
(0, _defineProperty2["default"])(Input, "Group", _Group["default"]);
(0, _defineProperty2["default"])(Input, "StatusError", _constants2.STATUS.ERROR);
(0, _defineProperty2["default"])(Input, "StatusWarning", _constants2.STATUS.WARNING);
(0, _defineProperty2["default"])(Input, "StatusLoading", _constants2.STATUS.LOADING);
Input.displayName = 'Input';
Input.defaultProps = {
focusOnClearClick: true,
autoSelect: true,
size: 'medium',
border: 'standard',
roundInput: false,
textOverflow: 'clip',
maxLength: 524288,
clearButton: false,
hideStatusSuffix: false
};
Input.propTypes = {
/** Applies a data-hook HTML attribute that can be used in the tests */
dataHook: _propTypes["default"].string,
/** Specifies a CSS class name to be appended to the component’s root element */
className: _propTypes["default"].string,
/** Assigns a unique identifier for the root element */
id: _propTypes["default"].string,
/** Associate a control with the regions that it controls */
ariaControls: _propTypes["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: _propTypes["default"].string,
/** Define a string that labels the current element in case where a text label is not visible on the screen */
ariaLabel: _propTypes["default"].string,
/** Focus the element on mount (standard React input autoFocus) */
autoFocus: _propTypes["default"].bool,
/** Select the entire text of the element on focus (standard React input autoSelect) */
autoSelect: _propTypes["default"].bool,
/** Sets the value of native autocomplete attribute (check the [HTML spec](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#attr-fe-autocomplete) for possible values */
autocomplete: _propTypes["default"].string,
/** Defines the initial value of an input */
defaultValue: _propTypes["default"].string,
/** Specifies whether input should be disabled or not */
disabled: _propTypes["default"].bool,
/** Specify the status of a field */
status: _propTypes["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: _propTypes["default"].node,
/** Specifies whether status suffix should be hidden */
hideStatusSuffix: _propTypes["default"].bool,
/** USED FOR TESTING - forces focus state on the input */
forceFocus: _propTypes["default"].bool,
/** USED FOR TESTING - forces hover state on the input */
forceHover: _propTypes["default"].bool,
/** Sets the maximum number of characters that can be inserted to a field */
maxLength: _propTypes["default"].number,
/** Specifies whether input should have a dropdown menu arrow on the right side */
menuArrow: _propTypes["default"].bool,
/** Displays clear button (X) on a non-empty input */
clearButton: _propTypes["default"].bool,
/** Reference element data when a form is submitted */
name: _propTypes["default"].string,
/** Control the border style of input */
border: _propTypes["default"].oneOf(['standard', 'round', 'bottomLine']),
/**
* When set to true, this input will be rounded
* @deprecated
*/
roundInput: _propTypes["default"].bool,
/** Specifies whether input shouldn’t have rounded corners on its left */
noLeftBorderRadius: _propTypes["default"].bool,
/** Specifies whether input shouldn’t have rounded corners on its right */
noRightBorderRadius: _propTypes["default"].bool,
/** Defines a standard input onBlur callback */
onBlur: _propTypes["default"].func,
/** Defines a standard input onChange callback */
onChange: _propTypes["default"].func,
/** Displays clear button (X) on a non-empty input and calls a callback function with no arguments */
onClear: _propTypes["default"].func,
/** Defines a callback function called on compositionstart/compositionend events */
onCompositionChange: _propTypes["default"].func,
/** Defines a callback handler that is called when the user presses -enter- */
onEnterPressed: _propTypes["default"].func,
/** Defines a callback handler that is called when the user presses -escape- */
onEscapePressed: _propTypes["default"].func,
/** Defines a standard input onFocus callback */
onFocus: _propTypes["default"].func,
/** Defines a standard input onClick callback */
onInputClicked: _propTypes["default"].func,
/** Defines a standard input onKeyDown callback */
onKeyDown: _propTypes["default"].func,
/** Defines a standard input onKeyUp callback */
onKeyUp: _propTypes["default"].func,
/** Defines a callback handler that is called when user pastes text from a clipboard (using a mouse or keyboard shortcut) */
onPaste: _propTypes["default"].func,
/** Sets a placeholder message to display */
placeholder: _propTypes["default"].string,
/** Pass a component you want to show as the prefix of the input, e.g., text, icon */
prefix: _propTypes["default"].node,
/** Specifies whether input is read only */
readOnly: _propTypes["default"].bool,
/** Restricts input editing */
disableEditing: _propTypes["default"].bool,
/** Flip component horizontally so it would be more suitable to RTL */
rtl: _propTypes["default"].bool,
/** Controls the size of the input */
size: _propTypes["default"].oneOf(['small', 'medium', 'large']),
/** Pass a component you want to show as the suffix of the input, e.g., text, icon */
suffix: _propTypes["default"].node,
/** Indicates that element can be focused and where it participates in sequential keyboard navigation */
tabIndex: _propTypes["default"].number,
/** Handles text overflow behavior. It can either `clip` (default) or display `ellipsis`. */
textOverflow: _propTypes["default"].string,
/** Controls placement of a status tooltip */
tooltipPlacement: _propTypes["default"].string,
/** Specifies the type of `<input/>` element to display. Default is text. */
type: _propTypes["default"].string,
/** Specifies the current value of the element */
value: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]),
/** Specifies whether input is mandatory */
required: _propTypes["default"].bool,
/** Sets a minimum value of an input. Similar to HTML5 min attribute. */
min: _propTypes["default"].number,
/** Sets a maximum value of an input. Similar to html5 max attribute. */
max: _propTypes["default"].number,
/** Specifies the interval between number values */
step: _propTypes["default"].number,
/** Render a custom input instead of the default html input tag */
customInput: _propTypes["default"].elementType ? _propTypes["default"].oneOfType([_propTypes["default"].func, _propTypes["default"].node, _propTypes["default"].elementType]) : _propTypes["default"].oneOfType([_propTypes["default"].func, _propTypes["default"].node]),
/** Sets a pattern that typed value must match to be valid (regex) */
pattern: _propTypes["default"].string,
/** Specifies whether to focus the field when clear button is clicked */
focusOnClearClick: _propTypes["default"].bool
};
var _default = Input;
exports["default"] = _default;