@true-engineering/true-react-common-ui-kit 1.4.1 → 1.5.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@true-engineering/true-react-common-ui-kit",
3
- "version": "1.4.1",
3
+ "version": "1.5.1",
4
4
  "description": "True Engineering React UI Kit with theming support",
5
5
  "author": "True Engineering (https://trueengineering.ru)",
6
6
  "keywords": [
@@ -21,6 +21,7 @@ Default.args = {
21
21
  precision: 3,
22
22
  intPartPrecision: 7,
23
23
  canBeFloat: false,
24
+ canBeNegative: false,
24
25
  label: 'Label',
25
26
  placeholder: 'Placeholder',
26
27
  infoMessage: 'Message Info',
@@ -1,4 +1,10 @@
1
- import React, { forwardRef, useState } from 'react';
1
+ import {
2
+ FormEvent,
3
+ KeyboardEvent,
4
+ FocusEvent,
5
+ forwardRef,
6
+ useState,
7
+ } from 'react';
2
8
 
3
9
  import {
4
10
  formatNumber,
@@ -10,23 +16,27 @@ import {
10
16
  stringToNumber,
11
17
  } from '../../helpers';
12
18
  import { Input, IInputProps } from '../Input';
13
- import { formatNumberWithDefault, getNewCaretPosition } from './helpers';
19
+ import {
20
+ constructRegExp,
21
+ formatNumberWithDefault,
22
+ getNewCaretPosition,
23
+ } from './helpers';
14
24
  import { useDidMountEffect } from '../../hooks';
15
25
 
16
26
  export interface INumberInputProps
17
27
  extends Omit<IInputProps, 'value' | 'onChange' | 'type'> {
18
28
  value?: number;
19
- canBeFloat?: boolean;
20
29
  precision?: number;
21
30
  intPartPrecision?: number;
22
31
  defaultValue?: number;
23
- // canBeNegative....TODO
32
+ canBeFloat?: boolean;
33
+ canBeNegative?: boolean;
24
34
  min?: number;
25
35
  max?: number;
26
- onChange: (
36
+ onChange(
27
37
  value: number | undefined,
28
- event?: React.FormEvent<HTMLInputElement>,
29
- ) => void;
38
+ event?: FormEvent<HTMLInputElement>,
39
+ ): void;
30
40
  }
31
41
 
32
42
  export const NumberInput = forwardRef<HTMLInputElement, INumberInputProps>(
@@ -34,10 +44,10 @@ export const NumberInput = forwardRef<HTMLInputElement, INumberInputProps>(
34
44
  {
35
45
  value,
36
46
  canBeFloat = false,
47
+ canBeNegative = false,
37
48
  defaultValue,
38
49
  precision = 3,
39
50
  intPartPrecision = 7,
40
- // canBeNegative....TODO
41
51
  onChange,
42
52
  onBlur,
43
53
  min,
@@ -53,7 +63,7 @@ export const NumberInput = forwardRef<HTMLInputElement, INumberInputProps>(
53
63
  // специальный костыль для обработки Delete - т.к. без него каретка будет работать неправильно при удалении пробелов
54
64
  const [isDeleteForwardAction, setIsDeleteForwardAction] = useState(false);
55
65
 
56
- const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
66
+ const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
57
67
  setIsDeleteForwardAction(event.key === 'Delete');
58
68
  };
59
69
 
@@ -63,7 +73,7 @@ export const NumberInput = forwardRef<HTMLInputElement, INumberInputProps>(
63
73
 
64
74
  const handleChange = async (
65
75
  inputValue: string,
66
- event: React.FormEvent<HTMLInputElement>,
76
+ event: FormEvent<HTMLInputElement>,
67
77
  ): Promise<void> => {
68
78
  const oldValue = showedValue;
69
79
  const target = event.target as HTMLInputElement;
@@ -77,20 +87,22 @@ export const NumberInput = forwardRef<HTMLInputElement, INumberInputProps>(
77
87
  return;
78
88
  }
79
89
 
80
- const intRegexp = new RegExp(`^\\d{0,${intPartPrecision}}$`);
81
- const floatRegexp = new RegExp(
82
- `^\\d{0,${intPartPrecision}}(\\.\\d{0,${precision}})?$`,
90
+ const numberRegexp = new RegExp(
91
+ constructRegExp({
92
+ precision,
93
+ intPartPrecision,
94
+ canBeNegative,
95
+ canBeFloat,
96
+ }),
83
97
  );
84
- const numberRegexp =
85
- canBeFloat && precision > 0 ? floatRegexp : intRegexp;
86
98
 
87
- if (!numString.match(numberRegexp)) {
99
+ if (!numberRegexp.test(numString)) {
88
100
  await setShowedValue(oldValue);
89
101
  setCaretPosition(target, defaultCaretPos - 1);
90
102
  return;
91
103
  }
92
104
 
93
- const hasDot = canBeFloat && inputValue.match(/^[\d\s]*[.,]$/);
105
+ const hasDot = canBeFloat && /^[-]*[\d\s]*[.,]$/.test(inputValue);
94
106
  const formattedValue = formatStringNumber(numString);
95
107
  const newValue = hasDot ? `${formattedValue}.` : formattedValue;
96
108
  await setShowedValue(newValue);
@@ -105,7 +117,7 @@ export const NumberInput = forwardRef<HTMLInputElement, INumberInputProps>(
105
117
  );
106
118
  };
107
119
 
108
- const handleBlur = (event: React.FocusEvent<HTMLInputElement>): void => {
120
+ const handleBlur = (event: FocusEvent<HTMLInputElement>): void => {
109
121
  const val = event.currentTarget.value;
110
122
  const num = stringToNumber(val);
111
123
  const newValue =
@@ -1,4 +1,5 @@
1
1
  import { formatNumber, isNotEmpty, isSpaceChar } from '../../helpers';
2
+ import { INumberInputProps } from './NumberInput';
2
3
 
3
4
  const getPrevSpaces = (val: string, position: number): number =>
4
5
  val
@@ -34,6 +35,24 @@ export const formatNumberWithDefault = (
34
35
  return isNotEmpty(val) ? val : formatNumber(defaultValue);
35
36
  };
36
37
 
38
+ export const constructRegExp = ({
39
+ canBeFloat,
40
+ canBeNegative,
41
+ intPartPrecision,
42
+ precision,
43
+ }: Pick<
44
+ INumberInputProps,
45
+ 'canBeFloat' | 'canBeNegative' | 'intPartPrecision' | 'precision'
46
+ >): string => {
47
+ const basePart = `\\d{0,${intPartPrecision}}`;
48
+ const floatPart = `(\\.\\d{0,${precision}})?`;
49
+ const negativePart = '(\\-)?';
50
+
51
+ return `^${canBeNegative ? negativePart : ''}${basePart}${
52
+ canBeFloat ? floatPart : ''
53
+ }$`;
54
+ };
55
+
37
56
  // const testNewCaretPosition = () => {
38
57
  // console.log(getNewCaretPosition(1, '', '1') === 1);
39
58
  // console.log(getNewCaretPosition(2, '1', '12') === 2);
@@ -170,6 +170,13 @@ export function Select<Value>({
170
170
  };
171
171
 
172
172
  const handleBlur = (event: FocusEvent<HTMLInputElement>) => {
173
+ // Когда что-то блокирует открытие листа, но блур все равно должен сработать
174
+ // например minSymbolsCount
175
+ if (isListOpen && !isOpen) {
176
+ handleListClose(event);
177
+ return;
178
+ }
179
+
173
180
  if (!isNotEmpty(event.relatedTarget) || !isNotEmpty(list.current)) {
174
181
  return;
175
182
  }
@@ -482,7 +489,7 @@ export function Select<Value>({
482
489
  event.preventDefault();
483
490
  }}
484
491
  onClick={onArrowClick}
485
- className={clsx(classes.arrow, isListOpen && classes.activeArrow)}
492
+ className={clsx(classes.arrow, isOpen && classes.activeArrow)}
486
493
  >
487
494
  <Icon type={dropdownIcon} />
488
495
  </div>