@vkontakte/vkui 7.3.8 → 7.4.1

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 (357) hide show
  1. package/dist/components/ActionSheet/ActionSheet.d.ts +1 -1
  2. package/dist/components/ActionSheet/ActionSheet.d.ts.map +1 -1
  3. package/dist/components/ActionSheet/ActionSheet.js.map +1 -1
  4. package/dist/components/AppRoot/ScrollContext.js +2 -2
  5. package/dist/components/AppRoot/ScrollContext.js.map +1 -1
  6. package/dist/components/Banner/Banner.d.ts +2 -2
  7. package/dist/components/Banner/Banner.d.ts.map +1 -1
  8. package/dist/components/Banner/Banner.js.map +1 -1
  9. package/dist/components/Button/Button.d.ts +2 -2
  10. package/dist/components/Button/Button.d.ts.map +1 -1
  11. package/dist/components/Button/Button.js.map +1 -1
  12. package/dist/components/Calendar/Calendar.d.ts.map +1 -1
  13. package/dist/components/Calendar/Calendar.js +9 -7
  14. package/dist/components/Calendar/Calendar.js.map +1 -1
  15. package/dist/components/CalendarRange/CalendarRange.d.ts +9 -2
  16. package/dist/components/CalendarRange/CalendarRange.d.ts.map +1 -1
  17. package/dist/components/CalendarRange/CalendarRange.js +48 -35
  18. package/dist/components/CalendarRange/CalendarRange.js.map +1 -1
  19. package/dist/components/CalendarRange/types.d.ts +2 -0
  20. package/dist/components/CalendarRange/types.d.ts.map +1 -0
  21. package/dist/components/CalendarRange/types.js +3 -0
  22. package/dist/components/CalendarRange/types.js.map +1 -0
  23. package/dist/components/CalendarRange/utils.d.ts +29 -0
  24. package/dist/components/CalendarRange/utils.d.ts.map +1 -0
  25. package/dist/components/CalendarRange/utils.js +123 -0
  26. package/dist/components/CalendarRange/utils.js.map +1 -0
  27. package/dist/components/Checkbox/Checkbox.d.ts +2 -2
  28. package/dist/components/Checkbox/Checkbox.d.ts.map +1 -1
  29. package/dist/components/Checkbox/Checkbox.js.map +1 -1
  30. package/dist/components/ChipsInput/useChipsInput.d.ts.map +1 -1
  31. package/dist/components/ChipsInput/useChipsInput.js +21 -2
  32. package/dist/components/ChipsInput/useChipsInput.js.map +1 -1
  33. package/dist/components/ChipsInputBase/types.d.ts +5 -1
  34. package/dist/components/ChipsInputBase/types.d.ts.map +1 -1
  35. package/dist/components/ChipsInputBase/types.js.map +1 -1
  36. package/dist/components/Clickable/Clickable.d.ts +4 -0
  37. package/dist/components/Clickable/Clickable.d.ts.map +1 -1
  38. package/dist/components/Clickable/Clickable.js +9 -5
  39. package/dist/components/Clickable/Clickable.js.map +1 -1
  40. package/dist/components/Clickable/RealClickable.d.ts +1 -1
  41. package/dist/components/Clickable/RealClickable.d.ts.map +1 -1
  42. package/dist/components/Clickable/RealClickable.js +3 -2
  43. package/dist/components/Clickable/RealClickable.js.map +1 -1
  44. package/dist/components/ContentCard/ContentCard.d.ts +2 -2
  45. package/dist/components/ContentCard/ContentCard.d.ts.map +1 -1
  46. package/dist/components/ContentCard/ContentCard.js.map +1 -1
  47. package/dist/components/CustomSelect/CustomSelect.d.ts +4 -1
  48. package/dist/components/CustomSelect/CustomSelect.d.ts.map +1 -1
  49. package/dist/components/CustomSelect/CustomSelect.js.map +1 -1
  50. package/dist/components/DateInput/DateInput.d.ts +1 -1
  51. package/dist/components/DateInput/DateInput.d.ts.map +1 -1
  52. package/dist/components/DateInput/DateInput.js +48 -50
  53. package/dist/components/DateInput/DateInput.js.map +1 -1
  54. package/dist/components/DateRangeInput/DateRangeInput.d.ts +22 -2
  55. package/dist/components/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  56. package/dist/components/DateRangeInput/DateRangeInput.js +159 -66
  57. package/dist/components/DateRangeInput/DateRangeInput.js.map +1 -1
  58. package/dist/components/FocusTrap/FocusTrap.d.ts +1 -1
  59. package/dist/components/FocusTrap/FocusTrap.d.ts.map +1 -1
  60. package/dist/components/FocusTrap/FocusTrap.js +6 -3
  61. package/dist/components/FocusTrap/FocusTrap.js.map +1 -1
  62. package/dist/components/HorizontalCell/HorizontalCell.d.ts +2 -2
  63. package/dist/components/HorizontalCell/HorizontalCell.d.ts.map +1 -1
  64. package/dist/components/HorizontalCell/HorizontalCell.js.map +1 -1
  65. package/dist/components/HorizontalScroll/HorizontalCellShowMore/HorizontalCellShowMore.d.ts +2 -2
  66. package/dist/components/HorizontalScroll/HorizontalCellShowMore/HorizontalCellShowMore.d.ts.map +1 -1
  67. package/dist/components/HorizontalScroll/HorizontalCellShowMore/HorizontalCellShowMore.js.map +1 -1
  68. package/dist/components/IconButton/IconButton.d.ts +2 -2
  69. package/dist/components/IconButton/IconButton.d.ts.map +1 -1
  70. package/dist/components/IconButton/IconButton.js.map +1 -1
  71. package/dist/components/InputLike/InputLike.d.ts +1 -1
  72. package/dist/components/InputLike/InputLike.d.ts.map +1 -1
  73. package/dist/components/InputLike/InputLike.js +7 -6
  74. package/dist/components/InputLike/InputLike.js.map +1 -1
  75. package/dist/components/Link/Link.d.ts +2 -2
  76. package/dist/components/Link/Link.d.ts.map +1 -1
  77. package/dist/components/Link/Link.js +2 -1
  78. package/dist/components/Link/Link.js.map +1 -1
  79. package/dist/components/MiniInfoCell/MiniInfoCell.d.ts.map +1 -1
  80. package/dist/components/MiniInfoCell/MiniInfoCell.js +1 -8
  81. package/dist/components/MiniInfoCell/MiniInfoCell.js.map +1 -1
  82. package/dist/components/ModalOutsideButton/ModalOutsideButton.d.ts +2 -2
  83. package/dist/components/ModalOutsideButton/ModalOutsideButton.d.ts.map +1 -1
  84. package/dist/components/ModalOutsideButton/ModalOutsideButton.js.map +1 -1
  85. package/dist/components/NumberInputLike/NumberInputLike.d.ts +8 -0
  86. package/dist/components/NumberInputLike/NumberInputLike.d.ts.map +1 -0
  87. package/dist/components/NumberInputLike/NumberInputLike.js +45 -0
  88. package/dist/components/NumberInputLike/NumberInputLike.js.map +1 -0
  89. package/dist/components/Pagination/PaginationPage/PaginationPageButton.d.ts +2 -2
  90. package/dist/components/Pagination/PaginationPage/PaginationPageButton.d.ts.map +1 -1
  91. package/dist/components/Pagination/PaginationPage/PaginationPageButton.js.map +1 -1
  92. package/dist/components/PanelHeader/PanelHeader.d.ts +3 -1
  93. package/dist/components/PanelHeader/PanelHeader.d.ts.map +1 -1
  94. package/dist/components/PanelHeader/PanelHeader.js.map +1 -1
  95. package/dist/components/PanelHeaderButton/PanelHeaderButton.d.ts +2 -2
  96. package/dist/components/PanelHeaderButton/PanelHeaderButton.d.ts.map +1 -1
  97. package/dist/components/PanelHeaderButton/PanelHeaderButton.js.map +1 -1
  98. package/dist/components/Radio/Radio.d.ts +2 -2
  99. package/dist/components/Radio/Radio.d.ts.map +1 -1
  100. package/dist/components/Radio/Radio.js.map +1 -1
  101. package/dist/components/Removable/Removable.d.ts +1 -4
  102. package/dist/components/Removable/Removable.d.ts.map +1 -1
  103. package/dist/components/Removable/Removable.js +39 -116
  104. package/dist/components/Removable/Removable.js.map +1 -1
  105. package/dist/components/Removable/RemovableIos.d.ts +10 -0
  106. package/dist/components/Removable/RemovableIos.d.ts.map +1 -0
  107. package/dist/components/Removable/RemovableIos.js +124 -0
  108. package/dist/components/Removable/RemovableIos.js.map +1 -0
  109. package/dist/components/RichCell/RichCell.d.ts +2 -2
  110. package/dist/components/RichCell/RichCell.d.ts.map +1 -1
  111. package/dist/components/RichCell/RichCell.js.map +1 -1
  112. package/dist/components/ScreenSpinner/ScreenSpinner.d.ts.map +1 -1
  113. package/dist/components/ScreenSpinner/ScreenSpinner.js +4 -2
  114. package/dist/components/ScreenSpinner/ScreenSpinner.js.map +1 -1
  115. package/dist/components/ScreenSpinner/ScreenSpinnerContainer.d.ts +2 -2
  116. package/dist/components/ScreenSpinner/ScreenSpinnerContainer.d.ts.map +1 -1
  117. package/dist/components/ScreenSpinner/ScreenSpinnerContainer.js +4 -3
  118. package/dist/components/ScreenSpinner/ScreenSpinnerContainer.js.map +1 -1
  119. package/dist/components/SelectionControl/SelectionControl.d.ts +2 -2
  120. package/dist/components/SelectionControl/SelectionControl.d.ts.map +1 -1
  121. package/dist/components/SelectionControl/SelectionControl.js.map +1 -1
  122. package/dist/components/SimpleCell/SimpleCell.d.ts +2 -2
  123. package/dist/components/SimpleCell/SimpleCell.d.ts.map +1 -1
  124. package/dist/components/SimpleCell/SimpleCell.js.map +1 -1
  125. package/dist/components/Skeleton/Skeleton.d.ts +5 -1
  126. package/dist/components/Skeleton/Skeleton.d.ts.map +1 -1
  127. package/dist/components/Skeleton/Skeleton.js +7 -4
  128. package/dist/components/Skeleton/Skeleton.js.map +1 -1
  129. package/dist/components/Spinner/Spinner.d.ts +5 -1
  130. package/dist/components/Spinner/Spinner.d.ts.map +1 -1
  131. package/dist/components/Spinner/Spinner.js +6 -3
  132. package/dist/components/Spinner/Spinner.js.map +1 -1
  133. package/dist/components/SubnavigationButton/SubnavigationButton.d.ts +2 -2
  134. package/dist/components/SubnavigationButton/SubnavigationButton.d.ts.map +1 -1
  135. package/dist/components/SubnavigationButton/SubnavigationButton.js.map +1 -1
  136. package/dist/components/Tabs/Tabs.d.ts +13 -9
  137. package/dist/components/Tabs/Tabs.d.ts.map +1 -1
  138. package/dist/components/Tabs/Tabs.js +14 -10
  139. package/dist/components/Tabs/Tabs.js.map +1 -1
  140. package/dist/components/Tabs/TabsController.d.ts +7 -0
  141. package/dist/components/Tabs/TabsController.d.ts.map +1 -0
  142. package/dist/components/Tabs/TabsController.js +19 -0
  143. package/dist/components/Tabs/TabsController.js.map +1 -0
  144. package/dist/components/Tabs/TabsModeContext.d.ts +13 -0
  145. package/dist/components/Tabs/TabsModeContext.d.ts.map +1 -0
  146. package/dist/components/Tabs/TabsModeContext.js +11 -0
  147. package/dist/components/Tabs/TabsModeContext.js.map +1 -0
  148. package/dist/components/TabsItem/TabsItem.d.ts +3 -3
  149. package/dist/components/TabsItem/TabsItem.d.ts.map +1 -1
  150. package/dist/components/TabsItem/TabsItem.js +21 -6
  151. package/dist/components/TabsItem/TabsItem.js.map +1 -1
  152. package/dist/components/Tappable/Tappable.d.ts +1 -0
  153. package/dist/components/Tappable/Tappable.d.ts.map +1 -1
  154. package/dist/components/Tappable/Tappable.js.map +1 -1
  155. package/dist/components/ToolButton/ToolButton.d.ts +2 -2
  156. package/dist/components/ToolButton/ToolButton.d.ts.map +1 -1
  157. package/dist/components/ToolButton/ToolButton.js.map +1 -1
  158. package/dist/components/View/ViewInfinite.js.map +1 -1
  159. package/dist/components.css +1 -1
  160. package/dist/components.css.map +1 -1
  161. package/dist/cssm/components/ActionSheet/ActionSheet.js.map +1 -1
  162. package/dist/cssm/components/AppRoot/ScrollContext.js +2 -2
  163. package/dist/cssm/components/AppRoot/ScrollContext.js.map +1 -1
  164. package/dist/cssm/components/Banner/Banner.js.map +1 -1
  165. package/dist/cssm/components/Button/Button.js.map +1 -1
  166. package/dist/cssm/components/Calendar/Calendar.js +9 -7
  167. package/dist/cssm/components/Calendar/Calendar.js.map +1 -1
  168. package/dist/cssm/components/CalendarRange/CalendarRange.js +44 -31
  169. package/dist/cssm/components/CalendarRange/CalendarRange.js.map +1 -1
  170. package/dist/cssm/components/CalendarRange/types.js +3 -0
  171. package/dist/cssm/components/CalendarRange/types.js.map +1 -0
  172. package/dist/cssm/components/CalendarRange/utils.js +122 -0
  173. package/dist/cssm/components/CalendarRange/utils.js.map +1 -0
  174. package/dist/cssm/components/Checkbox/Checkbox.js.map +1 -1
  175. package/dist/cssm/components/ChipsInput/useChipsInput.js +21 -2
  176. package/dist/cssm/components/ChipsInput/useChipsInput.js.map +1 -1
  177. package/dist/cssm/components/ChipsInputBase/types.js.map +1 -1
  178. package/dist/cssm/components/Clickable/Clickable.js +4 -3
  179. package/dist/cssm/components/Clickable/Clickable.js.map +1 -1
  180. package/dist/cssm/components/Clickable/RealClickable.js +1 -1
  181. package/dist/cssm/components/Clickable/RealClickable.js.map +1 -1
  182. package/dist/cssm/components/ContentCard/ContentCard.js.map +1 -1
  183. package/dist/cssm/components/CustomSelect/CustomSelect.js.map +1 -1
  184. package/dist/cssm/components/DateInput/DateInput.js +45 -46
  185. package/dist/cssm/components/DateInput/DateInput.js.map +1 -1
  186. package/dist/cssm/components/DateRangeInput/DateRangeInput.js +148 -58
  187. package/dist/cssm/components/DateRangeInput/DateRangeInput.js.map +1 -1
  188. package/dist/cssm/components/FocusTrap/FocusTrap.js +4 -2
  189. package/dist/cssm/components/FocusTrap/FocusTrap.js.map +1 -1
  190. package/dist/cssm/components/HorizontalCell/HorizontalCell.js.map +1 -1
  191. package/dist/cssm/components/HorizontalScroll/HorizontalCellShowMore/HorizontalCellShowMore.js.map +1 -1
  192. package/dist/cssm/components/HorizontalScroll/HorizontalScroll.module.css +2 -3
  193. package/dist/cssm/components/IconButton/IconButton.js.map +1 -1
  194. package/dist/cssm/components/ImageBase/ImageBase.module.css +2 -3
  195. package/dist/cssm/components/InputLike/InputLike.js +3 -3
  196. package/dist/cssm/components/InputLike/InputLike.js.map +1 -1
  197. package/dist/cssm/components/Link/Link.js +1 -0
  198. package/dist/cssm/components/Link/Link.js.map +1 -1
  199. package/dist/cssm/components/MiniInfoCell/MiniInfoCell.js +1 -8
  200. package/dist/cssm/components/MiniInfoCell/MiniInfoCell.js.map +1 -1
  201. package/dist/cssm/components/ModalOutsideButton/ModalOutsideButton.js.map +1 -1
  202. package/dist/cssm/components/NumberInputLike/NumberInputLike.js +33 -0
  203. package/dist/cssm/components/NumberInputLike/NumberInputLike.js.map +1 -0
  204. package/dist/cssm/components/Pagination/PaginationPage/PaginationPageButton.js.map +1 -1
  205. package/dist/cssm/components/PanelHeader/PanelHeader.js.map +1 -1
  206. package/dist/cssm/components/PanelHeaderButton/PanelHeaderButton.js.map +1 -1
  207. package/dist/cssm/components/Radio/Radio.js.map +1 -1
  208. package/dist/cssm/components/Removable/Removable.js +39 -115
  209. package/dist/cssm/components/Removable/Removable.js.map +1 -1
  210. package/dist/cssm/components/Removable/Removable.module.css +9 -0
  211. package/dist/cssm/components/Removable/RemovableIos.js +118 -0
  212. package/dist/cssm/components/Removable/RemovableIos.js.map +1 -0
  213. package/dist/cssm/components/RichCell/RichCell.js.map +1 -1
  214. package/dist/cssm/components/ScreenSpinner/ScreenSpinner.js +2 -1
  215. package/dist/cssm/components/ScreenSpinner/ScreenSpinner.js.map +1 -1
  216. package/dist/cssm/components/ScreenSpinner/ScreenSpinnerContainer.js +3 -2
  217. package/dist/cssm/components/ScreenSpinner/ScreenSpinnerContainer.js.map +1 -1
  218. package/dist/cssm/components/SelectionControl/SelectionControl.js.map +1 -1
  219. package/dist/cssm/components/SimpleCell/SimpleCell.js.map +1 -1
  220. package/dist/cssm/components/Skeleton/Skeleton.js +6 -3
  221. package/dist/cssm/components/Skeleton/Skeleton.js.map +1 -1
  222. package/dist/cssm/components/Spinner/Spinner.js +5 -2
  223. package/dist/cssm/components/Spinner/Spinner.js.map +1 -1
  224. package/dist/cssm/components/SubnavigationButton/SubnavigationButton.js.map +1 -1
  225. package/dist/cssm/components/Tabs/Tabs.js +10 -9
  226. package/dist/cssm/components/Tabs/Tabs.js.map +1 -1
  227. package/dist/cssm/components/Tabs/TabsController.js +19 -0
  228. package/dist/cssm/components/Tabs/TabsController.js.map +1 -0
  229. package/dist/cssm/components/Tabs/TabsModeContext.js +11 -0
  230. package/dist/cssm/components/Tabs/TabsModeContext.js.map +1 -0
  231. package/dist/cssm/components/TabsItem/TabsItem.js +17 -4
  232. package/dist/cssm/components/TabsItem/TabsItem.js.map +1 -1
  233. package/dist/cssm/components/Tappable/Tappable.js.map +1 -1
  234. package/dist/cssm/components/ToolButton/ToolButton.js.map +1 -1
  235. package/dist/cssm/components/View/ViewInfinite.js.map +1 -1
  236. package/dist/cssm/hooks/useCalendar.js +0 -10
  237. package/dist/cssm/hooks/useCalendar.js.map +1 -1
  238. package/dist/cssm/hooks/useDateInput.js +28 -17
  239. package/dist/cssm/hooks/useDateInput.js.map +1 -1
  240. package/dist/cssm/hooks/useEventListener.js.map +1 -1
  241. package/dist/cssm/hooks/useExternRef.js.map +1 -1
  242. package/dist/cssm/hooks/useFocusTrap.js +2 -2
  243. package/dist/cssm/hooks/useFocusTrap.js.map +1 -1
  244. package/dist/cssm/hooks/useMutationObserver.js +6 -5
  245. package/dist/cssm/hooks/useMutationObserver.js.map +1 -1
  246. package/dist/cssm/lib/dom.js +7 -1
  247. package/dist/cssm/lib/dom.js.map +1 -1
  248. package/dist/cssm/lib/floating/customResizeObserver.js.map +1 -1
  249. package/dist/cssm/lib/floating/index.js.map +1 -1
  250. package/dist/cssm/lib/floating/types/common.js.map +1 -1
  251. package/dist/cssm/lib/sheet/controllers/BottomSheetController.js.map +1 -1
  252. package/dist/cssm/lib/sheet/controllers/CSSTransitionController.js.map +1 -1
  253. package/dist/cssm/styles/animationVisibilityDelay.js +10 -0
  254. package/dist/cssm/styles/animationVisibilityDelay.js.map +1 -0
  255. package/dist/cssm/styles/animationVisibilityDelay.module.css +13 -0
  256. package/dist/cssm/styles/themes.css +4 -2
  257. package/dist/hooks/useCalendar.d.ts +0 -3
  258. package/dist/hooks/useCalendar.d.ts.map +1 -1
  259. package/dist/hooks/useCalendar.js +0 -10
  260. package/dist/hooks/useCalendar.js.map +1 -1
  261. package/dist/hooks/useDateInput.d.ts.map +1 -1
  262. package/dist/hooks/useDateInput.js +29 -18
  263. package/dist/hooks/useDateInput.js.map +1 -1
  264. package/dist/hooks/useEventListener.js.map +1 -1
  265. package/dist/hooks/useExternRef.js.map +1 -1
  266. package/dist/hooks/useFocusTrap.d.ts +5 -1
  267. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  268. package/dist/hooks/useFocusTrap.js +2 -2
  269. package/dist/hooks/useFocusTrap.js.map +1 -1
  270. package/dist/hooks/useMutationObserver.d.ts +2 -1
  271. package/dist/hooks/useMutationObserver.d.ts.map +1 -1
  272. package/dist/hooks/useMutationObserver.js +6 -5
  273. package/dist/hooks/useMutationObserver.js.map +1 -1
  274. package/dist/lib/dom.d.ts.map +1 -1
  275. package/dist/lib/dom.js +7 -1
  276. package/dist/lib/dom.js.map +1 -1
  277. package/dist/lib/floating/customResizeObserver.js.map +1 -1
  278. package/dist/lib/floating/index.d.ts +1 -1
  279. package/dist/lib/floating/index.d.ts.map +1 -1
  280. package/dist/lib/floating/index.js.map +1 -1
  281. package/dist/lib/floating/types/common.d.ts +1 -1
  282. package/dist/lib/floating/types/common.d.ts.map +1 -1
  283. package/dist/lib/floating/types/common.js.map +1 -1
  284. package/dist/lib/sheet/controllers/BottomSheetController.js.map +1 -1
  285. package/dist/lib/sheet/controllers/CSSTransitionController.js.map +1 -1
  286. package/dist/styles/animationVisibilityDelay.d.ts +3 -0
  287. package/dist/styles/animationVisibilityDelay.d.ts.map +1 -0
  288. package/dist/styles/animationVisibilityDelay.js +10 -0
  289. package/dist/styles/animationVisibilityDelay.js.map +1 -0
  290. package/dist/vkui.css +1 -1
  291. package/dist/vkui.css.map +1 -1
  292. package/package.json +3 -6
  293. package/src/components/ActionSheet/ActionSheet.tsx +4 -1
  294. package/src/components/AppRoot/AppRoot.mdx +1 -1
  295. package/src/components/AppRoot/ScrollContext.tsx +2 -2
  296. package/src/components/Banner/Banner.tsx +2 -2
  297. package/src/components/Button/Button.tsx +2 -2
  298. package/src/components/Calendar/Calendar.tsx +8 -7
  299. package/src/components/CalendarRange/CalendarRange.tsx +65 -42
  300. package/src/components/CalendarRange/types.ts +1 -0
  301. package/src/components/CalendarRange/utils.ts +190 -0
  302. package/src/components/Checkbox/Checkbox.tsx +2 -2
  303. package/src/components/ChipsInput/useChipsInput.ts +23 -2
  304. package/src/components/ChipsInputBase/types.ts +5 -1
  305. package/src/components/Clickable/Clickable.tsx +12 -4
  306. package/src/components/Clickable/RealClickable.tsx +1 -0
  307. package/src/components/ContentCard/ContentCard.tsx +2 -2
  308. package/src/components/CustomSelect/CustomSelect.tsx +11 -7
  309. package/src/components/DateInput/DateInput.tsx +41 -43
  310. package/src/components/DateRangeInput/DateRangeInput.tsx +183 -65
  311. package/src/components/FocusTrap/FocusTrap.tsx +3 -0
  312. package/src/components/FormItem/FormItemTop/FormItemTop.mdx +1 -1
  313. package/src/components/HorizontalCell/HorizontalCell.tsx +2 -2
  314. package/src/components/HorizontalScroll/HorizontalCellShowMore/HorizontalCellShowMore.tsx +2 -2
  315. package/src/components/HorizontalScroll/HorizontalScroll.module.css +2 -3
  316. package/src/components/HorizontalScroll/HorizontalScroll.module.css.d.ts.map +1 -1
  317. package/src/components/IconButton/IconButton.tsx +2 -2
  318. package/src/components/ImageBase/ImageBase.module.css +2 -3
  319. package/src/components/ImageBase/ImageBase.module.css.d.ts.map +1 -1
  320. package/src/components/InputLike/InputLike.tsx +4 -3
  321. package/src/components/Link/Link.tsx +3 -2
  322. package/src/components/MiniInfoCell/MiniInfoCell.tsx +2 -7
  323. package/src/components/ModalOutsideButton/ModalOutsideButton.tsx +2 -2
  324. package/src/components/NumberInputLike/NumberInputLike.tsx +56 -0
  325. package/src/components/Pagination/PaginationPage/PaginationPageButton.tsx +2 -2
  326. package/src/components/PanelHeader/PanelHeader.tsx +3 -1
  327. package/src/components/PanelHeaderButton/PanelHeaderButton.tsx +2 -2
  328. package/src/components/Radio/Radio.tsx +2 -2
  329. package/src/components/Removable/Removable.module.css +9 -0
  330. package/src/components/Removable/Removable.module.css.d.ts.map +1 -1
  331. package/src/components/Removable/Removable.tsx +50 -120
  332. package/src/components/Removable/RemovableIos.tsx +135 -0
  333. package/src/components/RichCell/RichCell.tsx +2 -2
  334. package/src/components/ScreenSpinner/ScreenSpinner.tsx +8 -1
  335. package/src/components/ScreenSpinner/ScreenSpinnerContainer.tsx +4 -1
  336. package/src/components/SelectionControl/SelectionControl.tsx +2 -2
  337. package/src/components/SimpleCell/SimpleCell.tsx +2 -2
  338. package/src/components/Skeleton/Skeleton.tsx +15 -2
  339. package/src/components/Spinner/Spinner.tsx +13 -1
  340. package/src/components/SubnavigationButton/SubnavigationButton.tsx +2 -2
  341. package/src/components/Tabs/Tabs.tsx +23 -19
  342. package/src/components/Tabs/TabsController.ts +37 -0
  343. package/src/components/Tabs/TabsModeContext.ts +24 -0
  344. package/src/components/TabsItem/TabsItem.tsx +22 -5
  345. package/src/components/Tappable/Tappable.tsx +5 -0
  346. package/src/components/ToolButton/ToolButton.tsx +2 -2
  347. package/src/components/UnstyledTextField/UnstyledTextField.mdx +1 -1
  348. package/src/hooks/useCalendar.ts +0 -12
  349. package/src/hooks/useDateInput.ts +21 -12
  350. package/src/hooks/useFocusTrap.ts +10 -1
  351. package/src/hooks/useMutationObserver.ts +7 -4
  352. package/src/lib/dom.tsx +7 -1
  353. package/src/lib/floating/index.ts +2 -0
  354. package/src/lib/floating/types/common.ts +2 -0
  355. package/src/styles/animationVisibilityDelay.module.css +13 -0
  356. package/src/styles/animationVisibilityDelay.module.css.d.ts.map +1 -0
  357. package/src/styles/animationVisibilityDelay.ts +13 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "type": "module",
3
- "version": "7.3.8",
3
+ "version": "7.4.1",
4
4
  "name": "@vkontakte/vkui",
5
5
  "description": "VKUI library",
6
6
  "module": "./dist/index.js",
@@ -74,8 +74,8 @@
74
74
  "lint:generated-files": "yarn run -T concurrently 'yarn:lint:generated-files:*'",
75
75
  "lint:generated-files:css-custom-medias": "yarn run -T tsc scripts/generateCSSCustomMedias.mjs --checkJs --module ESNext --moduleResolution node --resolveJsonModule --allowSyntheticDefaultImports --jsx react-jsx --noEmit && yarn run generate:css-custom-medias && git diff --exit-code src/styles/customMedias.generated.css",
76
76
  "lint:generated-files:css-modules": "yarn run generate:css-modules",
77
- "storybook": "bash -c 'source .env && yarn run -T cross-env SANDBOX=\\.storybook storybook dev -p ${STORYBOOK_DEV_PORT:=6006}'",
78
- "storybook:build": "yarn run -T cross-env SANDBOX=\\.storybook FROM_STORYBOOK=1 storybook build",
77
+ "storybook": "bash -c 'source .env && yarn run -T storybook dev -p ${STORYBOOK_DEV_PORT:=6006}'",
78
+ "storybook:build": "yarn run -T storybook build",
79
79
  "generate": "yarn run -T concurrently 'yarn:generate:*'",
80
80
  "generate:css-custom-medias": "node scripts/generateCSSCustomMedias.mjs",
81
81
  "generate:css-modules": "yarn run -T hcm 'src/**/*.css'"
@@ -93,12 +93,9 @@
93
93
  "date-fns": "^4.1.0"
94
94
  },
95
95
  "devDependencies": {
96
- "@storybook/react": "8.6.12",
97
- "@storybook/react-webpack5": "8.6.12",
98
96
  "@types/node": "*",
99
97
  "react": "^18.3.1",
100
98
  "react-dom": "^18.3.1",
101
- "storybook": "8.6.12",
102
99
  "ts-node": "*"
103
100
  },
104
101
  "size-limit": [
@@ -30,7 +30,10 @@ export interface ActionSheetProps
30
30
  SharedDropdownProps,
31
31
  'toggleRef' | 'popupOffsetDistance' | 'placement' | 'allowClickPropagation'
32
32
  >,
33
- Omit<UseFocusTrapProps, 'onClose' | 'mount' | 'disabled' | 'captureEscapeKeyboardEvent'>,
33
+ Omit<
34
+ UseFocusTrapProps,
35
+ 'onClose' | 'mount' | 'disabled' | 'captureEscapeKeyboardEvent' | 'mutationObserverOptions'
36
+ >,
34
37
  Omit<React.HTMLAttributes<HTMLDivElement>, 'autoFocus' | 'title'> {
35
38
  /**
36
39
  * Заголовок всплыващего окна.
@@ -1,4 +1,4 @@
1
- import { Meta, Title, ArgTypes, Description } from '@storybook/blocks';
1
+ import { Meta, Title, ArgTypes, Description } from '@storybook/addon-docs/blocks';
2
2
  import { AppRoot } from './AppRoot';
3
3
 
4
4
  <Meta title="Service/AppRoot" />
@@ -155,8 +155,8 @@ const _getScroll = ({
155
155
  ? [-parseFloat(elementStyles.left || '0'), -parseFloat(elementStyles.top || '0')]
156
156
  : [xOffset, yOffset];
157
157
  return {
158
- x: scrollLeft,
159
- y: customCalcY(scrollTop),
158
+ x: scrollLeft || 0,
159
+ y: customCalcY(scrollTop) || 0,
160
160
  };
161
161
  };
162
162
 
@@ -5,14 +5,14 @@ import { Icon24Cancel, Icon24Chevron, Icon24Dismiss, Icon24DismissDark } from '@
5
5
  import { classNames, hasReactNode } from '@vkontakte/vkjs';
6
6
  import { usePlatform } from '../../hooks/usePlatform';
7
7
  import { IconButton } from '../IconButton/IconButton';
8
- import { Tappable, type TappableProps } from '../Tappable/Tappable';
8
+ import { Tappable, type TappableOmitProps } from '../Tappable/Tappable';
9
9
  import { Headline } from '../Typography/Headline/Headline';
10
10
  import { Subhead } from '../Typography/Subhead/Subhead';
11
11
  import { Text } from '../Typography/Text/Text';
12
12
  import { Title } from '../Typography/Title/Title';
13
13
  import styles from './Banner.module.css';
14
14
 
15
- export interface BannerProps extends Omit<TappableProps, 'title' | 'size'> {
15
+ export interface BannerProps extends Omit<TappableOmitProps, 'title' | 'size'> {
16
16
  /**
17
17
  * Тип баннера.
18
18
  */
@@ -6,7 +6,7 @@ import { useAdaptivity } from '../../hooks/useAdaptivity';
6
6
  import { usePlatform } from '../../hooks/usePlatform';
7
7
  import type { HasAlign } from '../../types';
8
8
  import { Spinner } from '../Spinner/Spinner';
9
- import { Tappable, type TappableProps } from '../Tappable/Tappable';
9
+ import { Tappable, type TappableOmitProps } from '../Tappable/Tappable';
10
10
  import '../Tappable/Tappable.module.css';
11
11
  import '../Spinner/Spinner.module.css';
12
12
  import styles from './Button.module.css';
@@ -83,7 +83,7 @@ export interface VKUIButtonProps extends HasAlign {
83
83
  rounded?: boolean;
84
84
  }
85
85
 
86
- export interface ButtonProps extends Omit<TappableProps, 'size'>, VKUIButtonProps {}
86
+ export interface ButtonProps extends Omit<TappableOmitProps, 'size'>, VKUIButtonProps {}
87
87
 
88
88
  /**
89
89
  * @see https://vkcom.github.io/VKUI/#/Button
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import * as React from 'react';
4
- import { classNames } from '@vkontakte/vkjs';
4
+ import { classNames, isSameDate } from '@vkontakte/vkjs';
5
5
  import { isSameDay, isSameMonth, startOfMonth } from 'date-fns';
6
6
  import { useCalendar } from '../../hooks/useCalendar';
7
7
  import { useCustomEnsuredControl } from '../../hooks/useEnsuredControl';
@@ -220,8 +220,6 @@ export const Calendar = ({
220
220
  setNextMonth,
221
221
  focusedDay,
222
222
  setFocusedDay,
223
- focusableDay,
224
- setFocusableDay,
225
223
  isDayFocused,
226
224
  isDayDisabled,
227
225
  isMonthDisabled,
@@ -237,6 +235,8 @@ export const Calendar = ({
237
235
  minDateTime,
238
236
  maxDateTime,
239
237
  });
238
+ // соотвествует дню, на котором можно сфокусироваться с помощью Tab
239
+ const [focusableDay, setFocusableDay] = React.useState<Date>();
240
240
 
241
241
  useIsomorphicLayoutEffect(() => {
242
242
  if (timeZonedValue) {
@@ -291,10 +291,8 @@ export const Calendar = ({
291
291
  actualDate = clamp(actualDate, { min: minDateTime, max: maxDateTime });
292
292
  }
293
293
  updateValue(actualDate);
294
- setFocusedDay(actualDate);
295
- setFocusableDay(actualDate);
296
294
  },
297
- [timeZonedValue, updateValue, maxDateTime, minDateTime, setFocusedDay, setFocusableDay],
295
+ [timeZonedValue, updateValue, maxDateTime, minDateTime],
298
296
  );
299
297
 
300
298
  const onDayFocus = React.useCallback(
@@ -304,8 +302,11 @@ export const Calendar = ({
304
302
  }
305
303
 
306
304
  setFocusedDay(date);
305
+ if (!focusableDay || !isSameDate(date, focusableDay)) {
306
+ setFocusableDay(date);
307
+ }
307
308
  },
308
- [focusedDay, setFocusedDay],
309
+ [focusableDay, focusedDay, setFocusedDay],
309
310
  );
310
311
 
311
312
  // activeDay это день в календаре соответствующий значению в инпуте
@@ -7,16 +7,13 @@ import {
7
7
  isAfter,
8
8
  isBefore,
9
9
  isSameDay,
10
- isSameMonth,
11
10
  isWithinInterval,
12
11
  startOfDay,
13
12
  subMonths,
14
13
  } from 'date-fns';
15
14
  import { useCalendar } from '../../hooks/useCalendar';
16
15
  import { useCustomEnsuredControl } from '../../hooks/useEnsuredControl';
17
- import { Keys, pressedKey } from '../../lib/accessibility';
18
- import { isFirstDay, isLastDay, navigateDate, NAVIGATION_KEYS } from '../../lib/calendar';
19
- import { isHTMLElement } from '../../lib/dom';
16
+ import { isFirstDay, isLastDay } from '../../lib/calendar';
20
17
  import type { HTMLAttributesWithRootRef } from '../../types';
21
18
  import {
22
19
  CalendarDays,
@@ -29,9 +26,11 @@ import {
29
26
  type CalendarHeaderTestsProps,
30
27
  } from '../CalendarHeader/CalendarHeader';
31
28
  import { RootComponent } from '../RootComponent/RootComponent';
29
+ import type { DateRangeType } from './types';
30
+ import { useCalendarKeyboardNavigation, useIsDayFocusable } from './utils';
32
31
  import styles from './CalendarRange.module.css';
33
32
 
34
- export type DateRangeType = [Date | null, Date | null];
33
+ export type { DateRangeType };
35
34
 
36
35
  export type CalendarRangeTestsProps = CalendarDaysTestsProps & {
37
36
  /**
@@ -81,6 +80,12 @@ export interface CalendarRangeProps
81
80
  disablePickers?: boolean;
82
81
  /**
83
82
  * `aria-label` для изменения дня.
83
+ *
84
+ * @deprecated Since 7.4.0.
85
+ *
86
+ * Будет удалeно в **VKUI v8**. Использовалось для задания aria-label для контейнера дней в календаре.
87
+ * Теперь этот контейнер является таблицей (с помощью role="grid") и
88
+ * в aria-label рендерится текущий открытый в календаре месяц и год.
84
89
  */
85
90
  changeDayLabel?: string;
86
91
  /**
@@ -113,7 +118,7 @@ const getIsDaySelected = (day: Date, value?: DateRangeType | null) => {
113
118
  * @see https://vkcom.github.io/VKUI/#/CalendarRange
114
119
  */
115
120
  export const CalendarRange = ({
116
- value: valueProp,
121
+ 'value': valueProp,
117
122
  defaultValue,
118
123
  onChange,
119
124
  disablePast,
@@ -125,7 +130,7 @@ export const CalendarRange = ({
125
130
  nextMonthLabel = 'Следующий месяц',
126
131
  changeMonthLabel = 'Изменить месяц',
127
132
  changeYearLabel = 'Изменить год',
128
- changeDayLabel = 'Изменить день',
133
+ 'aria-label': ariaLabel = 'Календарь',
129
134
  prevMonthIcon,
130
135
  nextMonthIcon,
131
136
  listenDayChangesForUpdate,
@@ -156,7 +161,6 @@ export const CalendarRange = ({
156
161
  setFocusedDay,
157
162
  isDayFocused,
158
163
  isDayDisabled,
159
- resetSelectedDay,
160
164
  isMonthDisabled,
161
165
  isYearDisabled,
162
166
  } = useCalendar({ value, disableFuture, disablePast, shouldDisableDate });
@@ -164,33 +168,19 @@ export const CalendarRange = ({
164
168
  const [hintedDate, setHintedDate] = React.useState<DateRangeType>();
165
169
  const secondViewDate = addMonths(viewDate, 1);
166
170
 
167
- const handleKeyDown = React.useCallback(
168
- (event: React.KeyboardEvent) => {
169
- const key = pressedKey(event);
170
-
171
- if (key && NAVIGATION_KEYS.includes(key)) {
172
- event.preventDefault();
173
-
174
- const newFocusedDay = navigateDate(focusedDay ?? value?.[1], key);
175
-
176
- if (
177
- newFocusedDay &&
178
- !isSameMonth(newFocusedDay, viewDate) &&
179
- !isSameMonth(newFocusedDay, addMonths(viewDate, 1))
180
- ) {
181
- setViewDate(newFocusedDay);
182
- }
183
- setFocusedDay(newFocusedDay);
184
- return;
185
- }
186
-
187
- if ((key === Keys.ENTER || key === Keys.SPACE) && isHTMLElement(event.target)) {
188
- event.preventDefault();
189
- event.target.click?.();
190
- }
191
- },
192
- [focusedDay, setFocusedDay, setViewDate, value, viewDate],
193
- );
171
+ const {
172
+ focusableDayOnFirstCalendar,
173
+ focusableDayOnSecondCalendar,
174
+ handleFirstCalendarKeyDown,
175
+ handleSecondCalendarKeyDown,
176
+ handleDayFocus,
177
+ } = useCalendarKeyboardNavigation({
178
+ focusedDay,
179
+ setFocusedDay,
180
+ value,
181
+ viewDates: [viewDate, secondViewDate],
182
+ setViewDate,
183
+ });
194
184
 
195
185
  const getNewValue = React.useCallback(
196
186
  (date: Date): DateRangeType => {
@@ -270,8 +260,41 @@ export const CalendarRange = ({
270
260
  [setViewDate],
271
261
  );
272
262
 
263
+ const isDayFocusableInFirstCalendar = useIsDayFocusable({
264
+ value,
265
+ focusableDayOnFirstCalendar,
266
+ focusableDayOnSecondCalendar,
267
+ viewDate,
268
+ isDayActive,
269
+ });
270
+
271
+ const isDayFocusableInSecondCalendar = useIsDayFocusable({
272
+ value,
273
+ focusableDayOnFirstCalendar,
274
+ focusableDayOnSecondCalendar,
275
+ viewDate: secondViewDate,
276
+ isDayActive,
277
+ });
278
+
279
+ const onDayFocus = React.useCallback(
280
+ (date: Date) => {
281
+ if (focusedDay && isSameDay(focusedDay, date)) {
282
+ return;
283
+ }
284
+
285
+ setFocusedDay(date);
286
+ handleDayFocus(date);
287
+ },
288
+ [focusedDay, handleDayFocus, setFocusedDay],
289
+ );
290
+
273
291
  return (
274
- <RootComponent {...props} baseClassName={styles.host} getRootRef={getRootRef}>
292
+ <RootComponent
293
+ aria-label={ariaLabel}
294
+ {...props}
295
+ baseClassName={styles.host}
296
+ getRootRef={getRootRef}
297
+ >
275
298
  <div className={styles.inner}>
276
299
  <CalendarHeader
277
300
  viewDate={viewDate}
@@ -293,8 +316,10 @@ export const CalendarRange = ({
293
316
  viewDate={viewDate}
294
317
  value={value}
295
318
  weekStartsOn={weekStartsOn}
296
- onKeyDown={handleKeyDown}
319
+ onKeyDown={handleFirstCalendarKeyDown}
320
+ onDayFocus={onDayFocus}
297
321
  isDayFocused={isDayFocused}
322
+ isDayFocusable={isDayFocusableInFirstCalendar}
298
323
  onDayChange={onDayChange}
299
324
  isDaySelected={isDaySelected}
300
325
  isDayActive={isDayActive}
@@ -308,7 +333,6 @@ export const CalendarRange = ({
308
333
  isDayDisabled={isDayDisabled}
309
334
  listenDayChangesForUpdate={listenDayChangesForUpdate}
310
335
  renderDayContent={renderDayContent}
311
- aria-label={changeDayLabel}
312
336
  dayTestId={dayTestId}
313
337
  />
314
338
  </div>
@@ -333,9 +357,10 @@ export const CalendarRange = ({
333
357
  viewDate={secondViewDate}
334
358
  value={value}
335
359
  weekStartsOn={weekStartsOn}
336
- aria-label={changeDayLabel}
337
- onKeyDown={handleKeyDown}
360
+ onKeyDown={handleSecondCalendarKeyDown}
361
+ onDayFocus={onDayFocus}
338
362
  isDayFocused={isDayFocused}
363
+ isDayFocusable={isDayFocusableInSecondCalendar}
339
364
  onDayChange={onDayChange}
340
365
  isDaySelected={isDaySelected}
341
366
  isDayActive={isDayActive}
@@ -349,8 +374,6 @@ export const CalendarRange = ({
349
374
  isDayDisabled={isDayDisabled}
350
375
  listenDayChangesForUpdate={listenDayChangesForUpdate}
351
376
  renderDayContent={renderDayContent}
352
- tabIndex={0}
353
- onBlur={resetSelectedDay}
354
377
  dayTestId={dayTestId}
355
378
  />
356
379
  </div>
@@ -0,0 +1 @@
1
+ export type DateRangeType = [Date | null, Date | null];
@@ -0,0 +1,190 @@
1
+ import * as React from 'react';
2
+ import { isSameDate } from '@vkontakte/vkjs';
3
+ import { isAfter, isBefore, isSameDay, isSameMonth, startOfMonth } from 'date-fns';
4
+ import { Keys, pressedKey } from '../../lib/accessibility';
5
+ import { navigateDate, NAVIGATION_KEYS } from '../../lib/calendar';
6
+ import { isHTMLElement } from '../../lib/dom';
7
+ import type { DateRangeType } from './types';
8
+
9
+ export function useCalendarKeyboardNavigation({
10
+ focusedDay,
11
+ value,
12
+ setFocusedDay,
13
+ viewDates: [firstCalendarViewDate, secondCalendarViewDate],
14
+ setViewDate,
15
+ }: {
16
+ focusedDay: Date | undefined;
17
+ setViewDate: (date: Date) => void;
18
+ setFocusedDay: React.Dispatch<React.SetStateAction<Date | undefined>>;
19
+ viewDates: [Date, Date];
20
+ value: DateRangeType | null | undefined;
21
+ }) {
22
+ // соотвествует дню, на котором можно сфокусироваться с помощью Tab
23
+ const [focusableDayOnFirstCalendar, setFocusableDayOnFirstCalendar] = React.useState<Date>();
24
+ const [focusableDayOnSecondCalendar, setFocusableDayOnSecondCalendar] = React.useState<Date>();
25
+
26
+ const handleCalendarKeyDown = React.useCallback(
27
+ (event: React.KeyboardEvent, isFirst: boolean) => {
28
+ const key = pressedKey(event);
29
+ if (!key) {
30
+ return;
31
+ }
32
+
33
+ if (NAVIGATION_KEYS.includes(key)) {
34
+ event.preventDefault();
35
+
36
+ const newFocusedDay = navigateDate(focusedDay ?? value?.[0], key);
37
+
38
+ if (
39
+ newFocusedDay &&
40
+ !isSameMonth(newFocusedDay, firstCalendarViewDate) &&
41
+ !isSameMonth(newFocusedDay, secondCalendarViewDate)
42
+ ) {
43
+ setViewDate(newFocusedDay);
44
+ }
45
+
46
+ if (isFirst) {
47
+ if (isSameMonth(newFocusedDay, firstCalendarViewDate)) {
48
+ setFocusableDayOnFirstCalendar(newFocusedDay);
49
+ } else if (isAfter(newFocusedDay, firstCalendarViewDate)) {
50
+ setFocusableDayOnSecondCalendar(newFocusedDay);
51
+ }
52
+ } else {
53
+ if (isSameMonth(newFocusedDay, secondCalendarViewDate)) {
54
+ setFocusableDayOnSecondCalendar(newFocusedDay);
55
+ } else if (isBefore(newFocusedDay, secondCalendarViewDate)) {
56
+ setFocusableDayOnFirstCalendar(newFocusedDay);
57
+ }
58
+ }
59
+
60
+ setFocusedDay(newFocusedDay);
61
+
62
+ return;
63
+ }
64
+
65
+ if (key === Keys.TAB) {
66
+ setFocusedDay(undefined);
67
+ if (isFirst) {
68
+ setFocusableDayOnFirstCalendar(focusedDay);
69
+ } else {
70
+ setFocusableDayOnSecondCalendar(focusedDay);
71
+ }
72
+
73
+ return;
74
+ }
75
+
76
+ if ((key === Keys.ENTER || key === Keys.SPACE) && isHTMLElement(event.target)) {
77
+ event.preventDefault();
78
+ event.target.click?.();
79
+ }
80
+ },
81
+ [focusedDay, value, firstCalendarViewDate, secondCalendarViewDate, setFocusedDay, setViewDate],
82
+ );
83
+
84
+ const handleFirstCalendarKeyDown = React.useCallback(
85
+ (event: React.KeyboardEvent) => {
86
+ handleCalendarKeyDown(event, true);
87
+ },
88
+ [handleCalendarKeyDown],
89
+ );
90
+
91
+ const handleSecondCalendarKeyDown = React.useCallback(
92
+ (event: React.KeyboardEvent) => {
93
+ handleCalendarKeyDown(event, false);
94
+ },
95
+ [handleCalendarKeyDown],
96
+ );
97
+
98
+ const handleDayFocus = React.useCallback(
99
+ (value: Date) => {
100
+ if (
101
+ isSameMonth(firstCalendarViewDate, value) &&
102
+ (!focusableDayOnFirstCalendar || !isSameDate(focusableDayOnFirstCalendar, value))
103
+ ) {
104
+ setFocusableDayOnFirstCalendar(value);
105
+ }
106
+ if (
107
+ isSameMonth(secondCalendarViewDate, value) &&
108
+ (!focusableDayOnSecondCalendar || !isSameDate(focusableDayOnSecondCalendar, value))
109
+ ) {
110
+ setFocusableDayOnSecondCalendar(value);
111
+ }
112
+ },
113
+ [
114
+ firstCalendarViewDate,
115
+ focusableDayOnFirstCalendar,
116
+ focusableDayOnSecondCalendar,
117
+ secondCalendarViewDate,
118
+ ],
119
+ );
120
+
121
+ return {
122
+ focusableDayOnFirstCalendar,
123
+ focusableDayOnSecondCalendar,
124
+ handleFirstCalendarKeyDown,
125
+ handleSecondCalendarKeyDown,
126
+ handleDayFocus,
127
+ };
128
+ }
129
+
130
+ /**
131
+ * Возвращает функцию, которая позволяет проверить является ли день в календаре днём на который
132
+ * можно попасть с помощью Tab.
133
+ * Единственный день в таблице календаря у которого есть tabIndex="0"
134
+ * Чтобы на него можно было попасть из заголовка календаря.
135
+ */
136
+ export function useIsDayFocusable({
137
+ value,
138
+ focusableDayOnFirstCalendar,
139
+ focusableDayOnSecondCalendar,
140
+ viewDate,
141
+ isDayActive,
142
+ }: {
143
+ value: DateRangeType | null | undefined;
144
+ focusableDayOnFirstCalendar: Date | undefined;
145
+ focusableDayOnSecondCalendar: Date | undefined;
146
+ viewDate: Date;
147
+ isDayActive: (date: Date) => boolean;
148
+ }) {
149
+ const isValueVisibleOnCalendar = Boolean(
150
+ value &&
151
+ ((value[0] && isSameMonth(value[0], viewDate)) ||
152
+ (value[1] && isSameMonth(value[1], viewDate))),
153
+ );
154
+
155
+ const isCalendarHasFocusableDay = Boolean(
156
+ (focusableDayOnFirstCalendar && isSameMonth(focusableDayOnFirstCalendar, viewDate)) ||
157
+ (focusableDayOnSecondCalendar && isSameMonth(focusableDayOnSecondCalendar, viewDate)),
158
+ );
159
+
160
+ const isDayFocusable = React.useCallback(
161
+ (day: Date) => {
162
+ // если focusableDay день находится среди дней открытого сейчас месяца, то такой день получит tabIndex="0",
163
+ if (isCalendarHasFocusableDay) {
164
+ return Boolean(
165
+ (focusableDayOnFirstCalendar && isSameDay(focusableDayOnFirstCalendar, day)) ||
166
+ (focusableDayOnSecondCalendar && isSameDay(focusableDayOnSecondCalendar, day)),
167
+ );
168
+ }
169
+
170
+ // при открытии календаря focusableDay не определён,
171
+ // поэтому tabIndex="0" будет у дня, соответствующего дню в инпуте
172
+ if (isValueVisibleOnCalendar) {
173
+ return isDayActive(day);
174
+ }
175
+
176
+ // при переключении месяца любая навигация с помощью Tab начинается
177
+ // с первого дня месяца.
178
+ return isSameDay(startOfMonth(viewDate), day);
179
+ },
180
+ [
181
+ isCalendarHasFocusableDay,
182
+ isValueVisibleOnCalendar,
183
+ viewDate,
184
+ isDayActive,
185
+ focusableDayOnFirstCalendar,
186
+ focusableDayOnSecondCalendar,
187
+ ],
188
+ );
189
+ return isDayFocusable;
190
+ }
@@ -3,7 +3,7 @@ import { hasReactNode } from '@vkontakte/vkjs';
3
3
  import type { HasRootRef } from '../../types';
4
4
  import { SelectionControl } from '../SelectionControl/SelectionControl';
5
5
  import { SelectionControlLabel } from '../SelectionControl/SelectionControlLabel/SelectionControlLabel';
6
- import type { TappableProps } from '../Tappable/Tappable';
6
+ import type { TappableOmitProps } from '../Tappable/Tappable';
7
7
  import { CheckboxInput, type CheckboxInputProps } from './CheckboxInput/CheckboxInput';
8
8
  import { CheckboxSimple } from './CheckboxSimple/CheckboxSimple';
9
9
 
@@ -11,7 +11,7 @@ export interface CheckboxProps
11
11
  extends Omit<CheckboxInputProps, 'getRootRef'>,
12
12
  HasRootRef<HTMLLabelElement>,
13
13
  Pick<
14
- TappableProps,
14
+ TappableOmitProps,
15
15
  'hoverMode' | 'activeMode' | 'hasHover' | 'hasActive' | 'focusVisibleMode'
16
16
  > {
17
17
  /**
@@ -1,4 +1,5 @@
1
1
  import * as React from 'react';
2
+ import { escapeRegExp } from '@vkontakte/vkjs';
2
3
  import { useCustomEnsuredControl, useEnsuredControl } from '../../hooks/useEnsuredControl';
3
4
  import { useNativeFormResetListener } from '../../hooks/useNativeFormResetListener';
4
5
  import { simulateReactInput, type SimulateReactInputTargetState } from '../../lib/react';
@@ -36,6 +37,25 @@ export const transformValue = <O extends ChipOption>(
36
37
  value: getOptionValue(option),
37
38
  }));
38
39
 
40
+ function getRegExpFromArray(separators: string[]) {
41
+ const validSeparators = separators.filter((s) => s.length > 0);
42
+ if (validSeparators.length === 0) {
43
+ return null;
44
+ }
45
+ const escaped = validSeparators.map((s) => escapeRegExp(s));
46
+ return new RegExp(`(?:${escaped.join('|')})`);
47
+ }
48
+
49
+ function getRegexFromDelimiter(delimiter: string | RegExp | string[]): RegExp | null {
50
+ if (delimiter instanceof RegExp) {
51
+ return delimiter;
52
+ }
53
+ if (typeof delimiter === 'string') {
54
+ return new RegExp(escapeRegExp(delimiter));
55
+ }
56
+ return getRegExpFromArray(delimiter);
57
+ }
58
+
39
59
  interface ToggleOption<O extends ChipOption> {
40
60
  (optionsForAdd: Array<O | string>, isNewValue: true): void;
41
61
  (optionsForRemove: Array<O | ChipOptionValue>, isNewValue: false): void;
@@ -178,13 +198,14 @@ export const useChipsInput = <O extends ChipOption>({
178
198
  const onInputChange = React.useCallback(
179
199
  (e: React.ChangeEvent<HTMLInputElement>, canCreate = true) => {
180
200
  const newInputValue = e.target.value;
181
- if (!delimiter || !newInputValue.includes(delimiter) || !canCreate) {
201
+ const delimiterRegex = delimiter ? getRegexFromDelimiter(delimiter) : null;
202
+ if (!delimiterRegex || !delimiterRegex.test(newInputValue) || !canCreate) {
182
203
  setInputChange(e);
183
204
  return;
184
205
  }
185
206
  const values = newInputValue
186
207
  .trim()
187
- .split(delimiter)
208
+ .split(delimiterRegex)
188
209
  .map((v) => v.trim())
189
210
  .filter(Boolean);
190
211
 
@@ -128,6 +128,10 @@ export interface UseChipsInputBaseProps<O extends ChipOption = ChipOption> {
128
128
  onInputChange?: OnInputChange;
129
129
  /**
130
130
  * Символ или строка, которая будет использоваться как разделитель для автоматического создания опций из текста, введенного в поле ввода.
131
+ * Принимает:
132
+ * - `string` - простая строка
133
+ * - `RegExp` - регулярное выражение
134
+ * - `string[]` - массив строк, по которым нужно разелять ввод.
131
135
  *
132
136
  * Работает в двух сценариях:
133
137
  * 1. При вводе разделителя - текст до разделителя автоматически преобразуется в новую опцию.
@@ -138,7 +142,7 @@ export interface UseChipsInputBaseProps<O extends ChipOption = ChipOption> {
138
142
  * Например, при `delimiter=","` вставка "опция1,опция2,опция3" создаст
139
143
  * три отдельные опции: "опция1", "опция2" и "опция3".
140
144
  */
141
- delimiter?: string;
145
+ delimiter?: string | RegExp | string[];
142
146
  }
143
147
 
144
148
  /**
@@ -9,7 +9,12 @@ import styles from './Clickable.module.css';
9
9
  export interface ClickableProps<T = HTMLElement>
10
10
  extends RootComponentProps<T>,
11
11
  FocusVisibleModeProps,
12
- StateProps {}
12
+ StateProps {
13
+ /**
14
+ * Компонент который будет при передаче `onClick`. По умолчанию `"div"`.
15
+ */
16
+ DefaultComponent?: React.ElementType;
17
+ }
13
18
 
14
19
  /**
15
20
  * Некликабельный компонент. Отключаем возможность нажимать на компонент.
@@ -27,8 +32,10 @@ const NonClickable = <T,>({
27
32
  activated,
28
33
  activeEffectDelay,
29
34
  focusVisibleMode,
35
+ DefaultComponent,
36
+ Component,
30
37
  ...restProps
31
- }: ClickableProps<T>) => <RootComponent {...restProps} />;
38
+ }: ClickableProps<T>) => <RootComponent Component={Component || DefaultComponent} {...restProps} />;
32
39
 
33
40
  /**
34
41
  * Проверяем, является ли компонент кликабельным.
@@ -56,11 +63,12 @@ export function checkClickable<T>(props: ClickableProps<T>): boolean {
56
63
  */
57
64
  function component<T>({
58
65
  Component,
66
+ DefaultComponent = 'div',
59
67
  onClick,
60
68
  onClickCapture,
61
69
  href,
62
70
  disabled,
63
- }: RootComponentProps<T>): RootComponentProps<T> {
71
+ }: ClickableProps<T>): RootComponentProps<T> {
64
72
  if (Component !== undefined) {
65
73
  return { Component, disabled };
66
74
  } else if (href !== undefined) {
@@ -83,7 +91,7 @@ function component<T>({
83
91
  };
84
92
  } else if (onClick !== undefined || onClickCapture !== undefined) {
85
93
  return {
86
- Component: 'div',
94
+ Component: DefaultComponent,
87
95
  role: 'button',
88
96
  ...(disabled ? { 'aria-disabled': true } : { tabIndex: 0 }),
89
97
  };