123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- "use strict";
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
- var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.default = void 0;
- var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
- var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
- var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
- var _classnames = _interopRequireDefault(require("classnames"));
- var _rcUtil = require("rc-util");
- var _useLayoutEffect = _interopRequireDefault(require("rc-util/lib/hooks/useLayoutEffect"));
- var _raf = _interopRequireDefault(require("rc-util/lib/raf"));
- var React = _interopRequireWildcard(require("react"));
- var _miscUtil = require("../../utils/miscUtil");
- var _context = _interopRequireDefault(require("../context"));
- var _useLockEffect = _interopRequireDefault(require("../hooks/useLockEffect"));
- var _Icon = _interopRequireDefault(require("./Icon"));
- var _MaskFormat = _interopRequireDefault(require("./MaskFormat"));
- var _util = require("./util");
- var _excluded = ["active", "showActiveCls", "suffixIcon", "format", "validateFormat", "onChange", "onInput", "helped", "onHelp", "onSubmit", "onKeyDown", "preserveInvalidOnBlur", "invalid", "clearIcon"];
- // Format logic
- //
- // First time on focus:
- // 1. check if the text is valid, if not fill with format
- // 2. set highlight cell to the first cell
- // Cells
- // 1. Selection the index cell, set inner `cacheValue` to ''
- // 2. Key input filter non-number char, patch after the `cacheValue`
- // 1. Replace the `cacheValue` with input align the cell length
- // 2. Re-selection the mask cell
- // 3. If `cacheValue` match the limit length or cell format (like 1 ~ 12 month), go to next cell
- var Input = /*#__PURE__*/React.forwardRef(function (props, ref) {
- var active = props.active,
- _props$showActiveCls = props.showActiveCls,
- showActiveCls = _props$showActiveCls === void 0 ? true : _props$showActiveCls,
- suffixIcon = props.suffixIcon,
- format = props.format,
- validateFormat = props.validateFormat,
- onChange = props.onChange,
- onInput = props.onInput,
- helped = props.helped,
- onHelp = props.onHelp,
- onSubmit = props.onSubmit,
- onKeyDown = props.onKeyDown,
- _props$preserveInvali = props.preserveInvalidOnBlur,
- preserveInvalidOnBlur = _props$preserveInvali === void 0 ? false : _props$preserveInvali,
- invalid = props.invalid,
- clearIcon = props.clearIcon,
- restProps = (0, _objectWithoutProperties2.default)(props, _excluded);
- var value = props.value,
- onFocus = props.onFocus,
- onBlur = props.onBlur,
- onMouseUp = props.onMouseUp;
- var _React$useContext = React.useContext(_context.default),
- prefixCls = _React$useContext.prefixCls,
- _React$useContext$inp = _React$useContext.input,
- Component = _React$useContext$inp === void 0 ? 'input' : _React$useContext$inp;
- var inputPrefixCls = "".concat(prefixCls, "-input");
- // ======================== Value =========================
- var _React$useState = React.useState(false),
- _React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2),
- focused = _React$useState2[0],
- setFocused = _React$useState2[1];
- var _React$useState3 = React.useState(value),
- _React$useState4 = (0, _slicedToArray2.default)(_React$useState3, 2),
- internalInputValue = _React$useState4[0],
- setInputValue = _React$useState4[1];
- var _React$useState5 = React.useState(''),
- _React$useState6 = (0, _slicedToArray2.default)(_React$useState5, 2),
- focusCellText = _React$useState6[0],
- setFocusCellText = _React$useState6[1];
- var _React$useState7 = React.useState(null),
- _React$useState8 = (0, _slicedToArray2.default)(_React$useState7, 2),
- focusCellIndex = _React$useState8[0],
- setFocusCellIndex = _React$useState8[1];
- var _React$useState9 = React.useState(null),
- _React$useState10 = (0, _slicedToArray2.default)(_React$useState9, 2),
- forceSelectionSyncMark = _React$useState10[0],
- forceSelectionSync = _React$useState10[1];
- var inputValue = internalInputValue || '';
- // Sync value if needed
- React.useEffect(function () {
- setInputValue(value);
- }, [value]);
- // ========================= Refs =========================
- var holderRef = React.useRef();
- var inputRef = React.useRef();
- React.useImperativeHandle(ref, function () {
- return {
- nativeElement: holderRef.current,
- inputElement: inputRef.current,
- focus: function focus(options) {
- inputRef.current.focus(options);
- },
- blur: function blur() {
- inputRef.current.blur();
- }
- };
- });
- // ======================== Format ========================
- var maskFormat = React.useMemo(function () {
- return new _MaskFormat.default(format || '');
- }, [format]);
- var _React$useMemo = React.useMemo(function () {
- if (helped) {
- return [0, 0];
- }
- return maskFormat.getSelection(focusCellIndex);
- }, [maskFormat, focusCellIndex, helped]),
- _React$useMemo2 = (0, _slicedToArray2.default)(_React$useMemo, 2),
- selectionStart = _React$useMemo2[0],
- selectionEnd = _React$useMemo2[1];
- // ======================== Modify ========================
- // When input modify content, trigger `onHelp` if is not the format
- var onModify = function onModify(text) {
- if (text && text !== format && text !== value) {
- onHelp();
- }
- };
- // ======================== Change ========================
- /**
- * Triggered by paste, keyDown and focus to show format
- */
- var triggerInputChange = (0, _rcUtil.useEvent)(function (text) {
- if (validateFormat(text)) {
- onChange(text);
- }
- setInputValue(text);
- onModify(text);
- });
- // Directly trigger `onChange` if `format` is empty
- var onInternalChange = function onInternalChange(event) {
- // Hack `onChange` with format to do nothing
- if (!format) {
- var text = event.target.value;
- onModify(text);
- setInputValue(text);
- onChange(text);
- }
- };
- var onFormatPaste = function onFormatPaste(event) {
- // Get paste text
- var pasteText = event.clipboardData.getData('text');
- if (validateFormat(pasteText)) {
- triggerInputChange(pasteText);
- }
- };
- // ======================== Mouse =========================
- // When `mouseDown` get focus, it's better to not to change the selection
- // Since the up position maybe not is the first cell
- var mouseDownRef = React.useRef(false);
- var onFormatMouseDown = function onFormatMouseDown() {
- mouseDownRef.current = true;
- };
- var onFormatMouseUp = function onFormatMouseUp(event) {
- var _ref = event.target,
- start = _ref.selectionStart;
- var closeMaskIndex = maskFormat.getMaskCellIndex(start);
- setFocusCellIndex(closeMaskIndex);
- // Force update the selection
- forceSelectionSync({});
- onMouseUp === null || onMouseUp === void 0 || onMouseUp(event);
- mouseDownRef.current = false;
- };
- // ====================== Focus Blur ======================
- var onFormatFocus = function onFormatFocus(event) {
- setFocused(true);
- setFocusCellIndex(0);
- setFocusCellText('');
- onFocus(event);
- };
- var onSharedBlur = function onSharedBlur(event) {
- onBlur(event);
- };
- var onFormatBlur = function onFormatBlur(event) {
- setFocused(false);
- onSharedBlur(event);
- };
- // ======================== Active ========================
- // Check if blur need reset input value
- (0, _useLockEffect.default)(active, function () {
- if (!active && !preserveInvalidOnBlur) {
- setInputValue(value);
- }
- });
- // ======================= Keyboard =======================
- var onSharedKeyDown = function onSharedKeyDown(event) {
- if (event.key === 'Enter' && validateFormat(inputValue)) {
- onSubmit();
- }
- onKeyDown === null || onKeyDown === void 0 || onKeyDown(event);
- };
- var onFormatKeyDown = function onFormatKeyDown(event) {
- onSharedKeyDown(event);
- var key = event.key;
- // Save the cache with cell text
- var nextCellText = null;
- // Fill in the input
- var nextFillText = null;
- var maskCellLen = selectionEnd - selectionStart;
- var cellFormat = format.slice(selectionStart, selectionEnd);
- // Cell Index
- var offsetCellIndex = function offsetCellIndex(offset) {
- setFocusCellIndex(function (idx) {
- var nextIndex = idx + offset;
- nextIndex = Math.max(nextIndex, 0);
- nextIndex = Math.min(nextIndex, maskFormat.size() - 1);
- return nextIndex;
- });
- };
- // Range
- var offsetCellValue = function offsetCellValue(offset) {
- var _getMaskRange = (0, _util.getMaskRange)(cellFormat),
- _getMaskRange2 = (0, _slicedToArray2.default)(_getMaskRange, 3),
- rangeStart = _getMaskRange2[0],
- rangeEnd = _getMaskRange2[1],
- rangeDefault = _getMaskRange2[2];
- var currentText = inputValue.slice(selectionStart, selectionEnd);
- var currentTextNum = Number(currentText);
- if (isNaN(currentTextNum)) {
- return String(rangeDefault ? rangeDefault : offset > 0 ? rangeStart : rangeEnd);
- }
- var num = currentTextNum + offset;
- var range = rangeEnd - rangeStart + 1;
- return String(rangeStart + (range + num - rangeStart) % range);
- };
- switch (key) {
- // =============== Remove ===============
- case 'Backspace':
- case 'Delete':
- nextCellText = '';
- nextFillText = cellFormat;
- break;
- // =============== Arrows ===============
- // Left key
- case 'ArrowLeft':
- nextCellText = '';
- offsetCellIndex(-1);
- break;
- // Right key
- case 'ArrowRight':
- nextCellText = '';
- offsetCellIndex(1);
- break;
- // Up key
- case 'ArrowUp':
- nextCellText = '';
- nextFillText = offsetCellValue(1);
- break;
- // Down key
- case 'ArrowDown':
- nextCellText = '';
- nextFillText = offsetCellValue(-1);
- break;
- // =============== Number ===============
- default:
- if (!isNaN(Number(key))) {
- nextCellText = focusCellText + key;
- nextFillText = nextCellText;
- }
- break;
- }
- // Update cell text
- if (nextCellText !== null) {
- setFocusCellText(nextCellText);
- if (nextCellText.length >= maskCellLen) {
- // Go to next cell
- offsetCellIndex(1);
- setFocusCellText('');
- }
- }
- // Update the input text
- if (nextFillText !== null) {
- // Replace selection range with `nextCellText`
- var nextFocusValue =
- // before
- inputValue.slice(0, selectionStart) +
- // replace
- (0, _miscUtil.leftPad)(nextFillText, maskCellLen) +
- // after
- inputValue.slice(selectionEnd);
- triggerInputChange(nextFocusValue.slice(0, format.length));
- }
- // Always trigger selection sync after key down
- forceSelectionSync({});
- };
- // ======================== Format ========================
- var rafRef = React.useRef();
- (0, _useLayoutEffect.default)(function () {
- if (!focused || !format || mouseDownRef.current) {
- return;
- }
- // Reset with format if not match
- if (!maskFormat.match(inputValue)) {
- triggerInputChange(format);
- return;
- }
- // Match the selection range
- inputRef.current.setSelectionRange(selectionStart, selectionEnd);
- // Chrome has the bug anchor position looks not correct but actually correct
- rafRef.current = (0, _raf.default)(function () {
- inputRef.current.setSelectionRange(selectionStart, selectionEnd);
- });
- return function () {
- _raf.default.cancel(rafRef.current);
- };
- }, [maskFormat, format, focused, inputValue, focusCellIndex, selectionStart, selectionEnd, forceSelectionSyncMark, triggerInputChange]);
- // ======================== Render ========================
- // Input props for format
- var inputProps = format ? {
- onFocus: onFormatFocus,
- onBlur: onFormatBlur,
- onKeyDown: onFormatKeyDown,
- onMouseDown: onFormatMouseDown,
- onMouseUp: onFormatMouseUp,
- onPaste: onFormatPaste
- } : {};
- return /*#__PURE__*/React.createElement("div", {
- ref: holderRef,
- className: (0, _classnames.default)(inputPrefixCls, (0, _defineProperty2.default)((0, _defineProperty2.default)({}, "".concat(inputPrefixCls, "-active"), active && showActiveCls), "".concat(inputPrefixCls, "-placeholder"), helped))
- }, /*#__PURE__*/React.createElement(Component, (0, _extends2.default)({
- ref: inputRef,
- "aria-invalid": invalid,
- autoComplete: "off"
- }, restProps, {
- onKeyDown: onSharedKeyDown,
- onBlur: onSharedBlur
- // Replace with format
- }, inputProps, {
- // Value
- value: inputValue,
- onChange: onInternalChange
- })), /*#__PURE__*/React.createElement(_Icon.default, {
- type: "suffix",
- icon: suffixIcon
- }), clearIcon);
- });
- if (process.env.NODE_ENV !== 'production') {
- Input.displayName = 'Input';
- }
- var _default = exports.default = Input;
|