@true-engineering/true-react-common-ui-kit 4.0.0-alpha1 → 4.0.0-alpha11

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 (199) hide show
  1. package/README.md +11 -567
  2. package/dist/components/Button/Button.styles.d.ts +1 -1
  3. package/dist/components/Checkbox/Checkbox.styles.d.ts +1 -1
  4. package/dist/components/ControlWrapper/ControlWrapper.d.ts +2 -0
  5. package/dist/components/ControlWrapper/ControlWrapper.styles.d.ts +2 -1
  6. package/dist/components/ControlWrapper/index.d.ts +1 -0
  7. package/dist/components/ControlWrapper/types.d.ts +3 -0
  8. package/dist/components/DatePicker/DatePicker.d.ts +2 -2
  9. package/dist/components/DatePicker/helpers.d.ts +3 -0
  10. package/dist/components/DatePicker/types.d.ts +3 -1
  11. package/dist/components/FiltersPane/FiltersPane.d.ts +4 -2
  12. package/dist/components/FiltersPane/components/Filter/Filter.d.ts +2 -2
  13. package/dist/components/FiltersPane/components/Filter/helpers.d.ts +4 -0
  14. package/dist/components/FiltersPane/components/FilterInterval/FilterInterval.styles.d.ts +1 -1
  15. package/dist/components/FiltersPane/components/FilterSelect/FilterSelect.styles.d.ts +1 -1
  16. package/dist/components/FiltersPane/components/FilterValueView/FilterValueView.d.ts +3 -1
  17. package/dist/components/FiltersPane/components/FilterWithDates/FilterWithDates.styles.d.ts +2 -2
  18. package/dist/components/FiltersPane/components/FilterWrapper/FilterWrapper.d.ts +2 -2
  19. package/dist/components/FiltersPane/types.d.ts +15 -5
  20. package/dist/components/Flag/customFlags/customFlags.d.ts +10 -0
  21. package/dist/components/Flag/customFlags/index.d.ts +1 -0
  22. package/dist/components/FlexibleTable/FlexibleTable.d.ts +4 -2
  23. package/dist/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.d.ts +6 -6
  24. package/dist/components/FlexibleTable/constants.d.ts +18 -2
  25. package/dist/components/FlexibleTable/types.d.ts +1 -1
  26. package/dist/components/Icon/icons-list.d.ts +1 -1
  27. package/dist/components/IconButton/IconButton.styles.d.ts +1 -1
  28. package/dist/components/Input/Input.d.ts +3 -2
  29. package/dist/components/Input/InputBase.d.ts +2 -2
  30. package/dist/components/List/List.d.ts +1 -1
  31. package/dist/components/List/index.d.ts +2 -1
  32. package/dist/components/List/types.d.ts +4 -0
  33. package/dist/components/Modal/Modal.styles.d.ts +1 -1
  34. package/dist/components/Notification/Notification.styles.d.ts +1 -1
  35. package/dist/components/ScrollIntoViewIfNeeded/ScrollIntoViewIfNeeded.d.ts +1 -1
  36. package/dist/components/SearchInput/SearchInput.d.ts +2 -2
  37. package/dist/components/SearchInput/SearchInput.styles.d.ts +3 -5
  38. package/dist/components/Select/Select.d.ts +5 -3
  39. package/dist/components/Select/Select.styles.d.ts +4 -4
  40. package/dist/components/Select/index.d.ts +1 -1
  41. package/dist/components/Status/Status.styles.d.ts +3 -2
  42. package/dist/components/Status/constants.d.ts +0 -1
  43. package/dist/components/Status/types.d.ts +5 -2
  44. package/dist/components/TextArea/TextArea.d.ts +2 -3
  45. package/dist/components/TextArea/index.d.ts +0 -1
  46. package/dist/components/TextButton/TextButton.styles.d.ts +1 -1
  47. package/dist/components/Tooltip/Tooltip.d.ts +1 -1
  48. package/dist/components/Tooltip/Tooltip.styles.d.ts +1 -1
  49. package/dist/components/WithMessages/WithMessages.styles.d.ts +1 -1
  50. package/dist/components/WithPopup/WithPopup.d.ts +21 -6
  51. package/dist/components/WithPopup/WithPopup.styles.d.ts +1 -1
  52. package/dist/components/WithPopup/helpers.d.ts +2 -0
  53. package/dist/components/WithPopup/types.d.ts +3 -0
  54. package/dist/components/WithTooltip/WithTooltip.styles.d.ts +1 -0
  55. package/dist/hooks/index.d.ts +1 -0
  56. package/dist/hooks/use-merge.d.ts +1 -0
  57. package/dist/hooks/use-mixed-styles.d.ts +3 -1
  58. package/dist/hooks/use-tweak-styles.d.ts +5 -5
  59. package/dist/theme/Provider.d.ts +6 -3
  60. package/dist/theme/common.d.ts +4 -2
  61. package/dist/theme/create-themed-styles.d.ts +2 -0
  62. package/dist/theme/helpers.d.ts +9 -3
  63. package/dist/theme/index.d.ts +2 -0
  64. package/dist/theme/true-jss/ThemedStylesManager.d.ts +18 -0
  65. package/dist/theme/true-jss/TweakStylesManager.d.ts +34 -0
  66. package/dist/theme/true-jss/index.d.ts +2 -0
  67. package/dist/theme/true-jss/jss-context.d.ts +9 -0
  68. package/dist/theme/types.d.ts +4 -2
  69. package/dist/true-react-common-ui-kit.js +7308 -6412
  70. package/dist/true-react-common-ui-kit.js.map +1 -1
  71. package/dist/true-react-common-ui-kit.umd.cjs +7136 -6241
  72. package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
  73. package/dist/types.d.ts +10 -3
  74. package/package.json +1 -1
  75. package/src/components/ControlWrapper/ControlWrapper.styles.ts +6 -5
  76. package/src/components/ControlWrapper/ControlWrapper.tsx +8 -2
  77. package/src/components/ControlWrapper/index.ts +1 -0
  78. package/src/components/ControlWrapper/types.ts +3 -0
  79. package/src/components/DatePicker/DatePicker.tsx +9 -4
  80. package/src/components/DatePicker/helpers.ts +13 -1
  81. package/src/components/DatePicker/types.ts +4 -1
  82. package/src/components/FiltersPane/FiltersPane.stories.tsx +4 -2
  83. package/src/components/FiltersPane/FiltersPane.tsx +14 -9
  84. package/src/components/FiltersPane/components/Filter/Filter.tsx +24 -17
  85. package/src/components/FiltersPane/components/Filter/helpers.ts +18 -0
  86. package/src/components/FiltersPane/components/FilterInterval/FilterInterval.styles.ts +1 -1
  87. package/src/components/FiltersPane/components/FilterInterval/FilterInterval.tsx +6 -1
  88. package/src/components/FiltersPane/components/FilterValueView/FilterValueView.tsx +27 -22
  89. package/src/components/FiltersPane/components/FilterWithDates/FilterWithDates.styles.ts +1 -0
  90. package/src/components/FiltersPane/components/FilterWithPeriod/FilterWithPeriod.tsx +1 -1
  91. package/src/components/FiltersPane/components/FilterWrapper/FilterWrapper.tsx +7 -5
  92. package/src/components/FiltersPane/types.ts +23 -5
  93. package/src/components/Flag/Flag.stories.tsx +2 -1
  94. package/src/components/Flag/Flag.styles.ts +4 -0
  95. package/src/components/Flag/Flag.tsx +23 -9
  96. package/src/components/Flag/customFlags/AB.svg +1 -0
  97. package/src/components/Flag/customFlags/OS.svg +1 -0
  98. package/src/components/Flag/customFlags/augment.d.ts +1 -0
  99. package/src/components/Flag/customFlags/customFlags.ts +13 -0
  100. package/src/components/Flag/customFlags/index.ts +1 -0
  101. package/src/components/FlexibleTable/FlexibleTable.tsx +13 -12
  102. package/src/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.tsx +9 -8
  103. package/src/components/FlexibleTable/constants.ts +6 -3
  104. package/src/components/FlexibleTable/types.ts +1 -5
  105. package/src/components/IncrementInput/IncrementInput.styles.ts +1 -1
  106. package/src/components/Input/Input.tsx +5 -3
  107. package/src/components/Input/InputBase.tsx +22 -19
  108. package/src/components/List/List.tsx +5 -2
  109. package/src/components/List/index.ts +2 -1
  110. package/src/components/List/types.ts +5 -0
  111. package/src/components/PhoneInput/PhoneInput.stories.tsx +2 -1
  112. package/src/components/PhoneInput/PhoneInput.tsx +5 -2
  113. package/src/components/SearchInput/SearchInput.styles.ts +16 -29
  114. package/src/components/SearchInput/SearchInput.tsx +17 -30
  115. package/src/components/Select/Select.tsx +12 -2
  116. package/src/components/Select/components/SelectList/SelectList.tsx +1 -1
  117. package/src/components/Select/index.ts +1 -1
  118. package/src/components/Status/Status.stories.tsx +54 -1
  119. package/src/components/Status/Status.styles.ts +2 -37
  120. package/src/components/Status/constants.ts +0 -10
  121. package/src/components/Status/types.ts +7 -3
  122. package/src/components/TextArea/TextArea.tsx +29 -14
  123. package/src/components/TextArea/index.ts +0 -1
  124. package/src/components/Tooltip/Tooltip.styles.ts +2 -0
  125. package/src/components/Tooltip/Tooltip.tsx +1 -1
  126. package/src/components/WithPopup/WithPopup.stories.tsx +1 -0
  127. package/src/components/WithPopup/WithPopup.styles.ts +2 -0
  128. package/src/components/WithPopup/WithPopup.tsx +64 -16
  129. package/src/components/WithPopup/helpers.ts +9 -0
  130. package/src/components/WithPopup/types.ts +7 -0
  131. package/src/components/WithTooltip/WithTooltip.styles.ts +6 -0
  132. package/src/components/WithTooltip/WithTooltip.tsx +7 -2
  133. package/src/constants/phone-info.ts +20 -33
  134. package/src/helpers/phone.ts +19 -15
  135. package/src/hooks/index.ts +1 -0
  136. package/src/hooks/use-merge.ts +8 -0
  137. package/src/hooks/use-mixed-styles.ts +9 -11
  138. package/src/hooks/use-tweak-styles.ts +49 -27
  139. package/src/theme/Provider.tsx +10 -5
  140. package/src/theme/common.ts +5 -2
  141. package/src/theme/create-themed-styles.ts +78 -0
  142. package/src/theme/helpers.ts +39 -39
  143. package/src/theme/index.ts +2 -0
  144. package/src/theme/true-jss/ThemedStylesManager.ts +92 -0
  145. package/src/theme/true-jss/TweakStylesManager.ts +157 -0
  146. package/src/theme/true-jss/index.ts +2 -0
  147. package/src/theme/true-jss/jss-context.tsx +34 -0
  148. package/src/theme/types.ts +4 -2
  149. package/src/types.ts +17 -4
  150. package/dist/components/AccountInfo/AccountInfo.stories.d.ts +0 -6
  151. package/dist/components/AddButton/AddButton.stories.d.ts +0 -6
  152. package/dist/components/Button/Button.stories.d.ts +0 -6
  153. package/dist/components/Checkbox/Checkbox.stories.d.ts +0 -8
  154. package/dist/components/CloseButton/CloseButton.stories.d.ts +0 -5
  155. package/dist/components/Colors/Colors.stories.d.ts +0 -5
  156. package/dist/components/ControlWrapper/ControlWrapper.stories.d.ts +0 -6
  157. package/dist/components/DateInput/DateInput.stories.d.ts +0 -7
  158. package/dist/components/DatePicker/DatePicker.stories.d.ts +0 -7
  159. package/dist/components/Description/Description.stories.d.ts +0 -16
  160. package/dist/components/FileInput/FileInput.stories.d.ts +0 -7
  161. package/dist/components/FileItem/FileItem.stories.d.ts +0 -8
  162. package/dist/components/FiltersPane/FiltersPane.stories.d.ts +0 -31
  163. package/dist/components/Flag/Flag.stories.d.ts +0 -12
  164. package/dist/components/FlexibleTable/FlexibleTable.stories.d.ts +0 -19
  165. package/dist/components/Icon/Icon.stories.d.ts +0 -6
  166. package/dist/components/IconButton/IconButton.stories.d.ts +0 -6
  167. package/dist/components/IncrementInput/IncrementInput.stories.d.ts +0 -6
  168. package/dist/components/Input/Input.stories.d.ts +0 -25
  169. package/dist/components/List/List.stories.d.ts +0 -5
  170. package/dist/components/Modal/Modal.stories.d.ts +0 -29
  171. package/dist/components/MoreMenu/MoreMenu.stories.d.ts +0 -6
  172. package/dist/components/MultiSelect/MultiSelect.stories.d.ts +0 -13
  173. package/dist/components/NewMoreMenu/NewMoreMenu.stories.d.ts +0 -12
  174. package/dist/components/Notification/Notification.stories.d.ts +0 -8
  175. package/dist/components/NumberInput/NumberInput.stories.d.ts +0 -7
  176. package/dist/components/PhoneInput/PhoneInput.stories.d.ts +0 -28
  177. package/dist/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.stories.d.ts +0 -5
  178. package/dist/components/RadioButton/RadioButton.stories.d.ts +0 -7
  179. package/dist/components/SearchInput/SearchInput.stories.d.ts +0 -16
  180. package/dist/components/Select/CustomSelect.stories.d.ts +0 -11
  181. package/dist/components/Select/MultiSelect.stories.d.ts +0 -15
  182. package/dist/components/Select/Select.stories.d.ts +0 -15
  183. package/dist/components/Selector/Selector.stories.d.ts +0 -7
  184. package/dist/components/Skeleton/Skeleton.stories.d.ts +0 -6
  185. package/dist/components/SmartInput/SmartInput.stories.d.ts +0 -18
  186. package/dist/components/Status/Status.stories.d.ts +0 -6
  187. package/dist/components/Switch/Switch.stories.d.ts +0 -16
  188. package/dist/components/TextArea/TextArea.stories.d.ts +0 -17
  189. package/dist/components/TextArea/types.d.ts +0 -2
  190. package/dist/components/TextButton/TextButton.stories.d.ts +0 -6
  191. package/dist/components/TextWithInfo/TextWithInfo.stories.d.ts +0 -12
  192. package/dist/components/TextWithTooltip/TextWithTooltip.stories.d.ts +0 -24
  193. package/dist/components/ThemedPreloader/ThemedPreloader.stories.d.ts +0 -17
  194. package/dist/components/Toaster/Toaster.stories.d.ts +0 -5
  195. package/dist/components/Tooltip/Tooltip.stories.d.ts +0 -5
  196. package/dist/components/WithMessages/WithMessages.stories.d.ts +0 -7
  197. package/dist/components/WithPopup/WithPopup.stories.d.ts +0 -16
  198. package/dist/components/WithTooltip/WithTooltip.stories.d.ts +0 -6
  199. package/src/components/TextArea/types.ts +0 -6
@@ -1,18 +1,71 @@
1
1
  import { Status } from '.';
2
2
  import { ComponentStory } from '@storybook/react';
3
+ import { rgba } from '../../helpers';
4
+ import { IExtendableProps } from '../../types';
3
5
  import { iconsList, IIconType } from '../Icon';
4
6
  import { complexIcons } from '../Icon/complexIcons';
5
- import { STATUS_COLORS, STATUS_SIZES } from './constants';
7
+ import { STATUS_SIZES } from './constants';
6
8
  import { IStatusStyles } from './Status.styles';
7
9
 
10
+ export const STATUS_COLORS = [
11
+ 'green',
12
+ 'teal',
13
+ 'blue',
14
+ 'grey',
15
+ 'orange',
16
+ 'red',
17
+ 'violet',
18
+ 'custom',
19
+ ] as const;
20
+
8
21
  export default {
9
22
  title: 'Data Display/Status',
10
23
  component: Status,
11
24
  };
12
25
 
26
+ declare module './types' {
27
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
28
+ export interface IStatusColors extends IExtendableProps<typeof STATUS_COLORS> {}
29
+ }
30
+
13
31
  const icons = [undefined, ...Object.keys(iconsList), ...Object.keys(complexIcons)] as IIconType[];
14
32
 
15
33
  const customTweakStyles: IStatusStyles = {
34
+ green: {
35
+ '--status-background': rgba('#D4E3AC', 0.5),
36
+ '--status-color': '#6F990F',
37
+ },
38
+
39
+ blue: {
40
+ '--status-background': rgba('#AABFFC', 0.4),
41
+ '--status-color': '#4C6EBF',
42
+ },
43
+
44
+ grey: {
45
+ '--status-background': rgba('#95A0B3', 0.25),
46
+ '--status-color': '#7A869A',
47
+ },
48
+
49
+ orange: {
50
+ '--status-background': rgba('#FCD3A9', 0.5),
51
+ '--status-color': '#E5741C',
52
+ },
53
+
54
+ red: {
55
+ '--status-background': rgba('#F7949A', 0.25),
56
+ '--status-color': '#F14D56',
57
+ },
58
+
59
+ teal: {
60
+ '--status-background': rgba('#8CE3EA', 0.4),
61
+ '--status-color': '#0092A6',
62
+ },
63
+
64
+ violet: {
65
+ '--status-background': rgba('#BEABE0', 0.4),
66
+ '--status-color': '#7450B2',
67
+ },
68
+
16
69
  custom: {
17
70
  '--status-color': '#793472',
18
71
  '--status-background': '#F2B9ED',
@@ -1,5 +1,5 @@
1
- import { rgba } from '../../helpers';
2
1
  import { colors, createThemedStyles, ITweakStyles } from '../../theme';
2
+ import { IStatusColors } from './types';
3
3
 
4
4
  export const useStyles = createThemedStyles('Status', {
5
5
  root: {
@@ -102,42 +102,7 @@ export const useStyles = createThemedStyles('Status', {
102
102
  },
103
103
  },
104
104
 
105
- green: {
106
- '--status-background': rgba('#D4E3AC', 0.5),
107
- '--status-color': '#6F990F',
108
- },
109
-
110
- blue: {
111
- '--status-background': rgba('#AABFFC', 0.4),
112
- '--status-color': '#4C6EBF',
113
- },
114
-
115
- grey: {
116
- '--status-background': rgba('#95A0B3', 0.25),
117
- '--status-color': '#7A869A',
118
- },
119
-
120
- orange: {
121
- '--status-background': rgba('#FCD3A9', 0.5),
122
- '--status-color': '#E5741C',
123
- },
124
-
125
- red: {
126
- '--status-background': rgba('#F7949A', 0.25),
127
- '--status-color': '#F14D56',
128
- },
129
-
130
- teal: {
131
- '--status-background': rgba('#8CE3EA', 0.4),
132
- '--status-color': '#0092A6',
133
- },
134
-
135
- violet: {
136
- '--status-background': rgba('#BEABE0', 0.4),
137
- '--status-color': '#7450B2',
138
- },
139
-
140
105
  custom: {},
141
106
  });
142
107
 
143
- export type IStatusStyles = ITweakStyles<typeof useStyles>;
108
+ export type IStatusStyles = ITweakStyles<typeof useStyles, IStatusColors>;
@@ -1,11 +1 @@
1
- export const STATUS_COLORS = [
2
- 'green',
3
- 'teal',
4
- 'blue',
5
- 'grey',
6
- 'orange',
7
- 'red',
8
- 'violet',
9
- 'custom',
10
- ] as const;
11
1
  export const STATUS_SIZES = ['xs', 's', 'm'] as const;
@@ -1,5 +1,9 @@
1
- import { STATUS_COLORS, STATUS_SIZES } from './constants';
2
-
3
- export type IStatusColor = (typeof STATUS_COLORS)[number];
1
+ import { IDefaultExtendableProps } from '../../types';
2
+ import type { STATUS_SIZES } from './constants';
4
3
 
5
4
  export type IStatusSize = (typeof STATUS_SIZES)[number];
5
+
6
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
7
+ export interface IStatusColors extends IDefaultExtendableProps {}
8
+
9
+ export type IStatusColor = keyof IStatusColors;
@@ -1,7 +1,16 @@
1
- import { ChangeEvent, FocusEvent, FormEvent, forwardRef, useState } from 'react';
1
+ import {
2
+ ChangeEvent,
3
+ FocusEvent,
4
+ FormEvent,
5
+ forwardRef,
6
+ TextareaHTMLAttributes,
7
+ useState,
8
+ } from 'react';
2
9
  import clsx from 'clsx';
3
10
  import {
4
11
  addDataAttributes,
12
+ getTestId,
13
+ isArrayLikeNotEmpty,
5
14
  isNotEmpty,
6
15
  isReactNodeNotEmpty,
7
16
  isStringNotEmpty,
@@ -10,14 +19,13 @@ import { useTweakStyles } from '../../hooks';
10
19
  import { ICommonProps } from '../../types';
11
20
  import { ControlWrapper, IControlWrapperProps } from '../ControlWrapper';
12
21
  import { IWithMessagesProps, WithMessages } from '../WithMessages';
13
- import { ITextAreaHTMLBaseProps } from './types';
14
22
  import { controlWrapperStyles, ITextAreaStyles, useStyles } from './TextArea.styles';
15
23
 
16
24
  export interface ITextAreaProps
17
25
  extends ICommonProps<ITextAreaStyles>,
18
- Pick<IControlWrapperProps, 'label' | 'isInvalid' | 'isRequired' | 'isDisabled'>,
19
- Pick<IWithMessagesProps, 'infoMessage' | 'errorMessage'>,
20
- Pick<ITextAreaHTMLBaseProps, 'name' | 'maxLength' | 'rows' | 'onPaste' | 'onFocus' | 'onBlur'> {
26
+ Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'onChange'>,
27
+ Pick<IControlWrapperProps, 'label' | 'isInvalid' | 'isRequired' | 'isDisabled' | 'size'>,
28
+ Pick<IWithMessagesProps, 'infoMessage' | 'errorMessage'> {
21
29
  value?: string;
22
30
  placeholder?: string;
23
31
  /** @default false */
@@ -48,8 +56,6 @@ export const TextArea = forwardRef<HTMLTextAreaElement, ITextAreaProps>(
48
56
  value = DEFAULT_VALUE,
49
57
  label,
50
58
  placeholder,
51
- infoMessage,
52
- errorMessage,
53
59
  name,
54
60
  shouldFocusOnMount,
55
61
  hasCounter = true,
@@ -67,7 +73,14 @@ export const TextArea = forwardRef<HTMLTextAreaElement, ITextAreaProps>(
67
73
  onPaste,
68
74
  onFocus,
69
75
  onBlur,
70
- ...controlProps
76
+ // Пропсы WithMessages
77
+ infoMessage,
78
+ errorMessage,
79
+ // Пропсы ControlWrapper
80
+ isInvalid,
81
+ isRequired,
82
+ size,
83
+ ...textAreaProps
71
84
  },
72
85
  ref,
73
86
  ) => {
@@ -89,8 +102,7 @@ export const TextArea = forwardRef<HTMLTextAreaElement, ITextAreaProps>(
89
102
  const [isFocused, setFocused] = useState(false);
90
103
 
91
104
  const hasFocus = isFocused || isActive;
92
- // в hasValue нельзя использовать isStringNotEmpty из-за того что isStringNotEmpty делает trim
93
- const hasValue = value !== undefined && value !== '';
105
+ const hasValue = isArrayLikeNotEmpty(value);
94
106
  const hasLabel = isReactNodeNotEmpty(label);
95
107
  const hasPlaceholder =
96
108
  (!hasLabel || hasFocus || shouldAlwaysShowPlaceholder) && isStringNotEmpty(placeholder);
@@ -114,6 +126,7 @@ export const TextArea = forwardRef<HTMLTextAreaElement, ITextAreaProps>(
114
126
  errorMessage={errorMessage}
115
127
  infoMessage={infoMessage}
116
128
  tweakStyles={tweakWithMessagesStyles}
129
+ testId={getTestId(testId, 'wrapper')}
117
130
  >
118
131
  <ControlWrapper
119
132
  label={label}
@@ -121,13 +134,14 @@ export const TextArea = forwardRef<HTMLTextAreaElement, ITextAreaProps>(
121
134
  isFocused={hasFocus}
122
135
  isDisabled={isDisabled}
123
136
  hasValue={hasValue}
137
+ isInvalid={isInvalid}
138
+ isRequired={isRequired}
139
+ size={size}
124
140
  isFullWidth
125
- testId={testId}
126
- {...controlProps}
127
141
  >
128
142
  <div
129
143
  className={clsx(classes.wrapper, { [classes.autoSized]: isAutoSized })}
130
- {...(isAutoSized && { 'data-value': value })}
144
+ {...(isAutoSized && addDataAttributes({ value }))}
131
145
  >
132
146
  <textarea
133
147
  ref={ref}
@@ -142,7 +156,8 @@ export const TextArea = forwardRef<HTMLTextAreaElement, ITextAreaProps>(
142
156
  onFocus={handleFocus}
143
157
  onBlur={handleBlur}
144
158
  onChange={handleChange}
145
- {...addDataAttributes(data, testId, 'control')}
159
+ {...addDataAttributes(data, testId)}
160
+ {...textAreaProps}
146
161
  />
147
162
  </div>
148
163
  </ControlWrapper>
@@ -1,3 +1,2 @@
1
1
  export * from './TextArea';
2
- export * from './types';
3
2
  export type { ITextAreaStyles } from './TextArea.styles';
@@ -32,6 +32,8 @@ export const useStyles = createThemedStyles('Tooltip', {
32
32
  letterSpacing: 0.2,
33
33
  },
34
34
 
35
+ custom: {},
36
+
35
37
  info: {},
36
38
 
37
39
  error: {
@@ -8,7 +8,7 @@ import { useStyles, ITooltipStyles } from './Tooltip.styles';
8
8
  export interface ITooltipProps extends ICommonProps<ITooltipStyles> {
9
9
  text: ReactNode;
10
10
  /** @default 'tooltip' */
11
- view?: 'tooltip' | 'hint';
11
+ view?: 'tooltip' | 'hint' | 'custom';
12
12
  /** @default 'info' */
13
13
  type?: 'info' | 'error';
14
14
  }
@@ -91,6 +91,7 @@ Default.args = {
91
91
  shouldRenderInBody: true,
92
92
  shouldHideOnScroll: false,
93
93
  shouldStopPropagation: true,
94
+ shouldShowArrow: false,
94
95
  };
95
96
 
96
97
  Default.parameters = {
@@ -20,6 +20,8 @@ export const useStyles = createThemedStyles('WithPopup', {
20
20
  outline: 'none',
21
21
  },
22
22
 
23
+ arrow: {},
24
+
23
25
  animationEnd: {},
24
26
 
25
27
  animationStart: {},
@@ -1,7 +1,6 @@
1
- import { FC, useState } from 'react';
1
+ import { FC, useRef, useState } from 'react';
2
2
  import clsx from 'clsx';
3
3
  import {
4
- addDataTestId,
5
4
  applyAction,
6
5
  stopPropagation,
7
6
  addDataAttributes,
@@ -23,10 +22,18 @@ import {
23
22
  UseHoverProps,
24
23
  safePolygon,
25
24
  useFocus,
25
+ FloatingArrow,
26
+ arrow,
27
+ UseClickProps,
28
+ UseFocusProps,
29
+ UseDismissProps,
30
+ UseTransitionStatusProps,
26
31
  } from '@floating-ui/react';
27
- import { ICommonProps, IRenderNode } from '../../types';
32
+ import { ICommonProps, IDataAttributes, IRenderNode } from '../../types';
28
33
  import { DEFAULT_OFFSET } from './constants';
34
+ import { minWidthRelativeToTrigger } from './helpers';
29
35
  import {
36
+ IPopupArrowProps,
30
37
  IPopupEventType,
31
38
  IReferenceProps,
32
39
  IWithPopupChildrenProps,
@@ -43,11 +50,16 @@ export interface IWithPopupProps extends ICommonProps<IWithPopupStyles> {
43
50
  placement?: Placement;
44
51
  /** @default 'click' */
45
52
  eventType?: IPopupEventType;
46
- /** @default 0 */
47
- hoverDelay?: UseHoverProps['delay'];
53
+ /**
54
+ * @deprecated Используйте hoverOptions
55
+ * @default 0
56
+ */
57
+ hoverDelay?: number;
48
58
  /** @default 6 */
49
59
  popupOffset?: OffsetOptions;
50
- /** @default true */
60
+ arrowProps?: IPopupArrowProps;
61
+ popupData?: IDataAttributes;
62
+ /** @default true, if eventType === click */
51
63
  shouldStopPropagation?: boolean;
52
64
  /** @default false */
53
65
  shouldHideOnScroll?: boolean;
@@ -60,6 +72,16 @@ export interface IWithPopupProps extends ICommonProps<IWithPopupStyles> {
60
72
  canBeFlipped?: boolean;
61
73
  /** @default false */
62
74
  isDisabled?: boolean;
75
+ /** @default false */
76
+ shouldShowArrow?: boolean;
77
+ /** Должна ли минимальная ширина попапа быть равна ширине триггера
78
+ * @default false */
79
+ isMinWidthSameAsTrigger?: boolean;
80
+ hoverOptions?: UseHoverProps;
81
+ clickOptions?: UseClickProps;
82
+ focusOptions?: UseFocusProps;
83
+ dismissOptions?: UseDismissProps;
84
+ transitionOptions?: UseTransitionStatusProps;
63
85
  onToggle?: (isActive: boolean, event?: IWithPopupToggleEvent) => void;
64
86
  }
65
87
 
@@ -71,12 +93,21 @@ export const WithPopup: FC<IWithPopupProps> = ({
71
93
  placement = eventType === 'click' ? 'bottom-end' : 'top',
72
94
  hoverDelay = 0,
73
95
  popupOffset = DEFAULT_OFFSET,
74
- shouldStopPropagation = true,
96
+ arrowProps,
97
+ popupData,
98
+ shouldStopPropagation = eventType === 'click',
75
99
  shouldHideOnScroll = false,
76
100
  shouldRenderInBody = true,
77
101
  canBeFlipped = true,
78
102
  isTriggerWrapped = eventType === 'hover',
79
103
  isDisabled = false,
104
+ shouldShowArrow = false,
105
+ isMinWidthSameAsTrigger = false,
106
+ hoverOptions,
107
+ clickOptions,
108
+ focusOptions,
109
+ dismissOptions,
110
+ transitionOptions,
80
111
  tweakStyles,
81
112
  data,
82
113
  testId,
@@ -86,6 +117,8 @@ export const WithPopup: FC<IWithPopupProps> = ({
86
117
 
87
118
  const [isOpen, setIsOpen] = useState(false);
88
119
 
120
+ const arrowRef = useRef<SVGSVGElement>(null);
121
+
89
122
  const handleToggle = (isActive: boolean, event?: IWithPopupToggleEvent) => {
90
123
  event?.stopPropagation();
91
124
  if (!isDisabled) {
@@ -103,7 +136,9 @@ export const WithPopup: FC<IWithPopupProps> = ({
103
136
  middleware: [
104
137
  offset(popupOffset),
105
138
  canBeFlipped && flip({ fallbackAxisSideDirection: 'start' }),
139
+ isMinWidthSameAsTrigger && minWidthRelativeToTrigger,
106
140
  ...middlewares,
141
+ shouldShowArrow && arrow({ element: arrowRef }),
107
142
  ],
108
143
  whileElementsMounted: autoUpdate,
109
144
  placement,
@@ -112,22 +147,27 @@ export const WithPopup: FC<IWithPopupProps> = ({
112
147
 
113
148
  const hover = useHover(context, {
114
149
  enabled: eventType === 'hover',
115
- delay: typeof hoverDelay === 'number' ? { open: hoverDelay, close: 0 } : hoverDelay,
150
+ delay: { open: hoverDelay, close: 0 },
116
151
  handleClose: safePolygon(),
152
+ ...hoverOptions,
117
153
  });
118
154
 
119
- const focus = useFocus(context, { enabled: eventType === 'hover' });
155
+ const focus = useFocus(context, { enabled: eventType === 'hover', ...focusOptions });
120
156
 
121
- const click = useClick(context, { enabled: eventType === 'click' });
157
+ const click = useClick(context, { enabled: eventType === 'click', ...clickOptions });
122
158
 
123
159
  const dismiss = useDismiss(context, {
124
160
  enabled: eventType === 'click',
125
161
  ancestorScroll: shouldHideOnScroll,
162
+ ...dismissOptions,
126
163
  });
127
164
 
128
165
  const { getFloatingProps, getReferenceProps } = useInteractions([hover, click, focus, dismiss]);
129
166
 
130
- const { isMounted, status } = useTransitionStatus(context, { duration: { close: 500 } });
167
+ const { isMounted, status } = useTransitionStatus(context, {
168
+ duration: { close: 500 },
169
+ ...transitionOptions,
170
+ });
131
171
 
132
172
  const referenceProps: IReferenceProps = getReferenceProps({
133
173
  ref: refs.setReference,
@@ -155,8 +195,7 @@ export const WithPopup: FC<IWithPopupProps> = ({
155
195
  [classes.active]: isOpen,
156
196
  })}
157
197
  {...referenceProps}
158
- {...addDataTestId(testId)}
159
- {...addDataAttributes(data)}
198
+ {...addDataAttributes(data, testId)}
160
199
  >
161
200
  {triggerElement}
162
201
  </div>
@@ -165,16 +204,25 @@ export const WithPopup: FC<IWithPopupProps> = ({
165
204
  )}
166
205
  {isMounted && (
167
206
  <FloatingPortal
168
- root={!shouldRenderInBody ? (refs.reference.current as HTMLDivElement) : undefined}
207
+ root={shouldRenderInBody ? document.body : (refs.reference.current as HTMLElement)}
169
208
  >
170
209
  <div
210
+ ref={refs.setFloating}
171
211
  style={floatingStyles}
172
212
  className={classes.popup}
173
- ref={refs.setFloating}
174
213
  {...getFloatingProps()}
214
+ {...addDataAttributes(popupData, testId, 'popup')}
175
215
  >
176
216
  <div className={classes[`dropdown-${status}`]}>
177
- {applyAction(children, { onClose: handleClose })}
217
+ {shouldShowArrow && (
218
+ <FloatingArrow
219
+ {...arrowProps}
220
+ ref={arrowRef}
221
+ context={context}
222
+ className={classes.arrow}
223
+ />
224
+ )}
225
+ {applyAction(children, { floatingContext: context, onClose: handleClose })}
178
226
  </div>
179
227
  </div>
180
228
  </FloatingPortal>
@@ -0,0 +1,9 @@
1
+ import { Middleware, size } from '@floating-ui/react';
2
+
3
+ export const minWidthRelativeToTrigger: Middleware = size({
4
+ apply({ rects, elements }) {
5
+ Object.assign(elements.floating.style, {
6
+ minWidth: `${rects.reference.width}px`,
7
+ });
8
+ },
9
+ });
@@ -1,4 +1,5 @@
1
1
  import type { MouseEvent, KeyboardEvent } from 'react';
2
+ import type { FloatingArrowProps, UseFloatingReturn } from '@floating-ui/react';
2
3
  import type { IDataAttributesProps, IDomElementInteractions } from '../../types';
3
4
  import type { POPUP_EVENT_TYPES } from './constants';
4
5
 
@@ -21,5 +22,11 @@ export interface IWithPopupTriggerProps {
21
22
  }
22
23
 
23
24
  export interface IWithPopupChildrenProps {
25
+ floatingContext: UseFloatingReturn['context'];
24
26
  onClose: (event?: IWithPopupToggleEvent) => void;
25
27
  }
28
+
29
+ export type IPopupArrowProps = Pick<
30
+ FloatingArrowProps,
31
+ 'width' | 'height' | 'tipRadius' | 'staticOffset' | 'd' | 'stroke' | 'strokeWidth'
32
+ >;
@@ -1,6 +1,12 @@
1
1
  import { ITooltipStyles } from '../Tooltip';
2
2
  import { IWithPopupStyles } from '../WithPopup';
3
3
 
4
+ export const withPopupStyles: IWithPopupStyles = {
5
+ popup: {
6
+ zIndex: 9999,
7
+ },
8
+ };
9
+
4
10
  export interface IWithTooltipStyles {
5
11
  tweakWithPopup?: IWithPopupStyles;
6
12
  tweakTooltip?: ITooltipStyles;
@@ -4,7 +4,7 @@ import { useTweakStyles } from '../../hooks';
4
4
  import { ICommonProps } from '../../types';
5
5
  import { ITooltipProps, Tooltip } from '../Tooltip';
6
6
  import { IWithPopupProps, WithPopup } from '../WithPopup';
7
- import { IWithTooltipStyles } from './WithTooltip.styles';
7
+ import { IWithTooltipStyles, withPopupStyles } from './WithTooltip.styles';
8
8
 
9
9
  export interface IWithTooltipProps
10
10
  extends Omit<
@@ -32,17 +32,21 @@ export const WithTooltip: FC<IWithTooltipProps> = ({
32
32
  tooltipView = 'tooltip',
33
33
  tooltipType = 'info',
34
34
  isDisabled = false,
35
+ popupData,
35
36
  tweakStyles,
36
37
  ...restProps
37
38
  }) => {
38
39
  const tweakWithPopupStyles = useTweakStyles({
40
+ innerStyles: withPopupStyles,
39
41
  tweakStyles,
40
42
  className: 'tweakWithPopup',
43
+ currentComponentName: 'WithTooltip',
41
44
  });
42
45
 
43
46
  const tweakTooltipStyles = useTweakStyles({
44
47
  tweakStyles,
45
48
  className: 'tweakTooltip',
49
+ currentComponentName: 'WithTooltip',
46
50
  });
47
51
 
48
52
  return (
@@ -50,8 +54,9 @@ export const WithTooltip: FC<IWithTooltipProps> = ({
50
54
  trigger={children}
51
55
  placement={placement}
52
56
  eventType={eventType}
53
- isTriggerWrapped
57
+ popupData={{ ...popupData, tooltipView }}
54
58
  isDisabled={isDisabled || !isReactNodeNotEmpty(tooltipText)}
59
+ isTriggerWrapped
55
60
  tweakStyles={tweakWithPopupStyles}
56
61
  {...restProps}
57
62
  >
@@ -1,6 +1,15 @@
1
1
  import type { IPhoneInfo } from '../components';
2
2
 
3
3
  export const phoneInfo: IPhoneInfo[] = [
4
+ {
5
+ countryEn: 'Abkhazia',
6
+ countryRu: 'Абхазия',
7
+ countryCode: 'AB',
8
+ phoneMask: '(999) 999-99-99',
9
+ dialCode: '7',
10
+ dialCodePriority: 1,
11
+ fullCodes: ['7'],
12
+ },
4
13
  {
5
14
  countryEn: 'Afghanistan',
6
15
  countryRu: 'Афганистан',
@@ -785,40 +794,9 @@ export const phoneInfo: IPhoneInfo[] = [
785
794
  countryRu: 'Казахстан',
786
795
  countryCode: 'KZ',
787
796
  dialCode: '7',
788
- phoneMask: '999 999-99-99',
797
+ phoneMask: '(999) 999-99-99',
789
798
  dialCodePriority: 1,
790
- areaCodes: [
791
- '310',
792
- '311',
793
- '312',
794
- '313',
795
- '315',
796
- '318',
797
- '321',
798
- '324',
799
- '325',
800
- '326',
801
- '327',
802
- '336',
803
- '7172',
804
- '73622',
805
- ],
806
- fullCodes: [
807
- '7310',
808
- '7311',
809
- '7312',
810
- '7313',
811
- '7315',
812
- '7318',
813
- '7321',
814
- '7324',
815
- '7325',
816
- '7326',
817
- '7327',
818
- '7336',
819
- '77172',
820
- '773622',
821
- ],
799
+ fullCodes: ['7'],
822
800
  },
823
801
  {
824
802
  countryEn: 'Kenya',
@@ -1404,6 +1382,15 @@ export const phoneInfo: IPhoneInfo[] = [
1404
1382
  phoneMask: '999 9999 9999',
1405
1383
  fullCodes: ['82'],
1406
1384
  },
1385
+ {
1386
+ countryCode: 'OS',
1387
+ countryEn: 'South Ossetia',
1388
+ countryRu: 'Южная Осетия',
1389
+ phoneMask: '(999) 999-99-99',
1390
+ dialCode: '7',
1391
+ dialCodePriority: 1,
1392
+ fullCodes: ['7'],
1393
+ },
1407
1394
  {
1408
1395
  countryEn: 'South Sudan',
1409
1396
  countryRu: 'Южный Судан',
@@ -1,4 +1,4 @@
1
- import { isNotEmpty, isEmpty } from '@true-engineering/true-react-platform-helpers';
1
+ import { isNotEmpty, isStringEmpty } from '@true-engineering/true-react-platform-helpers';
2
2
  import type { IPhoneInfo, IPhoneValue } from '../components';
3
3
  import { phoneInfo } from '../constants';
4
4
 
@@ -46,22 +46,26 @@ export const getFullPhone = (phone?: IPhoneValue): string =>
46
46
  (phone?.dialCode ?? '') + (phone?.phoneNumber ?? '');
47
47
 
48
48
  export const getCountryCodeFromPhone = (phoneWithCode: string): string | undefined => {
49
- // попробуем найти уникальный код страны fullCode (dialCode + arealCode)
50
- let countryCode = phoneInfo.find((info) =>
51
- info.fullCodes.some((code) => phoneWithCode.startsWith(code)),
52
- )?.countryCode;
53
-
54
- if (isEmpty(countryCode) && isNotEmpty(phoneWithCode)) {
55
- // если не нашли уникальный fullCode (dialCode + arealCode),
56
- // то пробуем найти dialCode и выбираем с наименьшим Priority
57
- countryCode = phoneInfo
58
- .filter((info) => phoneWithCode.startsWith(info.dialCode))
59
- .sort(
60
- (infoA, infoB) => (infoA.dialCodePriority ?? 1000) - (infoB.dialCodePriority ?? 1000),
61
- )[0]?.countryCode;
49
+ if (isStringEmpty(phoneWithCode)) {
50
+ return;
62
51
  }
63
52
 
64
- return countryCode;
53
+ // ищем страны, для которых phoneWithCode начинается с fullCode (dialCode + areaCode)
54
+ const matchedCountries = phoneInfo.filter((info) =>
55
+ info.fullCodes.some((fullCode) => phoneWithCode.startsWith(fullCode)),
56
+ );
57
+
58
+ // если нашлась всего одна — ок, выдаём её
59
+ if (matchedCountries.length === 1) {
60
+ return matchedCountries[0].countryCode;
61
+ }
62
+
63
+ // если нашлось несколько, выбираем страну с наименьшим dialCodePriority (0 — самая приоритетная)
64
+ const highestPriorityCountries = phoneInfo
65
+ .filter((info) => phoneWithCode.startsWith(info.dialCode))
66
+ .sort((a, b) => (a.dialCodePriority ?? 1000) - (b.dialCodePriority ?? 1000));
67
+
68
+ return highestPriorityCountries.at(0)?.countryCode;
65
69
  };
66
70
 
67
71
  export const getPhoneObjFromString = (fullPhone: string, countryCode?: string): IPhoneValue => {