@vkontakte/vkui 6.7.3 → 6.7.4

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 (253) hide show
  1. package/dist/cjs/components/BaseGallery/BaseGallery.d.ts.map +1 -1
  2. package/dist/cjs/components/BaseGallery/BaseGallery.js +5 -2
  3. package/dist/cjs/components/BaseGallery/BaseGallery.js.map +1 -1
  4. package/dist/cjs/components/Calendar/Calendar.d.ts +6 -6
  5. package/dist/cjs/components/Calendar/Calendar.d.ts.map +1 -1
  6. package/dist/cjs/components/Calendar/Calendar.js +25 -5
  7. package/dist/cjs/components/Calendar/Calendar.js.map +1 -1
  8. package/dist/cjs/components/CalendarDay/CalendarDay.d.ts +4 -1
  9. package/dist/cjs/components/CalendarDay/CalendarDay.d.ts.map +1 -1
  10. package/dist/cjs/components/CalendarDay/CalendarDay.js +5 -3
  11. package/dist/cjs/components/CalendarDay/CalendarDay.js.map +1 -1
  12. package/dist/cjs/components/CalendarDays/CalendarDays.d.ts +6 -3
  13. package/dist/cjs/components/CalendarDays/CalendarDays.d.ts.map +1 -1
  14. package/dist/cjs/components/CalendarDays/CalendarDays.js +5 -3
  15. package/dist/cjs/components/CalendarDays/CalendarDays.js.map +1 -1
  16. package/dist/cjs/components/CalendarHeader/CalendarHeader.d.ts +8 -2
  17. package/dist/cjs/components/CalendarHeader/CalendarHeader.d.ts.map +1 -1
  18. package/dist/cjs/components/CalendarHeader/CalendarHeader.js +14 -6
  19. package/dist/cjs/components/CalendarHeader/CalendarHeader.js.map +1 -1
  20. package/dist/cjs/components/CalendarRange/CalendarRange.d.ts +8 -4
  21. package/dist/cjs/components/CalendarRange/CalendarRange.d.ts.map +1 -1
  22. package/dist/cjs/components/CalendarRange/CalendarRange.js +13 -8
  23. package/dist/cjs/components/CalendarRange/CalendarRange.js.map +1 -1
  24. package/dist/cjs/components/CalendarTime/CalendarTime.d.ts +9 -2
  25. package/dist/cjs/components/CalendarTime/CalendarTime.d.ts.map +1 -1
  26. package/dist/cjs/components/CalendarTime/CalendarTime.js +10 -5
  27. package/dist/cjs/components/CalendarTime/CalendarTime.js.map +1 -1
  28. package/dist/cjs/components/Clickable/useState.d.ts +1 -1
  29. package/dist/cjs/components/Clickable/useState.d.ts.map +1 -1
  30. package/dist/cjs/components/Clickable/useState.js +12 -19
  31. package/dist/cjs/components/Clickable/useState.js.map +1 -1
  32. package/dist/cjs/components/DateInput/DateInput.d.ts +12 -3
  33. package/dist/cjs/components/DateInput/DateInput.d.ts.map +1 -1
  34. package/dist/cjs/components/DateInput/DateInput.js +26 -11
  35. package/dist/cjs/components/DateInput/DateInput.js.map +1 -1
  36. package/dist/cjs/components/DateRangeInput/DateRangeInput.d.ts +15 -3
  37. package/dist/cjs/components/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  38. package/dist/cjs/components/DateRangeInput/DateRangeInput.js +22 -11
  39. package/dist/cjs/components/DateRangeInput/DateRangeInput.js.map +1 -1
  40. package/dist/cjs/components/FocusTrap/FocusTrap.d.ts +1 -1
  41. package/dist/cjs/components/FocusTrap/FocusTrap.d.ts.map +1 -1
  42. package/dist/cjs/components/FocusTrap/FocusTrap.js +50 -41
  43. package/dist/cjs/components/FocusTrap/FocusTrap.js.map +1 -1
  44. package/dist/cjs/components/Gallery/Gallery.d.ts +1 -1
  45. package/dist/cjs/components/Gallery/Gallery.d.ts.map +1 -1
  46. package/dist/cjs/components/Gallery/Gallery.js +12 -3
  47. package/dist/cjs/components/Gallery/Gallery.js.map +1 -1
  48. package/dist/cjs/components/Gallery/hooks.d.ts +9 -1
  49. package/dist/cjs/components/Gallery/hooks.d.ts.map +1 -1
  50. package/dist/cjs/components/Gallery/hooks.js +43 -25
  51. package/dist/cjs/components/Gallery/hooks.js.map +1 -1
  52. package/dist/cjs/components/HorizontalScroll/HorizontalScroll.d.ts.map +1 -1
  53. package/dist/cjs/components/HorizontalScroll/HorizontalScroll.js +19 -26
  54. package/dist/cjs/components/HorizontalScroll/HorizontalScroll.js.map +1 -1
  55. package/dist/cjs/components/Popover/Popover.js +1 -1
  56. package/dist/cjs/components/Popover/Popover.js.map +1 -1
  57. package/dist/cjs/hooks/useDateInput.d.ts +2 -1
  58. package/dist/cjs/hooks/useDateInput.d.ts.map +1 -1
  59. package/dist/cjs/hooks/useDateInput.js +29 -9
  60. package/dist/cjs/hooks/useDateInput.js.map +1 -1
  61. package/dist/cjs/lib/floating/customResizeObserver.d.ts.map +1 -1
  62. package/dist/cjs/lib/floating/customResizeObserver.js +0 -1
  63. package/dist/cjs/lib/floating/customResizeObserver.js.map +1 -1
  64. package/dist/cjs/lib/floating/types/component.d.ts +2 -2
  65. package/dist/cjs/lib/floating/types/component.d.ts.map +1 -1
  66. package/dist/cjs/lib/floating/useFloatingWithInteractions/index.d.ts +1 -0
  67. package/dist/cjs/lib/floating/useFloatingWithInteractions/index.d.ts.map +1 -1
  68. package/dist/cjs/lib/floating/useFloatingWithInteractions/index.js.map +1 -1
  69. package/dist/cjs/lib/floating/useFloatingWithInteractions/types.d.ts +2 -1
  70. package/dist/cjs/lib/floating/useFloatingWithInteractions/types.d.ts.map +1 -1
  71. package/dist/cjs/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.d.ts.map +1 -1
  72. package/dist/cjs/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js +14 -1
  73. package/dist/cjs/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js.map +1 -1
  74. package/dist/components/BaseGallery/BaseGallery.d.ts.map +1 -1
  75. package/dist/components/BaseGallery/BaseGallery.js +5 -2
  76. package/dist/components/BaseGallery/BaseGallery.js.map +1 -1
  77. package/dist/components/Calendar/Calendar.d.ts +6 -6
  78. package/dist/components/Calendar/Calendar.d.ts.map +1 -1
  79. package/dist/components/Calendar/Calendar.js +25 -5
  80. package/dist/components/Calendar/Calendar.js.map +1 -1
  81. package/dist/components/CalendarDay/CalendarDay.d.ts +4 -1
  82. package/dist/components/CalendarDay/CalendarDay.d.ts.map +1 -1
  83. package/dist/components/CalendarDay/CalendarDay.js +5 -3
  84. package/dist/components/CalendarDay/CalendarDay.js.map +1 -1
  85. package/dist/components/CalendarDays/CalendarDays.d.ts +6 -3
  86. package/dist/components/CalendarDays/CalendarDays.d.ts.map +1 -1
  87. package/dist/components/CalendarDays/CalendarDays.js +5 -3
  88. package/dist/components/CalendarDays/CalendarDays.js.map +1 -1
  89. package/dist/components/CalendarHeader/CalendarHeader.d.ts +8 -2
  90. package/dist/components/CalendarHeader/CalendarHeader.d.ts.map +1 -1
  91. package/dist/components/CalendarHeader/CalendarHeader.js +14 -6
  92. package/dist/components/CalendarHeader/CalendarHeader.js.map +1 -1
  93. package/dist/components/CalendarRange/CalendarRange.d.ts +8 -4
  94. package/dist/components/CalendarRange/CalendarRange.d.ts.map +1 -1
  95. package/dist/components/CalendarRange/CalendarRange.js +13 -8
  96. package/dist/components/CalendarRange/CalendarRange.js.map +1 -1
  97. package/dist/components/CalendarTime/CalendarTime.d.ts +9 -2
  98. package/dist/components/CalendarTime/CalendarTime.d.ts.map +1 -1
  99. package/dist/components/CalendarTime/CalendarTime.js +10 -5
  100. package/dist/components/CalendarTime/CalendarTime.js.map +1 -1
  101. package/dist/components/Clickable/useState.d.ts +1 -1
  102. package/dist/components/Clickable/useState.d.ts.map +1 -1
  103. package/dist/components/Clickable/useState.js +12 -19
  104. package/dist/components/Clickable/useState.js.map +1 -1
  105. package/dist/components/DateInput/DateInput.d.ts +12 -3
  106. package/dist/components/DateInput/DateInput.d.ts.map +1 -1
  107. package/dist/components/DateInput/DateInput.js +26 -11
  108. package/dist/components/DateInput/DateInput.js.map +1 -1
  109. package/dist/components/DateRangeInput/DateRangeInput.d.ts +15 -3
  110. package/dist/components/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  111. package/dist/components/DateRangeInput/DateRangeInput.js +22 -11
  112. package/dist/components/DateRangeInput/DateRangeInput.js.map +1 -1
  113. package/dist/components/FocusTrap/FocusTrap.d.ts +1 -1
  114. package/dist/components/FocusTrap/FocusTrap.d.ts.map +1 -1
  115. package/dist/components/FocusTrap/FocusTrap.js +51 -42
  116. package/dist/components/FocusTrap/FocusTrap.js.map +1 -1
  117. package/dist/components/Gallery/Gallery.d.ts +1 -1
  118. package/dist/components/Gallery/Gallery.d.ts.map +1 -1
  119. package/dist/components/Gallery/Gallery.js +12 -3
  120. package/dist/components/Gallery/Gallery.js.map +1 -1
  121. package/dist/components/Gallery/hooks.d.ts +9 -1
  122. package/dist/components/Gallery/hooks.d.ts.map +1 -1
  123. package/dist/components/Gallery/hooks.js +43 -25
  124. package/dist/components/Gallery/hooks.js.map +1 -1
  125. package/dist/components/HorizontalScroll/HorizontalScroll.d.ts.map +1 -1
  126. package/dist/components/HorizontalScroll/HorizontalScroll.js +20 -27
  127. package/dist/components/HorizontalScroll/HorizontalScroll.js.map +1 -1
  128. package/dist/components/Popover/Popover.js +1 -1
  129. package/dist/components/Popover/Popover.js.map +1 -1
  130. package/dist/components.css +1 -1
  131. package/dist/components.css.map +1 -1
  132. package/dist/components.js.tmp +374 -212
  133. package/dist/cssm/components/BaseGallery/BaseGallery.d.ts.map +1 -1
  134. package/dist/cssm/components/BaseGallery/BaseGallery.js +3 -1
  135. package/dist/cssm/components/BaseGallery/BaseGallery.js.map +1 -1
  136. package/dist/cssm/components/Calendar/Calendar.d.ts +6 -6
  137. package/dist/cssm/components/Calendar/Calendar.d.ts.map +1 -1
  138. package/dist/cssm/components/Calendar/Calendar.js +14 -4
  139. package/dist/cssm/components/Calendar/Calendar.js.map +1 -1
  140. package/dist/cssm/components/CalendarDay/CalendarDay.d.ts +4 -1
  141. package/dist/cssm/components/CalendarDay/CalendarDay.d.ts.map +1 -1
  142. package/dist/cssm/components/CalendarDay/CalendarDay.js +2 -1
  143. package/dist/cssm/components/CalendarDay/CalendarDay.js.map +1 -1
  144. package/dist/cssm/components/CalendarDays/CalendarDays.d.ts +6 -3
  145. package/dist/cssm/components/CalendarDays/CalendarDays.d.ts.map +1 -1
  146. package/dist/cssm/components/CalendarDays/CalendarDays.js +2 -1
  147. package/dist/cssm/components/CalendarDays/CalendarDays.js.map +1 -1
  148. package/dist/cssm/components/CalendarHeader/CalendarHeader.d.ts +8 -2
  149. package/dist/cssm/components/CalendarHeader/CalendarHeader.d.ts.map +1 -1
  150. package/dist/cssm/components/CalendarHeader/CalendarHeader.js +7 -3
  151. package/dist/cssm/components/CalendarHeader/CalendarHeader.js.map +1 -1
  152. package/dist/cssm/components/CalendarRange/CalendarRange.d.ts +8 -4
  153. package/dist/cssm/components/CalendarRange/CalendarRange.d.ts.map +1 -1
  154. package/dist/cssm/components/CalendarRange/CalendarRange.js +9 -5
  155. package/dist/cssm/components/CalendarRange/CalendarRange.js.map +1 -1
  156. package/dist/cssm/components/CalendarTime/CalendarTime.d.ts +9 -2
  157. package/dist/cssm/components/CalendarTime/CalendarTime.d.ts.map +1 -1
  158. package/dist/cssm/components/CalendarTime/CalendarTime.js +10 -5
  159. package/dist/cssm/components/CalendarTime/CalendarTime.js.map +1 -1
  160. package/dist/cssm/components/CalendarTime/CalendarTime.module.css +4 -0
  161. package/dist/cssm/components/Clickable/useState.d.ts +1 -1
  162. package/dist/cssm/components/Clickable/useState.d.ts.map +1 -1
  163. package/dist/cssm/components/Clickable/useState.js +10 -11
  164. package/dist/cssm/components/Clickable/useState.js.map +1 -1
  165. package/dist/cssm/components/DateInput/DateInput.d.ts +12 -3
  166. package/dist/cssm/components/DateInput/DateInput.d.ts.map +1 -1
  167. package/dist/cssm/components/DateInput/DateInput.js +18 -9
  168. package/dist/cssm/components/DateInput/DateInput.js.map +1 -1
  169. package/dist/cssm/components/DateRangeInput/DateRangeInput.d.ts +15 -3
  170. package/dist/cssm/components/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  171. package/dist/cssm/components/DateRangeInput/DateRangeInput.js +17 -9
  172. package/dist/cssm/components/DateRangeInput/DateRangeInput.js.map +1 -1
  173. package/dist/cssm/components/FocusTrap/FocusTrap.d.ts +1 -1
  174. package/dist/cssm/components/FocusTrap/FocusTrap.d.ts.map +1 -1
  175. package/dist/cssm/components/FocusTrap/FocusTrap.js +51 -42
  176. package/dist/cssm/components/FocusTrap/FocusTrap.js.map +1 -1
  177. package/dist/cssm/components/Gallery/Gallery.d.ts +1 -1
  178. package/dist/cssm/components/Gallery/Gallery.d.ts.map +1 -1
  179. package/dist/cssm/components/Gallery/Gallery.js +9 -2
  180. package/dist/cssm/components/Gallery/Gallery.js.map +1 -1
  181. package/dist/cssm/components/Gallery/hooks.d.ts +9 -1
  182. package/dist/cssm/components/Gallery/hooks.d.ts.map +1 -1
  183. package/dist/cssm/components/Gallery/hooks.js +43 -25
  184. package/dist/cssm/components/Gallery/hooks.js.map +1 -1
  185. package/dist/cssm/components/HorizontalScroll/HorizontalScroll.d.ts.map +1 -1
  186. package/dist/cssm/components/HorizontalScroll/HorizontalScroll.js +20 -27
  187. package/dist/cssm/components/HorizontalScroll/HorizontalScroll.js.map +1 -1
  188. package/dist/cssm/components/Popover/Popover.js +1 -1
  189. package/dist/cssm/components/Popover/Popover.js.map +1 -1
  190. package/dist/cssm/hooks/useDateInput.d.ts +2 -1
  191. package/dist/cssm/hooks/useDateInput.d.ts.map +1 -1
  192. package/dist/cssm/hooks/useDateInput.js +30 -9
  193. package/dist/cssm/hooks/useDateInput.js.map +1 -1
  194. package/dist/cssm/lib/floating/customResizeObserver.d.ts.map +1 -1
  195. package/dist/cssm/lib/floating/customResizeObserver.js +0 -1
  196. package/dist/cssm/lib/floating/customResizeObserver.js.map +1 -1
  197. package/dist/cssm/lib/floating/types/component.d.ts +2 -2
  198. package/dist/cssm/lib/floating/types/component.d.ts.map +1 -1
  199. package/dist/cssm/lib/floating/types/component.js.map +1 -1
  200. package/dist/cssm/lib/floating/useFloatingWithInteractions/index.d.ts +1 -0
  201. package/dist/cssm/lib/floating/useFloatingWithInteractions/index.d.ts.map +1 -1
  202. package/dist/cssm/lib/floating/useFloatingWithInteractions/index.js.map +1 -1
  203. package/dist/cssm/lib/floating/useFloatingWithInteractions/types.d.ts +2 -1
  204. package/dist/cssm/lib/floating/useFloatingWithInteractions/types.d.ts.map +1 -1
  205. package/dist/cssm/lib/floating/useFloatingWithInteractions/types.js.map +1 -1
  206. package/dist/cssm/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.d.ts.map +1 -1
  207. package/dist/cssm/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js +14 -1
  208. package/dist/cssm/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js.map +1 -1
  209. package/dist/hooks/useDateInput.d.ts +2 -1
  210. package/dist/hooks/useDateInput.d.ts.map +1 -1
  211. package/dist/hooks/useDateInput.js +30 -9
  212. package/dist/hooks/useDateInput.js.map +1 -1
  213. package/dist/lib/floating/customResizeObserver.d.ts.map +1 -1
  214. package/dist/lib/floating/customResizeObserver.js +0 -1
  215. package/dist/lib/floating/customResizeObserver.js.map +1 -1
  216. package/dist/lib/floating/types/component.d.ts +2 -2
  217. package/dist/lib/floating/types/component.d.ts.map +1 -1
  218. package/dist/lib/floating/types/component.js.map +1 -1
  219. package/dist/lib/floating/useFloatingWithInteractions/index.d.ts +1 -0
  220. package/dist/lib/floating/useFloatingWithInteractions/index.d.ts.map +1 -1
  221. package/dist/lib/floating/useFloatingWithInteractions/index.js.map +1 -1
  222. package/dist/lib/floating/useFloatingWithInteractions/types.d.ts +2 -1
  223. package/dist/lib/floating/useFloatingWithInteractions/types.d.ts.map +1 -1
  224. package/dist/lib/floating/useFloatingWithInteractions/types.js.map +1 -1
  225. package/dist/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.d.ts.map +1 -1
  226. package/dist/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js +14 -1
  227. package/dist/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js.map +1 -1
  228. package/dist/vkui.css +1 -1
  229. package/dist/vkui.css.map +1 -1
  230. package/dist/vkui.js.tmp +374 -212
  231. package/package.json +1 -1
  232. package/src/components/BaseGallery/BaseGallery.tsx +8 -1
  233. package/src/components/Calendar/Calendar.tsx +49 -6
  234. package/src/components/CalendarDay/CalendarDay.tsx +7 -1
  235. package/src/components/CalendarDays/CalendarDays.tsx +9 -1
  236. package/src/components/CalendarHeader/CalendarHeader.tsx +21 -1
  237. package/src/components/CalendarRange/CalendarRange.tsx +24 -3
  238. package/src/components/CalendarTime/CalendarTime.module.css +4 -0
  239. package/src/components/CalendarTime/CalendarTime.tsx +39 -10
  240. package/src/components/Clickable/useState.tsx +30 -27
  241. package/src/components/DateInput/DateInput.tsx +32 -3
  242. package/src/components/DateRangeInput/DateRangeInput.tsx +28 -1
  243. package/src/components/FocusTrap/FocusTrap.tsx +75 -45
  244. package/src/components/Gallery/Gallery.tsx +10 -1
  245. package/src/components/Gallery/hooks.ts +49 -33
  246. package/src/components/HorizontalScroll/HorizontalScroll.tsx +23 -28
  247. package/src/components/Popover/Popover.tsx +1 -1
  248. package/src/hooks/useDateInput.ts +23 -6
  249. package/src/lib/floating/customResizeObserver.ts +0 -1
  250. package/src/lib/floating/types/component.ts +2 -1
  251. package/src/lib/floating/useFloatingWithInteractions/index.ts +2 -0
  252. package/src/lib/floating/useFloatingWithInteractions/types.ts +3 -1
  253. package/src/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.ts +15 -3
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { Icon16Clear, Icon20CalendarOutline } from '@vkontakte/icons';
3
3
  import { classNames } from '@vkontakte/vkjs';
4
+ import { startOfDay, startOfMinute } from 'date-fns';
4
5
  import { useAdaptivity } from '../../hooks/useAdaptivity';
5
6
  import { useDateInput } from '../../hooks/useDateInput';
6
7
  import { useExternRef } from '../../hooks/useExternRef';
@@ -8,7 +9,7 @@ import { callMultiple } from '../../lib/callMultiple';
8
9
  import { format, isMatch, parse } from '../../lib/date';
9
10
  import type { PlacementWithAuto } from '../../lib/floating';
10
11
  import type { HasRootRef } from '../../types';
11
- import { Calendar, type CalendarProps } from '../Calendar/Calendar';
12
+ import { Calendar, type CalendarProps, type CalendarTestsProps } from '../Calendar/Calendar';
12
13
  import { FormField, type FormFieldProps } from '../FormField/FormField';
13
14
  import { IconButton } from '../IconButton/IconButton';
14
15
  import { InputLike } from '../InputLike/InputLike';
@@ -23,6 +24,14 @@ const sizeYClassNames = {
23
24
  compact: styles['DateInput--sizeY-compact'],
24
25
  };
25
26
 
27
+ export type DateInputPropsTestsProps = {
28
+ dayFieldTestId?: string;
29
+ monthFieldTestId?: string;
30
+ yearFieldTestId?: string;
31
+ hourFieldTestId?: string;
32
+ minuteFieldTestId?: string;
33
+ };
34
+
26
35
  export interface DateInputProps
27
36
  extends Omit<React.InputHTMLAttributes<HTMLDivElement>, 'value' | 'onChange' | 'size'>,
28
37
  Pick<
@@ -56,12 +65,15 @@ export interface DateInputProps
56
65
  | 'renderDayContent'
57
66
  >,
58
67
  HasRootRef<HTMLDivElement>,
59
- Omit<FormFieldProps, 'maxHeight'> {
68
+ Omit<FormFieldProps, 'maxHeight'>,
69
+ DateInputPropsTestsProps {
70
+ calendarTestsProps?: CalendarTestsProps;
60
71
  calendarPlacement?: PlacementWithAuto;
61
72
  closeOnChange?: boolean;
62
73
  clearFieldLabel?: string;
63
74
  showCalendarLabel?: string;
64
75
  disableCalendar?: boolean;
76
+ onCalendarOpenChanged?: (opened: boolean) => void;
65
77
  }
66
78
 
67
79
  const elementsConfig = (index: number) => {
@@ -147,6 +159,13 @@ export const DateInput = ({
147
159
  nextMonthIcon,
148
160
  disableCalendar = false,
149
161
  renderDayContent,
162
+ onCalendarOpenChanged,
163
+ calendarTestsProps,
164
+ dayFieldTestId,
165
+ monthFieldTestId,
166
+ yearFieldTestId,
167
+ hourFieldTestId,
168
+ minuteFieldTestId,
150
169
  ...props
151
170
  }: DateInputProps): React.ReactNode => {
152
171
  const daysRef = React.useRef<HTMLSpanElement>(null);
@@ -173,7 +192,10 @@ export const DateInput = ({
173
192
  }
174
193
 
175
194
  if (isMatch(formattedValue, mask)) {
176
- onChange?.(parse(formattedValue, mask, value ?? new Date()));
195
+ const now = new Date();
196
+ onChange?.(
197
+ parse(formattedValue, mask, value ?? (enableTime ? startOfMinute(now) : startOfDay(now))),
198
+ );
177
199
  }
178
200
  },
179
201
  [enableTime, maxElement, onChange, value],
@@ -205,6 +227,7 @@ export const DateInput = ({
205
227
  onInternalValueChange,
206
228
  getInternalValue,
207
229
  value,
230
+ onCalendarOpenChanged,
208
231
  });
209
232
 
210
233
  const { sizeY = 'none' } = useAdaptivity();
@@ -262,6 +285,7 @@ export const DateInput = ({
262
285
  onElementSelect={setFocusedElement}
263
286
  value={internalValue[0]}
264
287
  label={changeDayLabel}
288
+ data-testid={dayFieldTestId}
265
289
  />
266
290
  <InputLikeDivider>.</InputLikeDivider>
267
291
  <InputLike
@@ -271,6 +295,7 @@ export const DateInput = ({
271
295
  onElementSelect={setFocusedElement}
272
296
  value={internalValue[1]}
273
297
  label={changeMonthLabel}
298
+ data-testid={monthFieldTestId}
274
299
  />
275
300
  <InputLikeDivider>.</InputLikeDivider>
276
301
  <InputLike
@@ -280,6 +305,7 @@ export const DateInput = ({
280
305
  onElementSelect={setFocusedElement}
281
306
  value={internalValue[2]}
282
307
  label={changeYearLabel}
308
+ data-testid={yearFieldTestId}
283
309
  />
284
310
  {enableTime && (
285
311
  <React.Fragment>
@@ -293,6 +319,7 @@ export const DateInput = ({
293
319
  onElementSelect={setFocusedElement}
294
320
  value={internalValue[3]}
295
321
  label={changeHoursLabel}
322
+ data-testid={hourFieldTestId}
296
323
  />
297
324
  <InputLikeDivider>:</InputLikeDivider>
298
325
  <InputLike
@@ -302,6 +329,7 @@ export const DateInput = ({
302
329
  onElementSelect={setFocusedElement}
303
330
  value={internalValue[4]}
304
331
  label={changeMinutesLabel}
332
+ data-testid={minuteFieldTestId}
305
333
  />
306
334
  </React.Fragment>
307
335
  )}
@@ -342,6 +370,7 @@ export const DateInput = ({
342
370
  nextMonthIcon={nextMonthIcon}
343
371
  minDateTime={minDateTime}
344
372
  maxDateTime={maxDateTime}
373
+ {...calendarTestsProps}
345
374
  />
346
375
  </Popper>
347
376
  )}
@@ -12,6 +12,7 @@ import type { HasRootRef } from '../../types';
12
12
  import {
13
13
  CalendarRange,
14
14
  type CalendarRangeProps,
15
+ type CalendarRangeTestsProps,
15
16
  type DateRangeType,
16
17
  } from '../CalendarRange/CalendarRange';
17
18
  import { FormField, type FormFieldProps } from '../FormField/FormField';
@@ -29,6 +30,17 @@ const sizeYClassNames = {
29
30
  compact: styles['DateRangeInput--sizeY-compact'],
30
31
  };
31
32
 
33
+ type DateTestsProps = {
34
+ day?: string;
35
+ month?: string;
36
+ year?: string;
37
+ };
38
+
39
+ export type DateRangeInputTestsProps = {
40
+ startDateTestsProps?: DateTestsProps;
41
+ endDateTestsProps?: DateTestsProps;
42
+ };
43
+
32
44
  export interface DateRangeInputProps
33
45
  extends Omit<React.InputHTMLAttributes<HTMLDivElement>, 'value' | 'onChange'>,
34
46
  Pick<
@@ -50,9 +62,12 @@ export interface DateRangeInputProps
50
62
  | 'renderDayContent'
51
63
  >,
52
64
  HasRootRef<HTMLDivElement>,
53
- Omit<FormFieldProps, 'maxHeight'> {
65
+ Omit<FormFieldProps, 'maxHeight'>,
66
+ DateRangeInputTestsProps {
67
+ calendarTestsProps?: CalendarRangeTestsProps;
54
68
  calendarPlacement?: PlacementWithAuto;
55
69
  closeOnChange?: boolean;
70
+ onCalendarOpenChanged?: (opened: boolean) => void;
56
71
  clearFieldLabel?: string;
57
72
  showCalendarLabel?: string;
58
73
  changeStartDayLabel?: string;
@@ -140,7 +155,11 @@ export const DateRangeInput = ({
140
155
  prevMonthIcon,
141
156
  nextMonthIcon,
142
157
  disableCalendar = false,
158
+ onCalendarOpenChanged,
143
159
  renderDayContent,
160
+ calendarTestsProps,
161
+ startDateTestsProps,
162
+ endDateTestsProps,
144
163
  ...props
145
164
  }: DateRangeInputProps): React.ReactNode => {
146
165
  const daysStartRef = React.useRef<HTMLSpanElement>(null);
@@ -221,6 +240,7 @@ export const DateRangeInput = ({
221
240
  onInternalValueChange,
222
241
  getInternalValue,
223
242
  value,
243
+ onCalendarOpenChanged,
224
244
  });
225
245
 
226
246
  const { sizeY = 'none' } = useAdaptivity();
@@ -279,6 +299,7 @@ export const DateRangeInput = ({
279
299
  onElementSelect={setFocusedElement}
280
300
  value={internalValue[0]}
281
301
  label={changeStartDayLabel}
302
+ data-testid={startDateTestsProps?.day}
282
303
  />
283
304
  <InputLikeDivider>.</InputLikeDivider>
284
305
  <InputLike
@@ -288,6 +309,7 @@ export const DateRangeInput = ({
288
309
  onElementSelect={setFocusedElement}
289
310
  value={internalValue[1]}
290
311
  label={changeStartMonthLabel}
312
+ data-testid={startDateTestsProps?.month}
291
313
  />
292
314
  <InputLikeDivider>.</InputLikeDivider>
293
315
  <InputLike
@@ -297,6 +319,7 @@ export const DateRangeInput = ({
297
319
  onElementSelect={setFocusedElement}
298
320
  value={internalValue[2]}
299
321
  label={changeStartYearLabel}
322
+ data-testid={startDateTestsProps?.year}
300
323
  />
301
324
  <InputLikeDivider>{' — '}</InputLikeDivider>
302
325
  <InputLike
@@ -306,6 +329,7 @@ export const DateRangeInput = ({
306
329
  onElementSelect={setFocusedElement}
307
330
  value={internalValue[3]}
308
331
  label={changeEndDayLabel}
332
+ data-testid={endDateTestsProps?.day}
309
333
  />
310
334
  <InputLikeDivider>.</InputLikeDivider>
311
335
  <InputLike
@@ -315,6 +339,7 @@ export const DateRangeInput = ({
315
339
  onElementSelect={setFocusedElement}
316
340
  value={internalValue[4]}
317
341
  label={changeEndMonthLabel}
342
+ data-testid={endDateTestsProps?.month}
318
343
  />
319
344
  <InputLikeDivider>.</InputLikeDivider>
320
345
  <InputLike
@@ -324,6 +349,7 @@ export const DateRangeInput = ({
324
349
  onElementSelect={setFocusedElement}
325
350
  value={internalValue[5]}
326
351
  label={changeEndYearLabel}
352
+ data-testid={endDateTestsProps?.year}
327
353
  />
328
354
  </Text>
329
355
  {open && !disableCalendar && (
@@ -345,6 +371,7 @@ export const DateRangeInput = ({
345
371
  prevMonthIcon={prevMonthIcon}
346
372
  nextMonthIcon={nextMonthIcon}
347
373
  renderDayContent={renderDayContent}
374
+ {...calendarTestsProps}
348
375
  />
349
376
  </Popper>
350
377
  )}
@@ -1,7 +1,8 @@
1
- import { type AllHTMLAttributes, useCallback, useRef, useState } from 'react';
1
+ import { type AllHTMLAttributes, type RefObject, useRef, useState } from 'react';
2
2
  import { arraysEquals } from '../../helpers/array';
3
3
  import { useExternRef } from '../../hooks/useExternRef';
4
4
  import { useMutationObserver } from '../../hooks/useMutationObserver';
5
+ import { useStableCallback } from '../../hooks/useStableCallback';
5
6
  import { FOCUSABLE_ELEMENTS_LIST, Keys, pressedKey } from '../../lib/accessibility';
6
7
  import {
7
8
  contains,
@@ -14,12 +15,78 @@ import { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';
14
15
  import type { HasComponent, HasRootRef } from '../../types';
15
16
 
16
17
  const FOCUSABLE_ELEMENTS: string = FOCUSABLE_ELEMENTS_LIST.join();
18
+
19
+ const useRestoreFocus = ({
20
+ restoreFocus,
21
+ timeout,
22
+ mount,
23
+ ref,
24
+ }: Pick<FocusTrapProps, 'restoreFocus' | 'timeout' | 'mount'> & {
25
+ ref: RefObject<HTMLElement | null>;
26
+ }) => {
27
+ const restoreFocusRef = useRef(restoreFocus);
28
+ restoreFocusRef.current = restoreFocus;
29
+ const [restoreFocusTo, setRestoreFocusTo] = useState<Element | null>(null);
30
+
31
+ const restoreFocusImpl = useStableCallback(() => {
32
+ const shouldRestoreFocus =
33
+ typeof restoreFocusRef.current === 'function'
34
+ ? restoreFocusRef.current()
35
+ : restoreFocusRef.current;
36
+
37
+ if (!shouldRestoreFocus) {
38
+ return;
39
+ }
40
+
41
+ setTimeout(() => {
42
+ const restoreFocusElement =
43
+ (isHTMLElement(shouldRestoreFocus) && shouldRestoreFocus) ||
44
+ (isHTMLElement(restoreFocusTo) && restoreFocusTo) ||
45
+ null;
46
+
47
+ if (restoreFocusElement) {
48
+ restoreFocusElement.focus();
49
+ setRestoreFocusTo(null);
50
+ }
51
+ }, timeout);
52
+ });
53
+
54
+ useIsomorphicLayoutEffect(
55
+ function calculateRestoreFocusTo() {
56
+ if (!ref.current || !restoreFocusRef.current || !mount) {
57
+ setRestoreFocusTo(null);
58
+ return;
59
+ }
60
+ setRestoreFocusTo(getActiveElementByAnotherElement(ref.current));
61
+ },
62
+ [ref, mount],
63
+ );
64
+
65
+ useIsomorphicLayoutEffect(
66
+ function tryToRestoreFocusOnUnmount() {
67
+ return () => {
68
+ restoreFocusImpl();
69
+ };
70
+ },
71
+ [restoreFocusImpl],
72
+ );
73
+
74
+ useIsomorphicLayoutEffect(
75
+ function tryToRestoreFocusWhenFakeUnmount() {
76
+ if (!mount) {
77
+ restoreFocusImpl();
78
+ }
79
+ },
80
+ [mount, restoreFocusImpl],
81
+ );
82
+ };
83
+
17
84
  export interface FocusTrapProps<T extends HTMLElement = HTMLElement>
18
85
  extends Omit<AllHTMLAttributes<T>, 'autoFocus'>,
19
86
  HasRootRef<T>,
20
87
  HasComponent {
21
88
  autoFocus?: boolean | 'root';
22
- restoreFocus?: boolean | (() => boolean);
89
+ restoreFocus?: boolean | (() => boolean | HTMLElement);
23
90
  mount?: boolean;
24
91
  timeout?: number;
25
92
  onClose?: () => void;
@@ -49,7 +116,12 @@ export const FocusTrap = <T extends HTMLElement = HTMLElement>({
49
116
 
50
117
  const focusableNodesRef = useRef<HTMLElement[]>([]);
51
118
 
52
- const [restoreFocusTo, setRestoreFocusTo] = useState<Element | null>(null);
119
+ useRestoreFocus({
120
+ restoreFocus,
121
+ timeout,
122
+ mount,
123
+ ref,
124
+ });
53
125
 
54
126
  const focusNodeByIndex = (nodeIndex: number) => {
55
127
  const element = focusableNodesRef.current[nodeIndex];
@@ -131,48 +203,6 @@ export const FocusTrap = <T extends HTMLElement = HTMLElement>({
131
203
  [autoFocus, timeout, disabled],
132
204
  );
133
205
 
134
- const restoreFocusImpl = useCallback(() => {
135
- const shouldRestoreFocus = typeof restoreFocus === 'function' ? restoreFocus() : restoreFocus;
136
-
137
- if (!restoreFocusTo || !isHTMLElement(restoreFocusTo) || !shouldRestoreFocus) {
138
- return;
139
- }
140
-
141
- setTimeout(() => {
142
- if (restoreFocusTo) {
143
- restoreFocusTo.focus();
144
- setRestoreFocusTo(null);
145
- }
146
- }, timeout);
147
- }, [restoreFocus, restoreFocusTo, timeout]);
148
-
149
- useIsomorphicLayoutEffect(
150
- function calculateRestoreFocusTo() {
151
- if (!ref.current || !restoreFocus || !mount) {
152
- setRestoreFocusTo(null);
153
- return;
154
- }
155
- setRestoreFocusTo(getActiveElementByAnotherElement(ref.current));
156
- },
157
- [ref, mount, restoreFocus],
158
- );
159
-
160
- useIsomorphicLayoutEffect(
161
- function tryToRestoreFocusOnUnmount() {
162
- return () => restoreFocusImpl();
163
- },
164
- [restoreFocusImpl],
165
- );
166
-
167
- useIsomorphicLayoutEffect(
168
- function tryToRestoreFocusWhenFakeUnmount() {
169
- if (!mount) {
170
- restoreFocusImpl();
171
- }
172
- },
173
- [mount, restoreFocusImpl],
174
- );
175
-
176
206
  useIsomorphicLayoutEffect(() => {
177
207
  if (!ref.current) {
178
208
  return;
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { clamp } from '../../helpers/math';
3
3
  import { useIsClient } from '../../hooks/useIsClient';
4
+ import { callMultiple } from '../../lib/callMultiple';
4
5
  import { BaseGallery } from '../BaseGallery/BaseGallery';
5
6
  import { CarouselBase } from '../BaseGallery/CarouselBase/CarouselBase';
6
7
  import type { BaseGalleryProps } from '../BaseGallery/types';
@@ -23,6 +24,8 @@ export const Gallery = ({
23
24
  onChange,
24
25
  bullets,
25
26
  looped,
27
+ onDragStart,
28
+ onDragEnd,
26
29
  ...props
27
30
  }: GalleryProps): React.ReactNode => {
28
31
  const [localSlideIndex, setSlideIndex] = React.useState(initialSlideIndex);
@@ -46,7 +49,11 @@ export const Gallery = ({
46
49
  [isControlled, onChange, slideIndex],
47
50
  );
48
51
 
49
- useAutoPlay(timeout, slideIndex, () => handleChange((slideIndex + 1) % childCount));
52
+ const autoPlayControls = useAutoPlay({
53
+ timeout,
54
+ slideIndex,
55
+ onNext: () => handleChange((slideIndex + 1) % childCount),
56
+ });
50
57
 
51
58
  // prevent invalid slideIndex
52
59
  // any slide index is invalid with no slides, just keep it as is
@@ -69,6 +76,8 @@ export const Gallery = ({
69
76
  <Component
70
77
  dragDisabled={isControlled && !onChange}
71
78
  {...props}
79
+ onDragStart={callMultiple(onDragStart, autoPlayControls.pause)}
80
+ onDragEnd={callMultiple(onDragEnd, autoPlayControls.resume)}
72
81
  bullets={childCount > 0 && bullets}
73
82
  slideIndex={safeSlideIndex}
74
83
  onChange={handleChange}
@@ -3,49 +3,65 @@ import { useStableCallback } from '../../hooks/useStableCallback';
3
3
  import { useDOM } from '../../lib/dom';
4
4
  import type { TimeoutId } from '../../types';
5
5
 
6
- export function useAutoPlay(
7
- timeout: number,
8
- slideIndex: number,
9
- callbackFnProp: VoidFunction,
10
- ): void {
6
+ export interface AutoPlayConfig {
7
+ timeout: number;
8
+ slideIndex: number;
9
+ onNext: VoidFunction;
10
+ }
11
+
12
+ export function useAutoPlay({ timeout, slideIndex, onNext }: AutoPlayConfig): {
13
+ pause: VoidFunction;
14
+ resume: VoidFunction;
15
+ } {
11
16
  const { document } = useDOM();
12
- const callbackFn = useStableCallback(callbackFnProp);
17
+ const [paused, setPaused] = React.useState(false);
18
+ const timeoutRef = React.useRef<TimeoutId>(null);
19
+ const callbackFn = useStableCallback(onNext);
13
20
 
14
- React.useEffect(
15
- function initializeAutoPlay() {
16
- if (!document || !timeout) {
17
- return;
18
- }
21
+ const pause = React.useCallback(() => setPaused(true), []);
22
+ const resume = React.useCallback(() => setPaused(false), []);
19
23
 
20
- let timeoutId: TimeoutId = null;
24
+ // Выносим функции очистки и старта таймера в отдельные функции
25
+ const clearAutoPlayTimeout = React.useCallback(() => {
26
+ if (timeoutRef.current) {
27
+ clearTimeout(timeoutRef.current);
28
+ timeoutRef.current = null;
29
+ }
30
+ }, []);
21
31
 
22
- const stop = () => {
23
- if (timeoutId) {
24
- clearTimeout(timeoutId);
25
- timeoutId = null;
26
- }
27
- };
32
+ const startAutoPlayTimeout = React.useCallback(() => {
33
+ if (!document || !timeout || paused) {
34
+ return;
35
+ }
28
36
 
29
- const start = () => {
30
- switch (document.visibilityState) {
31
- case 'visible':
32
- stop();
33
- timeoutId = setTimeout(callbackFn, timeout);
34
- break;
35
- case 'hidden':
36
- stop();
37
- }
38
- };
37
+ if (document.visibilityState === 'visible') {
38
+ clearAutoPlayTimeout();
39
+ timeoutRef.current = setTimeout(callbackFn, timeout);
40
+ } else {
41
+ clearAutoPlayTimeout();
42
+ }
43
+ }, [document, timeout, paused, clearAutoPlayTimeout, callbackFn]);
39
44
 
40
- start();
45
+ // Основной эффект для управления автопроигрыванием
46
+ React.useEffect(
47
+ function initializeAutoPlay() {
48
+ if (!document || !timeout || paused) {
49
+ return;
50
+ }
41
51
 
42
- document.addEventListener('visibilitychange', start);
52
+ startAutoPlayTimeout();
53
+ document.addEventListener('visibilitychange', startAutoPlayTimeout);
43
54
 
44
55
  return () => {
45
- stop();
46
- document.removeEventListener('visibilitychange', start);
56
+ clearAutoPlayTimeout();
57
+ document.removeEventListener('visibilitychange', startAutoPlayTimeout);
47
58
  };
48
59
  },
49
- [document, timeout, slideIndex, callbackFn],
60
+ [document, timeout, slideIndex, startAutoPlayTimeout, clearAutoPlayTimeout, paused],
50
61
  );
62
+
63
+ return {
64
+ resume,
65
+ pause,
66
+ };
51
67
  }
@@ -1,8 +1,7 @@
1
1
  import * as React from 'react';
2
- import { classNames, noop } from '@vkontakte/vkjs';
2
+ import { classNames } from '@vkontakte/vkjs';
3
3
  import { useAdaptivityHasPointer } from '../../hooks/useAdaptivityHasPointer';
4
4
  import { useDirection } from '../../hooks/useDirection';
5
- import { useEventListener } from '../../hooks/useEventListener';
6
5
  import { useExternRef } from '../../hooks/useExternRef';
7
6
  import { easeInOutSine } from '../../lib/fx';
8
7
  import type { HasRef, HTMLAttributesWithRootRef } from '../../types';
@@ -236,44 +235,33 @@ export const HorizontalScroll = ({
236
235
  }
237
236
  }, [showArrows, hasPointer, scrollerRef, setCanScrollStart, setCanScrollEnd]);
238
237
 
239
- const scrollEvent = useEventListener('scroll', calculateArrowsVisibility);
240
- React.useEffect(
241
- function addScrollerRefToScrollEvent() {
242
- if (!scrollerRef.current) {
243
- return noop;
244
- }
238
+ React.useEffect(calculateArrowsVisibility, [calculateArrowsVisibility, children]);
245
239
 
246
- scrollEvent.add(scrollerRef.current);
247
- return scrollEvent.remove;
240
+ const _onWheel = React.useCallback(
241
+ (e: React.WheelEvent) => {
242
+ scrollerRef.current!.scrollBy({ left: e.deltaX + e.deltaY, behavior: 'auto' });
248
243
  },
249
- [scrollEvent, scrollerRef],
244
+ [scrollerRef],
250
245
  );
251
246
 
252
- React.useEffect(calculateArrowsVisibility, [calculateArrowsVisibility, children]);
253
-
254
247
  /**
255
248
  * Прокрутка с помощью любого колеса мыши
256
249
  */
257
- const onwheel = React.useCallback(
258
- (e: WheelEvent) => {
259
- scrollerRef.current!.scrollBy({ left: e.deltaX + e.deltaY, behavior: 'auto' });
250
+ const onScrollWheel = React.useCallback(
251
+ (e: React.WheelEvent) => {
252
+ _onWheel(e);
260
253
  e.preventDefault();
261
254
  },
262
- [scrollerRef],
255
+ [_onWheel],
263
256
  );
264
257
 
265
- const wheelEvent = useEventListener('wheel', onwheel);
266
- React.useEffect(
267
- function addScrollerRefToWheelEvent() {
268
- if (!scrollerRef.current || !scrollOnAnyWheel) {
269
- return noop;
258
+ const onArrowWheel = React.useCallback(
259
+ (e: React.WheelEvent) => {
260
+ if (e.deltaX || (e.deltaY && scrollOnAnyWheel)) {
261
+ _onWheel(e);
270
262
  }
271
-
272
- wheelEvent.add(scrollerRef.current);
273
-
274
- return wheelEvent.remove;
275
263
  },
276
- [wheelEvent, scrollerRef, scrollOnAnyWheel],
264
+ [_onWheel, scrollOnAnyWheel],
277
265
  );
278
266
 
279
267
  return (
@@ -300,6 +288,7 @@ export const HorizontalScroll = ({
300
288
  styles['HorizontalScroll__arrowLeft'],
301
289
  )}
302
290
  onClick={scrollToLeft}
291
+ onWheel={onArrowWheel}
303
292
  />
304
293
  )}
305
294
  {showArrows && (hasPointer || hasPointer === undefined) && canScrollRight && (
@@ -315,9 +304,15 @@ export const HorizontalScroll = ({
315
304
  styles['HorizontalScroll__arrowRight'],
316
305
  )}
317
306
  onClick={scrollToRight}
307
+ onWheel={onArrowWheel}
318
308
  />
319
309
  )}
320
- <div className={styles['HorizontalScroll__in']} ref={scrollerRef}>
310
+ <div
311
+ className={styles['HorizontalScroll__in']}
312
+ ref={scrollerRef}
313
+ onScroll={calculateArrowsVisibility}
314
+ onWheel={scrollOnAnyWheel ? onScrollWheel : undefined}
315
+ >
321
316
  <div className={styles['HorizontalScroll__in-wrapper']}>{children}</div>
322
317
  </div>
323
318
  </RootComponent>
@@ -267,7 +267,7 @@ export const Popover = ({
267
267
  mount={!hidden}
268
268
  disabled={hidden}
269
269
  autoFocus={disableInteractive ? false : autoFocus}
270
- restoreFocus={restoreFocus ? onRestoreFocus : false}
270
+ restoreFocus={restoreFocus ? () => onRestoreFocus(restoreFocus) : false}
271
271
  onClose={onEscapeKeyDown}
272
272
  >
273
273
  {arrow}