@true-engineering/true-react-common-ui-kit 3.8.0 → 3.8.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.
Files changed (117) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +6 -0
  3. package/dist/components/NewMoreMenu/NewMoreMenu.d.ts +1 -1
  4. package/dist/components/WithPopup/WithPopup.d.ts +2 -0
  5. package/dist/true-react-common-ui-kit.js +62 -60
  6. package/dist/true-react-common-ui-kit.js.map +1 -1
  7. package/dist/true-react-common-ui-kit.umd.cjs +62 -60
  8. package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
  9. package/package.json +1 -1
  10. package/src/components/AccountInfo/AccountInfo.stories.tsx +32 -32
  11. package/src/components/AccountInfo/AccountInfo.tsx +80 -80
  12. package/src/components/AddButton/AddButton.stories.tsx +21 -21
  13. package/src/components/AddButton/AddButton.tsx +52 -52
  14. package/src/components/Button/Button.stories.tsx +56 -56
  15. package/src/components/Button/Button.tsx +129 -129
  16. package/src/components/Checkbox/Checkbox.stories.tsx +28 -28
  17. package/src/components/Checkbox/Checkbox.tsx +85 -85
  18. package/src/components/CloseButton/CloseButton.tsx +34 -34
  19. package/src/components/Colors/Colors.stories.tsx +7 -7
  20. package/src/components/DateInput/DateInput.tsx +90 -90
  21. package/src/components/DateInput/constants.ts +2 -2
  22. package/src/components/DatePicker/DatePicker.tsx +308 -308
  23. package/src/components/Description/Description.stories.tsx +27 -27
  24. package/src/components/Description/Description.tsx +61 -61
  25. package/src/components/FiltersPane/FiltersPane.tsx +158 -158
  26. package/src/components/FiltersPane/components/Filter/Filter.tsx +203 -203
  27. package/src/components/FiltersPane/components/FilterValueView/FilterValueView.tsx +166 -166
  28. package/src/components/FiltersPane/components/FilterWithDates/FilterWithDates.tsx +210 -210
  29. package/src/components/FiltersPane/components/FilterWithPeriod/FilterWithPeriod.tsx +177 -177
  30. package/src/components/FiltersPane/components/FilterWrapper/FilterWrapper.tsx +167 -167
  31. package/src/components/Flag/Flag.stories.tsx +29 -29
  32. package/src/components/Flag/Flag.tsx +26 -26
  33. package/src/components/Flag/augment.d.ts +1 -1
  34. package/src/components/FlexibleTable/FlexibleTable.stories.tsx +267 -267
  35. package/src/components/FlexibleTable/FlexibleTable.styles.ts +110 -110
  36. package/src/components/FlexibleTable/FlexibleTable.tsx +271 -271
  37. package/src/components/FlexibleTable/components/FlexibleTableCell/FlexibleTableCell.styles.ts +38 -38
  38. package/src/components/FlexibleTable/components/FlexibleTableCell/FlexibleTableCell.tsx +83 -83
  39. package/src/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.styles.ts +25 -25
  40. package/src/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.tsx +196 -196
  41. package/src/components/FlexibleTable/helpers.ts +13 -13
  42. package/src/components/FlexibleTable/types.ts +52 -52
  43. package/src/components/Icon/Icon.stories.tsx +86 -86
  44. package/src/components/Icon/complexIcons/augment.d.ts +1 -1
  45. package/src/components/Icon/complexIcons/avatarGreen.svg +57 -57
  46. package/src/components/Icon/complexIcons/index.ts +1 -1
  47. package/src/components/IncrementInput/IncrementInput.tsx +105 -105
  48. package/src/components/Input/Input.tsx +297 -297
  49. package/src/components/Input/types.ts +32 -32
  50. package/src/components/List/List.stories.tsx +70 -70
  51. package/src/components/List/List.tsx +33 -33
  52. package/src/components/List/components/ListItem/ListItem.tsx +57 -57
  53. package/src/components/Modal/Modal.stories.tsx +105 -105
  54. package/src/components/Modal/Modal.tsx +196 -196
  55. package/src/components/MoreMenu/MoreMenu.styles.ts +68 -68
  56. package/src/components/MultiSelect/MultiSelect.stories.tsx +46 -46
  57. package/src/components/MultiSelect/MultiSelect.tsx +106 -106
  58. package/src/components/MultiSelect/components/MultiSelectInput/MultiSelectInput.tsx +53 -53
  59. package/src/components/MultiSelectList/MultiSelectList.tsx +461 -461
  60. package/src/components/NewMoreMenu/NewMoreMenu.stories.tsx +1 -0
  61. package/src/components/NewMoreMenu/NewMoreMenu.tsx +3 -1
  62. package/src/components/Notification/Notification.stories.tsx +46 -46
  63. package/src/components/Notification/Notification.tsx +69 -69
  64. package/src/components/NumberInput/NumberInput.tsx +137 -137
  65. package/src/components/NumberInput/index.ts +1 -1
  66. package/src/components/PhoneInput/PhoneInput.tsx +214 -214
  67. package/src/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.tsx +155 -155
  68. package/src/components/PhoneInput/types.ts +16 -16
  69. package/src/components/RadioButton/RadioButton.stories.tsx +46 -46
  70. package/src/components/RadioButton/RadioButton.tsx +57 -57
  71. package/src/components/ScrollIntoViewIfNeeded/index.ts +1 -1
  72. package/src/components/Select/CustomSelect.stories.tsx +217 -217
  73. package/src/components/Select/MultiSelect.stories.tsx +240 -240
  74. package/src/components/Select/Select.stories.tsx +235 -235
  75. package/src/components/Select/Select.tsx +580 -580
  76. package/src/components/Select/components/SelectList/SelectList.tsx +157 -157
  77. package/src/components/Select/components/SelectListItem/SelectListItem.tsx +68 -68
  78. package/src/components/Select/constants.ts +2 -2
  79. package/src/components/Select/types.ts +1 -1
  80. package/src/components/Selector/Selector.stories.tsx +62 -62
  81. package/src/components/Selector/Selector.styles.ts +164 -164
  82. package/src/components/Selector/Selector.tsx +115 -115
  83. package/src/components/Selector/index.ts +2 -2
  84. package/src/components/Selector/types.ts +12 -12
  85. package/src/components/Skeleton/Skeleton.stories.tsx +19 -19
  86. package/src/components/SmartInput/SmartInput.tsx +134 -134
  87. package/src/components/Status/Status.stories.tsx +73 -73
  88. package/src/components/Status/Status.styles.ts +143 -143
  89. package/src/components/Status/Status.tsx +49 -49
  90. package/src/components/Status/constants.ts +11 -11
  91. package/src/components/Status/index.ts +3 -3
  92. package/src/components/Status/types.ts +5 -5
  93. package/src/components/Switch/Switch.stories.tsx +40 -40
  94. package/src/components/Switch/Switch.tsx +75 -75
  95. package/src/components/TextArea/TextArea.tsx +180 -180
  96. package/src/components/TextButton/TextButton.stories.tsx +46 -46
  97. package/src/components/TextButton/TextButton.styles.ts +129 -129
  98. package/src/components/TextButton/TextButton.tsx +103 -103
  99. package/src/components/TextButton/index.ts +4 -4
  100. package/src/components/TextWithInfo/TextWithInfo.stories.tsx +53 -53
  101. package/src/components/TextWithInfo/TextWithInfo.tsx +62 -62
  102. package/src/components/TextWithTooltip/TextWithTooltip.stories.tsx +58 -58
  103. package/src/components/ThemedPreloader/ThemedPreloader.stories.tsx +41 -41
  104. package/src/components/ThemedPreloader/ThemedPreloader.tsx +54 -54
  105. package/src/components/ThemedPreloader/components/DefaultPreloader/index.ts +1 -1
  106. package/src/components/Toaster/Toaster.stories.tsx +30 -30
  107. package/src/components/Toaster/Toaster.tsx +108 -108
  108. package/src/components/Tooltip/Tooltip.stories.tsx +19 -19
  109. package/src/components/Tooltip/Tooltip.tsx +35 -35
  110. package/src/components/Tooltip/types.ts +1 -1
  111. package/src/components/WithPopup/WithPopup.stories.tsx +1 -0
  112. package/src/components/WithPopup/WithPopup.tsx +7 -1
  113. package/src/helpers/popper-helpers.ts +17 -17
  114. package/src/hooks/use-dropdown.ts +84 -84
  115. package/src/hooks/use-is-mounted.ts +15 -15
  116. package/src/theme/helpers.ts +76 -76
  117. package/src/vite-env.d.ts +1 -1
@@ -1,52 +1,52 @@
1
- import { CSSProperties, FC, ReactNode } from 'react';
2
-
3
- export type IFlexibleTableRenderMode = 'table' | 'divs';
4
-
5
- // TODO: Заменить Record<string, any> на Record<string, unknown>
6
- export type ITableRow = Record<string, any>;
7
-
8
- export type ITitleComponent<Value> = FC<{
9
- value?: Value;
10
- }>;
11
-
12
- export type IValueComponent<Values, Value> = (props: {
13
- value: Value;
14
- row: Values;
15
- isFocusedRow?: boolean;
16
- isNestedComponentExpanded: boolean;
17
- isRowNestedComponentExpanded: boolean;
18
- onSetNestedComponent: (component?: ReactNode) => void;
19
- }) => JSX.Element | ReactNode;
20
-
21
- export type IFlexibleTableConfigType<Values> = {
22
- [Key in keyof Values]?: {
23
- title?: ReactNode;
24
- titleComponent?: ITitleComponent<unknown>;
25
- component?: IValueComponent<Values, NonNullable<Values[Key]>>;
26
- dateFormat?: string;
27
- minWidth?: string | number;
28
- width?: string | number;
29
- maxWidth?: string | number;
30
- /** @default 'left' */
31
- titleAlign?: CSSProperties['textAlign'];
32
- cellAlign?: CSSProperties['textAlign'];
33
- cellVerticalAlign?: CSSProperties['verticalAlign'];
34
- position?: CSSProperties['position'];
35
- right?: number;
36
- left?: number;
37
- };
38
- };
39
-
40
- export interface IInfinityScrollConfig {
41
- activePage: number;
42
- totalPages: number;
43
- isLoading: boolean;
44
- isLastPage: boolean;
45
- onInfinityScroll: (skip: number) => void;
46
- }
47
-
48
- export interface INestedComponent {
49
- isOpen: boolean;
50
- component?: ReactNode;
51
- cellKey?: string;
52
- }
1
+ import { CSSProperties, FC, ReactNode } from 'react';
2
+
3
+ export type IFlexibleTableRenderMode = 'table' | 'divs';
4
+
5
+ // TODO: Заменить Record<string, any> на Record<string, unknown>
6
+ export type ITableRow = Record<string, any>;
7
+
8
+ export type ITitleComponent<Value> = FC<{
9
+ value?: Value;
10
+ }>;
11
+
12
+ export type IValueComponent<Values, Value> = (props: {
13
+ value: Value;
14
+ row: Values;
15
+ isFocusedRow?: boolean;
16
+ isNestedComponentExpanded: boolean;
17
+ isRowNestedComponentExpanded: boolean;
18
+ onSetNestedComponent: (component?: ReactNode) => void;
19
+ }) => JSX.Element | ReactNode;
20
+
21
+ export type IFlexibleTableConfigType<Values> = {
22
+ [Key in keyof Values]?: {
23
+ title?: ReactNode;
24
+ titleComponent?: ITitleComponent<unknown>;
25
+ component?: IValueComponent<Values, NonNullable<Values[Key]>>;
26
+ dateFormat?: string;
27
+ minWidth?: string | number;
28
+ width?: string | number;
29
+ maxWidth?: string | number;
30
+ /** @default 'left' */
31
+ titleAlign?: CSSProperties['textAlign'];
32
+ cellAlign?: CSSProperties['textAlign'];
33
+ cellVerticalAlign?: CSSProperties['verticalAlign'];
34
+ position?: CSSProperties['position'];
35
+ right?: number;
36
+ left?: number;
37
+ };
38
+ };
39
+
40
+ export interface IInfinityScrollConfig {
41
+ activePage: number;
42
+ totalPages: number;
43
+ isLoading: boolean;
44
+ isLastPage: boolean;
45
+ onInfinityScroll: (skip: number) => void;
46
+ }
47
+
48
+ export interface INestedComponent {
49
+ isOpen: boolean;
50
+ component?: ReactNode;
51
+ cellKey?: string;
52
+ }
@@ -1,86 +1,86 @@
1
- import { Icon } from './Icon';
2
- import { complexIcons } from './complexIcons';
3
- import { iconsList } from './icons-list';
4
- import { IIconType } from './types';
5
-
6
- const types: IIconType[] = [...Object.keys(iconsList), ...Object.keys(complexIcons)] as IIconType[];
7
-
8
- export default {
9
- title: 'Data Display/Icon',
10
- };
11
-
12
- export const Default = () => (
13
- <div
14
- style={{
15
- border: '1px dotted rgba(0,0,0,.2)',
16
- // color: color('Container color', colors.GREEN_FOCUS),
17
- display: 'flex',
18
- // width: number('Container width', 40, {
19
- // range: true,
20
- // min: 0,
21
- // max: 200,
22
- // step: 10,
23
- // }),
24
- // height: number('Container height', 40, {
25
- // range: true,
26
- // min: 0,
27
- // max: 200,
28
- // step: 10,
29
- // }),
30
- }}
31
- >
32
- {/* <Icon type={select('type', types, types[0])} /> */}
33
- </div>
34
- );
35
-
36
- export const Gallery = () => (
37
- <div
38
- style={{
39
- display: 'flex',
40
- alignItems: 'center',
41
- justifyContent: 'center',
42
- flexWrap: 'wrap',
43
- width: '80vw',
44
- }}
45
- >
46
- {types.map((type) => (
47
- <div
48
- key={type}
49
- style={{
50
- width: 100,
51
- height: 100,
52
- margin: 1,
53
- background: '#f7f7f7',
54
- display: 'flex',
55
- alignItems: 'center',
56
- justifyContent: 'center',
57
- flexDirection: 'column',
58
- }}
59
- >
60
- <div
61
- style={{
62
- width: 32,
63
- height: 32,
64
- margin: '10px 0',
65
- display: 'flex',
66
- alignItems: 'center',
67
- color: '#888',
68
- }}
69
- >
70
- <Icon type={type} />
71
- </div>
72
- <div
73
- style={{
74
- fontFamily: 'Arial',
75
- fontSize: 13,
76
- color: '#747679',
77
- overflow: 'hidden',
78
- padding: '0 5px',
79
- }}
80
- >
81
- {type}
82
- </div>
83
- </div>
84
- ))}
85
- </div>
86
- );
1
+ import { Icon } from './Icon';
2
+ import { complexIcons } from './complexIcons';
3
+ import { iconsList } from './icons-list';
4
+ import { IIconType } from './types';
5
+
6
+ const types: IIconType[] = [...Object.keys(iconsList), ...Object.keys(complexIcons)] as IIconType[];
7
+
8
+ export default {
9
+ title: 'Data Display/Icon',
10
+ };
11
+
12
+ export const Default = () => (
13
+ <div
14
+ style={{
15
+ border: '1px dotted rgba(0,0,0,.2)',
16
+ // color: color('Container color', colors.GREEN_FOCUS),
17
+ display: 'flex',
18
+ // width: number('Container width', 40, {
19
+ // range: true,
20
+ // min: 0,
21
+ // max: 200,
22
+ // step: 10,
23
+ // }),
24
+ // height: number('Container height', 40, {
25
+ // range: true,
26
+ // min: 0,
27
+ // max: 200,
28
+ // step: 10,
29
+ // }),
30
+ }}
31
+ >
32
+ {/* <Icon type={select('type', types, types[0])} /> */}
33
+ </div>
34
+ );
35
+
36
+ export const Gallery = () => (
37
+ <div
38
+ style={{
39
+ display: 'flex',
40
+ alignItems: 'center',
41
+ justifyContent: 'center',
42
+ flexWrap: 'wrap',
43
+ width: '80vw',
44
+ }}
45
+ >
46
+ {types.map((type) => (
47
+ <div
48
+ key={type}
49
+ style={{
50
+ width: 100,
51
+ height: 100,
52
+ margin: 1,
53
+ background: '#f7f7f7',
54
+ display: 'flex',
55
+ alignItems: 'center',
56
+ justifyContent: 'center',
57
+ flexDirection: 'column',
58
+ }}
59
+ >
60
+ <div
61
+ style={{
62
+ width: 32,
63
+ height: 32,
64
+ margin: '10px 0',
65
+ display: 'flex',
66
+ alignItems: 'center',
67
+ color: '#888',
68
+ }}
69
+ >
70
+ <Icon type={type} />
71
+ </div>
72
+ <div
73
+ style={{
74
+ fontFamily: 'Arial',
75
+ fontSize: 13,
76
+ color: '#747679',
77
+ overflow: 'hidden',
78
+ padding: '0 5px',
79
+ }}
80
+ >
81
+ {type}
82
+ </div>
83
+ </div>
84
+ ))}
85
+ </div>
86
+ );
@@ -1 +1 @@
1
- declare module '*.svg?raw';
1
+ declare module '*.svg?raw';
@@ -1,58 +1,58 @@
1
- <svg
2
- width="100%"
3
- height="100%"
4
- viewBox="0 0 32 32"
5
- fill="none"
6
- xmlns="http://www.w3.org/2000/svg"
7
- >
8
- <circle opacity="0.5" cx="16" cy="16" r="16" fill="#DDE3ED" />
9
- <mask
10
- id="mask0_0_12744"
11
- style="mask-type: 'alpha';"
12
- maskUnits="userSpaceOnUse"
13
- x="0"
14
- y="0"
15
- width="32"
16
- height="32"
17
- >
18
- <circle cx="16" cy="16" r="16" fill="white" />
19
- </mask>
20
- <g mask="url(#mask0_0_12744)">
21
- <circle cx="16" cy="29" r="13" fill="url(#paint0_linear_0_12744)" />
22
- <mask
23
- id="mask1_0_12744"
24
- style="mask-type: 'alpha';"
25
- maskUnits="userSpaceOnUse"
26
- x="3"
27
- y="16"
28
- width="26"
29
- height="26"
30
- >
31
- <circle cx="16" cy="29" r="13" fill="white" />
32
- </mask>
33
- <g mask="url(#mask1_0_12744)">
34
- <ellipse
35
- cx="16"
36
- cy="17.5"
37
- rx="6"
38
- ry="7.5"
39
- fill="#505F79"
40
- fill-opacity="0.204983"
41
- />
42
- </g>
43
- </g>
44
- <ellipse cx="16" cy="13" rx="6" ry="7" fill="white" />
45
- <defs>
46
- <linearGradient
47
- id="paint0_linear_0_12744"
48
- x1="13.347"
49
- y1="46.279"
50
- x2="33.5318"
51
- y2="30.8088"
52
- gradientUnits="userSpaceOnUse"
53
- >
54
- <stop stop-color="#ABD229" />
55
- <stop offset="1" stop-color="#9CD03F" />
56
- </linearGradient>
57
- </defs>
1
+ <svg
2
+ width="100%"
3
+ height="100%"
4
+ viewBox="0 0 32 32"
5
+ fill="none"
6
+ xmlns="http://www.w3.org/2000/svg"
7
+ >
8
+ <circle opacity="0.5" cx="16" cy="16" r="16" fill="#DDE3ED" />
9
+ <mask
10
+ id="mask0_0_12744"
11
+ style="mask-type: 'alpha';"
12
+ maskUnits="userSpaceOnUse"
13
+ x="0"
14
+ y="0"
15
+ width="32"
16
+ height="32"
17
+ >
18
+ <circle cx="16" cy="16" r="16" fill="white" />
19
+ </mask>
20
+ <g mask="url(#mask0_0_12744)">
21
+ <circle cx="16" cy="29" r="13" fill="url(#paint0_linear_0_12744)" />
22
+ <mask
23
+ id="mask1_0_12744"
24
+ style="mask-type: 'alpha';"
25
+ maskUnits="userSpaceOnUse"
26
+ x="3"
27
+ y="16"
28
+ width="26"
29
+ height="26"
30
+ >
31
+ <circle cx="16" cy="29" r="13" fill="white" />
32
+ </mask>
33
+ <g mask="url(#mask1_0_12744)">
34
+ <ellipse
35
+ cx="16"
36
+ cy="17.5"
37
+ rx="6"
38
+ ry="7.5"
39
+ fill="#505F79"
40
+ fill-opacity="0.204983"
41
+ />
42
+ </g>
43
+ </g>
44
+ <ellipse cx="16" cy="13" rx="6" ry="7" fill="white" />
45
+ <defs>
46
+ <linearGradient
47
+ id="paint0_linear_0_12744"
48
+ x1="13.347"
49
+ y1="46.279"
50
+ x2="33.5318"
51
+ y2="30.8088"
52
+ gradientUnits="userSpaceOnUse"
53
+ >
54
+ <stop stop-color="#ABD229" />
55
+ <stop offset="1" stop-color="#9CD03F" />
56
+ </linearGradient>
57
+ </defs>
58
58
  </svg>
@@ -1 +1 @@
1
- export * from './icons';
1
+ export * from './icons';
@@ -1,105 +1,105 @@
1
- import { FC, useEffect } from 'react';
2
- import clsx from 'clsx';
3
- import { addDataTestId, isNumberInteger } from '@true-engineering/true-react-platform-helpers';
4
- import { addDataAttributes, getNumberInRange, getNumberLength } from '../../helpers';
5
- import { useTweakStyles } from '../../hooks';
6
- import { ICommonProps } from '../../types';
7
- import { Icon } from '../Icon';
8
- import { INumberInputProps, NumberInput } from '../NumberInput';
9
- import { useStyles, IIncrementInputStyles, inputStyles } from './IncrementInput.styles';
10
-
11
- export interface IIncrementInputProps
12
- extends Omit<INumberInputProps, 'canBeFloat' | 'precision' | 'tweakStyles'>,
13
- ICommonProps<IIncrementInputStyles> {
14
- /** @default 1 */
15
- step?: number;
16
- }
17
-
18
- export const IncrementInput: FC<IIncrementInputProps> = ({
19
- value,
20
- onChange,
21
- min,
22
- max,
23
- step = 1,
24
- intPartPrecision,
25
- data,
26
- testId,
27
- tweakStyles,
28
- isDisabled,
29
- isReadonly,
30
- isInvalid,
31
- ...props
32
- }) => {
33
- const tweakInputStyles = useTweakStyles({
34
- innerStyles: inputStyles,
35
- tweakStyles,
36
- className: 'tweakInput',
37
- currentComponentName: 'IncrementInput',
38
- });
39
-
40
- const classes = useStyles({ theme: tweakStyles });
41
-
42
- const isIncreaseDisabled =
43
- isDisabled ||
44
- isReadonly ||
45
- (intPartPrecision !== undefined && getNumberLength((value ?? 0) + step) > intPartPrecision) ||
46
- (max !== undefined && value !== undefined && value >= max);
47
-
48
- const isDecreaseDisabled =
49
- isDisabled || isReadonly || (min !== undefined && value !== undefined ? value <= min : false);
50
-
51
- const increment = (): void => {
52
- onChange(getNumberInRange((value ?? 0) + step, min, max));
53
- };
54
-
55
- const decrement = (): void => {
56
- onChange(getNumberInRange((value ?? 0) - step, min, max));
57
- };
58
-
59
- useEffect(() => {
60
- if (!isNumberInteger(step)) {
61
- console.error('Параметр step должен быть целым числом');
62
- }
63
- }, [step]);
64
-
65
- return (
66
- <div className={classes.root} {...addDataTestId(testId)} {...addDataAttributes(data)}>
67
- <NumberInput
68
- {...props}
69
- isInvalid={isInvalid}
70
- isDisabled={isDisabled}
71
- isReadonly={isReadonly}
72
- min={min}
73
- max={max}
74
- intPartPrecision={intPartPrecision}
75
- onChange={onChange}
76
- value={value}
77
- tweakStyles={tweakInputStyles}
78
- />
79
- <div className={classes.buttons}>
80
- <button
81
- className={clsx(classes.button, {
82
- [classes.disabledButton]: isIncreaseDisabled,
83
- [classes.errorButton]: isInvalid,
84
- })}
85
- type="button"
86
- disabled={isIncreaseDisabled}
87
- onClick={increment}
88
- >
89
- <Icon type="plus" />
90
- </button>
91
- <button
92
- className={clsx(classes.button, {
93
- [classes.disabledButton]: isDecreaseDisabled,
94
- [classes.errorButton]: isInvalid,
95
- })}
96
- type="button"
97
- disabled={isDecreaseDisabled}
98
- onClick={decrement}
99
- >
100
- <Icon type="minus" />
101
- </button>
102
- </div>
103
- </div>
104
- );
105
- };
1
+ import { FC, useEffect } from 'react';
2
+ import clsx from 'clsx';
3
+ import { addDataTestId, isNumberInteger } from '@true-engineering/true-react-platform-helpers';
4
+ import { addDataAttributes, getNumberInRange, getNumberLength } from '../../helpers';
5
+ import { useTweakStyles } from '../../hooks';
6
+ import { ICommonProps } from '../../types';
7
+ import { Icon } from '../Icon';
8
+ import { INumberInputProps, NumberInput } from '../NumberInput';
9
+ import { useStyles, IIncrementInputStyles, inputStyles } from './IncrementInput.styles';
10
+
11
+ export interface IIncrementInputProps
12
+ extends Omit<INumberInputProps, 'canBeFloat' | 'precision' | 'tweakStyles'>,
13
+ ICommonProps<IIncrementInputStyles> {
14
+ /** @default 1 */
15
+ step?: number;
16
+ }
17
+
18
+ export const IncrementInput: FC<IIncrementInputProps> = ({
19
+ value,
20
+ onChange,
21
+ min,
22
+ max,
23
+ step = 1,
24
+ intPartPrecision,
25
+ data,
26
+ testId,
27
+ tweakStyles,
28
+ isDisabled,
29
+ isReadonly,
30
+ isInvalid,
31
+ ...props
32
+ }) => {
33
+ const tweakInputStyles = useTweakStyles({
34
+ innerStyles: inputStyles,
35
+ tweakStyles,
36
+ className: 'tweakInput',
37
+ currentComponentName: 'IncrementInput',
38
+ });
39
+
40
+ const classes = useStyles({ theme: tweakStyles });
41
+
42
+ const isIncreaseDisabled =
43
+ isDisabled ||
44
+ isReadonly ||
45
+ (intPartPrecision !== undefined && getNumberLength((value ?? 0) + step) > intPartPrecision) ||
46
+ (max !== undefined && value !== undefined && value >= max);
47
+
48
+ const isDecreaseDisabled =
49
+ isDisabled || isReadonly || (min !== undefined && value !== undefined ? value <= min : false);
50
+
51
+ const increment = (): void => {
52
+ onChange(getNumberInRange((value ?? 0) + step, min, max));
53
+ };
54
+
55
+ const decrement = (): void => {
56
+ onChange(getNumberInRange((value ?? 0) - step, min, max));
57
+ };
58
+
59
+ useEffect(() => {
60
+ if (!isNumberInteger(step)) {
61
+ console.error('Параметр step должен быть целым числом');
62
+ }
63
+ }, [step]);
64
+
65
+ return (
66
+ <div className={classes.root} {...addDataTestId(testId)} {...addDataAttributes(data)}>
67
+ <NumberInput
68
+ {...props}
69
+ isInvalid={isInvalid}
70
+ isDisabled={isDisabled}
71
+ isReadonly={isReadonly}
72
+ min={min}
73
+ max={max}
74
+ intPartPrecision={intPartPrecision}
75
+ onChange={onChange}
76
+ value={value}
77
+ tweakStyles={tweakInputStyles}
78
+ />
79
+ <div className={classes.buttons}>
80
+ <button
81
+ className={clsx(classes.button, {
82
+ [classes.disabledButton]: isIncreaseDisabled,
83
+ [classes.errorButton]: isInvalid,
84
+ })}
85
+ type="button"
86
+ disabled={isIncreaseDisabled}
87
+ onClick={increment}
88
+ >
89
+ <Icon type="plus" />
90
+ </button>
91
+ <button
92
+ className={clsx(classes.button, {
93
+ [classes.disabledButton]: isDecreaseDisabled,
94
+ [classes.errorButton]: isInvalid,
95
+ })}
96
+ type="button"
97
+ disabled={isDecreaseDisabled}
98
+ onClick={decrement}
99
+ >
100
+ <Icon type="minus" />
101
+ </button>
102
+ </div>
103
+ </div>
104
+ );
105
+ };