@alfalab/core-components-number-input 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Component.d.ts +2 -0
- package/Component.js +50 -39
- package/cssm/Component.d.ts +2 -0
- package/cssm/Component.js +50 -39
- package/cssm/utils.d.ts +10 -1
- package/cssm/utils.js +23 -0
- package/esm/Component.d.ts +2 -0
- package/esm/Component.js +51 -40
- package/esm/utils.d.ts +10 -1
- package/esm/utils.js +23 -1
- package/modern/Component.d.ts +2 -0
- package/modern/Component.js +51 -40
- package/modern/utils.d.ts +10 -1
- package/modern/utils.js +22 -1
- package/package.json +1 -1
- package/utils.d.ts +10 -1
- package/utils.js +23 -0
package/Component.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ type NumberInputProps = Omit<InputProps, 'value' | 'onChange' | 'type'> & {
|
|
|
28
28
|
value: number | null;
|
|
29
29
|
/**
|
|
30
30
|
* Строковое значение инпута
|
|
31
|
+
* Используйте для изменения значения инпута
|
|
31
32
|
*/
|
|
32
33
|
valueString: string;
|
|
33
34
|
}) => void;
|
|
@@ -59,6 +60,7 @@ declare const NumberInput: React.ForwardRefExoticComponent<Omit<InputProps, "typ
|
|
|
59
60
|
value: number | null;
|
|
60
61
|
/**
|
|
61
62
|
* Строковое значение инпута
|
|
63
|
+
* Используйте для изменения значения инпута
|
|
62
64
|
*/
|
|
63
65
|
valueString: string;
|
|
64
66
|
}) => void) | undefined;
|
package/Component.js
CHANGED
|
@@ -17,64 +17,75 @@ var NumberInput = React__default.default.forwardRef(function (_a, ref) {
|
|
|
17
17
|
var inputRef = React.useRef(null);
|
|
18
18
|
var _d = React.useState(defaultValue || ''), value = _d[0], setValue = _d[1];
|
|
19
19
|
var getNumberValueFromStr = function (valueString) {
|
|
20
|
+
if (valueString === '')
|
|
21
|
+
return null;
|
|
20
22
|
if (valueString.includes(',')) {
|
|
21
23
|
return parseFloat(valueString.replace(',', '.'));
|
|
22
24
|
}
|
|
23
25
|
return parseFloat(valueString);
|
|
24
26
|
};
|
|
25
|
-
var getNumberRegExp = function () {
|
|
26
|
-
var reStr = '[0-9]+';
|
|
27
|
-
if (fractionLength !== 0) {
|
|
28
|
-
reStr = "".concat(reStr, "[").concat(utils.SEPARATORS.map(function (s) { return "\\".concat(s); }).join(''), "]?[0-9]{0,").concat(fractionLength || Number.MAX_SAFE_INTEGER, "}");
|
|
29
|
-
}
|
|
30
|
-
return new RegExp("^".concat(reStr, "$"));
|
|
31
|
-
};
|
|
32
27
|
var restoreCaret = function (target) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
28
|
+
setTimeout(function () {
|
|
29
|
+
var input = target;
|
|
30
|
+
var positionCursor = input.selectionStart || 0;
|
|
31
|
+
var isEndPosition = input.value.length === positionCursor;
|
|
32
|
+
var enteredSign = utils.SIGNS.some(function (s) { return s === input.value[positionCursor - 1]; });
|
|
33
|
+
var enteredSeparator = utils.SEPARATORS.filter(function (s) { return s !== separator; }).some(function (s) { return s === input.value[positionCursor - 1]; });
|
|
34
|
+
var shouldRestore = enteredSeparator || enteredSign;
|
|
35
|
+
if (!isEndPosition && shouldRestore) {
|
|
41
36
|
input.selectionStart = positionCursor;
|
|
42
37
|
input.selectionEnd = positionCursor;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
38
|
+
}
|
|
39
|
+
});
|
|
45
40
|
};
|
|
46
41
|
var handleChange = function (event) {
|
|
47
42
|
var input = event.target;
|
|
48
|
-
var
|
|
49
|
-
var
|
|
50
|
-
|
|
51
|
-
:
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
if (uncontrolled) {
|
|
61
|
-
setValue(newValue);
|
|
62
|
-
}
|
|
63
|
-
restoreCaret(input);
|
|
43
|
+
var newValue = input.value.replace(utils.createSeparatorsRegExp(), separator);
|
|
44
|
+
var allowedValue = utils.getAllowedValue({
|
|
45
|
+
value: newValue,
|
|
46
|
+
fractionLength: fractionLength,
|
|
47
|
+
allowSigns: allowSigns,
|
|
48
|
+
separator: separator,
|
|
49
|
+
});
|
|
50
|
+
if (onChange) {
|
|
51
|
+
onChange(event, {
|
|
52
|
+
value: getNumberValueFromStr(allowedValue),
|
|
53
|
+
valueString: allowedValue,
|
|
54
|
+
});
|
|
64
55
|
}
|
|
56
|
+
if (uncontrolled) {
|
|
57
|
+
setValue(allowedValue);
|
|
58
|
+
}
|
|
59
|
+
restoreCaret(input);
|
|
65
60
|
};
|
|
66
61
|
var handleKeyDown = function (event) {
|
|
67
62
|
var disallowedSymbols = /[/|?!@#$%^&*()_=A-Za-zА-Яа-яЁё ]/;
|
|
68
|
-
var oneKeyPress = !event.altKey && !event.metaKey && !event.ctrlKey
|
|
69
|
-
// Запрещаем вводить неразрешенные символы за исключением
|
|
63
|
+
var oneKeyPress = !event.altKey && !event.metaKey && !event.ctrlKey;
|
|
64
|
+
// Запрещаем вводить неразрешенные символы за исключением комбинаций клавиш
|
|
70
65
|
if (oneKeyPress && event.key.length === 1 && disallowedSymbols.test(event.key)) {
|
|
71
|
-
event.preventDefault();
|
|
66
|
+
return event.preventDefault();
|
|
72
67
|
}
|
|
68
|
+
var val = event.target.value;
|
|
69
|
+
var hasSeparator = (val.match(utils.createSeparatorsRegExp()) || []).length > 0;
|
|
73
70
|
// Запрещаем вводить второй сепаратор
|
|
74
|
-
if (utils.SEPARATORS.some(function (s) { return s === event.key; })
|
|
75
|
-
|
|
76
|
-
|
|
71
|
+
if (hasSeparator && utils.SEPARATORS.some(function (s) { return s === event.key; })) {
|
|
72
|
+
return event.preventDefault();
|
|
73
|
+
}
|
|
74
|
+
// Запрещаем вводить лишний знак
|
|
75
|
+
if ((!allowSigns || utils.SIGNS.some(function (s) { return s === val[0]; })) &&
|
|
76
|
+
utils.SIGNS.some(function (s) { return s === event.key; })) {
|
|
77
|
+
return event.preventDefault();
|
|
78
|
+
}
|
|
79
|
+
var selectionStart = event.target.selectionStart || 0;
|
|
80
|
+
// Запрещаем вводить цифры в дробную часть, если кол-во цифр больше fractionLength
|
|
81
|
+
if (hasSeparator &&
|
|
82
|
+
fractionLength &&
|
|
83
|
+
event.key.length === 1 &&
|
|
84
|
+
selectionStart > val.indexOf(separator) &&
|
|
85
|
+
val.split(separator)[1].length >= fractionLength) {
|
|
86
|
+
return event.preventDefault();
|
|
77
87
|
}
|
|
88
|
+
return undefined;
|
|
78
89
|
};
|
|
79
90
|
var handleBlur = function (event) {
|
|
80
91
|
var valueBlur = event.target.value.replace(new RegExp("\\".concat(separator, "$")), '');
|
package/cssm/Component.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ type NumberInputProps = Omit<InputProps, 'value' | 'onChange' | 'type'> & {
|
|
|
28
28
|
value: number | null;
|
|
29
29
|
/**
|
|
30
30
|
* Строковое значение инпута
|
|
31
|
+
* Используйте для изменения значения инпута
|
|
31
32
|
*/
|
|
32
33
|
valueString: string;
|
|
33
34
|
}) => void;
|
|
@@ -59,6 +60,7 @@ declare const NumberInput: React.ForwardRefExoticComponent<Omit<InputProps, "typ
|
|
|
59
60
|
value: number | null;
|
|
60
61
|
/**
|
|
61
62
|
* Строковое значение инпута
|
|
63
|
+
* Используйте для изменения значения инпута
|
|
62
64
|
*/
|
|
63
65
|
valueString: string;
|
|
64
66
|
}) => void) | undefined;
|
package/cssm/Component.js
CHANGED
|
@@ -17,64 +17,75 @@ var NumberInput = React__default.default.forwardRef(function (_a, ref) {
|
|
|
17
17
|
var inputRef = React.useRef(null);
|
|
18
18
|
var _d = React.useState(defaultValue || ''), value = _d[0], setValue = _d[1];
|
|
19
19
|
var getNumberValueFromStr = function (valueString) {
|
|
20
|
+
if (valueString === '')
|
|
21
|
+
return null;
|
|
20
22
|
if (valueString.includes(',')) {
|
|
21
23
|
return parseFloat(valueString.replace(',', '.'));
|
|
22
24
|
}
|
|
23
25
|
return parseFloat(valueString);
|
|
24
26
|
};
|
|
25
|
-
var getNumberRegExp = function () {
|
|
26
|
-
var reStr = '[0-9]+';
|
|
27
|
-
if (fractionLength !== 0) {
|
|
28
|
-
reStr = "".concat(reStr, "[").concat(utils.SEPARATORS.map(function (s) { return "\\".concat(s); }).join(''), "]?[0-9]{0,").concat(fractionLength || Number.MAX_SAFE_INTEGER, "}");
|
|
29
|
-
}
|
|
30
|
-
return new RegExp("^".concat(reStr, "$"));
|
|
31
|
-
};
|
|
32
27
|
var restoreCaret = function (target) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
28
|
+
setTimeout(function () {
|
|
29
|
+
var input = target;
|
|
30
|
+
var positionCursor = input.selectionStart || 0;
|
|
31
|
+
var isEndPosition = input.value.length === positionCursor;
|
|
32
|
+
var enteredSign = utils.SIGNS.some(function (s) { return s === input.value[positionCursor - 1]; });
|
|
33
|
+
var enteredSeparator = utils.SEPARATORS.filter(function (s) { return s !== separator; }).some(function (s) { return s === input.value[positionCursor - 1]; });
|
|
34
|
+
var shouldRestore = enteredSeparator || enteredSign;
|
|
35
|
+
if (!isEndPosition && shouldRestore) {
|
|
41
36
|
input.selectionStart = positionCursor;
|
|
42
37
|
input.selectionEnd = positionCursor;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
38
|
+
}
|
|
39
|
+
});
|
|
45
40
|
};
|
|
46
41
|
var handleChange = function (event) {
|
|
47
42
|
var input = event.target;
|
|
48
|
-
var
|
|
49
|
-
var
|
|
50
|
-
|
|
51
|
-
:
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
if (uncontrolled) {
|
|
61
|
-
setValue(newValue);
|
|
62
|
-
}
|
|
63
|
-
restoreCaret(input);
|
|
43
|
+
var newValue = input.value.replace(utils.createSeparatorsRegExp(), separator);
|
|
44
|
+
var allowedValue = utils.getAllowedValue({
|
|
45
|
+
value: newValue,
|
|
46
|
+
fractionLength: fractionLength,
|
|
47
|
+
allowSigns: allowSigns,
|
|
48
|
+
separator: separator,
|
|
49
|
+
});
|
|
50
|
+
if (onChange) {
|
|
51
|
+
onChange(event, {
|
|
52
|
+
value: getNumberValueFromStr(allowedValue),
|
|
53
|
+
valueString: allowedValue,
|
|
54
|
+
});
|
|
64
55
|
}
|
|
56
|
+
if (uncontrolled) {
|
|
57
|
+
setValue(allowedValue);
|
|
58
|
+
}
|
|
59
|
+
restoreCaret(input);
|
|
65
60
|
};
|
|
66
61
|
var handleKeyDown = function (event) {
|
|
67
62
|
var disallowedSymbols = /[/|?!@#$%^&*()_=A-Za-zА-Яа-яЁё ]/;
|
|
68
|
-
var oneKeyPress = !event.altKey && !event.metaKey && !event.ctrlKey
|
|
69
|
-
// Запрещаем вводить неразрешенные символы за исключением
|
|
63
|
+
var oneKeyPress = !event.altKey && !event.metaKey && !event.ctrlKey;
|
|
64
|
+
// Запрещаем вводить неразрешенные символы за исключением комбинаций клавиш
|
|
70
65
|
if (oneKeyPress && event.key.length === 1 && disallowedSymbols.test(event.key)) {
|
|
71
|
-
event.preventDefault();
|
|
66
|
+
return event.preventDefault();
|
|
72
67
|
}
|
|
68
|
+
var val = event.target.value;
|
|
69
|
+
var hasSeparator = (val.match(utils.createSeparatorsRegExp()) || []).length > 0;
|
|
73
70
|
// Запрещаем вводить второй сепаратор
|
|
74
|
-
if (utils.SEPARATORS.some(function (s) { return s === event.key; })
|
|
75
|
-
|
|
76
|
-
|
|
71
|
+
if (hasSeparator && utils.SEPARATORS.some(function (s) { return s === event.key; })) {
|
|
72
|
+
return event.preventDefault();
|
|
73
|
+
}
|
|
74
|
+
// Запрещаем вводить лишний знак
|
|
75
|
+
if ((!allowSigns || utils.SIGNS.some(function (s) { return s === val[0]; })) &&
|
|
76
|
+
utils.SIGNS.some(function (s) { return s === event.key; })) {
|
|
77
|
+
return event.preventDefault();
|
|
78
|
+
}
|
|
79
|
+
var selectionStart = event.target.selectionStart || 0;
|
|
80
|
+
// Запрещаем вводить цифры в дробную часть, если кол-во цифр больше fractionLength
|
|
81
|
+
if (hasSeparator &&
|
|
82
|
+
fractionLength &&
|
|
83
|
+
event.key.length === 1 &&
|
|
84
|
+
selectionStart > val.indexOf(separator) &&
|
|
85
|
+
val.split(separator)[1].length >= fractionLength) {
|
|
86
|
+
return event.preventDefault();
|
|
77
87
|
}
|
|
88
|
+
return undefined;
|
|
78
89
|
};
|
|
79
90
|
var handleBlur = function (event) {
|
|
80
91
|
var valueBlur = event.target.value.replace(new RegExp("\\".concat(separator, "$")), '');
|
package/cssm/utils.d.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
declare const SIGNS: string[];
|
|
2
2
|
declare const SEPARATORS: string[];
|
|
3
3
|
declare function createSeparatorsRegExp(): RegExp;
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Проверка вводимых значений.
|
|
6
|
+
*/
|
|
7
|
+
declare const getAllowedValue: ({ value, fractionLength, separator, allowSigns, }: {
|
|
8
|
+
value: string;
|
|
9
|
+
fractionLength?: number | undefined;
|
|
10
|
+
separator: string;
|
|
11
|
+
allowSigns: boolean;
|
|
12
|
+
}) => string;
|
|
13
|
+
export { SIGNS, SEPARATORS, createSeparatorsRegExp, getAllowedValue };
|
package/cssm/utils.js
CHANGED
|
@@ -5,7 +5,30 @@ var SEPARATORS = [',', '.'];
|
|
|
5
5
|
function createSeparatorsRegExp() {
|
|
6
6
|
return new RegExp("[".concat(SEPARATORS.map(function (s) { return "\\".concat(s); }).join(''), "]"), 'g');
|
|
7
7
|
}
|
|
8
|
+
var getNumberRegExp = function (fractionLength) {
|
|
9
|
+
var reStr = '[0-9]+';
|
|
10
|
+
if (fractionLength !== 0) {
|
|
11
|
+
reStr = "".concat(reStr, "[").concat(SEPARATORS.map(function (s) { return "\\".concat(s); }).join(''), "]?[0-9]{0,").concat(fractionLength || Number.MAX_SAFE_INTEGER, "}");
|
|
12
|
+
}
|
|
13
|
+
return new RegExp("^".concat(reStr, "$"));
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Проверка вводимых значений.
|
|
17
|
+
*/
|
|
18
|
+
var getAllowedValue = function (_a) {
|
|
19
|
+
var _b = _a.value, value = _b === void 0 ? '' : _b, fractionLength = _a.fractionLength, separator = _a.separator, allowSigns = _a.allowSigns;
|
|
20
|
+
var sign = allowSigns && SIGNS.some(function (s) { return s === value[0]; }) ? value[0] : '';
|
|
21
|
+
var testedValue = sign ? value.slice(1) : value;
|
|
22
|
+
if (getNumberRegExp(fractionLength).test(testedValue)) {
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
var _c = testedValue
|
|
26
|
+
.split(separator)
|
|
27
|
+
.map(function (v) { return v.replace(/[^0-9]/g, ''); }), majorPart = _c[0], minorPart = _c[1];
|
|
28
|
+
return "".concat(sign).concat(majorPart).concat(minorPart ? separator + minorPart.slice(0, fractionLength) : '');
|
|
29
|
+
};
|
|
8
30
|
|
|
9
31
|
exports.SEPARATORS = SEPARATORS;
|
|
10
32
|
exports.SIGNS = SIGNS;
|
|
11
33
|
exports.createSeparatorsRegExp = createSeparatorsRegExp;
|
|
34
|
+
exports.getAllowedValue = getAllowedValue;
|
package/esm/Component.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ type NumberInputProps = Omit<InputProps, 'value' | 'onChange' | 'type'> & {
|
|
|
28
28
|
value: number | null;
|
|
29
29
|
/**
|
|
30
30
|
* Строковое значение инпута
|
|
31
|
+
* Используйте для изменения значения инпута
|
|
31
32
|
*/
|
|
32
33
|
valueString: string;
|
|
33
34
|
}) => void;
|
|
@@ -59,6 +60,7 @@ declare const NumberInput: React.ForwardRefExoticComponent<Omit<InputProps, "typ
|
|
|
59
60
|
value: number | null;
|
|
60
61
|
/**
|
|
61
62
|
* Строковое значение инпута
|
|
63
|
+
* Используйте для изменения значения инпута
|
|
62
64
|
*/
|
|
63
65
|
valueString: string;
|
|
64
66
|
}) => void) | undefined;
|
package/esm/Component.js
CHANGED
|
@@ -2,7 +2,7 @@ import { __rest, __assign } from 'tslib';
|
|
|
2
2
|
import React, { useRef, useState } from 'react';
|
|
3
3
|
import mergeRefs from 'react-merge-refs';
|
|
4
4
|
import { Input } from '@alfalab/core-components-input/esm';
|
|
5
|
-
import {
|
|
5
|
+
import { createSeparatorsRegExp, getAllowedValue, SEPARATORS, SIGNS } from './utils.js';
|
|
6
6
|
|
|
7
7
|
var NumberInput = React.forwardRef(function (_a, ref) {
|
|
8
8
|
var propValue = _a.value, onChange = _a.onChange, onBlur = _a.onBlur, _b = _a.allowSigns, allowSigns = _b === void 0 ? true : _b, _c = _a.separator, separator = _c === void 0 ? ',' : _c, fractionLength = _a.fractionLength, defaultValue = _a.defaultValue, restProps = __rest(_a, ["value", "onChange", "onBlur", "allowSigns", "separator", "fractionLength", "defaultValue"]);
|
|
@@ -10,64 +10,75 @@ var NumberInput = React.forwardRef(function (_a, ref) {
|
|
|
10
10
|
var inputRef = useRef(null);
|
|
11
11
|
var _d = useState(defaultValue || ''), value = _d[0], setValue = _d[1];
|
|
12
12
|
var getNumberValueFromStr = function (valueString) {
|
|
13
|
+
if (valueString === '')
|
|
14
|
+
return null;
|
|
13
15
|
if (valueString.includes(',')) {
|
|
14
16
|
return parseFloat(valueString.replace(',', '.'));
|
|
15
17
|
}
|
|
16
18
|
return parseFloat(valueString);
|
|
17
19
|
};
|
|
18
|
-
var getNumberRegExp = function () {
|
|
19
|
-
var reStr = '[0-9]+';
|
|
20
|
-
if (fractionLength !== 0) {
|
|
21
|
-
reStr = "".concat(reStr, "[").concat(SEPARATORS.map(function (s) { return "\\".concat(s); }).join(''), "]?[0-9]{0,").concat(fractionLength || Number.MAX_SAFE_INTEGER, "}");
|
|
22
|
-
}
|
|
23
|
-
return new RegExp("^".concat(reStr, "$"));
|
|
24
|
-
};
|
|
25
20
|
var restoreCaret = function (target) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
21
|
+
setTimeout(function () {
|
|
22
|
+
var input = target;
|
|
23
|
+
var positionCursor = input.selectionStart || 0;
|
|
24
|
+
var isEndPosition = input.value.length === positionCursor;
|
|
25
|
+
var enteredSign = SIGNS.some(function (s) { return s === input.value[positionCursor - 1]; });
|
|
26
|
+
var enteredSeparator = SEPARATORS.filter(function (s) { return s !== separator; }).some(function (s) { return s === input.value[positionCursor - 1]; });
|
|
27
|
+
var shouldRestore = enteredSeparator || enteredSign;
|
|
28
|
+
if (!isEndPosition && shouldRestore) {
|
|
34
29
|
input.selectionStart = positionCursor;
|
|
35
30
|
input.selectionEnd = positionCursor;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
31
|
+
}
|
|
32
|
+
});
|
|
38
33
|
};
|
|
39
34
|
var handleChange = function (event) {
|
|
40
35
|
var input = event.target;
|
|
41
|
-
var
|
|
42
|
-
var
|
|
43
|
-
|
|
44
|
-
:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
if (uncontrolled) {
|
|
54
|
-
setValue(newValue);
|
|
55
|
-
}
|
|
56
|
-
restoreCaret(input);
|
|
36
|
+
var newValue = input.value.replace(createSeparatorsRegExp(), separator);
|
|
37
|
+
var allowedValue = getAllowedValue({
|
|
38
|
+
value: newValue,
|
|
39
|
+
fractionLength: fractionLength,
|
|
40
|
+
allowSigns: allowSigns,
|
|
41
|
+
separator: separator,
|
|
42
|
+
});
|
|
43
|
+
if (onChange) {
|
|
44
|
+
onChange(event, {
|
|
45
|
+
value: getNumberValueFromStr(allowedValue),
|
|
46
|
+
valueString: allowedValue,
|
|
47
|
+
});
|
|
57
48
|
}
|
|
49
|
+
if (uncontrolled) {
|
|
50
|
+
setValue(allowedValue);
|
|
51
|
+
}
|
|
52
|
+
restoreCaret(input);
|
|
58
53
|
};
|
|
59
54
|
var handleKeyDown = function (event) {
|
|
60
55
|
var disallowedSymbols = /[/|?!@#$%^&*()_=A-Za-zА-Яа-яЁё ]/;
|
|
61
|
-
var oneKeyPress = !event.altKey && !event.metaKey && !event.ctrlKey
|
|
62
|
-
// Запрещаем вводить неразрешенные символы за исключением
|
|
56
|
+
var oneKeyPress = !event.altKey && !event.metaKey && !event.ctrlKey;
|
|
57
|
+
// Запрещаем вводить неразрешенные символы за исключением комбинаций клавиш
|
|
63
58
|
if (oneKeyPress && event.key.length === 1 && disallowedSymbols.test(event.key)) {
|
|
64
|
-
event.preventDefault();
|
|
59
|
+
return event.preventDefault();
|
|
65
60
|
}
|
|
61
|
+
var val = event.target.value;
|
|
62
|
+
var hasSeparator = (val.match(createSeparatorsRegExp()) || []).length > 0;
|
|
66
63
|
// Запрещаем вводить второй сепаратор
|
|
67
|
-
if (SEPARATORS.some(function (s) { return s === event.key; })
|
|
68
|
-
|
|
69
|
-
|
|
64
|
+
if (hasSeparator && SEPARATORS.some(function (s) { return s === event.key; })) {
|
|
65
|
+
return event.preventDefault();
|
|
66
|
+
}
|
|
67
|
+
// Запрещаем вводить лишний знак
|
|
68
|
+
if ((!allowSigns || SIGNS.some(function (s) { return s === val[0]; })) &&
|
|
69
|
+
SIGNS.some(function (s) { return s === event.key; })) {
|
|
70
|
+
return event.preventDefault();
|
|
71
|
+
}
|
|
72
|
+
var selectionStart = event.target.selectionStart || 0;
|
|
73
|
+
// Запрещаем вводить цифры в дробную часть, если кол-во цифр больше fractionLength
|
|
74
|
+
if (hasSeparator &&
|
|
75
|
+
fractionLength &&
|
|
76
|
+
event.key.length === 1 &&
|
|
77
|
+
selectionStart > val.indexOf(separator) &&
|
|
78
|
+
val.split(separator)[1].length >= fractionLength) {
|
|
79
|
+
return event.preventDefault();
|
|
70
80
|
}
|
|
81
|
+
return undefined;
|
|
71
82
|
};
|
|
72
83
|
var handleBlur = function (event) {
|
|
73
84
|
var valueBlur = event.target.value.replace(new RegExp("\\".concat(separator, "$")), '');
|
package/esm/utils.d.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
declare const SIGNS: string[];
|
|
2
2
|
declare const SEPARATORS: string[];
|
|
3
3
|
declare function createSeparatorsRegExp(): RegExp;
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Проверка вводимых значений.
|
|
6
|
+
*/
|
|
7
|
+
declare const getAllowedValue: ({ value, fractionLength, separator, allowSigns, }: {
|
|
8
|
+
value: string;
|
|
9
|
+
fractionLength?: number | undefined;
|
|
10
|
+
separator: string;
|
|
11
|
+
allowSigns: boolean;
|
|
12
|
+
}) => string;
|
|
13
|
+
export { SIGNS, SEPARATORS, createSeparatorsRegExp, getAllowedValue };
|
package/esm/utils.js
CHANGED
|
@@ -3,5 +3,27 @@ var SEPARATORS = [',', '.'];
|
|
|
3
3
|
function createSeparatorsRegExp() {
|
|
4
4
|
return new RegExp("[".concat(SEPARATORS.map(function (s) { return "\\".concat(s); }).join(''), "]"), 'g');
|
|
5
5
|
}
|
|
6
|
+
var getNumberRegExp = function (fractionLength) {
|
|
7
|
+
var reStr = '[0-9]+';
|
|
8
|
+
if (fractionLength !== 0) {
|
|
9
|
+
reStr = "".concat(reStr, "[").concat(SEPARATORS.map(function (s) { return "\\".concat(s); }).join(''), "]?[0-9]{0,").concat(fractionLength || Number.MAX_SAFE_INTEGER, "}");
|
|
10
|
+
}
|
|
11
|
+
return new RegExp("^".concat(reStr, "$"));
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Проверка вводимых значений.
|
|
15
|
+
*/
|
|
16
|
+
var getAllowedValue = function (_a) {
|
|
17
|
+
var _b = _a.value, value = _b === void 0 ? '' : _b, fractionLength = _a.fractionLength, separator = _a.separator, allowSigns = _a.allowSigns;
|
|
18
|
+
var sign = allowSigns && SIGNS.some(function (s) { return s === value[0]; }) ? value[0] : '';
|
|
19
|
+
var testedValue = sign ? value.slice(1) : value;
|
|
20
|
+
if (getNumberRegExp(fractionLength).test(testedValue)) {
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
var _c = testedValue
|
|
24
|
+
.split(separator)
|
|
25
|
+
.map(function (v) { return v.replace(/[^0-9]/g, ''); }), majorPart = _c[0], minorPart = _c[1];
|
|
26
|
+
return "".concat(sign).concat(majorPart).concat(minorPart ? separator + minorPart.slice(0, fractionLength) : '');
|
|
27
|
+
};
|
|
6
28
|
|
|
7
|
-
export { SEPARATORS, SIGNS, createSeparatorsRegExp };
|
|
29
|
+
export { SEPARATORS, SIGNS, createSeparatorsRegExp, getAllowedValue };
|
package/modern/Component.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ type NumberInputProps = Omit<InputProps, 'value' | 'onChange' | 'type'> & {
|
|
|
28
28
|
value: number | null;
|
|
29
29
|
/**
|
|
30
30
|
* Строковое значение инпута
|
|
31
|
+
* Используйте для изменения значения инпута
|
|
31
32
|
*/
|
|
32
33
|
valueString: string;
|
|
33
34
|
}) => void;
|
|
@@ -59,6 +60,7 @@ declare const NumberInput: React.ForwardRefExoticComponent<Omit<InputProps, "typ
|
|
|
59
60
|
value: number | null;
|
|
60
61
|
/**
|
|
61
62
|
* Строковое значение инпута
|
|
63
|
+
* Используйте для изменения значения инпута
|
|
62
64
|
*/
|
|
63
65
|
valueString: string;
|
|
64
66
|
}) => void) | undefined;
|
package/modern/Component.js
CHANGED
|
@@ -1,71 +1,82 @@
|
|
|
1
1
|
import React, { useRef, useState } from 'react';
|
|
2
2
|
import mergeRefs from 'react-merge-refs';
|
|
3
3
|
import { Input } from '@alfalab/core-components-input/modern';
|
|
4
|
-
import {
|
|
4
|
+
import { createSeparatorsRegExp, getAllowedValue, SEPARATORS, SIGNS } from './utils.js';
|
|
5
5
|
|
|
6
6
|
const NumberInput = React.forwardRef(({ value: propValue, onChange, onBlur, allowSigns = true, separator = ',', fractionLength, defaultValue, ...restProps }, ref) => {
|
|
7
7
|
const uncontrolled = propValue === undefined;
|
|
8
8
|
const inputRef = useRef(null);
|
|
9
9
|
const [value, setValue] = useState(defaultValue || '');
|
|
10
10
|
const getNumberValueFromStr = (valueString) => {
|
|
11
|
+
if (valueString === '')
|
|
12
|
+
return null;
|
|
11
13
|
if (valueString.includes(',')) {
|
|
12
14
|
return parseFloat(valueString.replace(',', '.'));
|
|
13
15
|
}
|
|
14
16
|
return parseFloat(valueString);
|
|
15
17
|
};
|
|
16
|
-
const getNumberRegExp = () => {
|
|
17
|
-
let reStr = '[0-9]+';
|
|
18
|
-
if (fractionLength !== 0) {
|
|
19
|
-
reStr = `${reStr}[${SEPARATORS.map((s) => `\\${s}`).join('')}]?[0-9]{0,${fractionLength || Number.MAX_SAFE_INTEGER}}`;
|
|
20
|
-
}
|
|
21
|
-
return new RegExp(`^${reStr}$`);
|
|
22
|
-
};
|
|
23
18
|
const restoreCaret = (target) => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
19
|
+
setTimeout(() => {
|
|
20
|
+
const input = target;
|
|
21
|
+
const positionCursor = input.selectionStart || 0;
|
|
22
|
+
const isEndPosition = input.value.length === positionCursor;
|
|
23
|
+
const enteredSign = SIGNS.some((s) => s === input.value[positionCursor - 1]);
|
|
24
|
+
const enteredSeparator = SEPARATORS.filter((s) => s !== separator).some((s) => s === input.value[positionCursor - 1]);
|
|
25
|
+
const shouldRestore = enteredSeparator || enteredSign;
|
|
26
|
+
if (!isEndPosition && shouldRestore) {
|
|
32
27
|
input.selectionStart = positionCursor;
|
|
33
28
|
input.selectionEnd = positionCursor;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
29
|
+
}
|
|
30
|
+
});
|
|
36
31
|
};
|
|
37
32
|
const handleChange = (event) => {
|
|
38
33
|
const input = event.target;
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
if (uncontrolled) {
|
|
52
|
-
setValue(newValue);
|
|
53
|
-
}
|
|
54
|
-
restoreCaret(input);
|
|
34
|
+
const newValue = input.value.replace(createSeparatorsRegExp(), separator);
|
|
35
|
+
const allowedValue = getAllowedValue({
|
|
36
|
+
value: newValue,
|
|
37
|
+
fractionLength,
|
|
38
|
+
allowSigns,
|
|
39
|
+
separator,
|
|
40
|
+
});
|
|
41
|
+
if (onChange) {
|
|
42
|
+
onChange(event, {
|
|
43
|
+
value: getNumberValueFromStr(allowedValue),
|
|
44
|
+
valueString: allowedValue,
|
|
45
|
+
});
|
|
55
46
|
}
|
|
47
|
+
if (uncontrolled) {
|
|
48
|
+
setValue(allowedValue);
|
|
49
|
+
}
|
|
50
|
+
restoreCaret(input);
|
|
56
51
|
};
|
|
57
52
|
const handleKeyDown = (event) => {
|
|
58
53
|
const disallowedSymbols = /[/|?!@#$%^&*()_=A-Za-zА-Яа-яЁё ]/;
|
|
59
|
-
const oneKeyPress = !event.altKey && !event.metaKey && !event.ctrlKey
|
|
60
|
-
// Запрещаем вводить неразрешенные символы за исключением
|
|
54
|
+
const oneKeyPress = !event.altKey && !event.metaKey && !event.ctrlKey;
|
|
55
|
+
// Запрещаем вводить неразрешенные символы за исключением комбинаций клавиш
|
|
61
56
|
if (oneKeyPress && event.key.length === 1 && disallowedSymbols.test(event.key)) {
|
|
62
|
-
event.preventDefault();
|
|
57
|
+
return event.preventDefault();
|
|
63
58
|
}
|
|
59
|
+
const val = event.target.value;
|
|
60
|
+
const hasSeparator = (val.match(createSeparatorsRegExp()) || []).length > 0;
|
|
64
61
|
// Запрещаем вводить второй сепаратор
|
|
65
|
-
if (SEPARATORS.some((s) => s === event.key)
|
|
66
|
-
|
|
67
|
-
|
|
62
|
+
if (hasSeparator && SEPARATORS.some((s) => s === event.key)) {
|
|
63
|
+
return event.preventDefault();
|
|
64
|
+
}
|
|
65
|
+
// Запрещаем вводить лишний знак
|
|
66
|
+
if ((!allowSigns || SIGNS.some((s) => s === val[0])) &&
|
|
67
|
+
SIGNS.some((s) => s === event.key)) {
|
|
68
|
+
return event.preventDefault();
|
|
69
|
+
}
|
|
70
|
+
const selectionStart = event.target.selectionStart || 0;
|
|
71
|
+
// Запрещаем вводить цифры в дробную часть, если кол-во цифр больше fractionLength
|
|
72
|
+
if (hasSeparator &&
|
|
73
|
+
fractionLength &&
|
|
74
|
+
event.key.length === 1 &&
|
|
75
|
+
selectionStart > val.indexOf(separator) &&
|
|
76
|
+
val.split(separator)[1].length >= fractionLength) {
|
|
77
|
+
return event.preventDefault();
|
|
68
78
|
}
|
|
79
|
+
return undefined;
|
|
69
80
|
};
|
|
70
81
|
const handleBlur = (event) => {
|
|
71
82
|
const valueBlur = event.target.value.replace(new RegExp(`\\${separator}$`), '');
|
package/modern/utils.d.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
declare const SIGNS: string[];
|
|
2
2
|
declare const SEPARATORS: string[];
|
|
3
3
|
declare function createSeparatorsRegExp(): RegExp;
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Проверка вводимых значений.
|
|
6
|
+
*/
|
|
7
|
+
declare const getAllowedValue: ({ value, fractionLength, separator, allowSigns, }: {
|
|
8
|
+
value: string;
|
|
9
|
+
fractionLength?: number | undefined;
|
|
10
|
+
separator: string;
|
|
11
|
+
allowSigns: boolean;
|
|
12
|
+
}) => string;
|
|
13
|
+
export { SIGNS, SEPARATORS, createSeparatorsRegExp, getAllowedValue };
|
package/modern/utils.js
CHANGED
|
@@ -3,5 +3,26 @@ const SEPARATORS = [',', '.'];
|
|
|
3
3
|
function createSeparatorsRegExp() {
|
|
4
4
|
return new RegExp(`[${SEPARATORS.map((s) => `\\${s}`).join('')}]`, 'g');
|
|
5
5
|
}
|
|
6
|
+
const getNumberRegExp = (fractionLength) => {
|
|
7
|
+
let reStr = '[0-9]+';
|
|
8
|
+
if (fractionLength !== 0) {
|
|
9
|
+
reStr = `${reStr}[${SEPARATORS.map((s) => `\\${s}`).join('')}]?[0-9]{0,${fractionLength || Number.MAX_SAFE_INTEGER}}`;
|
|
10
|
+
}
|
|
11
|
+
return new RegExp(`^${reStr}$`);
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Проверка вводимых значений.
|
|
15
|
+
*/
|
|
16
|
+
const getAllowedValue = ({ value = '', fractionLength, separator, allowSigns, }) => {
|
|
17
|
+
const sign = allowSigns && SIGNS.some((s) => s === value[0]) ? value[0] : '';
|
|
18
|
+
const testedValue = sign ? value.slice(1) : value;
|
|
19
|
+
if (getNumberRegExp(fractionLength).test(testedValue)) {
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
const [majorPart, minorPart] = testedValue
|
|
23
|
+
.split(separator)
|
|
24
|
+
.map((v) => v.replace(/[^0-9]/g, ''));
|
|
25
|
+
return `${sign}${majorPart}${minorPart ? separator + minorPart.slice(0, fractionLength) : ''}`;
|
|
26
|
+
};
|
|
6
27
|
|
|
7
|
-
export { SEPARATORS, SIGNS, createSeparatorsRegExp };
|
|
28
|
+
export { SEPARATORS, SIGNS, createSeparatorsRegExp, getAllowedValue };
|
package/package.json
CHANGED
package/utils.d.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
declare const SIGNS: string[];
|
|
2
2
|
declare const SEPARATORS: string[];
|
|
3
3
|
declare function createSeparatorsRegExp(): RegExp;
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Проверка вводимых значений.
|
|
6
|
+
*/
|
|
7
|
+
declare const getAllowedValue: ({ value, fractionLength, separator, allowSigns, }: {
|
|
8
|
+
value: string;
|
|
9
|
+
fractionLength?: number | undefined;
|
|
10
|
+
separator: string;
|
|
11
|
+
allowSigns: boolean;
|
|
12
|
+
}) => string;
|
|
13
|
+
export { SIGNS, SEPARATORS, createSeparatorsRegExp, getAllowedValue };
|
package/utils.js
CHANGED
|
@@ -5,7 +5,30 @@ var SEPARATORS = [',', '.'];
|
|
|
5
5
|
function createSeparatorsRegExp() {
|
|
6
6
|
return new RegExp("[".concat(SEPARATORS.map(function (s) { return "\\".concat(s); }).join(''), "]"), 'g');
|
|
7
7
|
}
|
|
8
|
+
var getNumberRegExp = function (fractionLength) {
|
|
9
|
+
var reStr = '[0-9]+';
|
|
10
|
+
if (fractionLength !== 0) {
|
|
11
|
+
reStr = "".concat(reStr, "[").concat(SEPARATORS.map(function (s) { return "\\".concat(s); }).join(''), "]?[0-9]{0,").concat(fractionLength || Number.MAX_SAFE_INTEGER, "}");
|
|
12
|
+
}
|
|
13
|
+
return new RegExp("^".concat(reStr, "$"));
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Проверка вводимых значений.
|
|
17
|
+
*/
|
|
18
|
+
var getAllowedValue = function (_a) {
|
|
19
|
+
var _b = _a.value, value = _b === void 0 ? '' : _b, fractionLength = _a.fractionLength, separator = _a.separator, allowSigns = _a.allowSigns;
|
|
20
|
+
var sign = allowSigns && SIGNS.some(function (s) { return s === value[0]; }) ? value[0] : '';
|
|
21
|
+
var testedValue = sign ? value.slice(1) : value;
|
|
22
|
+
if (getNumberRegExp(fractionLength).test(testedValue)) {
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
var _c = testedValue
|
|
26
|
+
.split(separator)
|
|
27
|
+
.map(function (v) { return v.replace(/[^0-9]/g, ''); }), majorPart = _c[0], minorPart = _c[1];
|
|
28
|
+
return "".concat(sign).concat(majorPart).concat(minorPart ? separator + minorPart.slice(0, fractionLength) : '');
|
|
29
|
+
};
|
|
8
30
|
|
|
9
31
|
exports.SEPARATORS = SEPARATORS;
|
|
10
32
|
exports.SIGNS = SIGNS;
|
|
11
33
|
exports.createSeparatorsRegExp = createSeparatorsRegExp;
|
|
34
|
+
exports.getAllowedValue = getAllowedValue;
|