@true-engineering/true-react-common-ui-kit 4.0.0-alpha3 → 4.0.0-alpha31

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 (237) hide show
  1. package/README.md +11 -607
  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 +4 -2
  5. package/dist/components/ControlWrapper/ControlWrapper.styles.d.ts +2 -1
  6. package/dist/components/ControlWrapper/helpers.d.ts +4 -0
  7. package/dist/components/ControlWrapper/index.d.ts +2 -0
  8. package/dist/components/ControlWrapper/types.d.ts +12 -0
  9. package/dist/components/DateInput/DateInput.d.ts +1 -2
  10. package/dist/components/DatePicker/DatePicker.d.ts +4 -3
  11. package/dist/components/DatePicker/DatePicker.styles.d.ts +1 -1
  12. package/dist/components/DatePicker/components/DatePickerBase/DatePickerBase.d.ts +5 -0
  13. package/dist/components/DatePicker/components/DatePickerBase/index.d.ts +1 -0
  14. package/dist/components/DatePicker/components/PopperContainer/PopperContainer.d.ts +2 -4
  15. package/dist/components/DatePicker/components/index.d.ts +1 -0
  16. package/dist/components/DatePicker/constants.d.ts +7 -2
  17. package/dist/components/DatePicker/index.d.ts +1 -0
  18. package/dist/components/DatePicker/types.d.ts +3 -3
  19. package/dist/components/FiltersPane/FiltersPane.d.ts +7 -2
  20. package/dist/components/FiltersPane/components/Filter/Filter.d.ts +2 -2
  21. package/dist/components/FiltersPane/components/Filter/helpers.d.ts +4 -0
  22. package/dist/components/FiltersPane/components/FilterInterval/FilterInterval.styles.d.ts +1 -1
  23. package/dist/components/FiltersPane/components/FilterSelect/FilterSelect.styles.d.ts +1 -1
  24. package/dist/components/FiltersPane/components/FilterValueView/FilterValueView.d.ts +3 -1
  25. package/dist/components/FiltersPane/components/FilterWithDates/FilterWithDates.styles.d.ts +2 -2
  26. package/dist/components/FiltersPane/components/FilterWrapper/FilterWrapper.d.ts +2 -2
  27. package/dist/components/FiltersPane/components/FiltersPaneSearch/FiltersPaneSearch.styles.d.ts +1 -1
  28. package/dist/components/FiltersPane/types.d.ts +16 -5
  29. package/dist/components/Flag/customFlags/customFlags.d.ts +10 -0
  30. package/dist/components/Flag/customFlags/index.d.ts +1 -0
  31. package/dist/components/FlexibleTable/FlexibleTable.d.ts +4 -2
  32. package/dist/components/FlexibleTable/components/FlexibleTableCell/FlexibleTableCell.d.ts +4 -3
  33. package/dist/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.d.ts +6 -6
  34. package/dist/components/FlexibleTable/constants.d.ts +18 -2
  35. package/dist/components/FlexibleTable/types.d.ts +20 -12
  36. package/dist/components/Icon/icons-list.d.ts +1 -1
  37. package/dist/components/IconButton/IconButton.styles.d.ts +1 -1
  38. package/dist/components/IncrementInput/IncrementInput.styles.d.ts +1 -3
  39. package/dist/components/Input/Input.d.ts +3 -2
  40. package/dist/components/Input/InputBase.d.ts +2 -2
  41. package/dist/components/List/List.d.ts +1 -1
  42. package/dist/components/List/index.d.ts +2 -1
  43. package/dist/components/List/types.d.ts +4 -0
  44. package/dist/components/Modal/Modal.styles.d.ts +1 -1
  45. package/dist/components/Notification/Notification.styles.d.ts +1 -1
  46. package/dist/components/RadioButton/RadioButton.styles.d.ts +1 -1
  47. package/dist/components/ScrollIntoViewIfNeeded/ScrollIntoViewIfNeeded.d.ts +1 -1
  48. package/dist/components/SearchInput/SearchInput.d.ts +2 -2
  49. package/dist/components/Select/Select.d.ts +5 -3
  50. package/dist/components/Select/Select.styles.d.ts +5 -5
  51. package/dist/components/Select/components/SelectListItem/SelectListItem.d.ts +2 -1
  52. package/dist/components/Select/index.d.ts +1 -1
  53. package/dist/components/Status/Status.styles.d.ts +3 -2
  54. package/dist/components/Status/constants.d.ts +0 -1
  55. package/dist/components/Status/index.d.ts +1 -0
  56. package/dist/components/Status/types.d.ts +5 -2
  57. package/dist/components/TextArea/TextArea.d.ts +4 -5
  58. package/dist/components/TextArea/TextArea.styles.d.ts +5 -4
  59. package/dist/components/TextArea/index.d.ts +1 -1
  60. package/dist/components/TextArea/types.d.ts +4 -2
  61. package/dist/components/TextButton/TextButton.styles.d.ts +1 -1
  62. package/dist/components/Tooltip/Tooltip.d.ts +1 -1
  63. package/dist/components/Tooltip/Tooltip.styles.d.ts +1 -1
  64. package/dist/components/WithMessages/WithMessages.styles.d.ts +1 -1
  65. package/dist/components/WithPopup/WithPopup.d.ts +11 -3
  66. package/dist/hooks/index.d.ts +7 -4
  67. package/dist/hooks/use-intersection-ref.d.ts +8 -0
  68. package/dist/hooks/use-latest-ref.d.ts +2 -0
  69. package/dist/hooks/use-merge.d.ts +1 -0
  70. package/dist/hooks/use-mixed-styles.d.ts +3 -1
  71. package/dist/hooks/use-on-click-outside.d.ts +2 -2
  72. package/dist/hooks/use-tweak-styles.d.ts +5 -5
  73. package/dist/style.css +78 -142
  74. package/dist/theme/Provider.d.ts +6 -3
  75. package/dist/theme/create-themed-styles.d.ts +2 -0
  76. package/dist/theme/helpers.d.ts +9 -3
  77. package/dist/theme/index.d.ts +2 -0
  78. package/dist/theme/true-jss/ThemedStylesManager.d.ts +18 -0
  79. package/dist/theme/true-jss/TweakStylesManager.d.ts +34 -0
  80. package/dist/theme/true-jss/index.d.ts +2 -0
  81. package/dist/theme/true-jss/jss-context.d.ts +9 -0
  82. package/dist/theme/types.d.ts +5 -3
  83. package/dist/true-react-common-ui-kit.js +8157 -6924
  84. package/dist/true-react-common-ui-kit.js.map +1 -1
  85. package/dist/true-react-common-ui-kit.umd.cjs +8004 -6772
  86. package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
  87. package/dist/types.d.ts +10 -3
  88. package/package.json +4 -5
  89. package/src/components/ControlWrapper/ControlWrapper.stories.tsx +8 -3
  90. package/src/components/ControlWrapper/ControlWrapper.styles.ts +7 -6
  91. package/src/components/ControlWrapper/ControlWrapper.tsx +31 -20
  92. package/src/components/ControlWrapper/helpers.ts +11 -0
  93. package/src/components/ControlWrapper/index.ts +2 -0
  94. package/src/components/ControlWrapper/types.ts +16 -0
  95. package/src/components/DateInput/DateInput.stories.tsx +0 -1
  96. package/src/components/DateInput/DateInput.tsx +3 -4
  97. package/src/components/DatePicker/DatePicker.stories.tsx +24 -11
  98. package/src/components/DatePicker/DatePicker.styles.ts +3 -1
  99. package/src/components/DatePicker/DatePicker.tsx +47 -16
  100. package/src/components/DatePicker/components/DatePickerBase/DatePickerBase.tsx +14 -0
  101. package/src/components/DatePicker/components/DatePickerBase/index.ts +1 -0
  102. package/src/components/DatePicker/components/PopperContainer/PopperContainer.tsx +4 -4
  103. package/src/components/DatePicker/components/index.ts +1 -0
  104. package/src/components/DatePicker/constants.ts +9 -3
  105. package/src/components/DatePicker/helpers.ts +1 -1
  106. package/src/components/DatePicker/index.ts +1 -0
  107. package/src/components/DatePicker/types.ts +6 -4
  108. package/src/components/FiltersPane/FiltersPane.stories.tsx +4 -2
  109. package/src/components/FiltersPane/FiltersPane.tsx +28 -19
  110. package/src/components/FiltersPane/components/Filter/Filter.tsx +36 -30
  111. package/src/components/FiltersPane/components/Filter/helpers.ts +18 -0
  112. package/src/components/FiltersPane/components/FilterSelect/FilterSelect.tsx +22 -23
  113. package/src/components/FiltersPane/components/FilterValueView/FilterValueView.tsx +27 -22
  114. package/src/components/FiltersPane/components/FilterWithDates/FilterWithDates.styles.ts +2 -1
  115. package/src/components/FiltersPane/components/FilterWithDates/FilterWithDates.tsx +3 -4
  116. package/src/components/FiltersPane/components/FilterWithPeriod/FilterWithPeriod.tsx +4 -3
  117. package/src/components/FiltersPane/components/FilterWrapper/FilterWrapper.tsx +14 -10
  118. package/src/components/FiltersPane/components/FiltersPaneSearch/FiltersPaneSearch.styles.ts +5 -0
  119. package/src/components/FiltersPane/components/FiltersPaneSearch/FiltersPaneSearch.tsx +16 -19
  120. package/src/components/FiltersPane/types.ts +24 -5
  121. package/src/components/Flag/Flag.stories.tsx +2 -1
  122. package/src/components/Flag/Flag.styles.ts +4 -0
  123. package/src/components/Flag/Flag.tsx +23 -9
  124. package/src/components/Flag/customFlags/AB.svg +1 -0
  125. package/src/components/Flag/customFlags/OS.svg +1 -0
  126. package/src/components/Flag/customFlags/augment.d.ts +1 -0
  127. package/src/components/Flag/customFlags/customFlags.ts +13 -0
  128. package/src/components/Flag/customFlags/index.ts +1 -0
  129. package/src/components/FlexibleTable/FlexibleTable.tsx +40 -63
  130. package/src/components/FlexibleTable/components/FlexibleTableCell/FlexibleTableCell.tsx +8 -5
  131. package/src/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.tsx +13 -12
  132. package/src/components/FlexibleTable/constants.ts +6 -3
  133. package/src/components/FlexibleTable/types.ts +20 -16
  134. package/src/components/IncrementInput/IncrementInput.stories.tsx +2 -0
  135. package/src/components/IncrementInput/IncrementInput.styles.ts +31 -39
  136. package/src/components/IncrementInput/IncrementInput.tsx +28 -25
  137. package/src/components/Input/Input.stories.tsx +1 -6
  138. package/src/components/Input/Input.tsx +5 -3
  139. package/src/components/Input/InputBase.tsx +27 -25
  140. package/src/components/List/List.tsx +5 -2
  141. package/src/components/List/index.ts +2 -1
  142. package/src/components/List/types.ts +5 -0
  143. package/src/components/MultiSelectList/MultiSelectList.tsx +15 -11
  144. package/src/components/NumberInput/NumberInput.stories.tsx +5 -1
  145. package/src/components/PhoneInput/PhoneInput.stories.tsx +2 -1
  146. package/src/components/PhoneInput/PhoneInput.tsx +5 -2
  147. package/src/components/SearchInput/SearchInput.tsx +20 -29
  148. package/src/components/Select/CustomSelect.stories.tsx +1 -0
  149. package/src/components/Select/MultiSelect.stories.tsx +5 -0
  150. package/src/components/Select/Select.stories.tsx +6 -0
  151. package/src/components/Select/Select.styles.ts +5 -40
  152. package/src/components/Select/Select.tsx +36 -22
  153. package/src/components/Select/components/SelectList/SelectList.tsx +4 -2
  154. package/src/components/Select/components/SelectListItem/SelectListItem.tsx +5 -2
  155. package/src/components/Select/index.ts +1 -1
  156. package/src/components/Status/Status.stories.tsx +54 -1
  157. package/src/components/Status/Status.styles.ts +2 -37
  158. package/src/components/Status/constants.ts +0 -10
  159. package/src/components/Status/index.ts +1 -1
  160. package/src/components/Status/types.ts +7 -3
  161. package/src/components/TextArea/TextArea.stories.tsx +15 -1
  162. package/src/components/TextArea/TextArea.styles.ts +15 -8
  163. package/src/components/TextArea/TextArea.tsx +96 -62
  164. package/src/components/TextArea/index.ts +1 -1
  165. package/src/components/TextArea/types.ts +5 -5
  166. package/src/components/TextButton/TextButton.styles.ts +1 -0
  167. package/src/components/Tooltip/Tooltip.styles.ts +2 -0
  168. package/src/components/Tooltip/Tooltip.tsx +1 -1
  169. package/src/components/WithMessages/WithMessages.stories.tsx +1 -1
  170. package/src/components/WithPopup/WithPopup.tsx +36 -15
  171. package/src/constants/phone-info.ts +20 -33
  172. package/src/helpers/phone.ts +19 -15
  173. package/src/hooks/index.ts +7 -4
  174. package/src/hooks/use-intersection-ref.ts +30 -0
  175. package/src/hooks/use-latest-ref.ts +7 -0
  176. package/src/hooks/use-merge.ts +8 -0
  177. package/src/hooks/use-mixed-styles.ts +9 -11
  178. package/src/hooks/use-on-click-outside.ts +22 -14
  179. package/src/hooks/use-tweak-styles.ts +49 -27
  180. package/src/theme/Provider.tsx +10 -5
  181. package/src/theme/create-themed-styles.ts +78 -0
  182. package/src/theme/helpers.ts +39 -39
  183. package/src/theme/index.ts +2 -0
  184. package/src/theme/true-jss/ThemedStylesManager.ts +92 -0
  185. package/src/theme/true-jss/TweakStylesManager.ts +157 -0
  186. package/src/theme/true-jss/index.ts +2 -0
  187. package/src/theme/true-jss/jss-context.tsx +34 -0
  188. package/src/theme/types.ts +5 -3
  189. package/src/types.ts +17 -4
  190. package/dist/components/AccountInfo/AccountInfo.stories.d.ts +0 -6
  191. package/dist/components/AddButton/AddButton.stories.d.ts +0 -6
  192. package/dist/components/Button/Button.stories.d.ts +0 -6
  193. package/dist/components/Checkbox/Checkbox.stories.d.ts +0 -8
  194. package/dist/components/CloseButton/CloseButton.stories.d.ts +0 -5
  195. package/dist/components/Colors/Colors.stories.d.ts +0 -5
  196. package/dist/components/ControlWrapper/ControlWrapper.stories.d.ts +0 -6
  197. package/dist/components/DateInput/DateInput.stories.d.ts +0 -7
  198. package/dist/components/DatePicker/DatePicker.stories.d.ts +0 -7
  199. package/dist/components/Description/Description.stories.d.ts +0 -16
  200. package/dist/components/FileInput/FileInput.stories.d.ts +0 -7
  201. package/dist/components/FileItem/FileItem.stories.d.ts +0 -8
  202. package/dist/components/FiltersPane/FiltersPane.stories.d.ts +0 -31
  203. package/dist/components/Flag/Flag.stories.d.ts +0 -12
  204. package/dist/components/FlexibleTable/FlexibleTable.stories.d.ts +0 -19
  205. package/dist/components/Icon/Icon.stories.d.ts +0 -6
  206. package/dist/components/IconButton/IconButton.stories.d.ts +0 -6
  207. package/dist/components/IncrementInput/IncrementInput.stories.d.ts +0 -6
  208. package/dist/components/Input/Input.stories.d.ts +0 -25
  209. package/dist/components/List/List.stories.d.ts +0 -5
  210. package/dist/components/Modal/Modal.stories.d.ts +0 -29
  211. package/dist/components/MoreMenu/MoreMenu.stories.d.ts +0 -6
  212. package/dist/components/MultiSelect/MultiSelect.stories.d.ts +0 -13
  213. package/dist/components/NewMoreMenu/NewMoreMenu.stories.d.ts +0 -12
  214. package/dist/components/Notification/Notification.stories.d.ts +0 -8
  215. package/dist/components/NumberInput/NumberInput.stories.d.ts +0 -7
  216. package/dist/components/PhoneInput/PhoneInput.stories.d.ts +0 -28
  217. package/dist/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.stories.d.ts +0 -5
  218. package/dist/components/RadioButton/RadioButton.stories.d.ts +0 -7
  219. package/dist/components/SearchInput/SearchInput.stories.d.ts +0 -6
  220. package/dist/components/Select/CustomSelect.stories.d.ts +0 -11
  221. package/dist/components/Select/MultiSelect.stories.d.ts +0 -15
  222. package/dist/components/Select/Select.stories.d.ts +0 -15
  223. package/dist/components/Selector/Selector.stories.d.ts +0 -7
  224. package/dist/components/Skeleton/Skeleton.stories.d.ts +0 -6
  225. package/dist/components/SmartInput/SmartInput.stories.d.ts +0 -18
  226. package/dist/components/Status/Status.stories.d.ts +0 -6
  227. package/dist/components/Switch/Switch.stories.d.ts +0 -16
  228. package/dist/components/TextArea/TextArea.stories.d.ts +0 -17
  229. package/dist/components/TextButton/TextButton.stories.d.ts +0 -6
  230. package/dist/components/TextWithInfo/TextWithInfo.stories.d.ts +0 -12
  231. package/dist/components/TextWithTooltip/TextWithTooltip.stories.d.ts +0 -24
  232. package/dist/components/ThemedPreloader/ThemedPreloader.stories.d.ts +0 -17
  233. package/dist/components/Toaster/Toaster.stories.d.ts +0 -5
  234. package/dist/components/Tooltip/Tooltip.stories.d.ts +0 -5
  235. package/dist/components/WithMessages/WithMessages.stories.d.ts +0 -7
  236. package/dist/components/WithPopup/WithPopup.stories.d.ts +0 -16
  237. package/dist/components/WithTooltip/WithTooltip.stories.d.ts +0 -6
package/dist/types.d.ts CHANGED
@@ -1,5 +1,7 @@
1
- import { FocusEventHandler, type KeyboardEvent, KeyboardEventHandler, MouseEvent, MouseEventHandler, PointerEventHandler, ReactNode } from 'react';
2
- import { Modifier, Placement } from 'react-overlays/usePopper';
1
+ import type { FocusEventHandler, KeyboardEvent, KeyboardEventHandler, MouseEvent, MouseEventHandler, PointerEventHandler, ReactNode } from 'react';
2
+ import type { Modifier, Placement } from 'react-overlays/usePopper';
3
+ import type { JssStyle } from 'jss';
4
+ import type { IMaybeArray } from './theme';
3
5
  export interface ITestIdProps {
4
6
  testId?: string;
5
7
  }
@@ -10,7 +12,7 @@ export interface IDataAttributesProps extends ITestIdProps {
10
12
  data?: IDataAttributes;
11
13
  }
12
14
  export interface ITweakStylesProps<TweakStyles> {
13
- tweakStyles?: TweakStyles;
15
+ tweakStyles?: IMaybeArray<TweakStyles>;
14
16
  }
15
17
  export type ICommonProps<TweakStyles> = IDataAttributesProps & ITweakStylesProps<TweakStyles>;
16
18
  export interface IDropdownWithPopperOptions {
@@ -43,3 +45,8 @@ export interface IDomElementInteractions<T> {
43
45
  onPointerUp?: PointerEventHandler<T>;
44
46
  }
45
47
  export type IRenderNode<T> = ReactNode | ((props: T) => ReactNode);
48
+ export type IExtendableProps<T extends string | readonly string[]> = Record<T extends ReadonlyArray<infer P> ? P : T, JssStyle>;
49
+ export type IDefaultExtendableProps = IExtendableProps<'custom'>;
50
+ export type IWithPrefix<T, P extends string> = {
51
+ [K in keyof T as `${P}${K & string}`]: T[K];
52
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@true-engineering/true-react-common-ui-kit",
3
- "version": "4.0.0-alpha3",
3
+ "version": "4.0.0-alpha31",
4
4
  "description": "True Engineering React UI Kit with theming support",
5
5
  "author": "True Engineering (https://trueengineering.ru)",
6
6
  "keywords": [
@@ -42,17 +42,17 @@
42
42
  "types-check": "tsc --noEmit"
43
43
  },
44
44
  "dependencies": {
45
- "@floating-ui/react": "0.26.12",
45
+ "@floating-ui/react": "0.27.13",
46
46
  "@true-engineering/true-react-platform-helpers": "0.4.4",
47
47
  "clsx": "1.2.1",
48
48
  "country-flag-icons": "1.5.5",
49
- "date-fns": "2.29.3",
49
+ "date-fns": "4.1.0",
50
50
  "filesize": "10.1.1",
51
51
  "hex-to-rgba": "2.0.1",
52
52
  "jss": "10.10.0",
53
53
  "lodash-es": "4.17.21",
54
54
  "react": "18.2.0",
55
- "react-datepicker": "4.25.0",
55
+ "react-datepicker": "8.4.0",
56
56
  "react-dom": "18.2.0",
57
57
  "react-input-mask": "3.0.0-alpha.2",
58
58
  "react-jss": "10.10.0",
@@ -73,7 +73,6 @@
73
73
  "@trivago/prettier-plugin-sort-imports": "4.3.0",
74
74
  "@types/lodash-es": "4.17.11",
75
75
  "@types/react": "18.2.79",
76
- "@types/react-datepicker": "4.19.4",
77
76
  "@types/react-dom": "18.2.25",
78
77
  "@types/react-input-mask": "3.0.2",
79
78
  "@types/react-transition-group": "4.4.10",
@@ -1,15 +1,15 @@
1
1
  import { doNothing } from '@true-engineering/true-react-platform-helpers';
2
2
  import { ComponentStory } from '@storybook/react';
3
- import { iconsList } from '../Icon';
3
+ import { Icon, iconsList } from '../Icon';
4
4
  import { ControlWrapper } from './ControlWrapper';
5
5
 
6
6
  export default {
7
- title: 'ControlWrapper',
7
+ title: 'Controls/ControlWrapper',
8
8
  component: ControlWrapper,
9
9
  };
10
10
 
11
11
  const Template: ComponentStory<typeof ControlWrapper> = (args) => (
12
- <ControlWrapper {...args} onClear={doNothing} onIconClick={doNothing}>
12
+ <ControlWrapper {...args} onClear={doNothing}>
13
13
  <div style={{ minWidth: 200, height: 48 }} />
14
14
  </ControlWrapper>
15
15
  );
@@ -24,6 +24,11 @@ Default.args = {
24
24
  isLoading: false,
25
25
  isDisabled: false,
26
26
  hasValue: false,
27
+ icon: [
28
+ { iconComponent: <div>Бу</div>, onClick: () => console.log('close'), shouldResetSize: true },
29
+ { iconComponent: <Icon type="question" /> },
30
+ { iconComponent: 'search', onClick: () => console.log('search') },
31
+ ],
27
32
  };
28
33
 
29
34
  Default.argTypes = {
@@ -1,5 +1,6 @@
1
1
  import { animations, createThemedStyles, dimensions, ITweakStyles } from '../../theme';
2
2
  import { IThemedPreloaderStyles } from '../ThemedPreloader';
3
+ import { IControlWrapperSizes } from './types';
3
4
 
4
5
  const { CONTROL, Z_INDEX } = dimensions;
5
6
 
@@ -20,10 +21,6 @@ export const useStyles = createThemedStyles('ControlWrapper', {
20
21
  zIndex: 0,
21
22
  },
22
23
 
23
- invalid: {
24
- zIndex: Z_INDEX.CONTROL_INVALID,
25
- },
26
-
27
24
  disabled: {},
28
25
 
29
26
  focused: {
@@ -31,6 +28,10 @@ export const useStyles = createThemedStyles('ControlWrapper', {
31
28
  zIndex: Z_INDEX.CONTROL_FOCUS,
32
29
  },
33
30
 
31
+ invalid: {
32
+ zIndex: Z_INDEX.CONTROL_INVALID,
33
+ },
34
+
34
35
  withValue: {},
35
36
 
36
37
  loading: {},
@@ -43,7 +44,7 @@ export const useStyles = createThemedStyles('ControlWrapper', {
43
44
  position: 'absolute',
44
45
  pointerEvents: 'none',
45
46
  left: 'var(--control-padding)',
46
- top: '50%',
47
+ top: 'calc(var(--control-height) / 2)',
47
48
  transformOrigin: 'top left',
48
49
  transform: 'translateY(-50%)',
49
50
  transition: animations.defaultTransition,
@@ -181,5 +182,5 @@ export const useStyles = createThemedStyles('ControlWrapper', {
181
182
 
182
183
  export type IControlWrapperStyles = ITweakStyles<
183
184
  typeof useStyles,
184
- { tweakPreloader: IThemedPreloaderStyles }
185
+ { tweakPreloader: IThemedPreloaderStyles } & IControlWrapperSizes
185
186
  >;
@@ -4,20 +4,25 @@ import {
4
4
  addClickHandler,
5
5
  addDataAttributes,
6
6
  addDataTestId,
7
+ getArray,
8
+ isArrayNotEmpty,
7
9
  isNotEmpty,
8
10
  isReactNodeNotEmpty,
9
- isString,
10
11
  } from '@true-engineering/true-react-platform-helpers';
11
12
  import { useTweakStyles } from '../../hooks';
13
+ import { IMaybeArray } from '../../theme';
12
14
  import { IClickHandlerEvent, ICommonProps } from '../../types';
13
15
  import { Icon, IIcon, renderIcon } from '../Icon';
14
16
  import { ThemedPreloader } from '../ThemedPreloader';
17
+ import { convertToControlWrapperIcon } from './helpers';
18
+ import { IControlWrapperIcon, IControlWrapperSize } from './types';
15
19
  import { IControlWrapperStyles, useStyles } from './ControlWrapper.styles';
16
20
 
17
21
  export interface IControlWrapperProps extends ICommonProps<IControlWrapperStyles> {
18
22
  children: ReactNode;
19
23
  label?: ReactNode;
20
- icon?: IIcon;
24
+ icon?: IMaybeArray<IIcon | IControlWrapperIcon>;
25
+ size?: IControlWrapperSize;
21
26
  groupPlacement?:
22
27
  | 'left'
23
28
  | 'right'
@@ -42,7 +47,6 @@ export interface IControlWrapperProps extends ICommonProps<IControlWrapperStyles
42
47
  isLoading?: boolean;
43
48
  /** @default false */
44
49
  isDisabled?: boolean;
45
- onIconClick?: (event: IClickHandlerEvent) => void;
46
50
  onClear?: (event: IClickHandlerEvent) => void;
47
51
  }
48
52
 
@@ -57,18 +61,22 @@ export const ControlWrapper: FC<IControlWrapperProps> = ({
57
61
  isFullWidth,
58
62
  isDisabled,
59
63
  hasValue,
64
+ size,
60
65
  testId,
61
66
  children,
62
67
  tweakStyles,
63
68
  data,
64
- onIconClick,
65
69
  onClear,
66
70
  }) => {
67
71
  const classes = useStyles({ theme: tweakStyles });
68
72
 
69
- const hasEndIcon = !isLoading && isReactNodeNotEmpty(icon);
73
+ const icons = getArray(icon).map(convertToControlWrapperIcon);
74
+
75
+ const hasIcons = !isLoading && isArrayNotEmpty(icons);
70
76
  const hasClearButton = !isDisabled && !isLoading && hasValue && isNotEmpty(onClear);
71
- const hasControls = hasEndIcon || hasClearButton || isLoading;
77
+ const hasControls = hasIcons || hasClearButton || isLoading;
78
+
79
+ const isActive = isFocused || hasValue;
72
80
 
73
81
  const tweakPreloaderStyles = useTweakStyles({
74
82
  tweakStyles,
@@ -80,7 +88,8 @@ export const ControlWrapper: FC<IControlWrapperProps> = ({
80
88
  <div
81
89
  className={clsx(
82
90
  classes.controlWrapper,
83
- isNotEmpty(groupPlacement) && [classes[`placement-${groupPlacement}`]],
91
+ isNotEmpty(groupPlacement) && classes[`placement-${groupPlacement}`],
92
+ isNotEmpty(size) && classes[size],
84
93
  {
85
94
  [classes.invalid]: isInvalid,
86
95
  [classes.focused]: isFocused,
@@ -97,7 +106,7 @@ export const ControlWrapper: FC<IControlWrapperProps> = ({
97
106
  className={clsx(classes.label, {
98
107
  [classes.requiredLabel]: isRequired,
99
108
  [classes.disabledLabel]: isDisabled,
100
- [classes.activeLabel]: isFocused || hasValue,
109
+ [classes.activeLabel]: isActive,
101
110
  })}
102
111
  >
103
112
  {label}
@@ -120,18 +129,20 @@ export const ControlWrapper: FC<IControlWrapperProps> = ({
120
129
  </div>
121
130
  )}
122
131
 
123
- {hasEndIcon && (
124
- <div
125
- className={clsx(classes.icon, classes.endIcon, {
126
- [classes.activeIcon]: !isDisabled && isNotEmpty(onIconClick),
127
- [classes.customIcon]: !isString(icon),
128
- })}
129
- {...addClickHandler(onIconClick, !isDisabled)}
130
- {...addDataTestId(testId, 'icon')}
131
- >
132
- <div className={classes.iconInner}>{renderIcon(icon)}</div>
133
- </div>
134
- )}
132
+ {hasIcons &&
133
+ icons.map(({ key, iconComponent, onClick, shouldResetSize = false }, index) => (
134
+ <div
135
+ key={key ?? index}
136
+ className={clsx(classes.icon, classes.endIcon, {
137
+ [classes.activeIcon]: !isDisabled && isNotEmpty(onClick),
138
+ [classes.customIcon]: shouldResetSize,
139
+ })}
140
+ {...addClickHandler(onClick, !isDisabled)}
141
+ {...addDataTestId(testId, 'icon')}
142
+ >
143
+ <div className={classes.iconInner}>{renderIcon(iconComponent)}</div>
144
+ </div>
145
+ ))}
135
146
 
136
147
  {isLoading && (
137
148
  <div
@@ -0,0 +1,11 @@
1
+ import { isObject } from 'lodash-es';
2
+ import { IIcon } from '../Icon';
3
+ import { IControlWrapperIcon } from './types';
4
+
5
+ export const isControlWrapperIcon = (
6
+ iconItem: IIcon | IControlWrapperIcon,
7
+ ): iconItem is IControlWrapperIcon => isObject(iconItem) && 'iconComponent' in iconItem;
8
+
9
+ export const convertToControlWrapperIcon = (
10
+ iconItem: IIcon | IControlWrapperIcon,
11
+ ): IControlWrapperIcon => (isControlWrapperIcon(iconItem) ? iconItem : { iconComponent: iconItem });
@@ -1,2 +1,4 @@
1
1
  export * from './ControlWrapper';
2
+ export * from './helpers';
3
+ export * from './types';
2
4
  export type { IControlWrapperStyles } from './ControlWrapper.styles';
@@ -0,0 +1,16 @@
1
+ import { type Key } from 'react';
2
+ import { IClickHandlerEvent } from '../../types';
3
+ import { IIcon } from '../Icon';
4
+
5
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
6
+ export interface IControlWrapperSizes {}
7
+
8
+ export type IControlWrapperSize = keyof IControlWrapperSizes;
9
+
10
+ // подумать над extend HTMLAttributes<HTMLDivElement>
11
+ export interface IControlWrapperIcon {
12
+ key?: Key;
13
+ iconComponent: IIcon;
14
+ onClick?: (event: IClickHandlerEvent) => void;
15
+ shouldResetSize?: boolean;
16
+ }
@@ -54,7 +54,6 @@ Default.parameters = {
54
54
  'onFocus',
55
55
  'onBlur',
56
56
  'onPaste',
57
- 'onIconClick',
58
57
  'onKeyDown',
59
58
  ],
60
59
  },
@@ -1,6 +1,6 @@
1
- import { ChangeEvent, forwardRef, MouseEvent } from 'react';
1
+ import { ChangeEvent, forwardRef } from 'react';
2
2
  import clsx from 'clsx';
3
- import { addDataAttributes } from '../../helpers';
3
+ import { addDataAttributes } from '@true-engineering/true-react-platform-helpers';
4
4
  import { useTweakStyles } from '../../hooks';
5
5
  import { ICommonProps } from '../../types';
6
6
  import { IChangeInputEvent, IInputProps, Input } from '../Input';
@@ -18,7 +18,6 @@ export interface IDateInputProps
18
18
  className?: string;
19
19
  /** @default false */
20
20
  isRange?: boolean;
21
- onClick?: (event: MouseEvent<HTMLDivElement>) => void;
22
21
  // react-datepicker ожидает event первым аргументом
23
22
  onChange?: (event: IChangeInputEvent, value: string) => void;
24
23
  }
@@ -71,7 +70,7 @@ export const DateInput = forwardRef<HTMLInputElement, IDateInputProps>(
71
70
  };
72
71
 
73
72
  return (
74
- <div className={clsx(classes.root, className)} onClick={onClick} {...addDataAttributes(data)}>
73
+ <div className={clsx(classes.root, className)} {...addDataAttributes(data)} onClick={onClick}>
75
74
  <Input
76
75
  {...inputProps}
77
76
  ref={ref}
@@ -1,5 +1,5 @@
1
1
  import { useState } from 'react';
2
- import ru from 'date-fns/locale/ru';
2
+ import { ru } from 'date-fns/locale';
3
3
  import { ComponentStory } from '@storybook/react';
4
4
  import { DatePicker } from './DatePicker';
5
5
 
@@ -52,6 +52,7 @@ const Template: ComponentStory<typeof DatePicker> = (args) => {
52
52
  selectedDate={date}
53
53
  startDate={startDate}
54
54
  endDate={endDate}
55
+ minDate={new Date()}
55
56
  onChangeDate={setDate}
56
57
  onChangeRange={(dates) => {
57
58
  setStartDate(dates?.[0] ?? null);
@@ -70,19 +71,31 @@ Default.args = {
70
71
  isRange: false,
71
72
  isClearable: true,
72
73
  shouldRenderPopperInBody: false,
74
+ popperPlacement: 'bottom-start',
75
+ };
76
+
77
+ Default.argTypes = {
78
+ popperPlacement: {
79
+ options: [
80
+ 'bottom-start',
81
+ 'bottom',
82
+ 'bottom-end',
83
+ 'top-start',
84
+ 'top',
85
+ 'top-end',
86
+ 'right-start',
87
+ 'right',
88
+ 'right-end',
89
+ 'left-start',
90
+ 'left',
91
+ 'left-end',
92
+ ],
93
+ control: 'select',
94
+ },
73
95
  };
74
96
 
75
97
  Default.parameters = {
76
98
  controls: {
77
- exclude: [
78
- 'data',
79
- 'testId',
80
- 'tabIndex',
81
- 'onFocus',
82
- 'onBlur',
83
- 'onPaste',
84
- 'onIconClick',
85
- 'onKeyDown',
86
- ],
99
+ exclude: ['data', 'testId', 'tabIndex', 'onFocus', 'onBlur', 'onPaste', 'onKeyDown'],
87
100
  },
88
101
  };
@@ -1,4 +1,4 @@
1
- import { ITweakStyles, createThemedStyles } from '../../theme';
1
+ import { createThemedStyles, ITweakStyles } from '../../theme';
2
2
  import { IDateInputStyles } from '../DateInput';
3
3
 
4
4
  export const useStyles = createThemedStyles('DatePicker', {
@@ -9,6 +9,8 @@ export const useStyles = createThemedStyles('DatePicker', {
9
9
 
10
10
  day: {},
11
11
 
12
+ dayInner: {},
13
+
12
14
  datepicker: {},
13
15
 
14
16
  popper: {
@@ -1,26 +1,42 @@
1
- import { FC, FocusEvent, forwardRef, SyntheticEvent, useEffect, useMemo, useState } from 'react';
2
- import ReactDatePicker from 'react-datepicker';
1
+ import {
2
+ FC,
3
+ FocusEvent,
4
+ SyntheticEvent,
5
+ forwardRef,
6
+ useEffect,
7
+ useMemo,
8
+ useRef,
9
+ useState,
10
+ } from 'react';
11
+ import type ReactDatePicker from 'react-datepicker';
3
12
  import 'react-datepicker/dist/react-datepicker.css';
4
13
  import clsx from 'clsx';
5
14
  import { isAfter, isBefore, isValid } from 'date-fns';
6
15
  import {
16
+ addDataAttributes,
7
17
  isEmpty,
8
18
  isNotEmpty,
19
+ isString,
9
20
  isStringNotEmpty,
10
21
  } from '@true-engineering/true-react-platform-helpers';
11
- import { addDataAttributes } from '../../helpers';
12
- import { useTweakStyles } from '../../hooks';
22
+ import { offset } from '@floating-ui/react';
23
+ import { useMergedRefs, useOnClickOutside, useTweakStyles } from '../../hooks';
13
24
  import { ICommonProps } from '../../types';
14
25
  import { DateInput, EMPTY_DATE_INPUT_VALUE, IDateInputProps } from '../DateInput';
15
- import { DatePickerHeader, PopperContainer } from './components';
16
- import { DatePickerComponent, DEFAULT_DATE_FORMAT } from './constants';
26
+ import { DatePickerBase, DatePickerHeader, PopperContainer } from './components';
27
+ import {
28
+ DEFAULT_DATE_FORMAT,
29
+ IDatePickerLocale,
30
+ LocalesMap,
31
+ OUTSIDE_CLICK_IGNORE_CLASS,
32
+ } from './constants';
17
33
  import { areDatesEquals, getDateFormatter, getDateValueParser } from './helpers';
18
34
  import { IDatePickerBaseProps, IRange } from './types';
19
35
  import { IDatePickerStyles, useStyles } from './DatePicker.styles';
20
36
 
21
37
  export interface IDatePickerProps extends IDatePickerBaseProps, ICommonProps<IDatePickerStyles> {
22
38
  selectedDate?: Date | null;
23
- locale: Locale;
39
+ locale: IDatePickerLocale;
24
40
  months?: string[];
25
41
  /** @default 'dd.MM.yyyy' */
26
42
  dateFormat?: string;
@@ -58,7 +74,6 @@ export const DatePicker = forwardRef<ReactDatePicker, IDatePickerProps>(
58
74
  isClearable,
59
75
  strictParsing,
60
76
  fixedHeight,
61
- excludeScrollbar,
62
77
  focusSelectedMonth,
63
78
  disabledKeyboardNavigation,
64
79
  shouldRenderPopperInBody = false,
@@ -66,8 +81,8 @@ export const DatePicker = forwardRef<ReactDatePicker, IDatePickerProps>(
66
81
  shouldCloseOnSelect,
67
82
  showPreviousMonths,
68
83
  preventOpenOnFocus,
69
- popperModifiers,
70
- popperPlacement,
84
+ popperModifiers = [],
85
+ popperPlacement = 'bottom-start',
71
86
  todayButton,
72
87
  highlightDates,
73
88
  calendarContainer,
@@ -106,6 +121,10 @@ export const DatePicker = forwardRef<ReactDatePicker, IDatePickerProps>(
106
121
  [dateFormat],
107
122
  );
108
123
 
124
+ const datePickerRef = useRef<DatePickerBase>();
125
+
126
+ const componentRef = useMergedRefs([ref, datePickerRef]);
127
+
109
128
  const [isOpen, setIsOpen] = useState(false);
110
129
 
111
130
  const [dateValue, setDateValue] = useState(formatDate(selectedDate));
@@ -153,6 +172,7 @@ export const DatePicker = forwardRef<ReactDatePicker, IDatePickerProps>(
153
172
  }
154
173
  };
155
174
 
175
+ // TODO: кажется это можно улучшить, т.к проблему пофиксили (https://github.com/Hacker0x01/react-datepicker/pull/5060)
156
176
  const handleChangeDateRangeInput = (value: string) => {
157
177
  const newStartDateValue = value.slice(0, 10);
158
178
  let newStart = parseDateValue(newStartDateValue);
@@ -236,20 +256,28 @@ export const DatePicker = forwardRef<ReactDatePicker, IDatePickerProps>(
236
256
  setDateRangeValues(startDate, endDate);
237
257
  }, [selectedDate, startDate, endDate]);
238
258
 
259
+ // Кастомный обработчик клика снаружи, чтобы можно было поставить фокус на Input при открытом календаре.
260
+ // Проблема в том, что класс OUTSIDE_CLICK_IGNORE_CLASS висит контейнере Input'а. А react-datepicker
261
+ // проверяет наличие класса непосредственно на элементе, который вызвал клик, но не на его родителях
262
+ useOnClickOutside(
263
+ () => datePickerRef.current?.calendar?.containerRef?.current,
264
+ (event) => datePickerRef.current?.handleClickOutside(event as MouseEvent),
265
+ OUTSIDE_CLICK_IGNORE_CLASS,
266
+ );
267
+
239
268
  return (
240
269
  <div className={classes.root} {...addDataAttributes(data)}>
241
- <DatePickerComponent
242
- ref={ref}
270
+ <DatePickerBase
271
+ ref={componentRef}
243
272
  minDate={minDate}
244
273
  maxDate={maxDate}
245
- locale={locale}
274
+ locale={isString(locale) ? LocalesMap[locale] : locale}
246
275
  dateFormat={dateFormat}
247
276
  placeholderText={placeholder}
248
277
  calendarStartDay={calendarStartDay}
249
278
  inline={isInline}
250
279
  disabled={isDisabled}
251
280
  fixedHeight={fixedHeight}
252
- excludeScrollbar={excludeScrollbar}
253
281
  showPreviousMonths={showPreviousMonths}
254
282
  focusSelectedMonth={focusSelectedMonth}
255
283
  monthsShown={monthsShown}
@@ -260,14 +288,16 @@ export const DatePicker = forwardRef<ReactDatePicker, IDatePickerProps>(
260
288
  dayClassName={(v) => clsx(classes.day, dayClassName?.(v))}
261
289
  disabledKeyboardNavigation={disabledKeyboardNavigation}
262
290
  popperContainer={shouldRenderPopperInBody ? PopperContainer : undefined}
263
- popperModifiers={popperModifiers}
291
+ // Убираем дефолтный отступ в 10px из либы
292
+ // https://github.com/Hacker0x01/react-datepicker/blob/db67a58de2b05d2681bdf0a4977b606095d514c4/src/with_floating.tsx#L58
293
+ popperModifiers={[offset(-10), ...popperModifiers]}
264
294
  popperPlacement={popperPlacement}
265
- selectsRange={isRange}
266
295
  strictParsing={strictParsing}
267
296
  preventOpenOnFocus={preventOpenOnFocus}
268
297
  shouldCloseOnSelect={shouldCloseOnSelect}
269
298
  customInputRef={customInputRef}
270
299
  customInput={<CustomInput {...dateInputProps} />}
300
+ renderDayContents={(day) => <div className={classes.dayInner}>{day}</div>}
271
301
  renderCustomHeader={
272
302
  renderCustomHeader ??
273
303
  ((baseProps) => <DatePickerHeader {...baseProps} months={months} />)
@@ -299,6 +329,7 @@ export const DatePicker = forwardRef<ReactDatePicker, IDatePickerProps>(
299
329
  startDate: start,
300
330
  endDate: end,
301
331
  selected: start,
332
+ selectsRange: true,
302
333
  onBlur: handleDateRangeInputBlur,
303
334
  onChange: handleChangeRange,
304
335
  }
@@ -0,0 +1,14 @@
1
+ import ReactDatePicker, { DatePickerProps } from 'react-datepicker';
2
+ import { doNothing } from '@true-engineering/true-react-platform-helpers';
3
+
4
+ export class DatePickerBase extends ReactDatePicker {
5
+ public handleClickOutside;
6
+
7
+ constructor(props: DatePickerProps) {
8
+ super(props);
9
+ this.handleClickOutside = this.handleCalendarClickOutside;
10
+ // Затираем дефолтный обработчик клика снаружи, чтобы обрабатывать его самим
11
+ // (см. использование useOnClickOutside в DatePicker)
12
+ this.handleCalendarClickOutside = doNothing;
13
+ }
14
+ }
@@ -0,0 +1 @@
1
+ export * from './DatePickerBase';
@@ -1,6 +1,6 @@
1
- import { FC, ReactElement, ReactNode } from 'react';
2
- import { Portal } from 'react-overlays';
1
+ import { FC, PropsWithChildren } from 'react';
2
+ import { FloatingPortal } from '@floating-ui/react';
3
3
 
4
- export const PopperContainer: FC<{ children: ReactNode }> = ({ children }) => (
5
- <Portal container={document.body}>{children as ReactElement}</Portal>
4
+ export const PopperContainer: FC<PropsWithChildren> = (props) => (
5
+ <FloatingPortal root={document.body} {...props} />
6
6
  );
@@ -1,2 +1,3 @@
1
+ export * from './DatePickerBase';
1
2
  export * from './DatePickerHeader';
2
3
  export * from './PopperContainer';
@@ -1,6 +1,12 @@
1
- import ReactDatePicker from 'react-datepicker';
1
+ import { enUS as enLocale, ru as ruLocale, type Locale } from 'date-fns/locale';
2
2
 
3
3
  export const DEFAULT_DATE_FORMAT = 'dd.MM.yyyy';
4
4
 
5
- export const DatePickerComponent =
6
- (ReactDatePicker as unknown as { default: typeof ReactDatePicker }).default ?? ReactDatePicker;
5
+ export const OUTSIDE_CLICK_IGNORE_CLASS = 'react-datepicker-ignore-onclickoutside';
6
+
7
+ export const LocalesMap = {
8
+ ru: ruLocale,
9
+ en: enLocale,
10
+ } satisfies Record<string, Locale>;
11
+
12
+ export type IDatePickerLocale = keyof typeof LocalesMap | Locale;
@@ -1,4 +1,4 @@
1
- import { parse, format, isSameDay } from 'date-fns';
1
+ import { format, isSameDay, parse } from 'date-fns';
2
2
  import {
3
3
  isEmpty,
4
4
  isNotEmpty,
@@ -1,4 +1,5 @@
1
1
  export * from './DatePicker';
2
2
  export * from './types';
3
+ export type { IDatePickerLocale } from './constants';
3
4
  export type { IDatePickerStyles } from './DatePicker.styles';
4
5
  export type { IDatePickerHeaderStyles } from './components';
@@ -1,10 +1,10 @@
1
- import { ReactDatePickerProps } from 'react-datepicker';
2
- import { IDateInputProps } from '../DateInput';
1
+ import { type DatePickerProps } from 'react-datepicker';
2
+ import { type IDateInputProps } from '../DateInput';
3
3
 
4
4
  export type IRange = [Date | null, Date | null] | null;
5
5
 
6
6
  export type IDatePickerBaseProps = Pick<
7
- ReactDatePickerProps,
7
+ DatePickerProps,
8
8
  | 'startDate'
9
9
  | 'endDate'
10
10
  | 'minDate'
@@ -31,7 +31,8 @@ export type IDatePickerBaseProps = Pick<
31
31
  | 'strictParsing'
32
32
  | 'highlightDates'
33
33
  | 'fixedHeight'
34
- | 'excludeScrollbar'
34
+ | 'swapRange'
35
+ | 'onKeyDown'
35
36
  > &
36
37
  Omit<
37
38
  IDateInputProps,
@@ -45,4 +46,5 @@ export type IDatePickerBaseProps = Pick<
45
46
  | 'onChange'
46
47
  | 'onClick'
47
48
  | 'tweakStyles'
49
+ | 'onKeyDown'
48
50
  >;