function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
/**
* Copyright (c) Nicolas Gallagher.
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*
*/
import applyLayout from '../../modules/applyLayout';
import applyNativeMethods from '../../modules/applyNativeMethods';
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
import { Component } from 'react';
import ColorPropType from '../ColorPropType';
import createElement from '../createElement';
import css from '../StyleSheet/css';
import findNodeHandle from '../findNodeHandle';
import StyleSheetPropType from '../../modules/StyleSheetPropType';
import TextInputStylePropTypes from './TextInputStylePropTypes';
import TextInputState from '../../modules/TextInputState';
import ViewPropTypes from '../ViewPropTypes';
import { any, bool, func, number, oneOf, shape, string } from 'prop-types';
var isAndroid = canUseDOM && /Android/i.test(navigator && navigator.userAgent);
var emptyObject = {};
/**
* React Native events differ from W3C events.
*/
var normalizeEventHandler = function normalizeEventHandler(handler) {
return function (e) {
if (handler) {
e.nativeEvent.text = e.target.value;
return handler(e);
}
};
};
/**
* Determines whether a 'selection' prop differs from a node's existing
* selection state.
*/
var isSelectionStale = function isSelectionStale(node, selection) {
if (node && selection) {
var selectionEnd = node.selectionEnd,
selectionStart = node.selectionStart;
var start = selection.start,
end = selection.end;
return start !== selectionStart || end !== selectionEnd;
}
return false;
};
/**
* Certain input types do no support 'selectSelectionRange' and will throw an
* error.
*/
var setSelection = function setSelection(node, selection) {
try {
if (isSelectionStale(node, selection)) {
var start = selection.start,
end = selection.end; // workaround for Blink on Android: see https://github.com/text-mask/text-mask/issues/300
if (isAndroid) {
setTimeout(function () {
return node.setSelectionRange(start, end || start);
}, 10);
} else {
node.setSelectionRange(start, end || start);
}
}
} catch (e) {}
};
var TextInput =
/*#__PURE__*/
function (_Component) {
_inheritsLoose(TextInput, _Component);
function TextInput() {
var _this;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = _Component.call.apply(_Component, [this].concat(args)) || this;
_this._handleBlur = function (e) {
var onBlur = _this.props.onBlur;
TextInputState._currentlyFocusedNode = null;
if (onBlur) {
onBlur(e);
}
};
_this._handleContentSizeChange = function () {
var _this$props = _this.props,
onContentSizeChange = _this$props.onContentSizeChange,
multiline = _this$props.multiline;
if (multiline && onContentSizeChange) {
var newHeight = _this._node.scrollHeight;
var newWidth = _this._node.scrollWidth;
if (newHeight !== _this._nodeHeight || newWidth !== _this._nodeWidth) {
_this._nodeHeight = newHeight;
_this._nodeWidth = newWidth;
onContentSizeChange({
nativeEvent: {
contentSize: {
height: _this._nodeHeight,
width: _this._nodeWidth
}
}
});
}
}
};
_this._handleChange = function (e) {
var _this$props2 = _this.props,
onChange = _this$props2.onChange,
onChangeText = _this$props2.onChangeText;
var text = e.nativeEvent.text;
_this._handleContentSizeChange();
if (onChange) {
onChange(e);
}
if (onChangeText) {
onChangeText(text);
}
_this._handleSelectionChange(e);
};
_this._handleFocus = function (e) {
var _this$props3 = _this.props,
clearTextOnFocus = _this$props3.clearTextOnFocus,
onFocus = _this$props3.onFocus,
selectTextOnFocus = _this$props3.selectTextOnFocus;
var node = _this._node;
TextInputState._currentlyFocusedNode = _this._node;
if (onFocus) {
onFocus(e);
}
if (clearTextOnFocus) {
_this.clear();
}
if (selectTextOnFocus) {
node && node.select();
}
};
_this._handleKeyDown = function (e) {
// Prevent key events bubbling (see #612)
e.stopPropagation(); // Backspace, Escape, Tab, Cmd+Enter, and Arrow keys only fire 'keydown'
// DOM events
if (e.key === 'ArrowLeft' || e.key === 'ArrowUp' || e.key === 'ArrowRight' || e.key === 'ArrowDown' || e.key === 'Backspace' || e.key === 'Escape' || e.key === 'Enter' && e.metaKey || e.key === 'Tab') {
_this._handleKeyPress(e);
}
};
_this._handleKeyPress = function (e) {
var _this$props4 = _this.props,
blurOnSubmit = _this$props4.blurOnSubmit,
multiline = _this$props4.multiline,
onKeyPress = _this$props4.onKeyPress,
onSubmitEditing = _this$props4.onSubmitEditing;
var blurOnSubmitDefault = !multiline;
var shouldBlurOnSubmit = blurOnSubmit == null ? blurOnSubmitDefault : blurOnSubmit;
if (onKeyPress) {
var keyValue = e.key;
if (keyValue) {
e.nativeEvent = {
altKey: e.altKey,
ctrlKey: e.ctrlKey,
key: keyValue,
metaKey: e.metaKey,
shiftKey: e.shiftKey,
target: e.target
};
onKeyPress(e);
}
}
if (!e.isDefaultPrevented() && e.key === 'Enter' && !e.shiftKey) {
if ((blurOnSubmit || !multiline) && onSubmitEditing) {
// prevent "Enter" from inserting a newline
e.preventDefault();
e.nativeEvent = {
target: e.target,
text: e.target.value
};
onSubmitEditing(e);
}
if (shouldBlurOnSubmit) {
// $FlowFixMe
_this.blur();
}
}
};
_this._handleSelectionChange = function (e) {
var _this$props5 = _this.props,
onSelectionChange = _this$props5.onSelectionChange,
_this$props5$selectio = _this$props5.selection,
selection = _this$props5$selectio === void 0 ? emptyObject : _this$props5$selectio;
if (onSelectionChange) {
try {
var node = e.target;
if (isSelectionStale(node, selection)) {
var selectionStart = node.selectionStart,
selectionEnd = node.selectionEnd;
e.nativeEvent.selection = {
start: selectionStart,
end: selectionEnd
};
onSelectionChange(e);
}
} catch (e) {}
}
};
_this._setNode = function (component) {
_this._node = findNodeHandle(component);
if (_this._node) {
_this._handleContentSizeChange();
}
};
return _this;
}
var _proto = TextInput.prototype;
_proto.clear = function clear() {
this._node.value = '';
};
_proto.isFocused = function isFocused() {
return TextInputState.currentlyFocusedField() === this._node;
};
_proto.componentDidMount = function componentDidMount() {
setSelection(this._node, this.props.selection);
if (document.activeElement === this._node) {
TextInputState._currentlyFocusedNode = this._node;
}
};
_proto.componentDidUpdate = function componentDidUpdate() {
setSelection(this._node, this.props.selection);
};
_proto.render = function render() {
var _this$props6 = this.props,
autoComplete = _this$props6.autoComplete,
autoCorrect = _this$props6.autoCorrect,
editable = _this$props6.editable,
keyboardType = _this$props6.keyboardType,
multiline = _this$props6.multiline,
numberOfLines = _this$props6.numberOfLines,
returnKeyType = _this$props6.returnKeyType,
secureTextEntry = _this$props6.secureTextEntry,
blurOnSubmit = _this$props6.blurOnSubmit,
clearTextOnFocus = _this$props6.clearTextOnFocus,
onChangeText = _this$props6.onChangeText,
onLayout = _this$props6.onLayout,
onSelectionChange = _this$props6.onSelectionChange,
onSubmitEditing = _this$props6.onSubmitEditing,
selection = _this$props6.selection,
selectTextOnFocus = _this$props6.selectTextOnFocus,
spellCheck = _this$props6.spellCheck,
accessibilityViewIsModal = _this$props6.accessibilityViewIsModal,
allowFontScaling = _this$props6.allowFontScaling,
caretHidden = _this$props6.caretHidden,
clearButtonMode = _this$props6.clearButtonMode,
dataDetectorTypes = _this$props6.dataDetectorTypes,
disableFullscreenUI = _this$props6.disableFullscreenUI,
enablesReturnKeyAutomatically = _this$props6.enablesReturnKeyAutomatically,
hitSlop = _this$props6.hitSlop,
inlineImageLeft = _this$props6.inlineImageLeft,
inlineImagePadding = _this$props6.inlineImagePadding,
inputAccessoryViewID = _this$props6.inputAccessoryViewID,
keyboardAppearance = _this$props6.keyboardAppearance,
maxFontSizeMultiplier = _this$props6.maxFontSizeMultiplier,
needsOffscreenAlphaCompositing = _this$props6.needsOffscreenAlphaCompositing,
onAccessibilityTap = _this$props6.onAccessibilityTap,
onContentSizeChange = _this$props6.onContentSizeChange,
onEndEditing = _this$props6.onEndEditing,
onMagicTap = _this$props6.onMagicTap,
onScroll = _this$props6.onScroll,
removeClippedSubviews = _this$props6.removeClippedSubviews,
renderToHardwareTextureAndroid = _this$props6.renderToHardwareTextureAndroid,
returnKeyLabel = _this$props6.returnKeyLabel,
scrollEnabled = _this$props6.scrollEnabled,
selectionColor = _this$props6.selectionColor,
selectionState = _this$props6.selectionState,
shouldRasterizeIOS = _this$props6.shouldRasterizeIOS,
textBreakStrategy = _this$props6.textBreakStrategy,
textContentType = _this$props6.textContentType,
underlineColorAndroid = _this$props6.underlineColorAndroid,
otherProps = _objectWithoutPropertiesLoose(_this$props6, ["autoComplete", "autoCorrect", "editable", "keyboardType", "multiline", "numberOfLines", "returnKeyType", "secureTextEntry", "blurOnSubmit", "clearTextOnFocus", "onChangeText", "onLayout", "onSelectionChange", "onSubmitEditing", "selection", "selectTextOnFocus", "spellCheck", "accessibilityViewIsModal", "allowFontScaling", "caretHidden", "clearButtonMode", "dataDetectorTypes", "disableFullscreenUI", "enablesReturnKeyAutomatically", "hitSlop", "inlineImageLeft", "inlineImagePadding", "inputAccessoryViewID", "keyboardAppearance", "maxFontSizeMultiplier", "needsOffscreenAlphaCompositing", "onAccessibilityTap", "onContentSizeChange", "onEndEditing", "onMagicTap", "onScroll", "removeClippedSubviews", "renderToHardwareTextureAndroid", "returnKeyLabel", "scrollEnabled", "selectionColor", "selectionState", "shouldRasterizeIOS", "textBreakStrategy", "textContentType", "underlineColorAndroid"]);
var type;
switch (keyboardType) {
case 'email-address':
type = 'email';
break;
case 'number-pad':
case 'numeric':
type = 'number';
break;
case 'phone-pad':
type = 'tel';
break;
case 'search':
case 'web-search':
type = 'search';
break;
case 'url':
type = 'url';
break;
default:
type = 'text';
}
if (secureTextEntry) {
type = 'password';
}
var component = multiline ? 'textarea' : 'input';
Object.assign(otherProps, {
// Browser's treat autocomplete "off" as "on"
// https://bugs.chromium.org/p/chromium/issues/detail?id=468153#c164
autoComplete: autoComplete === 'off' ? 'noop' : autoComplete,
autoCorrect: autoCorrect ? 'on' : 'off',
classList: [classes.textinput],
dir: 'auto',
enterkeyhint: returnKeyType,
onBlur: normalizeEventHandler(this._handleBlur),
onChange: normalizeEventHandler(this._handleChange),
onFocus: normalizeEventHandler(this._handleFocus),
onKeyDown: this._handleKeyDown,
onKeyPress: this._handleKeyPress,
onSelect: normalizeEventHandler(this._handleSelectionChange),
readOnly: !editable,
ref: this._setNode,
spellCheck: spellCheck != null ? spellCheck : autoCorrect
});
if (multiline) {
otherProps.rows = numberOfLines;
} else {
otherProps.type = type;
}
return createElement(component, otherProps);
};
return TextInput;
}(Component);
TextInput.displayName = 'TextInput';
TextInput.defaultProps = {
autoCapitalize: 'sentences',
autoComplete: 'on',
autoCorrect: true,
editable: true,
keyboardType: 'default',
multiline: false,
numberOfLines: 1,
secureTextEntry: false
};
TextInput.State = TextInputState;
TextInput.propTypes = process.env.NODE_ENV !== "production" ? _objectSpread({}, ViewPropTypes, {
autoCapitalize: oneOf(['characters', 'none', 'sentences', 'words']),
autoComplete: string,
autoCorrect: bool,
autoFocus: bool,
blurOnSubmit: bool,
clearTextOnFocus: bool,
defaultValue: string,
editable: bool,
inputAccessoryViewID: string,
keyboardType: oneOf(['default', 'email-address', 'number-pad', 'numbers-and-punctuation', 'numeric', 'phone-pad', 'search', 'url', 'web-search']),
maxFontSizeMultiplier: number,
maxLength: number,
multiline: bool,
numberOfLines: number,
onBlur: func,
onChange: func,
onChangeText: func,
onFocus: func,
onKeyPress: func,
onSelectionChange: func,
onSubmitEditing: func,
placeholder: string,
placeholderTextColor: ColorPropType,
returnKeyType: oneOf(['enter', 'done', 'go', 'next', 'previous', 'search', 'send']),
secureTextEntry: bool,
selectTextOnFocus: bool,
selection: shape({
start: number.isRequired,
end: number
}),
spellCheck: bool,
style: StyleSheetPropType(TextInputStylePropTypes),
value: string,
/* react-native compat */
/* eslint-disable */
caretHidden: bool,
clearButtonMode: string,
dataDetectorTypes: string,
disableFullscreenUI: bool,
enablesReturnKeyAutomatically: bool,
keyboardAppearance: string,
inlineImageLeft: string,
inlineImagePadding: number,
onContentSizeChange: func,
onEndEditing: func,
onScroll: func,
returnKeyLabel: string,
selectionColor: ColorPropType,
selectionState: any,
textBreakStrategy: string,
underlineColorAndroid: ColorPropType
/* eslint-enable */
}) : {};
var classes = css.create({
textinput: {
MozAppearance: 'textfield',
WebkitAppearance: 'none',
backgroundColor: 'transparent',
border: '0 solid black',
borderRadius: 0,
boxSizing: 'border-box',
font: '14px System',
padding: 0,
resize: 'none'
}
});
export default applyLayout(applyNativeMethods(TextInput));