@true-engineering/true-react-common-ui-kit 3.45.1 → 4.0.0-alpha0

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 (122) hide show
  1. package/README.md +0 -40
  2. package/dist/components/CloseButton/CloseButton.d.ts +1 -1
  3. package/dist/components/ControlGroup/ControlGroup.d.ts +10 -0
  4. package/dist/components/ControlGroup/ControlGroup.stories.d.ts +7 -0
  5. package/dist/components/ControlGroup/ControlGroup.styles.d.ts +3 -0
  6. package/dist/components/ControlGroup/index.d.ts +2 -0
  7. package/dist/components/ControlWrapper/ControlWrapper.d.ts +27 -0
  8. package/dist/components/ControlWrapper/ControlWrapper.stories.d.ts +6 -0
  9. package/dist/components/ControlWrapper/ControlWrapper.styles.d.ts +6 -0
  10. package/dist/components/ControlWrapper/index.d.ts +2 -0
  11. package/dist/components/DateInput/DateInput.d.ts +3 -3
  12. package/dist/components/DatePicker/components/DatePickerHeader/DatePickerHeader.styles.d.ts +1 -1
  13. package/dist/components/DatePicker/types.d.ts +1 -1
  14. package/dist/components/FiltersPane/FiltersPane.stories.d.ts +1 -2
  15. package/dist/components/FiltersPane/components/FilterWithDates/FilterWithDates.d.ts +1 -1
  16. package/dist/components/FiltersPane/components/FiltersPaneSearch/FiltersPaneSearch.d.ts +1 -2
  17. package/dist/components/Input/Input.d.ts +5 -52
  18. package/dist/components/Input/Input.stories.d.ts +4 -13
  19. package/dist/components/Input/Input.styles.d.ts +5 -4
  20. package/dist/components/Input/InputBase.d.ts +24 -0
  21. package/dist/components/Input/index.d.ts +1 -0
  22. package/dist/components/Input/types.d.ts +3 -4
  23. package/dist/components/NumberInput/NumberInput.d.ts +3 -3
  24. package/dist/components/PhoneInput/PhoneInput.d.ts +3 -3
  25. package/dist/components/PhoneInput/PhoneInput.stories.d.ts +2 -2
  26. package/dist/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.d.ts +3 -2
  27. package/dist/components/PhoneInput/types.d.ts +2 -0
  28. package/dist/components/SearchInput/SearchInput.d.ts +1 -3
  29. package/dist/components/SearchInput/SearchInput.stories.d.ts +11 -1
  30. package/dist/components/SearchInput/SearchInput.styles.d.ts +1 -1
  31. package/dist/components/Select/Select.d.ts +5 -5
  32. package/dist/components/Select/Select.styles.d.ts +17 -16
  33. package/dist/components/Select/types.d.ts +3 -0
  34. package/dist/components/SmartInput/SmartInput.d.ts +3 -3
  35. package/dist/components/TextArea/TextArea.d.ts +5 -14
  36. package/dist/components/TextArea/TextArea.styles.d.ts +8 -2
  37. package/dist/components/WithPopup/WithPopup.d.ts +3 -10
  38. package/dist/components/WithPopup/WithPopup.styles.d.ts +1 -1
  39. package/dist/components/WithPopup/types.d.ts +0 -3
  40. package/dist/components/WithTooltip/WithTooltip.styles.d.ts +0 -1
  41. package/dist/components/index.d.ts +2 -0
  42. package/dist/theme/common.d.ts +13 -5
  43. package/dist/theme/types.d.ts +4 -2
  44. package/dist/true-react-common-ui-kit.js +1184 -1029
  45. package/dist/true-react-common-ui-kit.js.map +1 -1
  46. package/dist/true-react-common-ui-kit.umd.cjs +1164 -1009
  47. package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
  48. package/dist/types.d.ts +2 -1
  49. package/package.json +1 -1
  50. package/src/components/Button/Button.stories.tsx +4 -8
  51. package/src/components/CloseButton/CloseButton.tsx +4 -4
  52. package/src/components/ControlGroup/ControlGroup.stories.tsx +40 -0
  53. package/src/components/ControlGroup/ControlGroup.styles.ts +46 -0
  54. package/src/components/ControlGroup/ControlGroup.tsx +55 -0
  55. package/src/components/ControlGroup/index.ts +2 -0
  56. package/src/components/ControlWrapper/ControlWrapper.stories.tsx +45 -0
  57. package/src/components/ControlWrapper/ControlWrapper.styles.ts +185 -0
  58. package/src/components/ControlWrapper/ControlWrapper.tsx +151 -0
  59. package/src/components/ControlWrapper/index.ts +2 -0
  60. package/src/components/DateInput/DateInput.styles.ts +2 -7
  61. package/src/components/DateInput/DateInput.tsx +4 -4
  62. package/src/components/DatePicker/DatePicker.tsx +3 -3
  63. package/src/components/DatePicker/components/DatePickerHeader/DatePickerHeader.styles.ts +7 -41
  64. package/src/components/DatePicker/components/DatePickerHeader/DatePickerHeader.tsx +18 -26
  65. package/src/components/DatePicker/types.ts +1 -1
  66. package/src/components/FileItem/FileItem.stories.tsx +4 -8
  67. package/src/components/FiltersPane/FiltersPane.stories.tsx +0 -4
  68. package/src/components/FiltersPane/components/FilterInterval/FilterInterval.styles.ts +9 -7
  69. package/src/components/FiltersPane/components/FilterInterval/FilterInterval.tsx +1 -8
  70. package/src/components/FiltersPane/components/FilterSelect/FilterSelect.styles.ts +7 -5
  71. package/src/components/FiltersPane/components/FilterWithDates/FilterWithDates.tsx +7 -9
  72. package/src/components/FiltersPane/components/FiltersPaneSearch/FiltersPaneSearch.styles.ts +12 -17
  73. package/src/components/FiltersPane/components/FiltersPaneSearch/FiltersPaneSearch.tsx +2 -5
  74. package/src/components/IconButton/IconButton.stories.tsx +5 -5
  75. package/src/components/IncrementInput/IncrementInput.stories.tsx +0 -2
  76. package/src/components/IncrementInput/IncrementInput.styles.ts +9 -9
  77. package/src/components/Input/Input.stories.tsx +17 -25
  78. package/src/components/Input/Input.styles.ts +50 -260
  79. package/src/components/Input/Input.tsx +22 -285
  80. package/src/components/Input/InputBase.tsx +250 -0
  81. package/src/components/Input/index.ts +1 -0
  82. package/src/components/Input/types.ts +3 -32
  83. package/src/components/MultiSelectList/MultiSelectList.styles.ts +7 -5
  84. package/src/components/Notification/Notification.stories.tsx +2 -6
  85. package/src/components/NumberInput/NumberInput.stories.tsx +0 -2
  86. package/src/components/NumberInput/NumberInput.tsx +4 -7
  87. package/src/components/PhoneInput/PhoneInput.stories.tsx +6 -10
  88. package/src/components/PhoneInput/PhoneInput.styles.ts +13 -10
  89. package/src/components/PhoneInput/PhoneInput.tsx +9 -12
  90. package/src/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.styles.ts +6 -4
  91. package/src/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.tsx +6 -6
  92. package/src/components/PhoneInput/types.ts +4 -0
  93. package/src/components/SearchInput/SearchInput.stories.tsx +1 -0
  94. package/src/components/SearchInput/SearchInput.styles.ts +17 -27
  95. package/src/components/SearchInput/SearchInput.tsx +13 -34
  96. package/src/components/Select/CustomSelect.stories.tsx +6 -9
  97. package/src/components/Select/MultiSelect.stories.tsx +4 -12
  98. package/src/components/Select/Select.stories.tsx +3 -11
  99. package/src/components/Select/Select.styles.ts +28 -42
  100. package/src/components/Select/Select.tsx +73 -81
  101. package/src/components/Select/types.ts +5 -0
  102. package/src/components/SmartInput/SmartInput.stories.tsx +0 -1
  103. package/src/components/SmartInput/SmartInput.tsx +4 -4
  104. package/src/components/Status/Status.stories.tsx +3 -7
  105. package/src/components/TextArea/TextArea.stories.tsx +1 -3
  106. package/src/components/TextArea/TextArea.styles.ts +27 -126
  107. package/src/components/TextArea/TextArea.tsx +86 -112
  108. package/src/components/TextButton/TextButton.stories.tsx +4 -8
  109. package/src/components/WithPopup/WithPopup.stories.tsx +0 -1
  110. package/src/components/WithPopup/WithPopup.styles.ts +0 -2
  111. package/src/components/WithPopup/WithPopup.tsx +10 -36
  112. package/src/components/WithPopup/types.ts +0 -7
  113. package/src/components/WithTooltip/WithTooltip.styles.ts +0 -6
  114. package/src/components/WithTooltip/WithTooltip.tsx +2 -7
  115. package/src/components/index.ts +2 -0
  116. package/src/theme/common.ts +15 -6
  117. package/src/theme/types.ts +8 -4
  118. package/src/types.ts +3 -0
  119. package/dist/components/Input/constants.d.ts +0 -1
  120. package/dist/components/WithPopup/helpers.d.ts +0 -2
  121. package/src/components/Input/constants.ts +0 -1
  122. package/src/components/WithPopup/helpers.ts +0 -9
@@ -1,7 +1,7 @@
1
- import { ClipboardEvent, FormEvent, forwardRef, useRef } from 'react';
1
+ import { ClipboardEvent, forwardRef, useRef } from 'react';
2
2
  import { isEmpty, isNotEmpty } from '@true-engineering/true-react-platform-helpers';
3
3
  import { useMergedRefs } from '../../hooks';
4
- import { IInputProps, Input } from '../Input';
4
+ import { IChangeInputEvent, IInputProps, Input } from '../Input';
5
5
  import {
6
6
  CharactersMap,
7
7
  EmailCharactersMap,
@@ -22,7 +22,7 @@ export interface ISmartInputProps extends Omit<IInputProps, 'onChange'> {
22
22
  onChange: (
23
23
  value: string,
24
24
  rawValue: IInputRawValue,
25
- event?: FormEvent<HTMLInputElement> | ClipboardEvent<HTMLInputElement>,
25
+ event?: IChangeInputEvent | ClipboardEvent<HTMLInputElement>,
26
26
  ) => void;
27
27
  }
28
28
 
@@ -56,7 +56,7 @@ export const SmartInput = forwardRef<HTMLInputElement, ISmartInputProps>(
56
56
  }
57
57
  };
58
58
 
59
- const handleChange = async (str: string, event: FormEvent<HTMLInputElement>) => {
59
+ const handleChange = async (str: string, event: IChangeInputEvent) => {
60
60
  const isValid = regex.test(str);
61
61
 
62
62
  const charactersMap = smartType === 'email' ? EmailCharactersMap : CharactersMap;
@@ -1,6 +1,6 @@
1
1
  import { Status } from '.';
2
2
  import { ComponentStory } from '@storybook/react';
3
- import { IIconType, iconsList } from '../Icon';
3
+ import { iconsList, IIconType } from '../Icon';
4
4
  import { complexIcons } from '../Icon/complexIcons';
5
5
  import { STATUS_COLORS, STATUS_SIZES } from './constants';
6
6
  import { IStatusStyles } from './Status.styles';
@@ -10,11 +10,7 @@ export default {
10
10
  component: Status,
11
11
  };
12
12
 
13
- const iconTypes = [
14
- undefined,
15
- ...Object.keys(iconsList),
16
- ...Object.keys(complexIcons),
17
- ] as IIconType[];
13
+ const icons = [undefined, ...Object.keys(iconsList), ...Object.keys(complexIcons)] as IIconType[];
18
14
 
19
15
  const customTweakStyles: IStatusStyles = {
20
16
  custom: {
@@ -62,7 +58,7 @@ Default.args = {
62
58
  };
63
59
 
64
60
  Default.argTypes = {
65
- icon: { options: iconTypes, control: 'select' },
61
+ icon: { options: icons, control: 'select' },
66
62
  iconPosition: { options: ['left', 'right'], control: 'inline-radio' },
67
63
  };
68
64
 
@@ -25,13 +25,11 @@ Default.args = {
25
25
  infoMessage: 'Message Info',
26
26
  rows: 5,
27
27
  maxLength: 500,
28
- hasFloatingLabel: true,
29
- hasRequiredLabel: true,
30
28
  isInvalid: false,
31
29
  errorMessage: 'Error Text',
32
30
  isActive: false,
33
31
  isDisabled: false,
34
32
  isRequired: false,
35
- isAutoSizeable: true,
33
+ isAutoSized: true,
36
34
  shouldAlwaysShowPlaceholder: false,
37
35
  };
@@ -1,46 +1,25 @@
1
- import { ITweakStyles, animations, createThemedStyles, helpers } from '../../theme';
2
-
3
- const PADDING_X = 12;
1
+ import { animations, createThemedStyles, helpers, ITweakStyles } from '../../theme';
2
+ import { IControlGroupStyles } from '../ControlGroup';
3
+ import { IControlWrapperStyles } from '../ControlWrapper';
4
4
 
5
5
  export const useStyles = createThemedStyles('TextArea', {
6
- root: {
7
- width: '100%',
8
- height: '100%',
9
- display: 'flex',
10
- flexDirection: 'column',
11
- },
12
-
13
- wrapper: {
14
- display: 'flex',
15
- position: 'relative',
16
- width: '100%',
17
- flexGrow: 1,
18
- boxSizing: 'border-box',
19
- transition: animations.defaultTransition,
20
- transitionProperty: 'border-color',
21
- backgroundColor: 'white',
22
- border: ['solid', 1, 'lightgray'],
23
- },
24
-
25
6
  textarea: {
26
7
  ...helpers.withScrollBar,
27
-
28
8
  width: '100%',
29
9
  height: '100%',
30
- outline: 'none',
31
- outlineStyle: 'none',
32
10
  fontFamily: 'inherit',
33
11
  fontSize: 16,
34
- padding: [14, PADDING_X, 8],
35
- scrollPadding: '14px 0 8px',
12
+ padding: [14, 0, 8, 'var(--control-padding)'],
13
+ scrollPadding: '14px 0 8px var(--control-padding)',
14
+ scrollbarGutter: 'stable',
15
+ boxSizing: 'border-box',
16
+ outline: 'none',
17
+ outlineStyle: 'none',
36
18
  transition: animations.defaultTransition,
37
19
  transitionProperty: 'background-color',
38
20
  border: 'none',
39
21
  resize: 'none',
40
-
41
- '&:disabled': {
42
- extend: 'disabled',
43
- },
22
+ background: 'transparent',
44
23
 
45
24
  '&::placeholder': {
46
25
  opacity: 1,
@@ -53,125 +32,47 @@ export const useStyles = createThemedStyles('TextArea', {
53
32
  },
54
33
  },
55
34
 
56
- autosize: {
57
- display: 'inline-grid',
35
+ autoSized: {
36
+ display: 'grid',
58
37
  gridTemplateRows: 'minmax(0, 100%)',
59
38
 
60
39
  '& > $textarea, &::after': {
61
- gridArea: '1 / 1 / 2 / 2',
40
+ gridArea: '1 / 2',
62
41
  },
63
42
 
64
43
  '&::after': {
65
44
  extend: 'textarea',
66
- content: 'attr(data-value) " "',
45
+ content: 'attr(data-value) " "', // Без пробела ломается!
67
46
  overflowWrap: 'break-word',
68
47
  whiteSpace: 'pre-wrap',
69
48
  visibility: 'hidden',
70
- scrollbarGutter: 'stable',
71
- },
72
- },
73
-
74
- focused: {
75
- position: 'relative',
76
- zIndex: 1,
77
- },
78
-
79
- withFloatingLabel: {
80
- '& $textarea, &::after': {
81
- paddingTop: 24,
82
- scrollPaddingTop: '24px',
83
- },
84
- },
85
-
86
- floating: {},
87
-
88
- activeLabel: {
89
- display: 'none',
90
-
91
- '&$floating': {
92
- display: 'block',
93
- transform: 'scale(0.75) translateY(-120%)',
94
- },
95
- },
96
-
97
- required: {
98
- '&:before': {
99
- content: '""',
100
- position: 'absolute',
101
- left: -12,
102
- top: 20,
103
- width: 6,
104
- height: 6,
105
- borderRadius: '50%',
106
-
107
- backgroundColor: 'red',
108
- },
109
- },
110
-
111
- disabled: {},
112
-
113
- label: {
114
- position: 'absolute',
115
- pointerEvents: 'none',
116
- left: PADDING_X,
117
- top: PADDING_X * 2,
118
- transformOrigin: 'top left',
119
- transform: 'translateY(-50%)',
120
- transition: animations.defaultTransition,
121
- transitionProperty: 'transform, color',
122
- fontSize: 16,
123
- },
124
-
125
- invalid: {
126
- borderColor: 'red',
127
- },
128
-
129
- invalidLabel: {},
130
-
131
- error: {
132
- fontSize: 12,
133
- paddingTop: 4,
134
- paddingLeft: 13,
135
- color: 'red',
136
- },
137
-
138
- requiredLabel: {
139
- '&:after': {
140
- content: '""',
141
- position: 'absolute',
142
- right: -8,
143
- top: 4,
144
- transform: 'translate(0, -50%)',
145
- width: 6,
146
- height: 6,
147
- borderRadius: '50%',
148
- backgroundColor: 'red',
149
49
  },
150
50
  },
151
51
 
152
52
  symbolsCount: {
153
- display: 'block',
154
53
  textAlign: 'right',
155
54
  marginTop: 4,
156
55
  fontSize: 12,
157
56
  marginLeft: 'auto',
158
- paddingLeft: 32,
159
57
  whiteSpace: 'nowrap',
58
+ pointerEvents: 'none',
160
59
  },
161
60
 
162
61
  symbolsCountError: {
163
62
  color: 'red',
164
63
  },
64
+ });
165
65
 
166
- footer: {
167
- display: 'flex',
168
- },
169
-
170
- info: {
171
- fontSize: 12,
172
- paddingTop: 4,
173
- paddingLeft: 13,
66
+ export const controlWrapperStyles: IControlWrapperStyles = {
67
+ label: {
68
+ top: 16,
174
69
  },
175
- });
70
+ };
176
71
 
177
- export type ITextAreaStyles = ITweakStyles<typeof useStyles>;
72
+ export type ITextAreaStyles = ITweakStyles<
73
+ typeof useStyles,
74
+ {
75
+ tweakControlGroup: IControlGroupStyles;
76
+ tweakControlWrapper: IControlWrapperStyles;
77
+ }
78
+ >;
@@ -1,39 +1,34 @@
1
- import { forwardRef, useState, FormEvent, FocusEvent, ChangeEvent, ReactNode } from 'react';
1
+ import { ChangeEvent, FocusEvent, FormEvent, forwardRef, useState } from 'react';
2
2
  import clsx from 'clsx';
3
3
  import {
4
- addDataTestId,
4
+ addDataAttributes,
5
5
  isNotEmpty,
6
6
  isReactNodeNotEmpty,
7
7
  isStringNotEmpty,
8
8
  } from '@true-engineering/true-react-platform-helpers';
9
- import { addDataAttributes, trimStringToMaxLength } from '../../helpers';
9
+ import { useTweakStyles } from '../../hooks';
10
10
  import { ICommonProps } from '../../types';
11
+ import { ControlGroup, IControlGroupProps } from '../ControlGroup';
12
+ import { ControlWrapper, IControlWrapperProps } from '../ControlWrapper';
11
13
  import { ITextAreaHTMLBaseProps } from './types';
12
- import { useStyles, ITextAreaStyles } from './TextArea.styles';
14
+ import { controlWrapperStyles, ITextAreaStyles, useStyles } from './TextArea.styles';
13
15
 
14
- export interface ITextAreaProps extends ICommonProps<ITextAreaStyles>, ITextAreaHTMLBaseProps {
16
+ export interface ITextAreaProps
17
+ extends ICommonProps<ITextAreaStyles>,
18
+ Pick<IControlWrapperProps, 'label' | 'isInvalid' | 'isRequired' | 'isDisabled'>,
19
+ Pick<IControlGroupProps, 'infoMessage' | 'errorMessage'>,
20
+ Pick<ITextAreaHTMLBaseProps, 'name' | 'maxLength' | 'rows' | 'onPaste' | 'onFocus' | 'onBlur'> {
15
21
  value?: string;
16
- label?: ReactNode;
17
22
  placeholder?: string;
18
23
  /** @default false */
19
24
  isDisabled?: boolean;
20
- /** @default true */
21
- hasFloatingLabel?: boolean;
22
- /** @default false */
23
- isInvalid?: boolean;
24
25
  /** @default false */
25
26
  isActive?: boolean;
26
27
  /**
27
28
  * Должна ли высота и ширина textarea подстраиваться под содержимое
28
29
  * @default true
29
30
  */
30
- isAutoSizeable?: boolean;
31
- infoMessage?: string;
32
- errorMessage?: string;
33
- /** @default false */
34
- isRequired?: boolean;
35
- /** @default false */
36
- hasRequiredLabel?: boolean;
31
+ isAutoSized?: boolean;
37
32
  /** @default false */
38
33
  shouldFocusOnMount?: boolean;
39
34
  /** @default true */
@@ -53,131 +48,110 @@ export const TextArea = forwardRef<HTMLTextAreaElement, ITextAreaProps>(
53
48
  value = DEFAULT_VALUE,
54
49
  label,
55
50
  placeholder,
56
- isDisabled,
57
- hasFloatingLabel = true,
58
- isInvalid = false,
59
- isActive = false,
60
51
  infoMessage,
61
52
  errorMessage,
62
- isRequired = false,
63
53
  name,
64
- hasRequiredLabel = false,
65
- shouldFocusOnMount = false,
54
+ shouldFocusOnMount,
66
55
  hasCounter = true,
67
- shouldTrimAfterMaxLength = false,
68
- isAutoSizeable = true,
69
- shouldAlwaysShowPlaceholder = false,
56
+ shouldTrimAfterMaxLength,
57
+ isAutoSized = true,
58
+ shouldAlwaysShowPlaceholder,
59
+ isDisabled,
60
+ isActive,
70
61
  maxLength,
71
62
  rows,
72
- testId,
73
63
  data,
64
+ testId,
74
65
  tweakStyles,
75
66
  onChange,
76
67
  onPaste,
77
68
  onFocus,
78
69
  onBlur,
70
+ ...controlProps
79
71
  },
80
72
  ref,
81
73
  ) => {
82
74
  const classes = useStyles({ theme: tweakStyles });
83
75
 
84
- const [isFocused, setFocused] = useState(false);
85
-
86
- const handleOnChange = (event: ChangeEvent<HTMLTextAreaElement>) => {
87
- const rawValue = event.currentTarget.value;
88
- const newValue =
89
- shouldTrimAfterMaxLength && maxLength !== undefined
90
- ? trimStringToMaxLength(rawValue, maxLength)
91
- : rawValue;
92
-
93
- onChange(newValue, event);
94
- };
76
+ const tweakControlGroupStyles = useTweakStyles({
77
+ tweakStyles,
78
+ className: 'tweakControlGroup',
79
+ currentComponentName: 'TextArea',
80
+ });
95
81
 
96
- const handleOnFocus = (event: FocusEvent<HTMLTextAreaElement>) => {
97
- setFocused(true);
98
- if (onFocus !== undefined) {
99
- onFocus(event);
100
- }
101
- };
82
+ const tweakControlWrapperStyles = useTweakStyles({
83
+ innerStyles: controlWrapperStyles,
84
+ tweakStyles,
85
+ className: 'tweakControlWrapper',
86
+ currentComponentName: 'TextArea',
87
+ });
102
88
 
103
- const handleOnBlur = (event: FocusEvent<HTMLTextAreaElement>) => {
104
- setFocused(false);
105
- if (onBlur !== undefined) {
106
- onBlur(event);
107
- }
108
- };
89
+ const [isFocused, setFocused] = useState(false);
109
90
 
110
91
  const hasFocus = isFocused || isActive;
111
92
  // в hasValue нельзя использовать isStringNotEmpty из-за того что isStringNotEmpty делает trim
112
93
  const hasValue = value !== undefined && value !== '';
113
94
  const hasLabel = isReactNodeNotEmpty(label);
114
- const hasPlaceholder =
115
- (!hasLabel || hasFocus || shouldAlwaysShowPlaceholder) && isStringNotEmpty(placeholder);
95
+ const hasPlaceholder = (!hasLabel || hasFocus || shouldAlwaysShowPlaceholder) && isStringNotEmpty(placeholder);
116
96
 
117
- const props = {
118
- className: classes.textarea,
119
- onFocus: handleOnFocus,
120
- onBlur: handleOnBlur,
121
- onChange: handleOnChange,
122
- value,
123
- onPaste,
124
- disabled: isDisabled,
125
- placeholder: hasPlaceholder ? placeholder : undefined,
126
- name,
127
- autoFocus: shouldFocusOnMount,
128
- rows,
129
- ...addDataTestId(testId),
97
+ const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => {
98
+ onChange(event.currentTarget.value, event);
130
99
  };
131
100
 
132
- const hasInfoMessage = isStringNotEmpty(infoMessage);
133
- const hasErrorMessage = isStringNotEmpty(errorMessage);
101
+ const handleFocus = (event: FocusEvent<HTMLTextAreaElement>) => {
102
+ setFocused(true);
103
+ onFocus?.(event);
104
+ };
105
+
106
+ const handleBlur = (event: FocusEvent<HTMLTextAreaElement>) => {
107
+ setFocused(false);
108
+ onBlur?.(event);
109
+ };
134
110
 
135
111
  return (
136
- <div className={classes.root} {...addDataAttributes(data)}>
137
- <div
138
- className={clsx(classes.wrapper, {
139
- [classes.required]: isRequired && !hasRequiredLabel,
140
- [classes.invalid]: isInvalid,
141
- [classes.focused]: hasFocus,
142
- [classes.disabled]: isDisabled,
143
- [classes.autosize]: isAutoSizeable,
144
- [classes.withFloatingLabel]: hasFloatingLabel && hasLabel,
145
- })}
146
- data-value={isAutoSizeable ? value : undefined}
112
+ <ControlGroup
113
+ errorMessage={errorMessage}
114
+ infoMessage={infoMessage}
115
+ tweakStyles={tweakControlGroupStyles}
116
+ >
117
+ <ControlWrapper
118
+ label={label}
119
+ tweakStyles={tweakControlWrapperStyles}
120
+ isFocused={hasFocus}
121
+ isDisabled={isDisabled}
122
+ hasValue={hasValue}
123
+ isFullWidth
124
+ testId={testId}
125
+ {...controlProps}
147
126
  >
148
- {hasLabel && (
149
- <span
150
- className={clsx(classes.label, {
151
- [classes.invalidLabel]: isInvalid,
152
- [classes.requiredLabel]: hasRequiredLabel && !isRequired,
153
- [classes.activeLabel]: hasFocus || hasValue,
154
- [classes.floating]: hasFloatingLabel,
155
- })}
156
- >
157
- {label}
158
- </span>
159
- )}
160
-
161
- <textarea ref={ref} {...props} />
162
- </div>
163
-
164
- <div className={classes.footer}>
165
- {hasInfoMessage && <div className={classes.info}>{infoMessage}</div>}
166
- {!hasInfoMessage && hasErrorMessage && (
167
- <div className={classes.error}>{errorMessage}</div>
168
- )}
169
- {hasCounter && isNotEmpty(maxLength) && (
170
- <span
171
- className={clsx(classes.symbolsCount, {
172
- [classes.symbolsCountError]: value.length > maxLength,
173
- })}
174
- >
175
- {value.length} / {maxLength}
176
- </span>
177
- )}
178
- </div>
179
- {hasInfoMessage && hasErrorMessage && <div className={classes.error}>{errorMessage}</div>}
180
- </div>
127
+ <div {...(isAutoSized && { className: classes.autoSized, 'data-value': value })}>
128
+ <textarea
129
+ ref={ref}
130
+ className={classes.textarea}
131
+ value={value}
132
+ disabled={isDisabled}
133
+ placeholder={hasPlaceholder ? placeholder : undefined}
134
+ maxLength={shouldTrimAfterMaxLength ? maxLength : undefined}
135
+ name={name}
136
+ rows={rows}
137
+ onPaste={onPaste}
138
+ onFocus={handleFocus}
139
+ onBlur={handleBlur}
140
+ onChange={handleChange}
141
+ {...addDataAttributes(data, testId, 'control')}
142
+ />
143
+ </div>
144
+ </ControlWrapper>
145
+ {hasCounter && isNotEmpty(maxLength) && (
146
+ <span
147
+ className={clsx(classes.symbolsCount, {
148
+ [classes.symbolsCountError]: value.length > maxLength,
149
+ })}
150
+ >
151
+ {value.length} / {maxLength}
152
+ </span>
153
+ )}
154
+ </ControlGroup>
181
155
  );
182
156
  },
183
157
  );
@@ -1,14 +1,10 @@
1
- import { ComponentStory, ComponentMeta } from '@storybook/react';
2
- import { IIconType, iconsList } from '../Icon';
1
+ import { ComponentMeta, ComponentStory } from '@storybook/react';
2
+ import { iconsList, IIconType } from '../Icon';
3
3
  import { complexIcons } from '../Icon/complexIcons';
4
4
  import { TextButton } from './TextButton';
5
5
  import { TEXT_BUTTON_SIZES, TEXT_BUTTON_VIEWS } from './constants';
6
6
 
7
- const iconTypes = [
8
- undefined,
9
- ...Object.keys(iconsList),
10
- ...Object.keys(complexIcons),
11
- ] as IIconType[];
7
+ const icons = [undefined, ...Object.keys(iconsList), ...Object.keys(complexIcons)] as IIconType[];
12
8
 
13
9
  export default {
14
10
  title: 'Buttons/TextButton',
@@ -28,7 +24,7 @@ export default {
28
24
  },
29
25
 
30
26
  argTypes: {
31
- icon: { control: 'select', options: iconTypes },
27
+ icon: { control: 'select', options: icons },
32
28
  size: { options: TEXT_BUTTON_SIZES, control: 'inline-radio' },
33
29
  view: { options: TEXT_BUTTON_VIEWS, control: 'inline-radio' },
34
30
  iconPosition: { control: 'inline-radio' },
@@ -91,7 +91,6 @@ Default.args = {
91
91
  shouldRenderInBody: true,
92
92
  shouldHideOnScroll: false,
93
93
  shouldStopPropagation: true,
94
- shouldShowArrow: false,
95
94
  };
96
95
 
97
96
  Default.parameters = {
@@ -20,8 +20,6 @@ export const useStyles = createThemedStyles('WithPopup', {
20
20
  outline: 'none',
21
21
  },
22
22
 
23
- arrow: {},
24
-
25
23
  animationEnd: {},
26
24
 
27
25
  animationStart: {},