UNPKG

@fruits-chain/react-native-xiaoshu

Version:
329 lines (276 loc) 13.5 kB
"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