intelicoreact 0.0.78 → 0.0.79
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/dist/Atomic/FormElements/Input/Input.js +43 -43
- package/dist/Atomic/FormElements/Input/Input.stories.js +17 -23
- package/dist/Atomic/FormElements/InputDateRange/InputDateRange.scss +38 -6
- package/dist/Atomic/FormElements/NumericInput/NumericInput.js +254 -0
- package/dist/Atomic/FormElements/NumericInput/NumericInput.scss +135 -0
- package/dist/Atomic/FormElements/NumericInput/NumericInput.stories.js +121 -0
- package/dist/Functions/inputExecutor.js +58 -0
- package/package.json +1 -1
- package/src/Atomic/FormElements/Input/Input.js +60 -42
- package/src/Atomic/FormElements/Input/Input.stories.js +41 -30
- package/src/Atomic/FormElements/InputDateRange/InputDateRange.scss +38 -6
- package/src/Atomic/FormElements/NumericInput/NumericInput.js +220 -0
- package/src/Atomic/FormElements/NumericInput/NumericInput.scss +135 -0
- package/src/Atomic/FormElements/NumericInput/NumericInput.stories.js +94 -0
- package/src/Functions/inputExecutor.js +62 -0
- package/src/Functions/utils.js +4 -1
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
.input {
|
|
2
|
+
position: relative;
|
|
3
|
+
word-break: break-all;
|
|
4
|
+
border: none;
|
|
5
|
+
background: none;
|
|
6
|
+
padding: 0 10px;
|
|
7
|
+
width: 100%;
|
|
8
|
+
&::-webkit-outer-spin-button,
|
|
9
|
+
&::-webkit-inner-spin-button {
|
|
10
|
+
-webkit-appearance: none;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
&__wrap {
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
border: 1px solid #e2e5ec;
|
|
17
|
+
box-sizing: border-box;
|
|
18
|
+
background-color: #fff;
|
|
19
|
+
height: 28px;
|
|
20
|
+
border-radius: 4px;
|
|
21
|
+
|
|
22
|
+
&_focus {
|
|
23
|
+
border-color: #6b81dd;
|
|
24
|
+
filter: drop-shadow(0px 0px 4px rgba(93, 120, 255, 0.5));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&_disabled {
|
|
28
|
+
background: #f7f8fa;
|
|
29
|
+
opacity: 0.5;
|
|
30
|
+
border-color: #a6acb1;
|
|
31
|
+
pointer-events: none;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
&_error {
|
|
35
|
+
border-color: #f06d8d;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
&_disabled {
|
|
40
|
+
background: #f7f8fa;
|
|
41
|
+
opacity: 0.5;
|
|
42
|
+
border-color: #a6acb1;
|
|
43
|
+
pointer-events: none;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
&_error {
|
|
47
|
+
border-color: #f06d8d;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
svg {
|
|
51
|
+
margin-right: 4px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&__input {
|
|
55
|
+
width: 100%;
|
|
56
|
+
height: 100%;
|
|
57
|
+
box-sizing: border-box;
|
|
58
|
+
font-size: 13px;
|
|
59
|
+
font-weight: 400;
|
|
60
|
+
color: #1e1e2d;
|
|
61
|
+
border: none;
|
|
62
|
+
padding: 0 5px;
|
|
63
|
+
border-radius: 4px;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
&__close {
|
|
67
|
+
position: relative;
|
|
68
|
+
opacity: 0.6;
|
|
69
|
+
width: 14px;
|
|
70
|
+
height: 14px;
|
|
71
|
+
background: none;
|
|
72
|
+
cursor: pointer;
|
|
73
|
+
margin-right: 4px;
|
|
74
|
+
visibility: hidden;
|
|
75
|
+
pointer-events: none;
|
|
76
|
+
&:hover {
|
|
77
|
+
opacity: 1;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
&:before,
|
|
81
|
+
&:after {
|
|
82
|
+
content: '';
|
|
83
|
+
position: absolute;
|
|
84
|
+
top: 0;
|
|
85
|
+
left: 0;
|
|
86
|
+
right: 0;
|
|
87
|
+
margin: auto;
|
|
88
|
+
height: 14px;
|
|
89
|
+
width: 2px;
|
|
90
|
+
background-color: #9aa0b9;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
&:before {
|
|
94
|
+
transform: rotate(45deg);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
&:after {
|
|
98
|
+
transform: rotate(-45deg);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
&__nums {
|
|
103
|
+
display: flex;
|
|
104
|
+
align-items: center;
|
|
105
|
+
height: 100%;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
&__num-btn {
|
|
109
|
+
cursor: pointer;
|
|
110
|
+
display: flex;
|
|
111
|
+
align-items: center;
|
|
112
|
+
justify-content: center;
|
|
113
|
+
height: 100%;
|
|
114
|
+
width: 24px;
|
|
115
|
+
border-left: 1px solid #e2e5ec;
|
|
116
|
+
background: none;
|
|
117
|
+
font-size: 20px;
|
|
118
|
+
user-select: none;
|
|
119
|
+
&.disabled {
|
|
120
|
+
opacity: 0.3;
|
|
121
|
+
}
|
|
122
|
+
svg {
|
|
123
|
+
margin-right: 0;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
&-label {
|
|
128
|
+
margin-bottom: 5px;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.input__wrap:hover .input__close {
|
|
133
|
+
visibility: visible;
|
|
134
|
+
pointer-events: all;
|
|
135
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
var _typeof = require("@babel/runtime/helpers/typeof");
|
|
6
|
+
|
|
7
|
+
Object.defineProperty(exports, "__esModule", {
|
|
8
|
+
value: true
|
|
9
|
+
});
|
|
10
|
+
exports.NumericInputTemplate = exports.default = void 0;
|
|
11
|
+
|
|
12
|
+
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
13
|
+
|
|
14
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
15
|
+
|
|
16
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
17
|
+
|
|
18
|
+
var _reactFeather = require("react-feather");
|
|
19
|
+
|
|
20
|
+
var _NumericInput = _interopRequireDefault(require("./NumericInput"));
|
|
21
|
+
|
|
22
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
23
|
+
|
|
24
|
+
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; }
|
|
25
|
+
|
|
26
|
+
global.lng = 'en';
|
|
27
|
+
var _default = {
|
|
28
|
+
title: 'Form Elements/NumericInput',
|
|
29
|
+
component: _NumericInput.default,
|
|
30
|
+
argTypes: {
|
|
31
|
+
disabled: {
|
|
32
|
+
description: 'boolean'
|
|
33
|
+
},
|
|
34
|
+
isInitialFocus: {
|
|
35
|
+
description: 'boolean - if true, the input will be focused on mount'
|
|
36
|
+
},
|
|
37
|
+
error: {
|
|
38
|
+
description: 'text - coloring input if is errored'
|
|
39
|
+
},
|
|
40
|
+
isPriceInput: {
|
|
41
|
+
description: 'boolean - if true, the input will be styled as PriceInput'
|
|
42
|
+
},
|
|
43
|
+
withDelete: {
|
|
44
|
+
description: 'boolean - add clear-cross by hover'
|
|
45
|
+
},
|
|
46
|
+
numStep: {
|
|
47
|
+
description: 'number/text - plus/minus buttons factor (default: 1)'
|
|
48
|
+
},
|
|
49
|
+
min: {
|
|
50
|
+
description: 'number/text - minimal number for numeric input'
|
|
51
|
+
},
|
|
52
|
+
max: {
|
|
53
|
+
description: 'number/text - maximal number for numeric input'
|
|
54
|
+
},
|
|
55
|
+
placeholder: {
|
|
56
|
+
description: 'text'
|
|
57
|
+
},
|
|
58
|
+
type: {
|
|
59
|
+
description: "'text', 'number', 'password', 'color', 'date', 'datetime-local', 'month', 'time', 'email', 'range'",
|
|
60
|
+
control: {
|
|
61
|
+
type: 'select',
|
|
62
|
+
options: ['text', 'number', 'password', 'color', 'date', 'datetime-local', 'month', 'time', 'email', 'range']
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
icon: {
|
|
66
|
+
description: 'JSX'
|
|
67
|
+
},
|
|
68
|
+
value: {
|
|
69
|
+
description: '(* - required prop)'
|
|
70
|
+
},
|
|
71
|
+
className: {
|
|
72
|
+
description: 'string'
|
|
73
|
+
},
|
|
74
|
+
mask: {
|
|
75
|
+
description: 'string: force input to masked https://www.npmjs.com/package/react-input-mask'
|
|
76
|
+
},
|
|
77
|
+
symbolsLimit: {
|
|
78
|
+
description: 'Set limit of symbols in input, overhead will be ignored'
|
|
79
|
+
},
|
|
80
|
+
onBlur: {
|
|
81
|
+
description: 'custom callback on blur'
|
|
82
|
+
},
|
|
83
|
+
onFocus: {
|
|
84
|
+
description: 'custom callback on focus'
|
|
85
|
+
},
|
|
86
|
+
onKeyUp: {
|
|
87
|
+
description: 'custom callback on keyup, returns event keyCode'
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
exports.default = _default;
|
|
92
|
+
|
|
93
|
+
var Template = function Template(args) {
|
|
94
|
+
var _useState = (0, _react.useState)(''),
|
|
95
|
+
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
96
|
+
value = _useState2[0],
|
|
97
|
+
setValue = _useState2[1];
|
|
98
|
+
|
|
99
|
+
return /*#__PURE__*/_react.default.createElement(_NumericInput.default, (0, _extends2.default)({}, args, {
|
|
100
|
+
value: value,
|
|
101
|
+
onChange: setValue
|
|
102
|
+
}));
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
var NumericInputTemplate = Template.bind({});
|
|
106
|
+
exports.NumericInputTemplate = NumericInputTemplate;
|
|
107
|
+
NumericInputTemplate.args = {
|
|
108
|
+
type: 'text',
|
|
109
|
+
disabled: false,
|
|
110
|
+
error: '',
|
|
111
|
+
isPriceInput: false,
|
|
112
|
+
mask: '',
|
|
113
|
+
withDelete: true,
|
|
114
|
+
isNumeric: false,
|
|
115
|
+
numStep: 100,
|
|
116
|
+
min: '0',
|
|
117
|
+
max: '15000',
|
|
118
|
+
symbolsLimit: 2,
|
|
119
|
+
placeholder: 'Placeholder',
|
|
120
|
+
icon: /*#__PURE__*/_react.default.createElement(_reactFeather.User, null)
|
|
121
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.formatInput = void 0;
|
|
9
|
+
|
|
10
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
11
|
+
|
|
12
|
+
var formatInput = {
|
|
13
|
+
priceInput: {
|
|
14
|
+
addCommas: function addCommas(value) {
|
|
15
|
+
value = value.toString();
|
|
16
|
+
var isFraction = value.includes('.');
|
|
17
|
+
var valueBeforeDot = isFraction ? value.slice(0, value.indexOf('.')) : value;
|
|
18
|
+
var intPart = valueBeforeDot.split('').reverse().reduce(function (acc, item, idx) {
|
|
19
|
+
return idx % 3 === 0 && idx !== 0 ? [].concat((0, _toConsumableArray2.default)(acc), [',', item]) : [].concat((0, _toConsumableArray2.default)(acc), [item]);
|
|
20
|
+
}, []).reverse().join('');
|
|
21
|
+
return isFraction ? intPart + value.slice(value.indexOf('.')) : intPart;
|
|
22
|
+
},
|
|
23
|
+
removeComma: function removeComma(value) {
|
|
24
|
+
return parseFloat(value.toString().replace(/\,/g, ''));
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
onlyNumbers: function onlyNumbers(value) {
|
|
28
|
+
var isDot = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
29
|
+
var val = value.slice(0, 1) !== '0' && value.slice(0, 1) !== '.' ? value : value.slice(1);
|
|
30
|
+
if (isDot) return twoDigitAfterDot(val.replace(/[^0-9.]/g, ''));else return +val.toString().replace(/\D/g, '');
|
|
31
|
+
},
|
|
32
|
+
onlyString: function onlyString(value) {
|
|
33
|
+
return value.toString().replace(/[^a-z]/gi, '');
|
|
34
|
+
}
|
|
35
|
+
}; //обрезает числа после точки до 2х
|
|
36
|
+
// 342.23423432 -> 342.23
|
|
37
|
+
|
|
38
|
+
exports.formatInput = formatInput;
|
|
39
|
+
|
|
40
|
+
var twoDigitAfterDot = function twoDigitAfterDot(value) {
|
|
41
|
+
if (value.includes('.')) {
|
|
42
|
+
var valueAfterDot = value.slice(0, value.indexOf('.') + 3);
|
|
43
|
+
var rest = value.slice(value.indexOf('.') + 1, value.indexOf('.') + 3);
|
|
44
|
+
return allButTheFirstDotCutter(valueAfterDot);
|
|
45
|
+
} else {
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
}; //обрезает все точки кроме первой.
|
|
49
|
+
//для фомата "2 цифры после точки"
|
|
50
|
+
// нельзя = 123...
|
|
51
|
+
// можно 123.99
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
function allButTheFirstDotCutter(str) {
|
|
55
|
+
return str.replace(/^([^.]*\.)(.*)$/, function (a, b, c) {
|
|
56
|
+
return b + c.replace(/\./g, '');
|
|
57
|
+
});
|
|
58
|
+
}
|
package/package.json
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
import React, { useState, useEffect, useRef } from 'react';
|
|
2
2
|
import cn from 'classnames';
|
|
3
|
-
import { Minus, Plus } from 'react-feather';
|
|
4
3
|
import InputMask from 'react-input-mask';
|
|
5
4
|
import { KEYBOARD_SERVICE_KEYS } from '../../../Constants/index.constants';
|
|
5
|
+
import { formatInput } from '../../../Functions/inputExecutor';
|
|
6
6
|
|
|
7
7
|
import './Input.scss';
|
|
8
8
|
|
|
9
9
|
const Input = ({
|
|
10
10
|
onChange,
|
|
11
|
+
onBlur,
|
|
12
|
+
onFocus,
|
|
13
|
+
onKeyUp,
|
|
14
|
+
isNotBlinkErrors,
|
|
15
|
+
isPriceInput,
|
|
16
|
+
isOnlyNumber,
|
|
17
|
+
isOnlyString,
|
|
18
|
+
isTwoDigitAfterDot,
|
|
11
19
|
disabled,
|
|
12
20
|
withDelete,
|
|
13
|
-
isNumeric,
|
|
14
|
-
numStep = 1,
|
|
15
|
-
min = 0,
|
|
16
|
-
max,
|
|
17
21
|
value,
|
|
18
22
|
placeholder,
|
|
19
23
|
className,
|
|
20
24
|
type = 'text',
|
|
21
|
-
onBlur,
|
|
22
|
-
onFocus,
|
|
23
|
-
onKeyUp,
|
|
24
25
|
mask,
|
|
25
26
|
maskChar,
|
|
26
27
|
formatChars,
|
|
27
28
|
error,
|
|
28
29
|
icon,
|
|
29
30
|
symbolsLimit,
|
|
30
|
-
|
|
31
|
-
blinkTime,
|
|
31
|
+
blinkTime
|
|
32
32
|
}) => {
|
|
33
33
|
const DEFAULT_BLINK_TIME = 100;
|
|
34
34
|
// STATES
|
|
@@ -38,42 +38,65 @@ const Input = ({
|
|
|
38
38
|
const previousValueRef = useRef(value);
|
|
39
39
|
const [isAttemptToChange, setIsAttemptToChange] = useState(false);
|
|
40
40
|
const [isToHighlightError, setIsToHighlightError] = useState(false);
|
|
41
|
+
|
|
42
|
+
const { onlyNumbers, onlyString } = formatInput;
|
|
43
|
+
const { addCommas, removeComma } = formatInput.priceInput;
|
|
41
44
|
// HANDLES
|
|
42
45
|
const handle = {
|
|
43
|
-
change: e => {
|
|
46
|
+
change: (e) => {
|
|
44
47
|
let inputValue = e.target ? e.target.value : e;
|
|
45
|
-
if (
|
|
46
|
-
inputValue =
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
if (symbolsLimit && inputValue.length > +symbolsLimit) {
|
|
49
|
+
inputValue = inputValue.substring(0, +symbolsLimit);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (isOnlyNumber && !isTwoDigitAfterDot)
|
|
53
|
+
inputValue = onlyNumbers(inputValue);
|
|
54
|
+
if (isTwoDigitAfterDot) inputValue = onlyNumbers(inputValue, true);
|
|
55
|
+
if (isOnlyString) inputValue = onlyString(inputValue);
|
|
56
|
+
|
|
51
57
|
onChange(inputValue.toString());
|
|
52
58
|
},
|
|
53
59
|
toggleEdit: () => {
|
|
54
60
|
setEditing(!isEditing);
|
|
55
61
|
onChange('');
|
|
56
62
|
},
|
|
57
|
-
focus: e => {
|
|
63
|
+
focus: (e) => {
|
|
58
64
|
setIsFocused(true);
|
|
65
|
+
if (isPriceInput && isOnlyNumber && !isTwoDigitAfterDot)
|
|
66
|
+
onChange(removeComma(value));
|
|
67
|
+
|
|
59
68
|
if (onFocus) onFocus(e);
|
|
60
69
|
},
|
|
61
|
-
blur: e => {
|
|
70
|
+
blur: (e) => {
|
|
62
71
|
setIsFocused(false);
|
|
63
72
|
setEditing(false);
|
|
73
|
+
if (isPriceInput && isOnlyNumber && !isTwoDigitAfterDot) {
|
|
74
|
+
onChange(addCommas(value));
|
|
75
|
+
}
|
|
76
|
+
if (isTwoDigitAfterDot && !isPriceInput) {
|
|
77
|
+
onChange(cutOffsingleDot(value));
|
|
78
|
+
}
|
|
64
79
|
if (onBlur) onBlur(e);
|
|
65
80
|
},
|
|
66
|
-
keyUp: e => {
|
|
81
|
+
keyUp: (e) => {
|
|
67
82
|
if (!isNotBlinkErrors) {
|
|
68
83
|
const changedValue = '' + (value ?? '');
|
|
69
84
|
const previousValue = '' + (previousValueRef.current ?? '');
|
|
70
85
|
const currentSet = (() => {
|
|
71
|
-
if (previousValue.length < changedValue.length)
|
|
86
|
+
if (previousValue.length < changedValue.length)
|
|
87
|
+
return value.slice(previousValue.length - changedValue.length);
|
|
72
88
|
else return changedValue.includes(e.key) ? e.key : '';
|
|
73
89
|
})();
|
|
74
90
|
|
|
75
|
-
if
|
|
76
|
-
|
|
91
|
+
if (
|
|
92
|
+
!KEYBOARD_SERVICE_KEYS.includes(e.key) &&
|
|
93
|
+
changedValue === previousValue
|
|
94
|
+
)
|
|
95
|
+
setIsAttemptToChange(true);
|
|
96
|
+
|
|
97
|
+
console.log(changedValue, previousValue);
|
|
98
|
+
if (KEYBOARD_SERVICE_KEYS.includes(e.key) || !currentSet)
|
|
99
|
+
previousValueRef.current = value;
|
|
77
100
|
else previousValueRef.current = previousValue + currentSet[0];
|
|
78
101
|
}
|
|
79
102
|
|
|
@@ -81,6 +104,10 @@ const Input = ({
|
|
|
81
104
|
}
|
|
82
105
|
};
|
|
83
106
|
|
|
107
|
+
function cutOffsingleDot(value) {
|
|
108
|
+
return value.slice(-1) === '.' ? value.slice(0, -1) : value;
|
|
109
|
+
}
|
|
110
|
+
|
|
84
111
|
useEffect(() => {
|
|
85
112
|
if (isEditing) inputRef.current.focus();
|
|
86
113
|
}, [isEditing, isFocused]);
|
|
@@ -94,10 +121,8 @@ const Input = ({
|
|
|
94
121
|
onFocus: handle.focus,
|
|
95
122
|
onBlur: handle.blur,
|
|
96
123
|
onKeyUp: handle.keyUp,
|
|
97
|
-
min,
|
|
98
|
-
max,
|
|
99
124
|
...(maskChar ? { maskChar } : {}),
|
|
100
|
-
...(formatChars ? { formatChars } : {})
|
|
125
|
+
...(formatChars ? { formatChars } : {})
|
|
101
126
|
};
|
|
102
127
|
|
|
103
128
|
function renderInput() {
|
|
@@ -106,28 +131,16 @@ const Input = ({
|
|
|
106
131
|
}
|
|
107
132
|
|
|
108
133
|
return (
|
|
109
|
-
|
|
110
|
-
<input {...uniProps} ref={inputRef} type={isNumeric ? 'number' : type} />
|
|
111
|
-
{isNumeric && (
|
|
112
|
-
<div className="input__nums">
|
|
113
|
-
<button onClick={() => handle.change(value - numStep)} className={cn(`input__num-btn`, { disabled: value <= min })}>
|
|
114
|
-
<Minus />
|
|
115
|
-
</button>
|
|
116
|
-
<button onClick={() => handle.change(+value + +numStep)} className={cn(`input__num-btn`, { disabled: value >= max })}>
|
|
117
|
-
<Plus />
|
|
118
|
-
</button>
|
|
119
|
-
</div>
|
|
120
|
-
)}
|
|
121
|
-
</>
|
|
134
|
+
<input {...uniProps} ref={inputRef} type={isPriceInput ? 'text' : type} />
|
|
122
135
|
);
|
|
123
136
|
}
|
|
124
|
-
|
|
137
|
+
|
|
125
138
|
useEffect(() => {
|
|
126
139
|
if (!isNotBlinkErrors && isAttemptToChange) {
|
|
127
140
|
setIsAttemptToChange(null);
|
|
128
141
|
setIsToHighlightError(true);
|
|
129
142
|
setTimeout(() => {
|
|
130
|
-
setIsToHighlightError(false)
|
|
143
|
+
setIsToHighlightError(false);
|
|
131
144
|
}, blinkTime || DEFAULT_BLINK_TIME);
|
|
132
145
|
}
|
|
133
146
|
}, [isAttemptToChange]);
|
|
@@ -143,7 +156,12 @@ const Input = ({
|
|
|
143
156
|
>
|
|
144
157
|
{renderInput()}
|
|
145
158
|
{icon}
|
|
146
|
-
{withDelete &&
|
|
159
|
+
{withDelete && (
|
|
160
|
+
<span
|
|
161
|
+
className={cn(`input__close`, { hidden: !value })}
|
|
162
|
+
onClick={handle.toggleEdit}
|
|
163
|
+
/>
|
|
164
|
+
)}
|
|
147
165
|
</div>
|
|
148
166
|
);
|
|
149
167
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
|
-
import {User} from 'react-feather';
|
|
2
|
+
import { User } from 'react-feather';
|
|
3
3
|
import Input from './Input';
|
|
4
4
|
|
|
5
5
|
global.lng = 'en';
|
|
@@ -9,48 +9,65 @@ export default {
|
|
|
9
9
|
component: Input,
|
|
10
10
|
argTypes: {
|
|
11
11
|
disabled: {
|
|
12
|
-
description: 'boolean'
|
|
12
|
+
description: 'boolean'
|
|
13
13
|
},
|
|
14
14
|
error: {
|
|
15
15
|
description: 'text - coloring input if is errored'
|
|
16
16
|
},
|
|
17
|
+
isPriceInput: {
|
|
18
|
+
description: 'boolean - if true, the input will be styled as PriceInput'
|
|
19
|
+
},
|
|
17
20
|
withDelete: {
|
|
18
21
|
description: 'boolean - add clear-cross by hover'
|
|
19
22
|
},
|
|
20
|
-
|
|
21
|
-
description: 'boolean -
|
|
22
|
-
},
|
|
23
|
-
numStep: {
|
|
24
|
-
description: 'number/text - plus/minus buttons factor (default: 1)'
|
|
23
|
+
isOnlyNumber: {
|
|
24
|
+
description: 'boolean - only numbers'
|
|
25
25
|
},
|
|
26
|
-
|
|
27
|
-
description: '
|
|
26
|
+
isOnlyString: {
|
|
27
|
+
description: 'boolean - only strings'
|
|
28
28
|
},
|
|
29
|
-
|
|
30
|
-
description: '
|
|
29
|
+
isTwoDigitAfterDot: {
|
|
30
|
+
description: 'boolean - only two digits after dot'
|
|
31
31
|
},
|
|
32
32
|
placeholder: {
|
|
33
33
|
description: 'text'
|
|
34
34
|
},
|
|
35
35
|
type: {
|
|
36
|
-
description:
|
|
36
|
+
description:
|
|
37
|
+
"'text', 'number', 'password', 'color', 'date', 'datetime-local', 'month', 'time', 'email', 'range'",
|
|
37
38
|
control: {
|
|
38
39
|
type: 'select',
|
|
39
|
-
options: [
|
|
40
|
+
options: [
|
|
41
|
+
'text',
|
|
42
|
+
'number',
|
|
43
|
+
'password',
|
|
44
|
+
'color',
|
|
45
|
+
'date',
|
|
46
|
+
'datetime-local',
|
|
47
|
+
'month',
|
|
48
|
+
'time',
|
|
49
|
+
'email',
|
|
50
|
+
'range'
|
|
51
|
+
]
|
|
40
52
|
}
|
|
41
53
|
},
|
|
42
54
|
icon: { description: 'JSX' },
|
|
43
55
|
value: { description: '(* - required prop)' },
|
|
44
56
|
className: { description: 'string' },
|
|
45
|
-
mask: {
|
|
46
|
-
|
|
57
|
+
mask: {
|
|
58
|
+
description:
|
|
59
|
+
'string: force input to masked https://www.npmjs.com/package/react-input-mask'
|
|
60
|
+
},
|
|
61
|
+
symbolsLimit: {
|
|
62
|
+
description: 'Set limit of symbols in input, overhead will be ignored'
|
|
63
|
+
},
|
|
47
64
|
onBlur: { description: 'custom callback on blur' },
|
|
48
65
|
onFocus: { description: 'custom callback on focus' },
|
|
49
66
|
onKeyUp: { description: 'custom callback on keyup, returns event keyCode' }
|
|
50
67
|
}
|
|
51
68
|
};
|
|
52
69
|
|
|
53
|
-
const Template = args => {
|
|
70
|
+
const Template = (args) => {
|
|
54
71
|
const [value, setValue] = useState('');
|
|
55
72
|
return <Input {...args} value={value} onChange={setValue} />;
|
|
56
73
|
};
|
|
@@ -58,22 +75,16 @@ const Template = args => {
|
|
|
58
75
|
export const InputTemplate = Template.bind({});
|
|
59
76
|
|
|
60
77
|
InputTemplate.args = {
|
|
61
|
-
type: '
|
|
78
|
+
type: 'text',
|
|
79
|
+
isOnlyNumber: false,
|
|
80
|
+
isOnlyString: false,
|
|
81
|
+
isPriceInput: false,
|
|
82
|
+
isTwoDigitAfterDot: false,
|
|
62
83
|
disabled: false,
|
|
63
84
|
error: '',
|
|
85
|
+
mask: '',
|
|
64
86
|
withDelete: true,
|
|
65
|
-
|
|
66
|
-
numStep: 1,
|
|
67
|
-
// min: '0',
|
|
68
|
-
// max: '5',
|
|
87
|
+
symbolsLimit: 255,
|
|
69
88
|
placeholder: 'Placeholder',
|
|
70
|
-
|
|
71
|
-
// maskChar: '_',
|
|
72
|
-
// formatChars: {
|
|
73
|
-
// 'n': '[0-9]',
|
|
74
|
-
// 's': '[A-Za-z]',
|
|
75
|
-
// '*': '[A-Za-z0-9]'
|
|
76
|
-
// },
|
|
77
|
-
icon: <User />,
|
|
78
|
-
symbolsLimit: 225
|
|
89
|
+
icon: <User />
|
|
79
90
|
};
|