1 | import _extends from "@babel/runtime/helpers/esm/extends";
|
2 | import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
|
3 | import _typeof from "@babel/runtime/helpers/esm/typeof";
|
4 | import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
5 | import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
|
6 | var _excluded = ["prefixCls", "className", "style", "min", "max", "step", "defaultValue", "value", "disabled", "readOnly", "upHandler", "downHandler", "keyboard", "controls", "classNames", "stringMode", "parser", "formatter", "precision", "decimalSeparator", "onChange", "onInput", "onPressEnter", "onStep"],
|
7 | _excluded2 = ["disabled", "style", "prefixCls", "value", "prefix", "suffix", "addonBefore", "addonAfter", "classes", "className", "classNames"];
|
8 | import getMiniDecimal, { getNumberPrecision, num2str, toFixed, validateNumber } from '@rc-component/mini-decimal';
|
9 | import clsx from 'classnames';
|
10 | import { BaseInput } from 'rc-input';
|
11 | import { useLayoutUpdateEffect } from "rc-util/es/hooks/useLayoutEffect";
|
12 | import { composeRef } from "rc-util/es/ref";
|
13 | import * as React from 'react';
|
14 | import useCursor from "./hooks/useCursor";
|
15 | import StepHandler from "./StepHandler";
|
16 | import { getDecupleSteps } from "./utils/numberUtil";
|
17 | import { triggerFocus } from "rc-input/es/utils/commonUtils";
|
18 | import useFrame from "./hooks/useFrame";
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 | var getDecimalValue = function getDecimalValue(stringMode, decimalValue) {
|
31 | if (stringMode || decimalValue.isEmpty()) {
|
32 | return decimalValue.toString();
|
33 | }
|
34 | return decimalValue.toNumber();
|
35 | };
|
36 | var getDecimalIfValidate = function getDecimalIfValidate(value) {
|
37 | var decimal = getMiniDecimal(value);
|
38 | return decimal.isInvalidate() ? null : decimal;
|
39 | };
|
40 | var InternalInputNumber = React.forwardRef(function (props, ref) {
|
41 | var _clsx;
|
42 | var _props$prefixCls = props.prefixCls,
|
43 | prefixCls = _props$prefixCls === void 0 ? 'rc-input-number' : _props$prefixCls,
|
44 | className = props.className,
|
45 | style = props.style,
|
46 | min = props.min,
|
47 | max = props.max,
|
48 | _props$step = props.step,
|
49 | step = _props$step === void 0 ? 1 : _props$step,
|
50 | defaultValue = props.defaultValue,
|
51 | value = props.value,
|
52 | disabled = props.disabled,
|
53 | readOnly = props.readOnly,
|
54 | upHandler = props.upHandler,
|
55 | downHandler = props.downHandler,
|
56 | keyboard = props.keyboard,
|
57 | _props$controls = props.controls,
|
58 | controls = _props$controls === void 0 ? true : _props$controls,
|
59 | classNames = props.classNames,
|
60 | stringMode = props.stringMode,
|
61 | parser = props.parser,
|
62 | formatter = props.formatter,
|
63 | precision = props.precision,
|
64 | decimalSeparator = props.decimalSeparator,
|
65 | onChange = props.onChange,
|
66 | onInput = props.onInput,
|
67 | onPressEnter = props.onPressEnter,
|
68 | onStep = props.onStep,
|
69 | inputProps = _objectWithoutProperties(props, _excluded);
|
70 | var inputClassName = "".concat(prefixCls, "-input");
|
71 | var inputRef = React.useRef(null);
|
72 | var _React$useState = React.useState(false),
|
73 | _React$useState2 = _slicedToArray(_React$useState, 2),
|
74 | focus = _React$useState2[0],
|
75 | setFocus = _React$useState2[1];
|
76 | var userTypingRef = React.useRef(false);
|
77 | var compositionRef = React.useRef(false);
|
78 | var shiftKeyRef = React.useRef(false);
|
79 |
|
80 |
|
81 |
|
82 | var _React$useState3 = React.useState(function () {
|
83 | return getMiniDecimal(value !== null && value !== void 0 ? value : defaultValue);
|
84 | }),
|
85 | _React$useState4 = _slicedToArray(_React$useState3, 2),
|
86 | decimalValue = _React$useState4[0],
|
87 | setDecimalValue = _React$useState4[1];
|
88 | function setUncontrolledDecimalValue(newDecimal) {
|
89 | if (value === undefined) {
|
90 | setDecimalValue(newDecimal);
|
91 | }
|
92 | }
|
93 |
|
94 |
|
95 | |
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 |
|
106 | var getPrecision = React.useCallback(function (numStr, userTyping) {
|
107 | if (userTyping) {
|
108 | return undefined;
|
109 | }
|
110 | if (precision >= 0) {
|
111 | return precision;
|
112 | }
|
113 | return Math.max(getNumberPrecision(numStr), getNumberPrecision(step));
|
114 | }, [precision, step]);
|
115 |
|
116 |
|
117 | var mergedParser = React.useCallback(function (num) {
|
118 | var numStr = String(num);
|
119 | if (parser) {
|
120 | return parser(numStr);
|
121 | }
|
122 | var parsedStr = numStr;
|
123 | if (decimalSeparator) {
|
124 | parsedStr = parsedStr.replace(decimalSeparator, '.');
|
125 | }
|
126 |
|
127 |
|
128 | return parsedStr.replace(/[^\w.-]+/g, '');
|
129 | }, [parser, decimalSeparator]);
|
130 |
|
131 |
|
132 | var inputValueRef = React.useRef('');
|
133 | var mergedFormatter = React.useCallback(function (number, userTyping) {
|
134 | if (formatter) {
|
135 | return formatter(number, {
|
136 | userTyping: userTyping,
|
137 | input: String(inputValueRef.current)
|
138 | });
|
139 | }
|
140 | var str = typeof number === 'number' ? num2str(number) : number;
|
141 |
|
142 |
|
143 | if (!userTyping) {
|
144 | var mergedPrecision = getPrecision(str, userTyping);
|
145 | if (validateNumber(str) && (decimalSeparator || mergedPrecision >= 0)) {
|
146 |
|
147 | var separatorStr = decimalSeparator || '.';
|
148 | str = toFixed(str, separatorStr, mergedPrecision);
|
149 | }
|
150 | }
|
151 | return str;
|
152 | }, [formatter, getPrecision, decimalSeparator]);
|
153 |
|
154 |
|
155 | |
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 | var _React$useState5 = React.useState(function () {
|
165 | var initValue = defaultValue !== null && defaultValue !== void 0 ? defaultValue : value;
|
166 | if (decimalValue.isInvalidate() && ['string', 'number'].includes(_typeof(initValue))) {
|
167 | return Number.isNaN(initValue) ? '' : initValue;
|
168 | }
|
169 | return mergedFormatter(decimalValue.toString(), false);
|
170 | }),
|
171 | _React$useState6 = _slicedToArray(_React$useState5, 2),
|
172 | inputValue = _React$useState6[0],
|
173 | setInternalInputValue = _React$useState6[1];
|
174 | inputValueRef.current = inputValue;
|
175 |
|
176 |
|
177 | function setInputValue(newValue, userTyping) {
|
178 | setInternalInputValue(mergedFormatter(
|
179 |
|
180 |
|
181 |
|
182 | newValue.isInvalidate() ? newValue.toString(false) : newValue.toString(!userTyping), userTyping));
|
183 | }
|
184 |
|
185 |
|
186 | var maxDecimal = React.useMemo(function () {
|
187 | return getDecimalIfValidate(max);
|
188 | }, [max, precision]);
|
189 | var minDecimal = React.useMemo(function () {
|
190 | return getDecimalIfValidate(min);
|
191 | }, [min, precision]);
|
192 | var upDisabled = React.useMemo(function () {
|
193 | if (!maxDecimal || !decimalValue || decimalValue.isInvalidate()) {
|
194 | return false;
|
195 | }
|
196 | return maxDecimal.lessEquals(decimalValue);
|
197 | }, [maxDecimal, decimalValue]);
|
198 | var downDisabled = React.useMemo(function () {
|
199 | if (!minDecimal || !decimalValue || decimalValue.isInvalidate()) {
|
200 | return false;
|
201 | }
|
202 | return decimalValue.lessEquals(minDecimal);
|
203 | }, [minDecimal, decimalValue]);
|
204 |
|
205 |
|
206 | var _useCursor = useCursor(inputRef.current, focus),
|
207 | _useCursor2 = _slicedToArray(_useCursor, 2),
|
208 | recordCursor = _useCursor2[0],
|
209 | restoreCursor = _useCursor2[1];
|
210 |
|
211 |
|
212 | |
213 |
|
214 |
|
215 |
|
216 |
|
217 |
|
218 |
|
219 | var getRangeValue = function getRangeValue(target) {
|
220 |
|
221 | if (maxDecimal && !target.lessEquals(maxDecimal)) {
|
222 | return maxDecimal;
|
223 | }
|
224 |
|
225 |
|
226 | if (minDecimal && !minDecimal.lessEquals(target)) {
|
227 | return minDecimal;
|
228 | }
|
229 | return null;
|
230 | };
|
231 |
|
232 | |
233 |
|
234 |
|
235 | var isInRange = function isInRange(target) {
|
236 | return !getRangeValue(target);
|
237 | };
|
238 |
|
239 | |
240 |
|
241 |
|
242 |
|
243 | var triggerValueUpdate = function triggerValueUpdate(newValue, userTyping) {
|
244 | var updateValue = newValue;
|
245 | var isRangeValidate = isInRange(updateValue) || updateValue.isEmpty();
|
246 |
|
247 |
|
248 |
|
249 |
|
250 | if (!updateValue.isEmpty() && !userTyping) {
|
251 |
|
252 | updateValue = getRangeValue(updateValue) || updateValue;
|
253 | isRangeValidate = true;
|
254 | }
|
255 | if (!readOnly && !disabled && isRangeValidate) {
|
256 | var numStr = updateValue.toString();
|
257 | var mergedPrecision = getPrecision(numStr, userTyping);
|
258 | if (mergedPrecision >= 0) {
|
259 | updateValue = getMiniDecimal(toFixed(numStr, '.', mergedPrecision));
|
260 |
|
261 |
|
262 |
|
263 | if (!isInRange(updateValue)) {
|
264 | updateValue = getMiniDecimal(toFixed(numStr, '.', mergedPrecision, true));
|
265 | }
|
266 | }
|
267 |
|
268 |
|
269 | if (!updateValue.equals(decimalValue)) {
|
270 | setUncontrolledDecimalValue(updateValue);
|
271 | onChange === null || onChange === void 0 ? void 0 : onChange(updateValue.isEmpty() ? null : getDecimalValue(stringMode, updateValue));
|
272 |
|
273 |
|
274 | if (value === undefined) {
|
275 | setInputValue(updateValue, userTyping);
|
276 | }
|
277 | }
|
278 | return updateValue;
|
279 | }
|
280 | return decimalValue;
|
281 | };
|
282 |
|
283 |
|
284 | var onNextPromise = useFrame();
|
285 |
|
286 |
|
287 | var collectInputValue = function collectInputValue(inputStr) {
|
288 | recordCursor();
|
289 |
|
290 |
|
291 |
|
292 | inputValueRef.current = inputStr;
|
293 | setInternalInputValue(inputStr);
|
294 |
|
295 |
|
296 | if (!compositionRef.current) {
|
297 | var finalValue = mergedParser(inputStr);
|
298 | var finalDecimal = getMiniDecimal(finalValue);
|
299 | if (!finalDecimal.isNaN()) {
|
300 | triggerValueUpdate(finalDecimal, true);
|
301 | }
|
302 | }
|
303 |
|
304 |
|
305 | onInput === null || onInput === void 0 ? void 0 : onInput(inputStr);
|
306 |
|
307 |
|
308 |
|
309 | onNextPromise(function () {
|
310 | var nextInputStr = inputStr;
|
311 | if (!parser) {
|
312 | nextInputStr = inputStr.replace(/。/g, '.');
|
313 | }
|
314 | if (nextInputStr !== inputStr) {
|
315 | collectInputValue(nextInputStr);
|
316 | }
|
317 | });
|
318 | };
|
319 |
|
320 |
|
321 | var onCompositionStart = function onCompositionStart() {
|
322 | compositionRef.current = true;
|
323 | };
|
324 | var onCompositionEnd = function onCompositionEnd() {
|
325 | compositionRef.current = false;
|
326 | collectInputValue(inputRef.current.value);
|
327 | };
|
328 |
|
329 |
|
330 | var onInternalInput = function onInternalInput(e) {
|
331 | collectInputValue(e.target.value);
|
332 | };
|
333 |
|
334 |
|
335 | var onInternalStep = function onInternalStep(up) {
|
336 | var _inputRef$current;
|
337 |
|
338 | if (up && upDisabled || !up && downDisabled) {
|
339 | return;
|
340 | }
|
341 |
|
342 |
|
343 |
|
344 | userTypingRef.current = false;
|
345 | var stepDecimal = getMiniDecimal(shiftKeyRef.current ? getDecupleSteps(step) : step);
|
346 | if (!up) {
|
347 | stepDecimal = stepDecimal.negate();
|
348 | }
|
349 | var target = (decimalValue || getMiniDecimal(0)).add(stepDecimal.toString());
|
350 | var updatedValue = triggerValueUpdate(target, false);
|
351 | onStep === null || onStep === void 0 ? void 0 : onStep(getDecimalValue(stringMode, updatedValue), {
|
352 | offset: shiftKeyRef.current ? getDecupleSteps(step) : step,
|
353 | type: up ? 'up' : 'down'
|
354 | });
|
355 | (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.focus();
|
356 | };
|
357 |
|
358 |
|
359 | |
360 |
|
361 |
|
362 |
|
363 |
|
364 | var flushInputValue = function flushInputValue(userTyping) {
|
365 | var parsedValue = getMiniDecimal(mergedParser(inputValue));
|
366 | var formatValue = parsedValue;
|
367 | if (!parsedValue.isNaN()) {
|
368 |
|
369 |
|
370 | formatValue = triggerValueUpdate(parsedValue, userTyping);
|
371 | } else {
|
372 | formatValue = triggerValueUpdate(decimalValue, userTyping);
|
373 | }
|
374 | if (value !== undefined) {
|
375 |
|
376 | setInputValue(decimalValue, false);
|
377 | } else if (!formatValue.isNaN()) {
|
378 |
|
379 | setInputValue(formatValue, false);
|
380 | }
|
381 | };
|
382 |
|
383 |
|
384 | var onBeforeInput = function onBeforeInput() {
|
385 | userTypingRef.current = true;
|
386 | };
|
387 | var onKeyDown = function onKeyDown(event) {
|
388 | var key = event.key,
|
389 | shiftKey = event.shiftKey;
|
390 | userTypingRef.current = true;
|
391 | shiftKeyRef.current = shiftKey;
|
392 | if (key === 'Enter') {
|
393 | if (!compositionRef.current) {
|
394 | userTypingRef.current = false;
|
395 | }
|
396 | flushInputValue(false);
|
397 | onPressEnter === null || onPressEnter === void 0 ? void 0 : onPressEnter(event);
|
398 | }
|
399 | if (keyboard === false) {
|
400 | return;
|
401 | }
|
402 |
|
403 |
|
404 | if (!compositionRef.current && ['Up', 'ArrowUp', 'Down', 'ArrowDown'].includes(key)) {
|
405 | onInternalStep(key === 'Up' || key === 'ArrowUp');
|
406 | event.preventDefault();
|
407 | }
|
408 | };
|
409 | var onKeyUp = function onKeyUp() {
|
410 | userTypingRef.current = false;
|
411 | shiftKeyRef.current = false;
|
412 | };
|
413 |
|
414 |
|
415 | var onBlur = function onBlur() {
|
416 | flushInputValue(false);
|
417 | setFocus(false);
|
418 | userTypingRef.current = false;
|
419 | };
|
420 |
|
421 |
|
422 |
|
423 | useLayoutUpdateEffect(function () {
|
424 | if (!decimalValue.isInvalidate()) {
|
425 | setInputValue(decimalValue, false);
|
426 | }
|
427 | }, [precision]);
|
428 |
|
429 |
|
430 | useLayoutUpdateEffect(function () {
|
431 | var newValue = getMiniDecimal(value);
|
432 | setDecimalValue(newValue);
|
433 | var currentParsedValue = getMiniDecimal(mergedParser(inputValue));
|
434 |
|
435 |
|
436 |
|
437 | if (!newValue.equals(currentParsedValue) || !userTypingRef.current || formatter) {
|
438 |
|
439 | setInputValue(newValue, userTypingRef.current);
|
440 | }
|
441 | }, [value]);
|
442 |
|
443 |
|
444 | useLayoutUpdateEffect(function () {
|
445 | if (formatter) {
|
446 | restoreCursor();
|
447 | }
|
448 | }, [inputValue]);
|
449 |
|
450 |
|
451 | return React.createElement("div", {
|
452 | className: clsx(prefixCls, classNames === null || classNames === void 0 ? void 0 : classNames.input, className, (_clsx = {}, _defineProperty(_clsx, "".concat(prefixCls, "-focused"), focus), _defineProperty(_clsx, "".concat(prefixCls, "-disabled"), disabled), _defineProperty(_clsx, "".concat(prefixCls, "-readonly"), readOnly), _defineProperty(_clsx, "".concat(prefixCls, "-not-a-number"), decimalValue.isNaN()), _defineProperty(_clsx, "".concat(prefixCls, "-out-of-range"), !decimalValue.isInvalidate() && !isInRange(decimalValue)), _clsx)),
|
453 | style: style,
|
454 | onFocus: function onFocus() {
|
455 | setFocus(true);
|
456 | },
|
457 | onBlur: onBlur,
|
458 | onKeyDown: onKeyDown,
|
459 | onKeyUp: onKeyUp,
|
460 | onCompositionStart: onCompositionStart,
|
461 | onCompositionEnd: onCompositionEnd,
|
462 | onBeforeInput: onBeforeInput
|
463 | }, controls && React.createElement(StepHandler, {
|
464 | prefixCls: prefixCls,
|
465 | upNode: upHandler,
|
466 | downNode: downHandler,
|
467 | upDisabled: upDisabled,
|
468 | downDisabled: downDisabled,
|
469 | onStep: onInternalStep
|
470 | }), React.createElement("div", {
|
471 | className: "".concat(inputClassName, "-wrap")
|
472 | }, React.createElement("input", _extends({
|
473 | autoComplete: "off",
|
474 | role: "spinbutton",
|
475 | "aria-valuemin": min,
|
476 | "aria-valuemax": max,
|
477 | "aria-valuenow": decimalValue.isInvalidate() ? null : decimalValue.toString(),
|
478 | step: step
|
479 | }, inputProps, {
|
480 | ref: composeRef(inputRef, ref),
|
481 | className: inputClassName,
|
482 | value: inputValue,
|
483 | onChange: onInternalInput,
|
484 | disabled: disabled,
|
485 | readOnly: readOnly
|
486 | }))));
|
487 | });
|
488 | var InputNumber = React.forwardRef(function (props, ref) {
|
489 | var disabled = props.disabled,
|
490 | style = props.style,
|
491 | prefixCls = props.prefixCls,
|
492 | value = props.value,
|
493 | prefix = props.prefix,
|
494 | suffix = props.suffix,
|
495 | addonBefore = props.addonBefore,
|
496 | addonAfter = props.addonAfter,
|
497 | classes = props.classes,
|
498 | className = props.className,
|
499 | classNames = props.classNames,
|
500 | rest = _objectWithoutProperties(props, _excluded2);
|
501 | var inputFocusRef = React.useRef(null);
|
502 | var focus = function focus(option) {
|
503 | if (inputFocusRef.current) {
|
504 | triggerFocus(inputFocusRef.current, option);
|
505 | }
|
506 | };
|
507 | return React.createElement(BaseInput, {
|
508 | inputElement: React.createElement(InternalInputNumber, _extends({
|
509 | prefixCls: prefixCls,
|
510 | disabled: disabled,
|
511 | classNames: classNames,
|
512 | ref: composeRef(inputFocusRef, ref)
|
513 | }, rest)),
|
514 | className: className,
|
515 | triggerFocus: focus,
|
516 | prefixCls: prefixCls,
|
517 | value: value,
|
518 | disabled: disabled,
|
519 | style: style,
|
520 | prefix: prefix,
|
521 | suffix: suffix,
|
522 | addonAfter: addonAfter,
|
523 | addonBefore: addonBefore,
|
524 | classes: classes,
|
525 | classNames: classNames,
|
526 | components: {
|
527 | affixWrapper: 'div',
|
528 | groupWrapper: 'div',
|
529 | wrapper: 'div',
|
530 | groupAddon: 'div'
|
531 | }
|
532 | });
|
533 | });
|
534 | InputNumber.displayName = 'InputNumber';
|
535 | export default InputNumber; |
\ | No newline at end of file |