intelicoreact 0.0.87 → 0.0.93

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.
Files changed (25) hide show
  1. package/dist/Atomic/FormElements/Dropdown/Dropdown.js +44 -19
  2. package/dist/Atomic/FormElements/Dropdown/Dropdown.scss +12 -0
  3. package/dist/Atomic/FormElements/Dropdown/Dropdown.stories.js +35 -7
  4. package/dist/Atomic/FormElements/Dropdown/components/DropdownLoader.js +24 -0
  5. package/dist/Atomic/FormElements/Dropdown/components/DropdownLoader.scss +57 -0
  6. package/dist/Atomic/FormElements/Input/Input.js +29 -10
  7. package/dist/Atomic/FormElements/InputCalendar/InputCalendar.js +10 -3
  8. package/dist/Atomic/FormElements/InputCalendar/InputCalendar.scss +18 -0
  9. package/dist/Atomic/FormElements/InputCalendar/InputCalendar.stories.js +4 -2
  10. package/dist/Atomic/UI/Calendar/Calendar.js +87 -15
  11. package/dist/Atomic/UI/Calendar/Calendar.scss +73 -26
  12. package/dist/Atomic/UI/Calendar/Calendar.stories.js +20 -3
  13. package/package.json +1 -2
  14. package/src/Atomic/FormElements/Dropdown/Dropdown.js +72 -35
  15. package/src/Atomic/FormElements/Dropdown/Dropdown.scss +12 -0
  16. package/src/Atomic/FormElements/Dropdown/Dropdown.stories.js +23 -8
  17. package/src/Atomic/FormElements/Dropdown/components/DropdownLoader.js +17 -0
  18. package/src/Atomic/FormElements/Dropdown/components/DropdownLoader.scss +57 -0
  19. package/src/Atomic/FormElements/Input/Input.js +46 -34
  20. package/src/Atomic/FormElements/InputCalendar/InputCalendar.js +28 -7
  21. package/src/Atomic/FormElements/InputCalendar/InputCalendar.scss +18 -0
  22. package/src/Atomic/FormElements/InputCalendar/InputCalendar.stories.js +8 -8
  23. package/src/Atomic/UI/Calendar/Calendar.js +75 -11
  24. package/src/Atomic/UI/Calendar/Calendar.scss +73 -26
  25. package/src/Atomic/UI/Calendar/Calendar.stories.js +9 -7
@@ -425,23 +425,25 @@
425
425
  // box-shadow: 0 0 3px 0 rgb(0 123 255 / 50%);
426
426
  // }
427
427
  // }
428
- .calendar-header {
429
- display: flex;
430
- justify-content: center;
431
- align-items: center;
428
+ // .calendar-header {
429
+ // display: flex;
430
+ // justify-content: center;
431
+ // align-items: center;
432
+
433
+ // &__prev,
434
+ // &__next {
435
+ // display: flex;
436
+ // height: auto;
437
+ // cursor: pointer;
438
+ // }
439
+ // }
432
440
 
433
- &__prev,
434
- &__next{
435
- display: flex;
436
- height: auto;
437
- }
438
- }
439
441
  .calendar {
440
442
  background: #ffffff;
441
- border: 1px solid #e2e5ec;
442
- box-shadow: 0 5px 20px rgb(0 0 0 / 15%);
443
- margin-top: 4px;
444
- padding: 5px 0;
443
+ border: 1px solid #e2e5ec;
444
+ box-shadow: 0 5px 20px rgb(0 0 0 / 15%);
445
+ margin-top: 4px;
446
+ padding: 5px 0;
445
447
 
446
448
  min-height: 195px;
447
449
  width: 260px;
@@ -449,6 +451,63 @@
449
451
  flex-direction: column;
450
452
  user-select: none;
451
453
 
454
+ &-header {
455
+ display: flex;
456
+ justify-content: center;
457
+ align-items: center;
458
+
459
+ box-sizing: border-box;
460
+ &__title {
461
+ &-month {
462
+ margin-right: 5px;
463
+ }
464
+ &-year {
465
+ box-sizing: border-box;
466
+ width: 45px;
467
+ height: 100%;
468
+ padding: 0 5px;
469
+ cursor: pointer;
470
+ display: flex;
471
+ flex-flow: row nowrap;
472
+ justify-content: center;
473
+ align-items: center;
474
+
475
+ &:hover:not(.calendar-header__title-year_change-mode) {
476
+ text-decoration: underline;
477
+ }
478
+
479
+ &.calendar-header__title-year_change-mode {
480
+ height: 24px;
481
+ padding: 0 3px;
482
+ border-style: solid;
483
+ border-width: 1px;
484
+ border-color: inherit;
485
+ border-radius: var(--border-radius);
486
+ }
487
+
488
+ &-change-input {
489
+ box-sizing: border-box;
490
+ width: 100%;
491
+ border: none;
492
+ outline: none;
493
+ margin: 0;
494
+ padding: 0;
495
+ display: inline;
496
+ font-size: inherit;
497
+ line-height: inherit;
498
+ font-weight: inherit;
499
+ }
500
+ }
501
+ }
502
+
503
+ &__prev,
504
+ &__next {
505
+ display: flex;
506
+ height: auto;
507
+ cursor: pointer;
508
+ }
509
+ }
510
+
452
511
  &__week {
453
512
  display: flex;
454
513
  }
@@ -516,18 +575,6 @@
516
575
  }
517
576
  }
518
577
 
519
- &-container {
520
- min-width: 200px;
521
- position: relative;
522
- .calendar {
523
- position: absolute;
524
- z-index: 9;
525
- top: 100%;
526
- padding: 10px 16px;
527
- border: 1px solid var(--border-color);
528
- }
529
- }
530
-
531
578
  &-dropdown {
532
579
  appearance: none;
533
580
  background-color: white;
@@ -2,15 +2,25 @@
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
4
 
5
+ var _typeof = require("@babel/runtime/helpers/typeof");
6
+
5
7
  Object.defineProperty(exports, "__esModule", {
6
8
  value: true
7
9
  });
8
10
  exports.CalendarTemplate = exports.default = void 0;
9
11
 
10
- var _react = _interopRequireDefault(require("react"));
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"));
11
17
 
12
18
  var _Calendar = _interopRequireDefault(require("./Calendar"));
13
19
 
20
+ 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); }
21
+
22
+ 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; }
23
+
14
24
  global.lng = 'en';
15
25
  var _default = {
16
26
  title: 'Calendar',
@@ -19,17 +29,24 @@ var _default = {
19
29
  exports.default = _default;
20
30
 
21
31
  var Template = function Template(args) {
32
+ var _useState = (0, _react.useState)('12/03/2021'),
33
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
34
+ date = _useState2[0],
35
+ setDate = _useState2[1];
36
+
22
37
  return /*#__PURE__*/_react.default.createElement("div", {
23
38
  style: {
24
39
  width: '320px'
25
40
  }
26
- }, /*#__PURE__*/_react.default.createElement(_Calendar.default, args));
41
+ }, /*#__PURE__*/_react.default.createElement(_Calendar.default, (0, _extends2.default)({}, args, {
42
+ date: date,
43
+ setDate: setDate
44
+ })));
27
45
  };
28
46
 
29
47
  var CalendarTemplate = Template.bind({});
30
48
  exports.CalendarTemplate = CalendarTemplate;
31
49
  CalendarTemplate.args = {
32
- date: '12/03/2021',
33
50
  params: {},
34
51
  setDate: function setDate() {
35
52
  return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "intelicoreact",
3
- "version": "0.0.87",
3
+ "version": "0.0.93",
4
4
  "description": "fix input-calendar",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -23,6 +23,5 @@
23
23
  "@babel/polyfill": "^7.12.1",
24
24
  "@babel/preset-env": "^7.15.6",
25
25
  "anme": "^1.0.0"
26
-
27
26
  }
28
27
  }
@@ -1,36 +1,40 @@
1
- import React, { useState, useRef, useEffect } from 'react';
1
+ import React, { useState, useRef, useEffect, useCallback } from 'react';
2
2
  import cn from 'classnames';
3
3
  import { Check, ChevronDown, ChevronUp } from 'react-feather';
4
4
 
5
+ import DropdownLoader from './components/DropdownLoader';
6
+
5
7
  import './Dropdown.scss';
6
8
 
7
9
  const RC = 'dropdown';
8
10
 
9
- const Dropdown = ({ options = [], value, error, onChange, placeholder, className, isSearchable, entity }) => {
11
+ const Dropdown = ({ options = [], value, error, disabled, onChange, placeholder, className, isSearchable, entity, scrollReactionObj, isListTop }) => {
10
12
  const [isOpen, setIsOpen] = useState(false);
11
- const [searchValue, setSearchValue] = useState('');
13
+ const [searchValue, setSearchValue] = useState();
12
14
  const dropdownRef = useRef(null);
15
+ const dropdownListRef = useRef(null);
16
+
13
17
  if (!options) return null;
14
18
  const filteredGroups = options
15
- .filter(item => item.items?.length)
16
- .map(item => ({ ...item, items: item.items.filter(el => el?.label?.toLowerCase().includes(searchValue?.toLowerCase() || '')) }))
17
- .filter(item => item.items?.length > 0);
19
+ .filter((item) => item.items?.length)
20
+ .map((item) => ({ ...item, items: item.items.filter((el) => el?.label?.toLowerCase().includes(searchValue?.toLowerCase() || '')) }))
21
+ .filter((item) => item.items?.length > 0);
18
22
 
19
23
  const filteredItems = options
20
- .filter(item => !item.items?.length)
21
- .filter(item => item?.label?.toLowerCase().includes(searchValue?.toLowerCase() || ''));
24
+ .filter((item) => !item.items?.length)
25
+ .filter((item) => item?.label?.toLowerCase().includes(searchValue?.toLowerCase() || ''));
22
26
 
23
27
  const filteredOptions = [...filteredItems, ...filteredGroups];
24
28
 
25
29
  const modalBtnTrigger = entity && entity !== '' && typeof entity === 'string';
26
- const onChangeHandler = item => {
30
+ const onChangeHandler = (item) => {
27
31
  setIsOpen(false);
28
32
  setSearchValue(null);
29
33
  onChange(item.value);
30
34
  };
31
35
  // decorator
32
- const getDepends = getDependsTrigger => {
33
- const newOnChange = e => {
36
+ const getDepends = (getDependsTrigger) => {
37
+ const newOnChange = (e) => {
34
38
  if (e.value === 'open_modal') {
35
39
  onChange('open_modal');
36
40
  } else {
@@ -43,34 +47,34 @@ const Dropdown = ({ options = [], value, error, onChange, placeholder, className
43
47
  {
44
48
  label: `New ${entity}`,
45
49
  value: 'open_modal',
46
- className: 'dropdown__list-item--modal'
50
+ className: 'dropdown__list-item--modal',
47
51
  },
48
- ...filteredOptions
52
+ ...filteredOptions,
49
53
  ];
50
54
 
51
55
  return {
52
- onChange: changeItem => (getDependsTrigger ? newOnChange(changeItem) : onChangeHandler(changeItem)),
53
- options: getDependsTrigger ? newOptions : options
56
+ onChange: (changeItem) => (getDependsTrigger ? newOnChange(changeItem) : onChangeHandler(changeItem)),
57
+ options: getDependsTrigger ? newOptions : options,
54
58
  };
55
59
  };
56
60
 
57
- const handleClickOutside = event => {
61
+ const handleClickOutside = (event) => {
58
62
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
59
63
  setIsOpen(false);
60
64
  setSearchValue(null);
61
65
  }
62
66
  };
63
67
 
64
- const onSearchHandler = name => {
68
+ const onSearchHandler = (name) => {
65
69
  setSearchValue(name);
66
70
  };
67
71
 
68
- const hightlightedText = text =>
69
- searchValue ? text?.replace(new RegExp(searchValue, 'i'), match => `<span class="bg--yellow">${match}</span>`) : text;
72
+ const hightlightedText = (text) =>
73
+ searchValue ? text?.replace(new RegExp(searchValue, 'i'), (match) => `<span class="bg--yellow">${match}</span>`) : text;
70
74
 
71
75
  const depend = getDepends(modalBtnTrigger);
72
76
 
73
- const getMarkupForElement = item =>
77
+ const getMarkupForElement = (item) =>
74
78
  item.label.toLowerCase().includes(searchValue?.toLowerCase() || '') ? (
75
79
  <button
76
80
  key={item.value}
@@ -84,25 +88,51 @@ const Dropdown = ({ options = [], value, error, onChange, placeholder, className
84
88
  </button>
85
89
  ) : null;
86
90
 
87
- useEffect(() => {
88
- if (!value) setSearchValue(null);
89
- document.addEventListener('click', handleClickOutside, true);
90
- return () => document.removeEventListener('click', handleClickOutside, true);
91
- }, [value]);
92
-
93
- const filteredOptionList = filteredOption =>
91
+ const filteredOptionList = (filteredOption) =>
94
92
  filteredOption.items?.length > 0 ? (
95
93
  <div key={filteredOption.value} className={`${RC}-group`}>
96
94
  <div className={`${RC}-group__name`}>{filteredOption.label}</div>
97
- {filteredOption.items.map(el => getMarkupForElement(el))}
95
+ {filteredOption.items.map((el) => getMarkupForElement(el))}
98
96
  </div>
99
97
  ) : null;
100
98
 
101
99
  const selectedLabel =
102
- options.find(el => el.value === value)?.label || options.reduce((acc, item) => acc || item.items?.find(el => el.value === value)?.label, null);
100
+ options.find((el) => el.value === value)?.label ||
101
+ options.reduce((acc, item) => acc || item.items?.find((el) => el.value === value)?.label, null);
102
+
103
+ const doScrollCallback = useCallback(
104
+ (e) => {
105
+ const { callback, isWithAnyScrolling } = scrollReactionObj;
106
+ if (callback && typeof callback === 'function') {
107
+ if (isWithAnyScrolling) callback(e);
108
+ else if (e.target.clientHeight + e.target.scrollTop >= e.target.scrollHeight) callback(e);
109
+ }
110
+ },
111
+ [filteredOptions]
112
+ );
113
+
114
+ useEffect(() => {
115
+ if (!value) setSearchValue(null);
116
+ document.addEventListener('click', handleClickOutside, true);
117
+ return () => document.removeEventListener('click', handleClickOutside, true);
118
+ }, [value]);
119
+
120
+ useEffect(() => {
121
+ if (scrollReactionObj && typeof scrollReactionObj === 'object' && isOpen && dropdownListRef && dropdownListRef.current) {
122
+ dropdownListRef.current.addEventListener('scroll', doScrollCallback);
123
+ }
124
+ return () => {
125
+ if (scrollReactionObj && typeof scrollReactionObj === 'object') removeEventListener('scroll', doScrollCallback);
126
+ };
127
+ }, [isOpen, dropdownListRef]);
103
128
 
104
129
  return (
105
- <div className={cn(RC, className)} ref={dropdownRef}>
130
+ <div
131
+ className={cn(RC, className, {
132
+ disabled: disabled,
133
+ })}
134
+ ref={dropdownRef}
135
+ >
106
136
  <button
107
137
  className={`${RC}__trigger input__wrap ${!value ? 'placeholder' : ''} ${error ? 'error' : ''}`}
108
138
  onClick={() => (!isSearchable ? setIsOpen(!isOpen) : null)}
@@ -110,12 +140,12 @@ const Dropdown = ({ options = [], value, error, onChange, placeholder, className
110
140
  {isSearchable ? (
111
141
  <input
112
142
  className={`${RC}__input`}
113
- value={searchValue || filteredOptions.find(el => el.value === value)?.label || ''}
114
- onChange={e => {
143
+ value={searchValue || selectedLabel || ''}
144
+ onChange={(e) => {
115
145
  onSearchHandler(e.target.value);
116
146
  }}
117
147
  placeholder={placeholder}
118
- onFocus={e => {
148
+ onFocus={(e) => {
119
149
  e.target.select();
120
150
  setIsOpen(true);
121
151
  }}
@@ -127,11 +157,18 @@ const Dropdown = ({ options = [], value, error, onChange, placeholder, className
127
157
  {isOpen ? <ChevronUp /> : <ChevronDown />}
128
158
  </span>
129
159
  </button>
160
+
130
161
  {isOpen && filteredOptions.length > 0 && (
131
- <div className={`${RC}__list`}>
132
- {depend.options.map(filteredOption =>
162
+ <div
163
+ className={cn(`${RC}__list`, {
164
+ [`${RC}__list-top`]: isListTop,
165
+ })}
166
+ ref={dropdownListRef}
167
+ >
168
+ {depend.options.map((filteredOption) =>
133
169
  filteredOption.items?.length ? filteredOptionList(filteredOption) : getMarkupForElement(filteredOption)
134
170
  )}
171
+ {disabled && isOpen && <DropdownLoader />}
135
172
  </div>
136
173
  )}
137
174
  </div>
@@ -45,6 +45,7 @@
45
45
  }
46
46
 
47
47
  &__list {
48
+ position: relative;
48
49
  background: #ffffff;
49
50
  border: 1px solid #e2e5ec;
50
51
  box-shadow: 0 5px 20px rgb(0 0 0 / 15%);
@@ -70,6 +71,12 @@
70
71
  border-radius: 4px;
71
72
  }
72
73
 
74
+ &-top {
75
+ bottom: calc(100% + 4px);
76
+ top: auto;
77
+ box-shadow: 0 -3px 10px rgb(0 0 0 / 15%);
78
+ }
79
+
73
80
  &-item {
74
81
  display: flex;
75
82
  align-items: center;
@@ -177,4 +184,9 @@
177
184
  font-size: 10px;
178
185
  color: $color--secondary;
179
186
  }
187
+
188
+ &.disabled {
189
+ pointer-events: none;
190
+ opacity: 0.5;
191
+ }
180
192
  }
@@ -20,26 +20,41 @@ export default {
20
20
  },
21
21
  };
22
22
 
23
- const buttonStyles={
23
+ const blockStyles = {
24
+ display: 'flex',
25
+ flexFlow: 'row no-wrap',
26
+ alignItems: 'center',
27
+ };
28
+
29
+ const buttonStyles = {
24
30
  border: 'solid 1px #000',
25
- padding: '5px'
31
+ padding: '5px',
32
+ margin: '0 0 0 50px',
26
33
  };
27
34
 
28
35
  const Template = (args) => {
29
- const [value, setValue] = useState('');
36
+ const [value, setValue] = useState(args.value);
37
+ const [disabled, setDisabled] = useState(false);
30
38
  return (
31
- <>
32
- <div style={{ width: 200 }}>
33
- <Dropdown {...args} value={value} onChange={setValue} />
39
+ <div style={blockStyles}>
40
+ <div key="dropdown" style={{ width: 200 }}>
41
+ <Dropdown {...args} value={value} onChange={setValue} disabled={disabled} scrollReactionObj={{ callback: (e) => setDisabled(true) }} />
34
42
  </div>
35
- <button style={buttonStyles} className='mt10' onClick={() => {console.log('click!'); setValue('')}} >Reset</button>
36
- </>
43
+ <button key="reset" style={buttonStyles} className="mt10" onClick={() => setValue('')}>
44
+ Reset
45
+ </button>
46
+
47
+ <button key="enable/disable" style={buttonStyles} className="mt10" onClick={() => setDisabled(!disabled)}>
48
+ {disabled ? 'enable' : 'disable'}
49
+ </button>
50
+ </div>
37
51
  );
38
52
  };
39
53
 
40
54
  export const DropdownTemplate = Template.bind({});
41
55
 
42
56
  DropdownTemplate.args = {
57
+ isListTop: true,
43
58
  entity: 'entity',
44
59
  value: 'drop6',
45
60
  placeholder: 'Placeholder',
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import './DropdownLoader.scss';
3
+
4
+ const DropdownLoader = function ({ variant }) {
5
+ return (
6
+ <div className="dropdown-loader-box j5">
7
+ <div className={`lds-ring${variant === 'little' ? ' lds-ring_little' : ''}`}>
8
+ <div />
9
+ <div />
10
+ <div />
11
+ <div />
12
+ </div>
13
+ </div>
14
+ );
15
+ };
16
+
17
+ export default DropdownLoader;
@@ -0,0 +1,57 @@
1
+ @mixin fill-parent {
2
+ left: 0;
3
+ top: 0;
4
+ width: 100%;
5
+ height: 100%;
6
+ }
7
+
8
+ .dropdown-loader-box {
9
+ position: absolute;
10
+ @include fill-parent;
11
+ background: #fff;
12
+ opacity: 0.1;
13
+ z-index: 100;
14
+ }
15
+ .lds-ring {
16
+ display: inline-block;
17
+ position: relative;
18
+ width: 100px;
19
+ height: 100px;
20
+ }
21
+ .lds-ring.lds-ring_little {
22
+ width: 20px;
23
+ height: 20px;
24
+ }
25
+ .lds-ring div {
26
+ box-sizing: border-box;
27
+ display: block;
28
+ position: absolute;
29
+ width: 84px;
30
+ height: 84px;
31
+ margin: 8px;
32
+ border: 8px solid #000;
33
+ border-radius: 50%;
34
+ animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
35
+ border-color: #000 transparent transparent transparent;
36
+ }
37
+ .lds-ring_little div {
38
+ width: 20px;
39
+ height: 20px;
40
+ }
41
+ .lds-ring div:nth-child(1) {
42
+ animation-delay: -0.45s;
43
+ }
44
+ .lds-ring div:nth-child(2) {
45
+ animation-delay: -0.3s;
46
+ }
47
+ .lds-ring div:nth-child(3) {
48
+ animation-delay: -0.15s;
49
+ }
50
+ @keyframes lds-ring {
51
+ 0% {
52
+ transform: rotate(0deg);
53
+ }
54
+ 100% {
55
+ transform: rotate(360deg);
56
+ }
57
+ }
@@ -29,7 +29,7 @@ const Input = ({
29
29
  icon,
30
30
  symbolsLimit,
31
31
  blinkTime,
32
- isFocusDefault = false
32
+ isFocusDefault = false,
33
33
  }) => {
34
34
  const DEFAULT_BLINK_TIME = 100;
35
35
  // STATES
@@ -42,6 +42,8 @@ const Input = ({
42
42
 
43
43
  const { onlyNumbers, onlyString } = formatInput;
44
44
  const { addCommas, removeComma } = formatInput.priceInput;
45
+ const isUseErrorsBlink = !isNotBlinkErrors && !mask;
46
+
45
47
  // HANDLES
46
48
  const handle = {
47
49
  change: (e) => {
@@ -50,8 +52,7 @@ const Input = ({
50
52
  inputValue = inputValue.substring(0, +symbolsLimit);
51
53
  }
52
54
 
53
- if (isOnlyNumber && !isTwoDigitAfterDot)
54
- inputValue = onlyNumbers(inputValue);
55
+ if (isOnlyNumber && !isTwoDigitAfterDot) inputValue = onlyNumbers(inputValue);
55
56
  if (isTwoDigitAfterDot) inputValue = onlyNumbers(inputValue, true);
56
57
  if (isOnlyString) inputValue = onlyString(inputValue);
57
58
 
@@ -79,28 +80,47 @@ const Input = ({
79
80
  if (onBlur) onBlur(e);
80
81
  },
81
82
  keyUp: (e) => {
82
- if (!isNotBlinkErrors) {
83
+ if (isUseErrorsBlink) {
83
84
  const changedValue = '' + (value ?? '');
84
85
  const previousValue = '' + (previousValueRef.current ?? '');
85
- const currentSet = (() => {
86
- if (previousValue.length < changedValue.length)
87
- return value.slice(previousValue.length - changedValue.length);
88
- else return changedValue.includes(e.key) ? e.key : '';
89
- })();
90
-
91
- if (
92
- !KEYBOARD_SERVICE_KEYS.includes(e.key) &&
93
- changedValue === previousValue
94
- )
95
- setIsAttemptToChange(true);
96
-
97
- if (KEYBOARD_SERVICE_KEYS.includes(e.key) || !currentSet)
98
- previousValueRef.current = value;
99
- else previousValueRef.current = previousValue + currentSet[0];
86
+
87
+ const short = previousValue.length <= changedValue.length ? previousValue : changedValue;
88
+ const long = previousValue.length > changedValue.length ? previousValue : changedValue;
89
+
90
+ const infoAboutDifferencesSameness = short.split('').reduce(
91
+ (acc, symbol, idx) => {
92
+ if (acc.countOn && symbol === long[idx]) acc.same.push(symbol);
93
+ else {
94
+ acc.countOn = false;
95
+ acc.differences.push([idx, symbol]);
96
+ }
97
+ return acc;
98
+ },
99
+ { same: [], countOn: true, differences: [] }
100
+ );
101
+
102
+ const samePart = infoAboutDifferencesSameness.same.join('');
103
+ const differencesLength = infoAboutDifferencesSameness.differences.length;
104
+ const currentSet = changedValue.replace(samePart, '');
105
+
106
+ const getNext = (inputPartToAdd, correctedSamePart) => {
107
+ const partToAdd = inputPartToAdd || currentSet;
108
+ const currentSamePart = correctedSamePart || samePart;
109
+ return changedValue.includes(e.key) && e.key !== changedValue[changedValue.length - 1]
110
+ ? currentSamePart + (partToAdd[0] || '')
111
+ : changedValue;
112
+ };
113
+
114
+ if (!KEYBOARD_SERVICE_KEYS.includes(e.key) && changedValue === previousValue)
115
+ setIsAttemptToChange(!(!differencesLength && e.key === changedValue[changedValue.length - 2]));
116
+
117
+ if (!previousValueRef.current || KEYBOARD_SERVICE_KEYS.includes(e.key)) previousValueRef.current = getNext();
118
+ else if (changedValue === samePart) previousValueRef.current = getNext(changedValue, changedValue.slice(0, -1));
119
+ else previousValueRef.current = getNext();
100
120
  }
101
121
 
102
122
  if (onKeyUp) onKeyUp(e.keyCode, e);
103
- }
123
+ },
104
124
  };
105
125
 
106
126
  function cutOffsingleDot(value) {
@@ -121,7 +141,7 @@ const Input = ({
121
141
  onBlur: handle.blur,
122
142
  onKeyUp: handle.keyUp,
123
143
  ...(maskChar ? { maskChar } : {}),
124
- ...(formatChars ? { formatChars } : {})
144
+ ...(formatChars ? { formatChars } : {}),
125
145
  };
126
146
 
127
147
  function renderInput() {
@@ -129,13 +149,11 @@ const Input = ({
129
149
  return <InputMask {...uniProps} ref={inputRef} mask={mask} />;
130
150
  }
131
151
 
132
- return (
133
- <input {...uniProps} ref={inputRef} type={isPriceInput ? 'text' : type} />
134
- );
152
+ return <input {...uniProps} ref={inputRef} type={isPriceInput ? 'text' : type} />;
135
153
  }
136
154
 
137
155
  useEffect(() => {
138
- if (!isNotBlinkErrors && isAttemptToChange) {
156
+ if (isUseErrorsBlink && isAttemptToChange) {
139
157
  setIsAttemptToChange(null);
140
158
  setIsToHighlightError(true);
141
159
  setTimeout(() => {
@@ -145,9 +163,8 @@ const Input = ({
145
163
  }, [isAttemptToChange]);
146
164
 
147
165
  useEffect(() => {
148
- if (inputRef?.current && typeof isFocusDefault === 'boolean')
149
- setIsFocused(isFocusDefault);
150
- setEditing(isFocusDefault);
166
+ if (inputRef?.current && typeof isFocusDefault === 'boolean') setIsFocused(isFocusDefault);
167
+ setEditing(isFocusDefault);
151
168
  }, [inputRef, isFocusDefault]);
152
169
 
153
170
  return (
@@ -161,12 +178,7 @@ const Input = ({
161
178
  >
162
179
  {renderInput()}
163
180
  {icon}
164
- {withDelete && (
165
- <span
166
- className={cn(`input__close`, { hidden: !value })}
167
- onClick={handle.toggleEdit}
168
- />
169
- )}
181
+ {withDelete && <span className={cn(`input__close`, { hidden: !value })} onClick={handle.toggleEdit} />}
170
182
  </div>
171
183
  );
172
184
  };