@true-engineering/true-react-common-ui-kit 1.12.0 → 2.0.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.
Files changed (266) hide show
  1. package/LICENSE +201 -201
  2. package/dist/components/Button/Button.d.ts +2 -2
  3. package/dist/components/DateInput/DateInput.d.ts +8 -8
  4. package/dist/components/DateInput/DateInput.styles.d.ts +2 -2
  5. package/dist/components/DateInput/constants.d.ts +2 -0
  6. package/dist/components/DateInput/index.d.ts +1 -0
  7. package/dist/components/DatePicker/DatePicker.d.ts +16 -24
  8. package/dist/components/DatePicker/DatePicker.styles.d.ts +12 -24
  9. package/dist/components/DatePicker/DatePickerHeader/DatePickerHeader.d.ts +3 -9
  10. package/dist/components/DatePicker/DatePickerHeader/index.d.ts +1 -0
  11. package/dist/components/DatePicker/constants.d.ts +1 -0
  12. package/dist/components/DatePicker/helpers.d.ts +3 -0
  13. package/dist/components/DatePicker/index.d.ts +1 -2
  14. package/dist/components/DatePicker/types.d.ts +4 -0
  15. package/dist/components/FiltersPane/FilterWithDates/FilterWithDates.d.ts +1 -1
  16. package/dist/components/Flag/augment.d.ts +1 -1
  17. package/dist/components/Icon/complexIcons/augment.d.ts +1 -1
  18. package/dist/helpers/utils.d.ts +2 -1
  19. package/dist/style.css +125 -50
  20. package/dist/true-react-common-ui-kit.js +392 -427
  21. package/dist/true-react-common-ui-kit.js.map +1 -1
  22. package/dist/true-react-common-ui-kit.umd.cjs +392 -427
  23. package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
  24. package/dist/types.d.ts +1 -1
  25. package/dist/vite-env.d.ts +1 -1
  26. package/package.json +91 -91
  27. package/src/components/AccountInfo/AccountInfo.stories.tsx +35 -35
  28. package/src/components/AccountInfo/AccountInfo.styles.ts +55 -55
  29. package/src/components/AccountInfo/AccountInfo.tsx +106 -106
  30. package/src/components/AccountInfo/index.ts +2 -2
  31. package/src/components/AddButton/AddButton.stories.tsx +21 -21
  32. package/src/components/AddButton/AddButton.styles.ts +34 -34
  33. package/src/components/AddButton/AddButton.tsx +49 -49
  34. package/src/components/AddButton/index.ts +2 -2
  35. package/src/components/Button/Button.stories.tsx +61 -61
  36. package/src/components/Button/Button.styles.ts +196 -196
  37. package/src/components/Button/Button.tsx +207 -207
  38. package/src/components/Button/index.ts +2 -2
  39. package/src/components/Checkbox/Checkbox.stories.tsx +35 -35
  40. package/src/components/Checkbox/Checkbox.styles.ts +62 -62
  41. package/src/components/Checkbox/Checkbox.tsx +106 -106
  42. package/src/components/Checkbox/index.ts +2 -2
  43. package/src/components/CloseButton/CloseButton.styles.ts +34 -34
  44. package/src/components/CloseButton/CloseButton.tsx +37 -37
  45. package/src/components/CloseButton/index.ts +2 -2
  46. package/src/components/Colors/Colors.stories.tsx +7 -7
  47. package/src/components/Colors/Colors.styles.ts +38 -38
  48. package/src/components/Colors/Colors.tsx +34 -34
  49. package/src/components/Colors/index.ts +2 -2
  50. package/src/components/CssBaseline/CssBaseline.styles.ts +15 -15
  51. package/src/components/CssBaseline/CssBaseline.tsx +17 -17
  52. package/src/components/CssBaseline/index.ts +2 -2
  53. package/src/components/DateInput/DateInput.stories.tsx +67 -63
  54. package/src/components/DateInput/DateInput.styles.ts +14 -14
  55. package/src/components/DateInput/DateInput.tsx +101 -60
  56. package/src/components/DateInput/constants.ts +2 -0
  57. package/src/components/DateInput/index.ts +3 -2
  58. package/src/components/DatePicker/DatePicker.stories.tsx +90 -96
  59. package/src/components/DatePicker/DatePicker.styles.ts +44 -54
  60. package/src/components/DatePicker/DatePicker.tsx +354 -358
  61. package/src/components/DatePicker/DatePickerHeader/DatePickerHeader.styles.ts +84 -84
  62. package/src/components/DatePicker/DatePickerHeader/DatePickerHeader.tsx +80 -94
  63. package/src/components/DatePicker/DatePickerHeader/index.ts +2 -1
  64. package/src/components/DatePicker/constants.ts +1 -0
  65. package/src/components/DatePicker/helpers.ts +24 -0
  66. package/src/components/DatePicker/index.ts +3 -4
  67. package/src/components/DatePicker/types.ts +40 -0
  68. package/src/components/Description/Description.stories.tsx +29 -29
  69. package/src/components/Description/Description.styles.ts +31 -31
  70. package/src/components/Description/Description.tsx +69 -69
  71. package/src/components/Description/index.ts +2 -2
  72. package/src/components/FiltersPane/FilterInterval/FilterInterval.styles.ts +64 -64
  73. package/src/components/FiltersPane/FilterInterval/FilterInterval.tsx +162 -162
  74. package/src/components/FiltersPane/FilterInterval/index.ts +1 -1
  75. package/src/components/FiltersPane/FilterMultiSelect/FilterMultiSelect.tsx +14 -14
  76. package/src/components/FiltersPane/FilterMultiSelect/index.ts +1 -1
  77. package/src/components/FiltersPane/FilterSelect/FilterSelect.styles.ts +144 -144
  78. package/src/components/FiltersPane/FilterSelect/FilterSelect.tsx +397 -397
  79. package/src/components/FiltersPane/FilterSelect/index.ts +1 -1
  80. package/src/components/FiltersPane/FilterSelect/locales.ts +37 -37
  81. package/src/components/FiltersPane/FilterValueView/FilterValueView.styles.tsx +15 -15
  82. package/src/components/FiltersPane/FilterValueView/FilterValueView.tsx +186 -186
  83. package/src/components/FiltersPane/FilterValueView/index.tsx +1 -1
  84. package/src/components/FiltersPane/FilterWithDates/FilterWithDates.styles.ts +60 -60
  85. package/src/components/FiltersPane/FilterWithDates/FilterWithDates.tsx +210 -222
  86. package/src/components/FiltersPane/FilterWithDates/index.ts +1 -1
  87. package/src/components/FiltersPane/FilterWithPeriod/FilterWithPeriod.styles.ts +17 -17
  88. package/src/components/FiltersPane/FilterWithPeriod/FilterWithPeriod.tsx +231 -231
  89. package/src/components/FiltersPane/FilterWithPeriod/index.ts +1 -1
  90. package/src/components/FiltersPane/FilterWrapper/FilterWrapper.styles.ts +110 -110
  91. package/src/components/FiltersPane/FilterWrapper/FilterWrapper.tsx +360 -360
  92. package/src/components/FiltersPane/FilterWrapper/index.ts +1 -1
  93. package/src/components/FiltersPane/FiltersPane.stories.tsx +308 -308
  94. package/src/components/FiltersPane/FiltersPane.styles.ts +71 -71
  95. package/src/components/FiltersPane/FiltersPane.tsx +193 -193
  96. package/src/components/FiltersPane/FiltersPaneSearch/FiltersPaneSearch.styles.ts +109 -109
  97. package/src/components/FiltersPane/FiltersPaneSearch/FiltersPaneSearch.tsx +175 -175
  98. package/src/components/FiltersPane/FiltersPaneSearch/index.ts +1 -1
  99. package/src/components/FiltersPane/index.ts +20 -20
  100. package/src/components/FiltersPane/locales.ts +107 -107
  101. package/src/components/FiltersPane/types.ts +126 -126
  102. package/src/components/Flag/Flag.stories.tsx +29 -29
  103. package/src/components/Flag/Flag.styles.ts +18 -18
  104. package/src/components/Flag/Flag.tsx +28 -28
  105. package/src/components/Flag/augment.d.ts +1 -1
  106. package/src/components/Flag/index.ts +2 -2
  107. package/src/components/FlexibleTable/FlexibleTable.stories.tsx +86 -86
  108. package/src/components/FlexibleTable/FlexibleTable.styles.ts +131 -131
  109. package/src/components/FlexibleTable/FlexibleTable.tsx +243 -243
  110. package/src/components/FlexibleTable/TableRow.tsx +171 -171
  111. package/src/components/FlexibleTable/TableValue.tsx +81 -81
  112. package/src/components/FlexibleTable/fixture-test.ts +254 -254
  113. package/src/components/FlexibleTable/index.ts +3 -3
  114. package/src/components/FlexibleTable/types.ts +58 -58
  115. package/src/components/Icon/ComplexIconBoilerplate.tsx +17 -17
  116. package/src/components/Icon/Icon.stories.tsx +88 -88
  117. package/src/components/Icon/Icon.styles.ts +10 -10
  118. package/src/components/Icon/Icon.tsx +34 -34
  119. package/src/components/Icon/IconBoilerplate.tsx +42 -42
  120. package/src/components/Icon/complexIcons/augment.d.ts +1 -1
  121. package/src/components/Icon/complexIcons/avatarGreen.svg +57 -57
  122. package/src/components/Icon/complexIcons/icons.ts +7 -7
  123. package/src/components/Icon/complexIcons/index.ts +1 -1
  124. package/src/components/Icon/icons/icons.ts +838 -838
  125. package/src/components/Icon/icons/index.ts +1 -1
  126. package/src/components/Icon/index.ts +4 -4
  127. package/src/components/IncrementInput/ChangeButton.tsx +34 -34
  128. package/src/components/IncrementInput/IncrementInput.stories.tsx +34 -34
  129. package/src/components/IncrementInput/IncrementInput.styles.ts +77 -77
  130. package/src/components/IncrementInput/IncrementInput.tsx +95 -95
  131. package/src/components/IncrementInput/index.ts +2 -2
  132. package/src/components/Input/Input.stories.tsx +92 -92
  133. package/src/components/Input/Input.styles.ts +307 -307
  134. package/src/components/Input/Input.tsx +321 -321
  135. package/src/components/Input/index.ts +2 -2
  136. package/src/components/List/List.stories.tsx +62 -62
  137. package/src/components/List/List.styles.ts +52 -52
  138. package/src/components/List/List.tsx +82 -82
  139. package/src/components/List/index.ts +2 -2
  140. package/src/components/Modal/Modal.stories.tsx +113 -113
  141. package/src/components/Modal/Modal.styles.ts +308 -308
  142. package/src/components/Modal/Modal.tsx +210 -210
  143. package/src/components/Modal/index.ts +2 -2
  144. package/src/components/MoreMenu/MoreMenu.stories.tsx +46 -46
  145. package/src/components/MoreMenu/MoreMenu.styles.ts +70 -70
  146. package/src/components/MoreMenu/MoreMenu.tsx +102 -102
  147. package/src/components/MoreMenu/index.ts +2 -2
  148. package/src/components/MultiSelect/MultiSelect.stories.tsx +46 -46
  149. package/src/components/MultiSelect/MultiSelect.styles.ts +55 -55
  150. package/src/components/MultiSelect/MultiSelect.tsx +98 -98
  151. package/src/components/MultiSelect/MultiSelectInput/MultiSelectInput.styles.ts +73 -73
  152. package/src/components/MultiSelect/MultiSelectInput/MultiSelectInput.tsx +62 -62
  153. package/src/components/MultiSelect/MultiSelectInput/index.ts +1 -1
  154. package/src/components/MultiSelect/index.ts +3 -3
  155. package/src/components/MultiSelectList/MultiSelectList.styles.ts +125 -125
  156. package/src/components/MultiSelectList/MultiSelectList.tsx +519 -519
  157. package/src/components/MultiSelectList/index.ts +2 -2
  158. package/src/components/MultiSelectList/locales.ts +37 -37
  159. package/src/components/Notification/Notification.stories.tsx +51 -51
  160. package/src/components/Notification/Notification.styles.ts +50 -50
  161. package/src/components/Notification/Notification.tsx +84 -84
  162. package/src/components/Notification/index.ts +2 -2
  163. package/src/components/NumberInput/NumberInput.stories.tsx +36 -36
  164. package/src/components/NumberInput/NumberInput.tsx +154 -154
  165. package/src/components/NumberInput/helpers.ts +87 -87
  166. package/src/components/NumberInput/index.ts +1 -1
  167. package/src/components/PhoneInput/PhoneInput.stories.tsx +71 -71
  168. package/src/components/PhoneInput/PhoneInput.styles.ts +84 -84
  169. package/src/components/PhoneInput/PhoneInput.tsx +223 -223
  170. package/src/components/PhoneInput/PhoneInputCountryList/PhoneInputCountryList.stories.tsx +21 -21
  171. package/src/components/PhoneInput/PhoneInputCountryList/PhoneInputCountryList.styles.ts +100 -100
  172. package/src/components/PhoneInput/PhoneInputCountryList/PhoneInputCountryList.tsx +171 -171
  173. package/src/components/PhoneInput/PhoneInputCountryList/index.ts +2 -2
  174. package/src/components/PhoneInput/index.ts +6 -6
  175. package/src/components/PhoneInput/phone-info.ts +2167 -2167
  176. package/src/components/PhoneInput/types.ts +16 -16
  177. package/src/components/RadioButton/RadioButton.stories.tsx +46 -46
  178. package/src/components/RadioButton/RadioButton.styles.ts +37 -37
  179. package/src/components/RadioButton/RadioButton.tsx +56 -56
  180. package/src/components/RadioButton/index.ts +2 -2
  181. package/src/components/ScrollIntoViewIfNeeded/ScrollIntoViewIfNeeded.ts +66 -66
  182. package/src/components/ScrollIntoViewIfNeeded/index.ts +1 -1
  183. package/src/components/SearchInput/SearchInput.stories.tsx +24 -24
  184. package/src/components/SearchInput/SearchInput.styles.ts +50 -50
  185. package/src/components/SearchInput/SearchInput.tsx +63 -63
  186. package/src/components/SearchInput/index.ts +2 -2
  187. package/src/components/Select/MultiSelect.stories.tsx +263 -263
  188. package/src/components/Select/Select.stories.tsx +258 -258
  189. package/src/components/Select/Select.styles.ts +96 -96
  190. package/src/components/Select/Select.tsx +630 -630
  191. package/src/components/Select/SelectList/SelectList.styles.ts +72 -72
  192. package/src/components/Select/SelectList/SelectList.tsx +165 -165
  193. package/src/components/Select/SelectList/index.ts +1 -1
  194. package/src/components/Select/SelectListItem/SelectListItem.styles.ts +14 -14
  195. package/src/components/Select/SelectListItem/SelectListItem.tsx +73 -73
  196. package/src/components/Select/constants.ts +2 -2
  197. package/src/components/Select/helpers.ts +29 -29
  198. package/src/components/Select/index.ts +4 -4
  199. package/src/components/Select/types.ts +1 -1
  200. package/src/components/SmartInput/SmartInput.stories.tsx +63 -63
  201. package/src/components/SmartInput/SmartInput.tsx +180 -180
  202. package/src/components/SmartInput/helpers.ts +85 -85
  203. package/src/components/SmartInput/index.ts +1 -1
  204. package/src/components/Switch/Switch.stories.tsx +40 -40
  205. package/src/components/Switch/Switch.styles.ts +75 -75
  206. package/src/components/Switch/Switch.tsx +89 -89
  207. package/src/components/Switch/index.ts +2 -2
  208. package/src/components/TextArea/TextArea.stories.tsx +35 -35
  209. package/src/components/TextArea/TextArea.styles.ts +153 -153
  210. package/src/components/TextArea/TextArea.tsx +178 -178
  211. package/src/components/TextArea/index.ts +2 -2
  212. package/src/components/TextWithInfo/TextWithInfo.stories.tsx +53 -53
  213. package/src/components/TextWithInfo/TextWithInfo.styles.ts +60 -60
  214. package/src/components/TextWithInfo/TextWithInfo.tsx +67 -67
  215. package/src/components/TextWithInfo/index.ts +2 -2
  216. package/src/components/TextWithTooltip/TextWithTooltip.stories.tsx +58 -58
  217. package/src/components/TextWithTooltip/TextWithTooltip.styles.ts +19 -19
  218. package/src/components/TextWithTooltip/TextWithTooltip.tsx +163 -163
  219. package/src/components/TextWithTooltip/index.ts +2 -2
  220. package/src/components/ThemedPreloader/ThemedPreloader.stories.tsx +41 -41
  221. package/src/components/ThemedPreloader/ThemedPreloader.styles.ts +21 -21
  222. package/src/components/ThemedPreloader/ThemedPreloader.tsx +56 -56
  223. package/src/components/ThemedPreloader/components/DefaultPreloader/DefaultPreloader.tsx +34 -34
  224. package/src/components/ThemedPreloader/components/DefaultPreloader/index.ts +1 -1
  225. package/src/components/ThemedPreloader/components/DotsPreloader/DotsPreloader.styles.ts +54 -54
  226. package/src/components/ThemedPreloader/components/DotsPreloader/DotsPreloader.tsx +18 -18
  227. package/src/components/ThemedPreloader/components/DotsPreloader/index.ts +2 -2
  228. package/src/components/ThemedPreloader/components/SvgPreloader/SvgPreloader.styles.ts +11 -11
  229. package/src/components/ThemedPreloader/components/SvgPreloader/SvgPreloader.tsx +32 -32
  230. package/src/components/ThemedPreloader/components/SvgPreloader/index.ts +2 -2
  231. package/src/components/ThemedPreloader/components/index.ts +2 -2
  232. package/src/components/ThemedPreloader/index.ts +2 -2
  233. package/src/components/Toaster/Toaster.stories.tsx +34 -34
  234. package/src/components/Toaster/Toaster.styles.ts +59 -59
  235. package/src/components/Toaster/Toaster.tsx +113 -113
  236. package/src/components/Toaster/index.ts +2 -2
  237. package/src/components/Tooltip/Tooltip.stories.tsx +21 -21
  238. package/src/components/Tooltip/Tooltip.styles.ts +45 -45
  239. package/src/components/Tooltip/Tooltip.tsx +40 -40
  240. package/src/components/Tooltip/index.ts +3 -3
  241. package/src/components/Tooltip/types.ts +1 -1
  242. package/src/components/index.ts +36 -36
  243. package/src/helpers/colors.ts +2 -2
  244. package/src/helpers/dateHelpers/date-helpers.ts +9 -9
  245. package/src/helpers/index.ts +4 -4
  246. package/src/helpers/phone.ts +106 -106
  247. package/src/helpers/popper-helpers.ts +17 -17
  248. package/src/helpers/snippets.tsx +5 -5
  249. package/src/helpers/utils.ts +261 -250
  250. package/src/hooks/index.ts +6 -6
  251. package/src/hooks/use-did-mount-effect.ts +21 -21
  252. package/src/hooks/use-dropdown.ts +85 -85
  253. package/src/hooks/use-is-mounted.ts +15 -15
  254. package/src/hooks/use-on-click-outside.ts +92 -92
  255. package/src/hooks/use-theme.ts +36 -36
  256. package/src/hooks/use-tweak-styles.ts +14 -14
  257. package/src/index.ts +6 -6
  258. package/src/theme.ts +155 -155
  259. package/src/types.ts +105 -106
  260. package/src/vite-env.d.ts +1 -1
  261. package/dist/components/DatePicker/DatePickerInput/DatePickerInput.d.ts +0 -11
  262. package/dist/components/DatePicker/DatePickerInput/DatePickerInput.styles.d.ts +0 -20
  263. package/dist/components/DatePicker/DatePickerInput/index.d.ts +0 -1
  264. package/src/components/DatePicker/DatePickerInput/DatePickerInput.styles.ts +0 -25
  265. package/src/components/DatePicker/DatePickerInput/DatePickerInput.tsx +0 -31
  266. package/src/components/DatePicker/DatePickerInput/index.ts +0 -1
@@ -1,250 +1,261 @@
1
- import { IDataAttributes } from '../types';
2
- import { HTMLAttributes, KeyboardEvent, MouseEvent } from 'react';
3
-
4
- export const transformToKebab = (string: string): string => {
5
- let result = '';
6
- string.split('').forEach((char) => {
7
- if (char.toLowerCase() === char) {
8
- result += char;
9
- } else {
10
- result += `-${char.toLowerCase()}`;
11
- }
12
- });
13
-
14
- return result;
15
- };
16
-
17
- export const hasExactParent = (element: Element, parent: Element): boolean => {
18
- if (element === parent) {
19
- return true; // Found the exact parent
20
- }
21
-
22
- const parentNode = getParentNode(element);
23
-
24
- if (parentNode === element) {
25
- return false; // Reached the top-level HTML element or Shadow DOM host
26
- }
27
-
28
- return hasExactParent(parentNode, parent);
29
- };
30
-
31
- export const getParentNode = (
32
- element: Element | ShadowRoot | Document,
33
- ): Element =>
34
- element.nodeName === 'HTML' || element === document
35
- ? (element as Element)
36
- : (element.parentNode as Element) ?? (element as ShadowRoot).host;
37
-
38
- export const getStyleComputedProperty = (
39
- element: Element,
40
- ): Partial<CSSStyleDeclaration> =>
41
- element.nodeType !== 1 ? {} : getComputedStyle(element, null);
42
-
43
- export const getScrollParent = (element: Element | Document): Element => {
44
- if (!element) {
45
- return document.body;
46
- }
47
-
48
- switch (element.nodeName) {
49
- case 'HTML':
50
- case 'BODY':
51
- return (element as Element).ownerDocument.body;
52
- case '#document':
53
- return (element as Document).body;
54
- }
55
-
56
- const { overflow, overflowX, overflowY } =
57
- getStyleComputedProperty(element as Element) ?? {};
58
- if (
59
- /(auto|scroll|overlay)/.test(
60
- (overflow ?? '') + (overflowY ?? '') + (overflowX ?? ''),
61
- )
62
- ) {
63
- return element as Element;
64
- }
65
- return getScrollParent(getParentNode(element as Element));
66
- };
67
-
68
- export const isElementOffScreen = (
69
- element: HTMLElement,
70
- input?: HTMLElement,
71
- ): boolean => {
72
- const el = element;
73
- const scrollParent = getScrollParent(element);
74
-
75
- const { scrollHeight: scrollHeightWithElement } = scrollParent;
76
- el.hidden = true;
77
- const { scrollHeight: scrollHeightWithoutElement } = scrollParent;
78
- el.hidden = false;
79
-
80
- const isOffscreen = scrollHeightWithElement !== scrollHeightWithoutElement;
81
-
82
- if (isOffscreen && input !== undefined) {
83
- const elRect = el.getBoundingClientRect();
84
- const scrollParentRect = scrollParent.getBoundingClientRect();
85
- const topOffset = elRect.top - scrollParentRect.top;
86
- if (input.clientHeight + el.clientHeight > topOffset) {
87
- return false;
88
- }
89
- }
90
-
91
- return isOffscreen;
92
- };
93
-
94
- export const getNumberInRange = (
95
- value: number,
96
- min = -Infinity,
97
- max = Infinity,
98
- ): number => Math.min(max, Math.max(min, value));
99
-
100
- const DEFAULT_THOUSANDS_SEPARATOR = '\u2009';
101
-
102
- export const formatStringNumber = (
103
- val?: string,
104
- separator = DEFAULT_THOUSANDS_SEPARATOR,
105
- ): string => {
106
- if (val === undefined) {
107
- return '';
108
- }
109
- const parts = val.split('.');
110
-
111
- parts[0] = parts[0]
112
- // убрать лидирующие нули
113
- .replace(/^0+(?=\d)/, '')
114
- // проставить сепараторы тысяч
115
- .replace(/\B(?=(\d{3})+(?!\d))/g, separator);
116
- return (parts[1] ?? '').length > 0 ? parts.join('.') : parts[0];
117
- };
118
-
119
- export const formatNumber = (
120
- val?: number,
121
- separator = DEFAULT_THOUSANDS_SEPARATOR,
122
- ): string => {
123
- if (val === undefined || isNaN(val)) {
124
- return '';
125
- }
126
- return formatStringNumber(String(val), separator);
127
- };
128
-
129
- export const removeStringFormat = (val?: string): string =>
130
- (val ?? '').replace(',', '.').replace(/\s/g, '');
131
-
132
- export const stringToNumber = (val?: string): number | undefined => {
133
- const trimmed = removeStringFormat(val);
134
- if (trimmed === '') {
135
- return undefined;
136
- }
137
- const num = Number(trimmed);
138
- return isNaN(num) ? undefined : num;
139
- };
140
-
141
- export const setCaretPosition = (
142
- elem: HTMLInputElement,
143
- caretPos: number | null,
144
- ): void => {
145
- if (caretPos === null || elem === null) {
146
- return;
147
- }
148
- if (elem.selectionStart) {
149
- elem.focus();
150
- elem.setSelectionRange(caretPos, caretPos);
151
- } else {
152
- elem.focus();
153
- }
154
- };
155
-
156
- export const isSpaceChar = (char?: string): boolean =>
157
- char !== undefined && char.match(/\s/) !== null;
158
-
159
- export const isInt = (n: number): boolean => n % 1 === 0;
160
-
161
- export const getNumberLength = (n?: number): number =>
162
- n === undefined || isNaN(n) ? 0 : n.toString().length;
163
-
164
- /**
165
- * Проверяет, что `val` не `null`, не `undefined` и не пустая строка
166
- */
167
- export const isNotEmpty = <T>(val: T | null | undefined): val is T =>
168
- typeof val === 'string'
169
- ? val.trim() !== ''
170
- : val !== null && val !== undefined;
171
-
172
- /**
173
- * Проверяет, что передана непустая строка
174
- */
175
- export const isStringNotEmpty = <T extends string>(
176
- value: T | undefined | null,
177
- ): value is T => (value ?? '').trim() !== '';
178
-
179
- export const trimStringToMaxLength = (val: string, maxLength: number) =>
180
- val.length > maxLength ? val.slice(0, maxLength) : val;
181
-
182
- export const addDataAttributes = (
183
- data: IDataAttributes = {},
184
- ): IDataAttributes =>
185
- Object.fromEntries(
186
- Object.entries(data).map(([key, value]) =>
187
- isNotEmpty(value) ? [`data-${transformToKebab(key)}`, value] : [],
188
- ),
189
- );
190
-
191
- export const addDataTestId = (
192
- ...args: Parameters<typeof getTestId>
193
- ): { 'data-testid': string } | undefined => {
194
- const testId = getTestId(...args);
195
- return isNotEmpty(testId) ? { 'data-testid': testId } : undefined;
196
- };
197
-
198
- export const getTestId = (
199
- testId: string | undefined,
200
- postfix?: string | number,
201
- ): string | undefined => {
202
- if (!isNotEmpty(testId)) {
203
- return undefined;
204
- }
205
- return isNotEmpty(postfix) ? `${testId}-${postfix}` : testId;
206
- };
207
-
208
- export const getSelectKeyHandler =
209
- (cb: (e: KeyboardEvent) => void): ((e: KeyboardEvent) => void) =>
210
- (e) => {
211
- if (e.code === 'Enter' || e.code === 'NumpadEnter') {
212
- cb(e);
213
- }
214
- };
215
-
216
- export const addClickHandler = (
217
- cb?: (e: MouseEvent | KeyboardEvent) => void,
218
- hasAction = true,
219
- ): HTMLAttributes<unknown> =>
220
- hasAction && isNotEmpty(cb)
221
- ? {
222
- tabIndex: 0,
223
- onClick: cb as (e: MouseEvent) => void,
224
- onKeyDown: getSelectKeyHandler(cb),
225
- }
226
- : {
227
- tabIndex: -1,
228
- };
229
-
230
- /**
231
- * Позволяет создать текстовый фильтр для набора items
232
- * @param getter - функция возвращающая набор строковых значений из каждого item,
233
- * по которым должен осуществляться поиск
234
- */
235
- export const createFilter =
236
- <T>(
237
- getter: (item: T) => Array<string | undefined>,
238
- ): ((items: T[], query: string) => T[]) =>
239
- (items, query) =>
240
- items.filter((item) => {
241
- const possibleValues = getter(item).reduce(
242
- (acc, cur) => [
243
- ...acc,
244
- ...(isStringNotEmpty(cur) ? [cur?.toLowerCase()] : []),
245
- ],
246
- [] as string[],
247
- );
248
- const queryString = query.toLowerCase().trim();
249
- return possibleValues.some((v) => v?.includes(queryString));
250
- });
1
+ import { IDataAttributes } from '../types';
2
+ import { HTMLAttributes, KeyboardEvent, MouseEvent } from 'react';
3
+
4
+ export const transformToKebab = (string: string): string => {
5
+ let result = '';
6
+ string.split('').forEach((char) => {
7
+ if (char.toLowerCase() === char) {
8
+ result += char;
9
+ } else {
10
+ result += `-${char.toLowerCase()}`;
11
+ }
12
+ });
13
+
14
+ return result;
15
+ };
16
+
17
+ export const hasExactParent = (element: Element, parent: Element): boolean => {
18
+ if (element === parent) {
19
+ return true; // Found the exact parent
20
+ }
21
+
22
+ const parentNode = getParentNode(element);
23
+
24
+ if (parentNode === element) {
25
+ return false; // Reached the top-level HTML element or Shadow DOM host
26
+ }
27
+
28
+ return hasExactParent(parentNode, parent);
29
+ };
30
+
31
+ export const getParentNode = (
32
+ element: Element | ShadowRoot | Document,
33
+ ): Element =>
34
+ element.nodeName === 'HTML' || element === document
35
+ ? (element as Element)
36
+ : (element.parentNode as Element) ?? (element as ShadowRoot).host;
37
+
38
+ export const getStyleComputedProperty = (
39
+ element: Element,
40
+ ): Partial<CSSStyleDeclaration> =>
41
+ element.nodeType !== 1 ? {} : getComputedStyle(element, null);
42
+
43
+ export const getScrollParent = (element: Element | Document): Element => {
44
+ if (!element) {
45
+ return document.body;
46
+ }
47
+
48
+ switch (element.nodeName) {
49
+ case 'HTML':
50
+ case 'BODY':
51
+ return (element as Element).ownerDocument.body;
52
+ case '#document':
53
+ return (element as Document).body;
54
+ }
55
+
56
+ const { overflow, overflowX, overflowY } =
57
+ getStyleComputedProperty(element as Element) ?? {};
58
+ if (
59
+ /(auto|scroll|overlay)/.test(
60
+ (overflow ?? '') + (overflowY ?? '') + (overflowX ?? ''),
61
+ )
62
+ ) {
63
+ return element as Element;
64
+ }
65
+ return getScrollParent(getParentNode(element as Element));
66
+ };
67
+
68
+ export const isElementOffScreen = (
69
+ element: HTMLElement,
70
+ input?: HTMLElement,
71
+ ): boolean => {
72
+ const el = element;
73
+ const scrollParent = getScrollParent(element);
74
+
75
+ const { scrollHeight: scrollHeightWithElement } = scrollParent;
76
+ el.hidden = true;
77
+ const { scrollHeight: scrollHeightWithoutElement } = scrollParent;
78
+ el.hidden = false;
79
+
80
+ const isOffscreen = scrollHeightWithElement !== scrollHeightWithoutElement;
81
+
82
+ if (isOffscreen && input !== undefined) {
83
+ const elRect = el.getBoundingClientRect();
84
+ const scrollParentRect = scrollParent.getBoundingClientRect();
85
+ const topOffset = elRect.top - scrollParentRect.top;
86
+ if (input.clientHeight + el.clientHeight > topOffset) {
87
+ return false;
88
+ }
89
+ }
90
+
91
+ return isOffscreen;
92
+ };
93
+
94
+ export const getNumberInRange = (
95
+ value: number,
96
+ min = -Infinity,
97
+ max = Infinity,
98
+ ): number => Math.min(max, Math.max(min, value));
99
+
100
+ const DEFAULT_THOUSANDS_SEPARATOR = '\u2009';
101
+
102
+ export const formatStringNumber = (
103
+ val?: string,
104
+ separator = DEFAULT_THOUSANDS_SEPARATOR,
105
+ ): string => {
106
+ if (val === undefined) {
107
+ return '';
108
+ }
109
+ const parts = val.split('.');
110
+
111
+ parts[0] = parts[0]
112
+ // убрать лидирующие нули
113
+ .replace(/^0+(?=\d)/, '')
114
+ // проставить сепараторы тысяч
115
+ .replace(/\B(?=(\d{3})+(?!\d))/g, separator);
116
+ return (parts[1] ?? '').length > 0 ? parts.join('.') : parts[0];
117
+ };
118
+
119
+ export const formatNumber = (
120
+ val?: number,
121
+ separator = DEFAULT_THOUSANDS_SEPARATOR,
122
+ ): string => {
123
+ if (val === undefined || isNaN(val)) {
124
+ return '';
125
+ }
126
+ return formatStringNumber(String(val), separator);
127
+ };
128
+
129
+ export const removeStringFormat = (val?: string): string =>
130
+ (val ?? '').replace(',', '.').replace(/\s/g, '');
131
+
132
+ export const stringToNumber = (val?: string): number | undefined => {
133
+ const trimmed = removeStringFormat(val);
134
+ if (trimmed === '') {
135
+ return undefined;
136
+ }
137
+ const num = Number(trimmed);
138
+ return isNaN(num) ? undefined : num;
139
+ };
140
+
141
+ export const setCaretPosition = (
142
+ elem: HTMLInputElement,
143
+ caretPos: number | null,
144
+ ): void => {
145
+ if (caretPos === null || elem === null) {
146
+ return;
147
+ }
148
+ if (elem.selectionStart) {
149
+ elem.focus();
150
+ elem.setSelectionRange(caretPos, caretPos);
151
+ } else {
152
+ elem.focus();
153
+ }
154
+ };
155
+
156
+ export const isSpaceChar = (char?: string): boolean =>
157
+ char !== undefined && char.match(/\s/) !== null;
158
+
159
+ export const isInt = (n: number): boolean => n % 1 === 0;
160
+
161
+ export const getNumberLength = (n?: number): number =>
162
+ n === undefined || isNaN(n) ? 0 : n.toString().length;
163
+
164
+ // TODO: Не должен проверять строку, т.к. под это есть отдельный хелпер
165
+ /**
166
+ * Проверяет, что `val` не `null`, не `undefined` и не пустая строка
167
+ */
168
+ export const isNotEmpty = <T>(val: T | null | undefined): val is T =>
169
+ typeof val === 'string'
170
+ ? val.trim() !== ''
171
+ : val !== null && val !== undefined;
172
+
173
+ /**
174
+ * Проверяет, что переданное значение `null` или `undefined`
175
+ */
176
+ export const isEmpty = <T>(
177
+ val: T | null | undefined,
178
+ ): val is null | undefined => val === null || val === undefined;
179
+
180
+ /**
181
+ * Проверяет, что передана непустая строка
182
+ */
183
+ export const isStringNotEmpty = <T extends string>(
184
+ value: T | undefined | null,
185
+ ): value is T => (value ?? '').trim() !== '';
186
+
187
+ export const trimStringToMaxLength = (val: string, maxLength: number) =>
188
+ val.length > maxLength ? val.slice(0, maxLength) : val;
189
+
190
+ export const addDataAttributes = (
191
+ data: IDataAttributes = {},
192
+ ): IDataAttributes =>
193
+ Object.fromEntries(
194
+ Object.entries(data).map(([key, value]) =>
195
+ isNotEmpty(value) ? [`data-${transformToKebab(key)}`, value] : [],
196
+ ),
197
+ );
198
+
199
+ export const addDataTestId = (
200
+ ...args: Parameters<typeof getTestId>
201
+ ): { 'data-testid': string } | undefined => {
202
+ const testId = getTestId(...args);
203
+ return isNotEmpty(testId) ? { 'data-testid': testId } : undefined;
204
+ };
205
+
206
+ export const getTestId = (
207
+ testId: string | undefined,
208
+ postfix?: string | number,
209
+ ): string | undefined => {
210
+ if (!isNotEmpty(testId)) {
211
+ return undefined;
212
+ }
213
+ return isNotEmpty(postfix) ? `${testId}-${postfix}` : testId;
214
+ };
215
+
216
+ export const getSelectKeyHandler =
217
+ (cb: (e: KeyboardEvent) => void): ((e: KeyboardEvent) => void) =>
218
+ (e) => {
219
+ if (e.code === 'Enter' || e.code === 'NumpadEnter') {
220
+ cb(e);
221
+ }
222
+ };
223
+
224
+ export const addClickHandler = (
225
+ cb?: (e: MouseEvent | KeyboardEvent) => void,
226
+ hasAction = true,
227
+ ): HTMLAttributes<unknown> =>
228
+ hasAction && isNotEmpty(cb)
229
+ ? {
230
+ tabIndex: 0,
231
+ onClick: cb as (e: MouseEvent) => void,
232
+ onKeyDown: getSelectKeyHandler(cb),
233
+ }
234
+ : {
235
+ tabIndex: -1,
236
+ };
237
+
238
+ /**
239
+ * Позволяет создать текстовый фильтр для набора items
240
+ * @param getter - функция возвращающая набор строковых значений из каждого item,
241
+ * по которым должен осуществляться поиск
242
+ */
243
+ export const createFilter =
244
+ <T>(
245
+ getter: (item: T) => Array<string | undefined>,
246
+ compareFn?: (item: string, query: string) => boolean,
247
+ ): ((items: T[], query: string) => T[]) =>
248
+ (items, query) =>
249
+ items.filter((item) => {
250
+ const possibleValues = getter(item).reduce(
251
+ (acc, cur) => [
252
+ ...acc,
253
+ ...(isStringNotEmpty(cur) ? [cur.toLowerCase()] : []),
254
+ ],
255
+ [] as string[],
256
+ );
257
+ const queryString = query.toLowerCase().trim();
258
+ return possibleValues.some((v) =>
259
+ (compareFn ?? (() => v?.includes(queryString)))(v, queryString),
260
+ );
261
+ });
@@ -1,6 +1,6 @@
1
- export * from './use-is-mounted';
2
- export * from './use-on-click-outside';
3
- export * from './use-theme';
4
- export * from './use-dropdown';
5
- export * from './use-tweak-styles';
6
- export * from './use-did-mount-effect';
1
+ export * from './use-is-mounted';
2
+ export * from './use-on-click-outside';
3
+ export * from './use-theme';
4
+ export * from './use-dropdown';
5
+ export * from './use-tweak-styles';
6
+ export * from './use-did-mount-effect';
@@ -1,21 +1,21 @@
1
- import { DependencyList, EffectCallback, useEffect, useRef } from 'react';
2
-
3
- export const useDidMountEffect = (
4
- effect: EffectCallback,
5
- dependencies: DependencyList,
6
- ): void => {
7
- const isMountedRef = useRef(false);
8
- useEffect(() => {
9
- let unmount: ReturnType<EffectCallback>;
10
- if (isMountedRef.current) {
11
- unmount = effect();
12
- } else {
13
- isMountedRef.current = true;
14
- }
15
- return () => {
16
- if (unmount !== undefined) {
17
- unmount();
18
- }
19
- };
20
- }, dependencies);
21
- };
1
+ import { DependencyList, EffectCallback, useEffect, useRef } from 'react';
2
+
3
+ export const useDidMountEffect = (
4
+ effect: EffectCallback,
5
+ dependencies: DependencyList,
6
+ ): void => {
7
+ const isMountedRef = useRef(false);
8
+ useEffect(() => {
9
+ let unmount: ReturnType<EffectCallback>;
10
+ if (isMountedRef.current) {
11
+ unmount = effect();
12
+ } else {
13
+ isMountedRef.current = true;
14
+ }
15
+ return () => {
16
+ if (unmount !== undefined) {
17
+ unmount();
18
+ }
19
+ };
20
+ }, dependencies);
21
+ };