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

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.0",
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);
package/src/types.ts CHANGED
@@ -1,106 +1,106 @@
1
- import { Styles } from 'react-jss';
2
- import { Modifier, Placement } from 'react-overlays/usePopper';
3
- import {
4
- ICommonIcon,
5
- IComplexIcon,
6
- IPreloaderSvgType,
7
- ISvgIcon,
8
- } from './components';
9
-
10
- export interface IDataAttributes {
11
- [key: string]: unknown;
12
- }
13
-
14
- export interface ICommonProps {
15
- data?: IDataAttributes;
16
- }
17
-
18
- export interface IDropdownWithPopperOptions {
19
- shouldUsePopper?: boolean;
20
- shouldRenderInBody?: boolean;
21
- scrollParent?: 'auto' | 'document' | Element;
22
-
23
- shouldHideOnScroll?: boolean; // работает весьма условно без shouldUsePopper
24
- canBeFlipped?: boolean; // только с shouldUsePopper
25
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
- modifiers?: Array<Partial<Modifier<any, any>>>; // только с shouldUsePopper
27
- placement?: Placement; // only with shouldUsePopper
28
- // https://popper.js.org/docs/v2/modifiers/flip/
29
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
- flipOptions?: Record<string, any>; // только с shouldUsePopper
31
- }
32
-
33
- export type ComponentStyles<StyleSheet, Props = unknown> = Partial<
34
- Styles<keyof StyleSheet, Props>
35
- >;
36
-
37
- // TODO: Скрипт
38
- export type ComponentName =
39
- | 'AccountInfo'
40
- | 'AddButton'
41
- | 'Button'
42
- | 'CloseButton'
43
- | 'Checkbox'
44
- | 'CssBaseline'
45
- | 'Colors'
46
- | 'DateInput'
47
- | 'DatePicker'
48
- | 'DatePickerInput'
49
- | 'DatePickerHeader'
50
- | 'Description'
51
- | 'DotsPreloader'
52
- | 'SvgPreloader'
53
- | 'FiltersPane'
54
- | 'FilterInterval'
55
- | 'FilterSelect'
56
- | 'FilterWithDates'
57
- | 'FilterWithPeriod'
58
- | 'FilterWrapper'
59
- | 'FiltersPaneSearch'
60
- | 'Flag'
61
- | 'FlexibleTable'
62
- | 'Icon'
63
- | 'IncrementInput'
64
- | 'Input'
65
- | 'List'
66
- | 'Modal'
67
- | 'MoreMenu'
68
- | 'MultiSelect'
69
- | 'MultiSelectInput'
70
- | 'MultiSelectList'
71
- | 'Notification'
72
- | 'PhoneInput'
73
- | 'PhoneInputCountryList'
74
- | 'RadioButton'
75
- | 'SearchInput'
76
- | 'Select'
77
- | 'SelectList'
78
- | 'ScrollIntoViewIfNeeded'
79
- | 'Switch'
80
- | 'TextArea'
81
- | 'TextWithInfo'
82
- | 'TextWithTooltip'
83
- | 'ThemedPreloader'
84
- | 'Tooltip'
85
- | 'Toaster';
86
-
87
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
88
- export type UiKitAnimations = Record<string, any>;
89
- export type UiKitHelpers = Record<string, Styles | (() => Styles)>;
90
-
91
- export interface UiKitTheme {
92
- name: string;
93
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
94
- components?: Partial<Record<ComponentName, ComponentStyles<any, any>>>;
95
- /**
96
- * Для переопределения иконок, которые есть в UiKit
97
- */
98
- icons?: Partial<Record<ICommonIcon, ISvgIcon>>;
99
- complexIcons?: Partial<Record<IComplexIcon, string>>;
100
- preloaders?: Partial<Record<IPreloaderSvgType, string>>; // TODO: заменить string
101
- animations?: UiKitAnimations;
102
- colors?: Record<string, string>;
103
- dimensions?: Record<string, number>;
104
- boxShadows?: Record<string, string>;
105
- helpers?: UiKitHelpers;
106
- }
1
+ import { Styles } from 'react-jss';
2
+ import { Modifier, Placement } from 'react-overlays/usePopper';
3
+ import {
4
+ ICommonIcon,
5
+ IComplexIcon,
6
+ IPreloaderSvgType,
7
+ ISvgIcon,
8
+ } from './components';
9
+
10
+ export interface IDataAttributes {
11
+ [key: string]: unknown;
12
+ }
13
+
14
+ export interface ICommonProps {
15
+ data?: IDataAttributes;
16
+ }
17
+
18
+ export interface IDropdownWithPopperOptions {
19
+ shouldUsePopper?: boolean;
20
+ shouldRenderInBody?: boolean;
21
+ scrollParent?: 'auto' | 'document' | Element;
22
+
23
+ shouldHideOnScroll?: boolean; // работает весьма условно без shouldUsePopper
24
+ canBeFlipped?: boolean; // только с shouldUsePopper
25
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
+ modifiers?: Array<Partial<Modifier<any, any>>>; // только с shouldUsePopper
27
+ placement?: Placement; // only with shouldUsePopper
28
+ // https://popper.js.org/docs/v2/modifiers/flip/
29
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
30
+ flipOptions?: Record<string, any>; // только с shouldUsePopper
31
+ }
32
+
33
+ export type ComponentStyles<StyleSheet, Props = unknown> = Partial<
34
+ Styles<keyof StyleSheet, Props>
35
+ >;
36
+
37
+ // TODO: Скрипт
38
+ export type ComponentName =
39
+ | 'AccountInfo'
40
+ | 'AddButton'
41
+ | 'Button'
42
+ | 'CloseButton'
43
+ | 'Checkbox'
44
+ | 'CssBaseline'
45
+ | 'Colors'
46
+ | 'DateInput'
47
+ | 'DatePicker'
48
+ | 'DatePickerInput'
49
+ | 'DatePickerHeader'
50
+ | 'Description'
51
+ | 'DotsPreloader'
52
+ | 'SvgPreloader'
53
+ | 'FiltersPane'
54
+ | 'FilterInterval'
55
+ | 'FilterSelect'
56
+ | 'FilterWithDates'
57
+ | 'FilterWithPeriod'
58
+ | 'FilterWrapper'
59
+ | 'FiltersPaneSearch'
60
+ | 'Flag'
61
+ | 'FlexibleTable'
62
+ | 'Icon'
63
+ | 'IncrementInput'
64
+ | 'Input'
65
+ | 'List'
66
+ | 'Modal'
67
+ | 'MoreMenu'
68
+ | 'MultiSelect'
69
+ | 'MultiSelectInput'
70
+ | 'MultiSelectList'
71
+ | 'Notification'
72
+ | 'PhoneInput'
73
+ | 'PhoneInputCountryList'
74
+ | 'RadioButton'
75
+ | 'SearchInput'
76
+ | 'Select'
77
+ | 'SelectList'
78
+ | 'ScrollIntoViewIfNeeded'
79
+ | 'Switch'
80
+ | 'TextArea'
81
+ | 'TextWithInfo'
82
+ | 'TextWithTooltip'
83
+ | 'ThemedPreloader'
84
+ | 'Tooltip'
85
+ | 'Toaster';
86
+
87
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
88
+ export type UiKitAnimations = Record<string, any>;
89
+ export type UiKitHelpers = Record<string, Styles | (() => Styles)>;
90
+
91
+ export interface UiKitTheme {
92
+ name: string;
93
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
94
+ components?: Partial<Record<ComponentName, ComponentStyles<any, any>>>;
95
+ /**
96
+ * Для переопределения иконок, которые есть в UiKit
97
+ */
98
+ icons?: Partial<Record<ICommonIcon, ISvgIcon>>;
99
+ complexIcons?: Partial<Record<IComplexIcon, string>>;
100
+ preloaders?: Partial<Record<IPreloaderSvgType, string>>; // TODO: заменить string
101
+ animations?: UiKitAnimations;
102
+ colors?: Record<string, string>;
103
+ dimensions?: Record<string, number>;
104
+ boxShadows?: Record<string, string>;
105
+ helpers?: UiKitHelpers;
106
+ }