mobile-more
Version:
基于 antd-mobile v5 扩展移动端 UI 组件
184 lines (183 loc) • 7.39 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
var _excluded = ["type", "disabledWhiteSpace", "prefix", "suffix", "onBlur", "max", "min", "precision", "useFloor", "inputMode", "format", "maxLength"];
import React from 'react';
import { floor, isUndefined } from 'ut2';
import { calculateCursorPosition } from 'util-helpers';
import { useControllableValue } from 'rc-hooks';
import { Input } from 'antd-mobile';
import { prefixClass } from "../../../config";
import { normalizeBankCard, normalizeEmail, normalizeIdCard, normalizeMobile, normalizeNotWhiteSpace, normalizeNumber } from "../utils/normalize";
import "./SuperInput.css";
var prefixCls = "".concat(prefixClass, "-input");
var SuperInput = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
var type = _ref.type,
disabledWhiteSpace = _ref.disabledWhiteSpace,
prefix = _ref.prefix,
suffix = _ref.suffix,
onBlur = _ref.onBlur,
_ref$max = _ref.max,
max = _ref$max === void 0 ? Number.MAX_SAFE_INTEGER : _ref$max,
_ref$min = _ref.min,
min = _ref$min === void 0 ? Number.MIN_SAFE_INTEGER : _ref$min,
precision = _ref.precision,
useFloor = _ref.useFloor,
inputMode = _ref.inputMode,
_ref$format = _ref.format,
format = _ref$format === void 0 ? true : _ref$format,
maxLength = _ref.maxLength,
restProps = _objectWithoutProperties(_ref, _excluded);
var internalRef = React.useRef(null);
var _useControllableValue = useControllableValue(restProps),
_useControllableValue2 = _slicedToArray(_useControllableValue, 2),
state = _useControllableValue2[0],
setState = _useControllableValue2[1];
var maxLen = React.useMemo(function () {
if (!isUndefined(maxLength)) {
return maxLength;
}
if (!format) {
if (type === 'mobile') {
return 11;
} else if (type === 'idCard') {
return 18;
}
}
return undefined;
}, [format, maxLength, type]);
var needAdjustPos = React.useMemo(function () {
return format && (type === 'mobile' || type === 'bankCard' || type === 'idCard' || type === 'number' || disabledWhiteSpace);
}, [disabledWhiteSpace, format, type]);
var realType = React.useMemo(function () {
if (type === 'mobile') {
return 'tel';
}
if (type === 'bankCard' || type === 'idCard' || type === 'number' || type === 'email') {
return 'text';
}
return type;
}, [type]);
var realInputMode = React.useMemo(function () {
if (!inputMode && type === 'number') {
return 'decimal';
}
return inputMode;
}, [type, inputMode]);
var calcPosOpts = React.useMemo(function () {
var ret = {};
if (type === 'bankCard') {
ret.type = 'bankCard';
} else if (type === 'mobile') {
ret.type = 'mobile';
} else if (type === 'idCard') {
ret.maskReg = /[^\dx]/gi;
ret.placeholderChars = [];
} else if (type === 'number') {
ret.maskReg = /[^\d\\.-]/g;
ret.placeholderChars = [];
} else if (disabledWhiteSpace) {
ret.maskReg = /\s/g;
ret.placeholderChars = [];
}
return ret;
}, [type, disabledWhiteSpace]);
var normalize = React.useCallback(function (val) {
var newValue = val;
if (type === 'mobile') {
newValue = normalizeMobile(val, format);
} else if (type === 'bankCard') {
newValue = normalizeBankCard(val, format);
} else if (type === 'idCard') {
newValue = normalizeIdCard(val, format);
} else if (type === 'number') {
newValue = normalizeNumber(val);
} else if (type === 'email') {
newValue = normalizeEmail(val);
} else if (disabledWhiteSpace) {
newValue = normalizeNotWhiteSpace(val);
}
return newValue;
}, [disabledWhiteSpace, format, type]);
var handleChange = React.useCallback(function (val) {
var _internalRef$current, _internalRef$current2;
var inputElement = (_internalRef$current = internalRef.current) === null || _internalRef$current === void 0 ? void 0 : _internalRef$current.nativeElement;
var prevPos = (_internalRef$current2 = internalRef.current) === null || _internalRef$current2 === void 0 || (_internalRef$current2 = _internalRef$current2.nativeElement) === null || _internalRef$current2 === void 0 ? void 0 : _internalRef$current2.selectionEnd;
var nextCtrlValue = normalize(val);
setState(nextCtrlValue);
if (inputElement && needAdjustPos) {
var adjustPos = calculateCursorPosition(prevPos, state, val, nextCtrlValue, calcPosOpts);
if (inputElement) {
if (val !== nextCtrlValue) {
window.setTimeout(function () {
inputElement.selectionStart = inputElement.selectionEnd = adjustPos;
});
} else {
inputElement.selectionStart = inputElement.selectionEnd = adjustPos;
}
}
}
}, [normalize, setState, needAdjustPos, state, calcPosOpts]);
// 处理最大最小值,以及精度
var handelBlur = React.useCallback(function (e) {
if (type === 'number' && state) {
var numberValue = Number(state);
if (numberValue > max) {
numberValue = max;
} else if (numberValue < min) {
numberValue = min;
}
var newValue = typeof precision === 'number' && precision >= 0 ? (useFloor ? floor(numberValue, precision) : numberValue).toFixed(precision) : String(numberValue);
if (newValue !== state) {
setState(newValue);
}
}
onBlur === null || onBlur === void 0 || onBlur(e);
}, [type, state, onBlur, max, min, precision, useFloor, setState]);
var triggerFocus = React.useCallback(function () {
var _internalRef$current3;
var inputEl = (_internalRef$current3 = internalRef.current) === null || _internalRef$current3 === void 0 ? void 0 : _internalRef$current3.nativeElement;
if (inputEl) {
var startPos = inputEl.selectionStart;
var endPos = inputEl.selectionEnd;
inputEl.focus();
window.setTimeout(function () {
inputEl.setSelectionRange(startPos, endPos);
});
}
}, []);
React.useImperativeHandle(ref, function () {
return _objectSpread(_objectSpread({}, internalRef.current), {}, {
focus: triggerFocus
});
}, [triggerFocus]);
React.useEffect(function () {
// 处理直接通过 form.setFieldsValue 或 initialValues
if (state && needAdjustPos) {
var newValue = normalize(state);
if (newValue !== state) {
handleChange(newValue);
}
}
}, [handleChange, needAdjustPos, normalize, type, state]);
return /*#__PURE__*/React.createElement("div", {
className: "".concat(prefixCls)
}, prefix && /*#__PURE__*/React.createElement("div", {
className: "".concat(prefixCls, "-prefix")
}, prefix), /*#__PURE__*/React.createElement(Input, _extends({
inputMode: realInputMode,
ref: internalRef,
autoComplete: "off"
}, restProps, {
type: realType,
value: state,
onChange: handleChange,
onBlur: handelBlur,
maxLength: maxLen
})), suffix && /*#__PURE__*/React.createElement("div", {
className: "".concat(prefixCls, "-suffix")
}, suffix));
});
SuperInput.displayName = 'SuperInput';
export default SuperInput;