@fruits-chain/react-native-xiaoshu
Version:
React Native UI library
329 lines (276 loc) • 13.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
var _cross = _interopRequireDefault(require("../icon/cross"));
var _theme = require("../theme");
var _hooks = require("../hooks");
var _helpers = require("../helpers");
var _style = require("./style");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (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 _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
const defaultFormatter = t => t;
let nextInputAccessoryViewID = 0;
const getNextInputAccessoryViewID = () => ++nextInputAccessoryViewID;
const iOSPlatform = _reactNative.Platform.OS === 'ios';
/**
* 自定义输入项
* @description 在和 react-native-keyboard-aware-scroll-view 配合做软键盘适配时,如果是 textarea 类型默认 scrollEnabled 禁用,避免软键盘遮挡输入内容
* @description 动态切换输入内容可见,请手动控制 secureTextEntry,如果只是切换 type 在 iOS 正式环境可能会不生效
*/
const TextInputBase = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
let {
addonGroupStyle,
addonBeforeTextStyle,
addonAfterTextStyle,
fixGroupStyles,
prefixTextStyle,
suffixTextStyle,
type = 'text',
rows = 2,
clearable = false,
clearTrigger = 'focus',
formatter,
formatTrigger = 'onChangeText',
showWordLimit = false,
bordered = false,
addonAfter,
addonBefore,
prefix,
suffix,
inputWidth,
size = 'middle',
onChange,
// TextInput 的属性
value,
defaultValue,
style,
multiline,
selectionColor,
secureTextEntry,
placeholderTextColor,
keyboardType,
onChangeText,
onEndEditing,
onFocus,
onBlur,
maxLength,
scrollEnabled = false,
returnKeyType,
...resetProps
} = _ref;
// 修正数据
if (type === 'textarea') {
multiline = true;
clearable = false;
} else {
returnKeyType = (0, _helpers.getDefaultValue)(returnKeyType, 'done');
}
if (type === 'password') {
secureTextEntry = true;
}
if (type === 'number') {
keyboardType = 'numeric';
}
if (type === 'digit') {
keyboardType = 'number-pad';
}
if (showWordLimit && (0, _helpers.isValue)(maxLength)) {
showWordLimit = false;
}
const onChangeTextPersistFn = (0, _hooks.usePersistFn)(onChangeText || _helpers.noop);
const onEndEditingPersistFn = (0, _hooks.usePersistFn)(onEndEditing || _helpers.noop);
const onFocusPersistFn = (0, _hooks.usePersistFn)(onFocus || _helpers.noop);
const onBlurPersistFn = (0, _hooks.usePersistFn)(onBlur || _helpers.noop);
const onChangePersistFn = (0, _hooks.usePersistFn)(onChange || _helpers.noop);
const formatterPersistFn = (0, _hooks.usePersistFn)(formatter || defaultFormatter);
const [localValue, setLocalValue] = (0, _react.useState)((0, _helpers.isValue)(value) ? value : defaultValue);
const [focus, setFocus] = (0, _react.useState)(false);
const TextInputRef = (0, _react.useRef)(null);
const colorScheme = (0, _reactNative.useColorScheme)();
const THEME_VAR = (0, _theme.useTheme)();
const inputAccessoryViewID = (0, _react.useMemo)(() => `TextInputBase_${getNextInputAccessoryViewID()}`, []);
const STYLES = (0, _style.createStyles)(THEME_VAR);
/** 显示禁用样子 bordered 才显示 */
const showDisabledInput = bordered && (0, _helpers.isDef)(resetProps.editable) && !resetProps.editable;
/** 输入框最小高度 */
const textInputMinHeight = THEME_VAR[`text_input_${size}_min_height`] || THEME_VAR.text_input_middle_min_height;
/** 所有文字/文案相关的大小 */
const textInputFontSize = THEME_VAR[`text_input_${size}_font_size`] || THEME_VAR.text_input_middle_font_size;
selectionColor = (0, _helpers.getDefaultValue)(selectionColor, THEME_VAR.text_input_selection_color);
placeholderTextColor = (0, _helpers.getDefaultValue)(placeholderTextColor, THEME_VAR.text_input_placeholder_text_color);
/**
* 转发实例
*/
(0, _react.useImperativeHandle)(ref, () => {
return TextInputRef.current;
}); // 同步外部的数据
(0, _hooks.useUpdateEffect)(() => {
setLocalValue(value);
}, [value]);
/**
* 点击完成收起软键盘
*/
const onPressFinish = (0, _react.useCallback)(() => {
_reactNative.Keyboard.dismiss();
setFocus(false);
}, []);
/** 点击视觉上的输入框,聚焦,多行文本 */
const onPressTextInput = (0, _react.useCallback)(() => {
var _TextInputRef$current;
(_TextInputRef$current = TextInputRef.current) === null || _TextInputRef$current === void 0 ? void 0 : _TextInputRef$current.focus();
}, []);
/**
* 当文字变化
* @description 在这个阶段判断字符长度、格式化数据
*/
const onChangeTextTextInput = (0, _react.useCallback)(t => {
// 部分数据开始格式化
// 允许输入正整数
if (type === 'digit' || type === 'number') {
const isNumber = type === 'number';
t = (0, _helpers.formatNumber)(t, isNumber, isNumber);
}
if (typeof maxLength === 'number' && t.length > maxLength) {
t = t.slice(0, maxLength);
}
if (formatTrigger === 'onChangeText') {
t = formatterPersistFn(t);
}
setLocalValue(t);
onChangeTextPersistFn(t);
}, [type, maxLength, formatTrigger, formatterPersistFn, onChangeTextPersistFn]);
/**
* 编辑结束的时候
*/
const onEndEditingTextInput = (0, _react.useCallback)(e => {
if (formatTrigger === 'onEndEditing') {
e.nativeEvent.text = formatterPersistFn(e.nativeEvent.text);
}
setLocalValue(e.nativeEvent.text);
onEndEditingPersistFn(e);
}, [onEndEditingPersistFn, formatterPersistFn, formatTrigger]);
/**
* 当文本框内容变化时
*/
const onChangeTextInput = (0, _react.useCallback)(e => {
onChangePersistFn(e.nativeEvent.text);
}, [onChangePersistFn]);
/**
* 点击清除按钮
* @description 目前不能在输入框聚焦的时候触发点击,输入框失去焦点后才能触发点击,可能是软键盘的问题?
*/
const onPressClearable = (0, _react.useCallback)(() => {
var _TextInputRef$current2;
(_TextInputRef$current2 = TextInputRef.current) === null || _TextInputRef$current2 === void 0 ? void 0 : _TextInputRef$current2.clear();
setLocalValue('');
onChangeTextPersistFn('');
onPressTextInput();
}, [onChangeTextPersistFn, onPressTextInput]);
/**
* 输入框聚焦
*/
const onFocusTextInput = (0, _react.useCallback)(e => {
setFocus(true);
onFocusPersistFn(e);
}, [onFocusPersistFn]);
/**
* 输入框失焦
*/
const onBlurTextInput = (0, _react.useCallback)(e => {
setFocus(false);
onBlurPersistFn(e);
}, [onBlurPersistFn]);
const textInputTextStyle = {
fontSize: textInputFontSize
};
const isTextarea = type === 'textarea'; // textarea 模式就是纯输入框
const addonBeforeJSX = isTextarea ? null : (0, _helpers.renderTextLikeJSX)(addonBefore, [STYLES.addon_text, STYLES.addon_text_before, textInputTextStyle, addonBeforeTextStyle]);
const addonAfterJSX = isTextarea ? null : (0, _helpers.renderTextLikeJSX)(addonAfter, [STYLES.addon_text, STYLES.addon_text_after, textInputTextStyle, addonAfterTextStyle]);
const prefixJSX = isTextarea ? null : (0, _helpers.renderTextLikeJSX)(prefix, [STYLES.input_fix_text, STYLES.input_fix_text_pre, textInputTextStyle, prefixTextStyle]);
const suffixJSX = isTextarea ? null : (0, _helpers.renderTextLikeJSX)(suffix, [STYLES.input_fix_text, STYLES.input_fix_text_suf, textInputTextStyle, suffixTextStyle]);
const customTextInputWidthStyle = (0, _helpers.isDef)(inputWidth) ? {
flexShrink: 1,
flexGrow: 0,
flexBasis: inputWidth,
width: inputWidth
} : {};
/** 在添加了 addonXxx 的情况下,需要输入框部分自适应宽 */
const inputAddonModeStyle = {
flex: 1
};
/** 输入框不确定是否要排除边框 */
const inputUncertainHeight = bordered ? 2 : 0;
const inputStyles = [STYLES.input, isTextarea ? {
minHeight: textInputMinHeight * rows - inputUncertainHeight,
paddingVertical: 2,
alignItems: 'flex-start'
} : {
minHeight: textInputMinHeight - inputUncertainHeight,
alignContent: 'center'
}, (addonAfterJSX || addonBeforeJSX) && bordered ? inputAddonModeStyle : null, customTextInputWidthStyle];
/**
* 显示辅助工具栏
* @description 单行输入框回车键已具备收起键盘的作用
*/
const showInputAccessoryView = iOSPlatform && type !== 'text' && type !== 'password';
const keyboardAppearance = !(0, _helpers.isValue)(resetProps.keyboardAppearance) || resetProps.keyboardAppearance === 'default' ? colorScheme || 'light' : resetProps.keyboardAppearance;
const textInputJSX = /*#__PURE__*/_react.default.createElement(_reactNative.TouchableOpacity, {
activeOpacity: 1,
style: inputStyles,
onPress: onPressTextInput
}, /*#__PURE__*/_react.default.createElement(_reactNative.TextInput, _extends({}, resetProps, {
ref: TextInputRef,
style: [STYLES.text_input, textInputTextStyle, showDisabledInput ? STYLES.text_input_disabled : null, style],
placeholder: focus && resetProps.textAlign === 'center' ? undefined : resetProps.placeholder,
value: (0, _helpers.isValue)(value) ? value : localValue,
defaultValue: defaultValue,
multiline: multiline,
secureTextEntry: secureTextEntry,
keyboardType: keyboardType,
returnKeyType: returnKeyType,
scrollEnabled: scrollEnabled,
selectionColor: selectionColor,
placeholderTextColor: placeholderTextColor,
onChangeText: onChangeTextTextInput,
onEndEditing: onEndEditingTextInput,
onChange: onChangeTextInput,
onFocus: onFocusTextInput,
onBlur: onBlurTextInput,
inputAccessoryViewID: resetProps.inputAccessoryViewID || (showInputAccessoryView ? inputAccessoryViewID : undefined)
})), clearable && (clearTrigger === 'focus' ? focus : true) && localValue && localValue.length ? /*#__PURE__*/_react.default.createElement(_cross.default, {
style: STYLES.clearable,
color: THEME_VAR.text_input_clearable_color,
size: THEME_VAR.text_input_clearable_size / 4 * 3,
onPress: onPressClearable
}) : null, showWordLimit ? /*#__PURE__*/_react.default.createElement(_reactNative.Text, {
style: STYLES.word_limit_text
}, (localValue === null || localValue === void 0 ? void 0 : localValue.length) || 0, "/", maxLength) : null);
const inputJSX = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, showInputAccessoryView ? /*#__PURE__*/_react.default.createElement(_reactNative.InputAccessoryView, {
nativeID: inputAccessoryViewID,
backgroundColor: THEME_VAR[`text_input_${keyboardAppearance}_accessory_background_color`]
}, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
style: STYLES.accessory
}, /*#__PURE__*/_react.default.createElement(_reactNative.TouchableOpacity, {
onPress: onPressFinish,
activeOpacity: THEME_VAR.active_opacity
}, /*#__PURE__*/_react.default.createElement(_reactNative.Text, {
style: STYLES.accessory_text
}, "\u5B8C\u6210")))) : null, prefixJSX || suffixJSX || bordered ? /*#__PURE__*/_react.default.createElement(_reactNative.View, {
style: [STYLES.input_fix_group, bordered ? [STYLES.input_border, addonAfterJSX || addonBeforeJSX ? inputAddonModeStyle : null, (0, _helpers.isDef)(resetProps.editable) && !resetProps.editable ? STYLES.input_disabled : null] : null, prefixJSX || suffixJSX ? null : customTextInputWidthStyle, fixGroupStyles]
}, prefixJSX, textInputJSX, suffixJSX) : textInputJSX);
if (addonAfterJSX || addonBeforeJSX) {
return /*#__PURE__*/_react.default.createElement(_reactNative.View, {
style: [STYLES.addon_group, addonGroupStyle]
}, addonBeforeJSX, inputJSX, addonAfterJSX);
}
return inputJSX;
});
var _default = /*#__PURE__*/(0, _react.memo)(TextInputBase);
exports.default = _default;
//# sourceMappingURL=index.js.map