@true-engineering/true-react-common-ui-kit 4.0.0-alpha2 → 4.0.0-alpha20

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 (209) 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 +3 -3
  9. package/dist/components/DatePicker/DatePicker.styles.d.ts +1 -1
  10. package/dist/components/DatePicker/components/PopperContainer/PopperContainer.d.ts +2 -4
  11. package/dist/components/DatePicker/helpers.d.ts +3 -0
  12. package/dist/components/DatePicker/types.d.ts +5 -3
  13. package/dist/components/FiltersPane/FiltersPane.d.ts +7 -2
  14. package/dist/components/FiltersPane/components/Filter/Filter.d.ts +2 -2
  15. package/dist/components/FiltersPane/components/Filter/helpers.d.ts +4 -0
  16. package/dist/components/FiltersPane/components/FilterInterval/FilterInterval.styles.d.ts +1 -1
  17. package/dist/components/FiltersPane/components/FilterSelect/FilterSelect.styles.d.ts +1 -1
  18. package/dist/components/FiltersPane/components/FilterValueView/FilterValueView.d.ts +3 -1
  19. package/dist/components/FiltersPane/components/FilterWithDates/FilterWithDates.styles.d.ts +2 -2
  20. package/dist/components/FiltersPane/components/FilterWrapper/FilterWrapper.d.ts +2 -2
  21. package/dist/components/FiltersPane/types.d.ts +15 -5
  22. package/dist/components/Flag/customFlags/customFlags.d.ts +10 -0
  23. package/dist/components/Flag/customFlags/index.d.ts +1 -0
  24. package/dist/components/FlexibleTable/FlexibleTable.d.ts +4 -2
  25. package/dist/components/FlexibleTable/components/FlexibleTableCell/FlexibleTableCell.d.ts +4 -3
  26. package/dist/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.d.ts +6 -6
  27. package/dist/components/FlexibleTable/constants.d.ts +18 -2
  28. package/dist/components/FlexibleTable/types.d.ts +8 -8
  29. package/dist/components/Icon/icons-list.d.ts +1 -1
  30. package/dist/components/IconButton/IconButton.styles.d.ts +1 -1
  31. package/dist/components/Input/Input.d.ts +3 -2
  32. package/dist/components/Input/InputBase.d.ts +2 -2
  33. package/dist/components/List/List.d.ts +1 -1
  34. package/dist/components/List/index.d.ts +2 -1
  35. package/dist/components/List/types.d.ts +4 -0
  36. package/dist/components/Modal/Modal.styles.d.ts +1 -1
  37. package/dist/components/Notification/Notification.styles.d.ts +1 -1
  38. package/dist/components/ScrollIntoViewIfNeeded/ScrollIntoViewIfNeeded.d.ts +1 -1
  39. package/dist/components/SearchInput/SearchInput.d.ts +2 -2
  40. package/dist/components/Select/Select.d.ts +5 -3
  41. package/dist/components/Select/Select.styles.d.ts +4 -4
  42. package/dist/components/Select/index.d.ts +1 -1
  43. package/dist/components/Status/Status.styles.d.ts +3 -2
  44. package/dist/components/Status/constants.d.ts +0 -1
  45. package/dist/components/Status/index.d.ts +1 -0
  46. package/dist/components/Status/types.d.ts +5 -2
  47. package/dist/components/TextArea/TextArea.d.ts +2 -5
  48. package/dist/components/TextArea/TextArea.styles.d.ts +1 -2
  49. package/dist/components/TextArea/index.d.ts +0 -1
  50. package/dist/components/TextButton/TextButton.styles.d.ts +1 -1
  51. package/dist/components/Tooltip/Tooltip.d.ts +1 -1
  52. package/dist/components/Tooltip/Tooltip.styles.d.ts +1 -1
  53. package/dist/components/WithMessages/WithMessages.styles.d.ts +1 -1
  54. package/dist/components/WithPopup/WithPopup.d.ts +21 -6
  55. package/dist/components/WithPopup/WithPopup.styles.d.ts +1 -1
  56. package/dist/components/WithPopup/helpers.d.ts +2 -0
  57. package/dist/components/WithPopup/types.d.ts +3 -0
  58. package/dist/components/WithTooltip/WithTooltip.styles.d.ts +1 -0
  59. package/dist/hooks/index.d.ts +1 -0
  60. package/dist/hooks/use-merge.d.ts +1 -0
  61. package/dist/hooks/use-mixed-styles.d.ts +3 -1
  62. package/dist/hooks/use-tweak-styles.d.ts +5 -5
  63. package/dist/style.css +78 -142
  64. package/dist/theme/Provider.d.ts +6 -3
  65. package/dist/theme/common.d.ts +4 -2
  66. package/dist/theme/create-themed-styles.d.ts +2 -0
  67. package/dist/theme/helpers.d.ts +9 -3
  68. package/dist/theme/index.d.ts +2 -0
  69. package/dist/theme/true-jss/ThemedStylesManager.d.ts +18 -0
  70. package/dist/theme/true-jss/TweakStylesManager.d.ts +34 -0
  71. package/dist/theme/true-jss/index.d.ts +2 -0
  72. package/dist/theme/true-jss/jss-context.d.ts +9 -0
  73. package/dist/theme/types.d.ts +5 -3
  74. package/dist/true-react-common-ui-kit.js +7519 -6456
  75. package/dist/true-react-common-ui-kit.js.map +1 -1
  76. package/dist/true-react-common-ui-kit.umd.cjs +7455 -6393
  77. package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
  78. package/dist/types.d.ts +10 -3
  79. package/package.json +4 -5
  80. package/src/components/ControlWrapper/ControlWrapper.styles.ts +7 -6
  81. package/src/components/ControlWrapper/ControlWrapper.tsx +8 -2
  82. package/src/components/ControlWrapper/index.ts +1 -0
  83. package/src/components/ControlWrapper/types.ts +4 -0
  84. package/src/components/DatePicker/DatePicker.stories.tsx +2 -1
  85. package/src/components/DatePicker/DatePicker.styles.ts +3 -1
  86. package/src/components/DatePicker/DatePicker.tsx +12 -7
  87. package/src/components/DatePicker/components/PopperContainer/PopperContainer.tsx +4 -4
  88. package/src/components/DatePicker/helpers.ts +13 -1
  89. package/src/components/DatePicker/types.ts +9 -4
  90. package/src/components/FiltersPane/FiltersPane.stories.tsx +4 -2
  91. package/src/components/FiltersPane/FiltersPane.tsx +19 -13
  92. package/src/components/FiltersPane/components/Filter/Filter.tsx +24 -17
  93. package/src/components/FiltersPane/components/Filter/helpers.ts +18 -0
  94. package/src/components/FiltersPane/components/FilterValueView/FilterValueView.tsx +27 -22
  95. package/src/components/FiltersPane/components/FilterWithDates/FilterWithDates.styles.ts +1 -0
  96. package/src/components/FiltersPane/components/FilterWithDates/FilterWithDates.tsx +3 -4
  97. package/src/components/FiltersPane/components/FilterWithPeriod/FilterWithPeriod.tsx +1 -1
  98. package/src/components/FiltersPane/components/FilterWrapper/FilterWrapper.tsx +7 -5
  99. package/src/components/FiltersPane/types.ts +23 -5
  100. package/src/components/Flag/Flag.stories.tsx +2 -1
  101. package/src/components/Flag/Flag.styles.ts +4 -0
  102. package/src/components/Flag/Flag.tsx +23 -9
  103. package/src/components/Flag/customFlags/AB.svg +1 -0
  104. package/src/components/Flag/customFlags/OS.svg +1 -0
  105. package/src/components/Flag/customFlags/augment.d.ts +1 -0
  106. package/src/components/Flag/customFlags/customFlags.ts +13 -0
  107. package/src/components/Flag/customFlags/index.ts +1 -0
  108. package/src/components/FlexibleTable/FlexibleTable.tsx +13 -12
  109. package/src/components/FlexibleTable/components/FlexibleTableCell/FlexibleTableCell.tsx +8 -5
  110. package/src/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.tsx +13 -12
  111. package/src/components/FlexibleTable/constants.ts +6 -3
  112. package/src/components/FlexibleTable/types.ts +8 -12
  113. package/src/components/Input/Input.tsx +5 -3
  114. package/src/components/Input/InputBase.tsx +27 -24
  115. package/src/components/List/List.tsx +5 -2
  116. package/src/components/List/index.ts +2 -1
  117. package/src/components/List/types.ts +5 -0
  118. package/src/components/NumberInput/NumberInput.stories.tsx +5 -1
  119. package/src/components/PhoneInput/PhoneInput.stories.tsx +2 -1
  120. package/src/components/PhoneInput/PhoneInput.tsx +5 -2
  121. package/src/components/SearchInput/SearchInput.tsx +20 -29
  122. package/src/components/Select/Select.tsx +12 -2
  123. package/src/components/Select/components/SelectList/SelectList.tsx +1 -1
  124. package/src/components/Select/index.ts +1 -1
  125. package/src/components/Status/Status.stories.tsx +54 -1
  126. package/src/components/Status/Status.styles.ts +2 -37
  127. package/src/components/Status/constants.ts +0 -10
  128. package/src/components/Status/index.ts +1 -1
  129. package/src/components/Status/types.ts +7 -3
  130. package/src/components/TextArea/TextArea.styles.ts +2 -6
  131. package/src/components/TextArea/TextArea.tsx +41 -20
  132. package/src/components/TextArea/index.ts +0 -1
  133. package/src/components/TextButton/TextButton.styles.ts +1 -0
  134. package/src/components/Tooltip/Tooltip.styles.ts +2 -0
  135. package/src/components/Tooltip/Tooltip.tsx +1 -1
  136. package/src/components/WithPopup/WithPopup.stories.tsx +1 -0
  137. package/src/components/WithPopup/WithPopup.styles.ts +2 -0
  138. package/src/components/WithPopup/WithPopup.tsx +64 -16
  139. package/src/components/WithPopup/helpers.ts +9 -0
  140. package/src/components/WithPopup/types.ts +7 -0
  141. package/src/components/WithTooltip/WithTooltip.styles.ts +6 -0
  142. package/src/components/WithTooltip/WithTooltip.tsx +7 -2
  143. package/src/constants/phone-info.ts +20 -33
  144. package/src/helpers/phone.ts +19 -15
  145. package/src/hooks/index.ts +1 -0
  146. package/src/hooks/use-merge.ts +8 -0
  147. package/src/hooks/use-mixed-styles.ts +9 -11
  148. package/src/hooks/use-tweak-styles.ts +49 -27
  149. package/src/theme/Provider.tsx +10 -5
  150. package/src/theme/common.ts +5 -2
  151. package/src/theme/create-themed-styles.ts +78 -0
  152. package/src/theme/helpers.ts +39 -39
  153. package/src/theme/index.ts +2 -0
  154. package/src/theme/true-jss/ThemedStylesManager.ts +92 -0
  155. package/src/theme/true-jss/TweakStylesManager.ts +157 -0
  156. package/src/theme/true-jss/index.ts +2 -0
  157. package/src/theme/true-jss/jss-context.tsx +34 -0
  158. package/src/theme/types.ts +5 -3
  159. package/src/types.ts +17 -4
  160. package/dist/components/AccountInfo/AccountInfo.stories.d.ts +0 -6
  161. package/dist/components/AddButton/AddButton.stories.d.ts +0 -6
  162. package/dist/components/Button/Button.stories.d.ts +0 -6
  163. package/dist/components/Checkbox/Checkbox.stories.d.ts +0 -8
  164. package/dist/components/CloseButton/CloseButton.stories.d.ts +0 -5
  165. package/dist/components/Colors/Colors.stories.d.ts +0 -5
  166. package/dist/components/ControlWrapper/ControlWrapper.stories.d.ts +0 -6
  167. package/dist/components/DateInput/DateInput.stories.d.ts +0 -7
  168. package/dist/components/DatePicker/DatePicker.stories.d.ts +0 -7
  169. package/dist/components/Description/Description.stories.d.ts +0 -16
  170. package/dist/components/FileInput/FileInput.stories.d.ts +0 -7
  171. package/dist/components/FileItem/FileItem.stories.d.ts +0 -8
  172. package/dist/components/FiltersPane/FiltersPane.stories.d.ts +0 -31
  173. package/dist/components/Flag/Flag.stories.d.ts +0 -12
  174. package/dist/components/FlexibleTable/FlexibleTable.stories.d.ts +0 -19
  175. package/dist/components/Icon/Icon.stories.d.ts +0 -6
  176. package/dist/components/IconButton/IconButton.stories.d.ts +0 -6
  177. package/dist/components/IncrementInput/IncrementInput.stories.d.ts +0 -6
  178. package/dist/components/Input/Input.stories.d.ts +0 -25
  179. package/dist/components/List/List.stories.d.ts +0 -5
  180. package/dist/components/Modal/Modal.stories.d.ts +0 -29
  181. package/dist/components/MoreMenu/MoreMenu.stories.d.ts +0 -6
  182. package/dist/components/MultiSelect/MultiSelect.stories.d.ts +0 -13
  183. package/dist/components/NewMoreMenu/NewMoreMenu.stories.d.ts +0 -12
  184. package/dist/components/Notification/Notification.stories.d.ts +0 -8
  185. package/dist/components/NumberInput/NumberInput.stories.d.ts +0 -7
  186. package/dist/components/PhoneInput/PhoneInput.stories.d.ts +0 -28
  187. package/dist/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.stories.d.ts +0 -5
  188. package/dist/components/RadioButton/RadioButton.stories.d.ts +0 -7
  189. package/dist/components/SearchInput/SearchInput.stories.d.ts +0 -6
  190. package/dist/components/Select/CustomSelect.stories.d.ts +0 -11
  191. package/dist/components/Select/MultiSelect.stories.d.ts +0 -15
  192. package/dist/components/Select/Select.stories.d.ts +0 -15
  193. package/dist/components/Selector/Selector.stories.d.ts +0 -7
  194. package/dist/components/Skeleton/Skeleton.stories.d.ts +0 -6
  195. package/dist/components/SmartInput/SmartInput.stories.d.ts +0 -18
  196. package/dist/components/Status/Status.stories.d.ts +0 -6
  197. package/dist/components/Switch/Switch.stories.d.ts +0 -16
  198. package/dist/components/TextArea/TextArea.stories.d.ts +0 -17
  199. package/dist/components/TextArea/types.d.ts +0 -2
  200. package/dist/components/TextButton/TextButton.stories.d.ts +0 -6
  201. package/dist/components/TextWithInfo/TextWithInfo.stories.d.ts +0 -12
  202. package/dist/components/TextWithTooltip/TextWithTooltip.stories.d.ts +0 -24
  203. package/dist/components/ThemedPreloader/ThemedPreloader.stories.d.ts +0 -17
  204. package/dist/components/Toaster/Toaster.stories.d.ts +0 -5
  205. package/dist/components/Tooltip/Tooltip.stories.d.ts +0 -5
  206. package/dist/components/WithMessages/WithMessages.stories.d.ts +0 -7
  207. package/dist/components/WithPopup/WithPopup.stories.d.ts +0 -16
  208. package/dist/components/WithTooltip/WithTooltip.stories.d.ts +0 -6
  209. package/src/components/TextArea/types.ts +0 -6
@@ -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 => {
@@ -5,3 +5,4 @@ export * from './use-tweak-styles';
5
5
  export * from './use-did-mount-effect';
6
6
  export * from './use-mixed-styles';
7
7
  export * from './use-merged-refs';
8
+ export * from './use-merge';
@@ -0,0 +1,8 @@
1
+ import { useMemo } from 'react';
2
+ import { isNotEmpty, mergeStyles } from '@true-engineering/true-react-platform-helpers';
3
+
4
+ export const useMerge = <T>(one?: T, two?: T): T | undefined =>
5
+ useMemo(
6
+ () => (isNotEmpty(one) && isNotEmpty(two) ? mergeStyles(one, two) : one ?? two),
7
+ [one, two],
8
+ );
@@ -1,14 +1,12 @@
1
1
  import { useMemo } from 'react';
2
- import { isNotEmpty, mergeStyles } from '@true-engineering/true-react-platform-helpers';
2
+ import { isObject } from '@true-engineering/true-react-platform-helpers';
3
+ import type { IMixedStyles } from '../theme';
4
+
5
+ export const mixStyles = <T>(...tweakStyles: Array<IMixedStyles<T>>): Array<NonNullable<T>> =>
6
+ tweakStyles.flat().filter(isObject) as Array<NonNullable<T>>;
3
7
 
4
8
  export const useMixedStyles = <StyleSheet>(
5
- baseStyles?: StyleSheet,
6
- tweakStyles?: StyleSheet,
7
- ): StyleSheet | undefined =>
8
- useMemo(
9
- () =>
10
- isNotEmpty(baseStyles) && isNotEmpty(tweakStyles)
11
- ? mergeStyles(baseStyles, tweakStyles)
12
- : baseStyles ?? tweakStyles,
13
- [baseStyles, tweakStyles],
14
- );
9
+ baseStyles?: IMixedStyles<StyleSheet>,
10
+ tweakStyles?: IMixedStyles<StyleSheet>,
11
+ ): Array<NonNullable<StyleSheet>> =>
12
+ useMemo(() => mixStyles(baseStyles, tweakStyles), [baseStyles, tweakStyles]);
@@ -1,11 +1,24 @@
1
- import { useMemo } from 'react';
2
- import { isEmpty, isNotEmpty, mergeStyles } from '@true-engineering/true-react-platform-helpers';
3
- import { areStylesThemed, getTheme, IComponentName, themedStyles } from '../theme';
1
+ import { useContext, useMemo } from 'react';
2
+ import {
3
+ isArrayNotEmpty,
4
+ isNotEmpty,
5
+ mergeStyles,
6
+ } from '@true-engineering/true-react-platform-helpers';
7
+ import {
8
+ areStylesThemed,
9
+ themedStyles,
10
+ IComponentName,
11
+ IMaybeArray,
12
+ useTheme,
13
+ JssContext,
14
+ IMixedStyles,
15
+ } from '../theme';
16
+ import { mixStyles } from './use-mixed-styles';
4
17
 
5
18
  // TODO: Можно усилить типы
6
19
  export const useTweakStyles = <StyleSheet, ClassName extends keyof StyleSheet & `tweak${string}`>({
7
20
  innerStyles,
8
- tweakStyles: currentComponentTweakStyles,
21
+ tweakStyles,
9
22
  className,
10
23
  currentComponentName,
11
24
  }: {
@@ -13,12 +26,12 @@ export const useTweakStyles = <StyleSheet, ClassName extends keyof StyleSheet &
13
26
  * Это tweakStyles, определенные в родительском компоненте
14
27
  * (например, стили для Input, определенные в стилях компонента Select)
15
28
  */
16
- innerStyles?: StyleSheet[ClassName];
29
+ innerStyles?: IMixedStyles<StyleSheet[ClassName]>;
17
30
  /**
18
31
  * Пропса tweakStyles из родительского компонента
19
32
  * (это уже непосредственно ISelectProps.tweakStyles)
20
33
  */
21
- tweakStyles?: StyleSheet;
34
+ tweakStyles?: IMaybeArray<StyleSheet>;
22
35
  /**
23
36
  * Класс для переопределения tweakStyles из-вне. (Например, 'tweakInput')
24
37
  */
@@ -27,31 +40,40 @@ export const useTweakStyles = <StyleSheet, ClassName extends keyof StyleSheet &
27
40
  * Название компонента который вызывает useTweakStyles. (В данном примере 'Select')
28
41
  */
29
42
  currentComponentName?: IComponentName;
30
- }): StyleSheet[ClassName] =>
31
- useMemo(() => {
32
- const theme = getTheme();
33
- // tweakStyles, переопределенные в теме родительского компонента
43
+ }): Array<NonNullable<StyleSheet[ClassName]>> => {
44
+ const theme = useTheme();
45
+ const isMergeDisabled = isNotEmpty(useContext(JssContext).tweakStylesArch);
46
+
47
+ return useMemo(() => {
34
48
  const themeStyles = isNotEmpty(currentComponentName)
35
- ? (theme.components?.[currentComponentName]?.[className as never] as StyleSheet[ClassName])
49
+ ? (theme.components?.[currentComponentName] as StyleSheet)
36
50
  : undefined;
37
- const tweakStyles = currentComponentTweakStyles?.[className];
38
51
 
39
- // Если нечего мержить
40
- const styles = [innerStyles, tweakStyles, themeStyles].filter(isNotEmpty);
41
- if (styles.length <= 1) {
42
- return styles[0];
52
+ const resultStyles = mixStyles(
53
+ innerStyles,
54
+ mixStyles(themeStyles, tweakStyles).map((style) => style[className]),
55
+ );
56
+
57
+ if (isMergeDisabled || resultStyles.length < 2) {
58
+ return resultStyles;
59
+ }
60
+
61
+ const [maybeInnerStyles, maybeThemeStyles, ...rest] = resultStyles;
62
+
63
+ if (
64
+ maybeThemeStyles !== themeStyles?.[className] || // Если нет themeStyles или innerStyles
65
+ isArrayNotEmpty(rest) // Или есть tweakStyles
66
+ ) {
67
+ // Мёржим как есть
68
+ return [mergeStyles(maybeInnerStyles, maybeThemeStyles, ...rest)];
43
69
  }
44
70
 
45
- // Мы можем подмержить тему в innerStyles, чтобы сохранить кэширование
46
- if (isNotEmpty(innerStyles) && isNotEmpty(themeStyles) && isEmpty(tweakStyles)) {
47
- return areStylesThemed(innerStyles) ? innerStyles : themedStyles(innerStyles, themeStyles);
71
+ // Иначе мёржим themeStyles в innerStyles
72
+ if (!areStylesThemed(maybeInnerStyles)) {
73
+ themedStyles(maybeInnerStyles, maybeThemeStyles);
48
74
  }
49
75
 
50
- // Ну тут уже прощай кэш
51
- return mergeStyles(innerStyles, themeStyles, tweakStyles);
52
- }, [
53
- innerStyles,
54
- className,
55
- currentComponentName,
56
- currentComponentTweakStyles,
57
- ]) as StyleSheet[ClassName];
76
+ // И возвращаем только innerStyles
77
+ return [maybeInnerStyles];
78
+ }, [innerStyles, className, currentComponentName, tweakStyles, theme, isMergeDisabled]);
79
+ };
@@ -1,6 +1,6 @@
1
- import { createContext, FC, ReactNode } from 'react';
1
+ import { createContext, FC, ReactNode, useContext, useMemo } from 'react';
2
2
  import { common } from './common';
3
- import { IUiKitTheme } from './types';
3
+ import type { IUiKitTheme } from './types';
4
4
 
5
5
  export interface IThemedProviderProps {
6
6
  theme: IUiKitTheme;
@@ -11,11 +11,16 @@ let globalTheme: IUiKitTheme;
11
11
 
12
12
  export const getTheme = (): IUiKitTheme => globalTheme;
13
13
 
14
- export const ThemeContext = createContext<{
14
+ interface ThemeContextValue {
15
15
  theme: IUiKitTheme;
16
- }>({ theme: common });
16
+ }
17
+
18
+ export const ThemeContext = createContext<ThemeContextValue>({ theme: common });
17
19
 
18
20
  export const ThemeProvider: FC<IThemedProviderProps> = ({ theme, children }) => {
19
21
  globalTheme = theme;
20
- return <ThemeContext.Provider value={{ theme }}>{children}</ThemeContext.Provider>;
22
+ const value: ThemeContextValue = useMemo(() => ({ theme }), [theme]);
23
+ return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;
21
24
  };
25
+
26
+ export const useTheme = (): IUiKitTheme => useContext(ThemeContext).theme;
@@ -91,9 +91,12 @@ export const helpers = {
91
91
 
92
92
  // Chromium
93
93
  '@supports selector(::-webkit-scrollbar)': {
94
+ '--webkit-scrollbar-width': '10px',
95
+ '--webkit-scrollbar-height': '10px',
96
+
94
97
  '&::-webkit-scrollbar': {
95
- height: 10,
96
- width: 10,
98
+ width: 'var(--webkit-scrollbar-width)',
99
+ height: 'var(--webkit-scrollbar-height)',
97
100
 
98
101
  '&-thumb': {
99
102
  width: 6,
@@ -0,0 +1,78 @@
1
+ import { useContext, useInsertionEffect, useMemo } from 'react';
2
+ import { createUseStyles, Styles } from 'react-jss';
3
+ import { isNotEmpty, mergeStyles } from '@true-engineering/true-react-platform-helpers';
4
+ import { mixStyles } from '../hooks/use-mixed-styles';
5
+ import { getTheme, useTheme } from './Provider';
6
+ import {
7
+ checkStyles,
8
+ cleanStyles,
9
+ getTweakStylesCache,
10
+ isStylesNotEmpty,
11
+ mergeTweakStyles,
12
+ } from './helpers';
13
+ import { ThemedStylesManager, JssContext } from './true-jss';
14
+ import { IComponentName, IStyles, IUseStyles } from './types';
15
+
16
+ const DEFAULT_NAME = 'LocalComponent';
17
+
18
+ export function createThemedStyles<C extends string>(
19
+ ...args: [IStyles<C>] | [IComponentName, IStyles<C>]
20
+ ): IUseStyles<C> {
21
+ const [componentName, styles] = args.length === 2 ? args : [undefined, args[0]];
22
+ const name = componentName ?? DEFAULT_NAME;
23
+
24
+ if (process.env.NODE_ENV !== 'production') {
25
+ checkStyles(name, styles);
26
+ }
27
+
28
+ const tweakStylesManager = new ThemedStylesManager({ styles, name });
29
+ const tweakStylesCache = getTweakStylesCache();
30
+
31
+ const useStyles = createUseStyles<C>((tweakStyles) => {
32
+ const theme = getTheme();
33
+ return mergeStyles(
34
+ styles as Styles<C>,
35
+ isNotEmpty(componentName) ? (theme?.components?.[componentName] as Styles<C>) : undefined,
36
+ tweakStyles,
37
+ );
38
+ });
39
+
40
+ return (data) => {
41
+ const jssContext = useContext(JssContext);
42
+
43
+ const tweakStyles = useMemo(
44
+ () => mixStyles(data?.theme).filter(isStylesNotEmpty),
45
+ [data?.theme],
46
+ );
47
+
48
+ if (jssContext.tweakStylesArch !== 'true-jss') {
49
+ const tweakStylesStrategy =
50
+ jssContext.tweakStylesArch === 'react-jss' ? tweakStylesCache : mergeTweakStyles;
51
+
52
+ const theme = useMemo(
53
+ () => cleanStyles(tweakStylesStrategy(tweakStyles)),
54
+ [tweakStylesStrategy, tweakStyles],
55
+ );
56
+
57
+ return useStyles(isNotEmpty(data) ? { ...data, theme } : data);
58
+ }
59
+
60
+ const { components } = useTheme();
61
+
62
+ const themeStyles = isNotEmpty(componentName) ? components?.[componentName] : undefined;
63
+
64
+ const classes = tweakStylesManager.getClasses(themeStyles, tweakStyles, jssContext);
65
+
66
+ useInsertionEffect(() => {
67
+ const unmanage = tweakStylesManager.manage(themeStyles);
68
+ return unmanage;
69
+ }, [themeStyles]);
70
+
71
+ useInsertionEffect(() => {
72
+ const unmanage = tweakStylesManager.manageTweak(themeStyles, tweakStyles);
73
+ return unmanage;
74
+ }, [themeStyles, classes]);
75
+
76
+ return classes;
77
+ };
78
+ }