@vkontakte/vkui 4.34.2 → 4.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (453) hide show
  1. package/.browserslistrc +5 -0
  2. package/.cache/.eslintcache +1 -1
  3. package/.cache/.stylelintcache +1 -1
  4. package/.cache/.tsbuildinfo +237 -211
  5. package/.cache/ts/src/components/ConfigProvider/ConfigProviderContext.d.ts +1 -0
  6. package/.cache/ts/src/components/CustomSelect/CustomSelect.d.ts +1 -1
  7. package/.cache/ts/src/components/Dropdown/Dropdown.d.ts +46 -5
  8. package/.cache/ts/src/components/FocusTrap/FocusTrap.d.ts +1 -1
  9. package/.cache/ts/src/components/ModalRoot/ModalRoot.d.ts +1 -1
  10. package/.cache/ts/src/components/ModalRoot/ModalRootDesktop.d.ts +1 -1
  11. package/.cache/ts/src/components/Popper/Popper.d.ts +18 -1
  12. package/.cache/ts/src/components/PopperArrow/PopperArrow.d.ts +8 -0
  13. package/.cache/ts/src/components/RichTooltip/RichTooltip.d.ts +7 -2
  14. package/.cache/ts/src/components/Snackbar/Snackbar.d.ts +5 -1
  15. package/.cache/ts/src/components/SplitCol/SplitCol.d.ts +1 -0
  16. package/.cache/ts/src/components/Tabbar/Tabbar.d.ts +8 -1
  17. package/.cache/ts/src/components/Tabs/Tabs.d.ts +13 -2
  18. package/.cache/ts/src/components/TabsItem/TabsItem.d.ts +22 -1
  19. package/.cache/ts/src/components/TextTooltip/TextTooltip.d.ts +5 -1
  20. package/.cache/ts/src/components/Tooltip/Tooltip.d.ts +18 -1
  21. package/.cache/ts/src/components/Typography/Headline/Headline.d.ts +3 -3
  22. package/.cache/ts/src/components/View/View.d.ts +2 -18
  23. package/.cache/ts/src/components/View/ViewInfinite.d.ts +1 -1
  24. package/.cache/ts/src/components/WriteBar/WriteBar.d.ts +5 -1
  25. package/.cache/ts/src/tokenized/index.d.ts +26 -0
  26. package/.eslintrc.json +14 -4
  27. package/dist/cjs/components/CardScroll/CardScroll.js +3 -1
  28. package/dist/cjs/components/CardScroll/CardScroll.js.map +1 -1
  29. package/dist/cjs/components/ConfigProvider/ConfigProviderContext.js +7 -1
  30. package/dist/cjs/components/ConfigProvider/ConfigProviderContext.js.map +1 -1
  31. package/dist/cjs/components/CustomSelect/CustomSelect.js +477 -554
  32. package/dist/cjs/components/CustomSelect/CustomSelect.js.map +1 -1
  33. package/dist/cjs/components/Dropdown/Dropdown.js +147 -26
  34. package/dist/cjs/components/Dropdown/Dropdown.js.map +1 -1
  35. package/dist/cjs/components/Epic/Epic.js +1 -6
  36. package/dist/cjs/components/Epic/Epic.js.map +1 -1
  37. package/dist/cjs/components/FocusTrap/FocusTrap.js +9 -10
  38. package/dist/cjs/components/FocusTrap/FocusTrap.js.map +1 -1
  39. package/dist/cjs/components/HorizontalCell/HorizontalCell.js +4 -7
  40. package/dist/cjs/components/HorizontalCell/HorizontalCell.js.map +1 -1
  41. package/dist/cjs/components/MiniInfoCell/MiniInfoCell.js +2 -2
  42. package/dist/cjs/components/MiniInfoCell/MiniInfoCell.js.map +1 -1
  43. package/dist/cjs/components/Popper/Popper.js +11 -19
  44. package/dist/cjs/components/Popper/Popper.js.map +1 -1
  45. package/dist/cjs/components/PopperArrow/PopperArrow.js +40 -0
  46. package/dist/cjs/components/PopperArrow/PopperArrow.js.map +1 -0
  47. package/dist/cjs/components/RichTooltip/RichTooltip.js +6 -15
  48. package/dist/cjs/components/RichTooltip/RichTooltip.js.map +1 -1
  49. package/dist/cjs/components/SimpleCell/SimpleCell.js +20 -31
  50. package/dist/cjs/components/SimpleCell/SimpleCell.js.map +1 -1
  51. package/dist/cjs/components/Snackbar/Snackbar.js +7 -11
  52. package/dist/cjs/components/Snackbar/Snackbar.js.map +1 -1
  53. package/dist/cjs/components/SplitCol/SplitCol.js +7 -1
  54. package/dist/cjs/components/SplitCol/SplitCol.js.map +1 -1
  55. package/dist/cjs/components/SplitLayout/SplitLayout.js +5 -8
  56. package/dist/cjs/components/SplitLayout/SplitLayout.js.map +1 -1
  57. package/dist/cjs/components/Tabbar/Tabbar.js +15 -14
  58. package/dist/cjs/components/Tabbar/Tabbar.js.map +1 -1
  59. package/dist/cjs/components/TabbarItem/TabbarItem.js +8 -10
  60. package/dist/cjs/components/TabbarItem/TabbarItem.js.map +1 -1
  61. package/dist/cjs/components/Tabs/Tabs.js +23 -5
  62. package/dist/cjs/components/Tabs/Tabs.js.map +1 -1
  63. package/dist/cjs/components/TabsItem/TabsItem.js +39 -22
  64. package/dist/cjs/components/TabsItem/TabsItem.js.map +1 -1
  65. package/dist/cjs/components/TextTooltip/TextTooltip.js +6 -9
  66. package/dist/cjs/components/TextTooltip/TextTooltip.js.map +1 -1
  67. package/dist/cjs/components/Tooltip/Tooltip.js +94 -71
  68. package/dist/cjs/components/Tooltip/Tooltip.js.map +1 -1
  69. package/dist/cjs/components/Typography/Headline/Headline.js +11 -2
  70. package/dist/cjs/components/Typography/Headline/Headline.js.map +1 -1
  71. package/dist/cjs/components/View/View.js +388 -453
  72. package/dist/cjs/components/View/View.js.map +1 -1
  73. package/dist/cjs/components/WriteBar/WriteBar.js +12 -5
  74. package/dist/cjs/components/WriteBar/WriteBar.js.map +1 -1
  75. package/dist/cjs/components/WriteBarIcon/WriteBarIcon.js +3 -8
  76. package/dist/cjs/components/WriteBarIcon/WriteBarIcon.js.map +1 -1
  77. package/dist/cjs/hooks/useOrientationChange.js +2 -1
  78. package/dist/cjs/hooks/useOrientationChange.js.map +1 -1
  79. package/dist/cjs/tokenized/index.js +104 -0
  80. package/dist/cjs/tokenized/index.js.map +1 -1
  81. package/dist/components/CardScroll/CardScroll.js +3 -1
  82. package/dist/components/CardScroll/CardScroll.js.map +1 -1
  83. package/dist/components/ConfigProvider/ConfigProviderContext.d.ts +1 -0
  84. package/dist/components/ConfigProvider/ConfigProviderContext.js +3 -0
  85. package/dist/components/ConfigProvider/ConfigProviderContext.js.map +1 -1
  86. package/dist/components/CustomSelect/CustomSelect.d.ts +1 -1
  87. package/dist/components/CustomSelect/CustomSelect.js +473 -580
  88. package/dist/components/CustomSelect/CustomSelect.js.map +1 -1
  89. package/dist/components/Dropdown/Dropdown.d.ts +46 -5
  90. package/dist/components/Dropdown/Dropdown.js +137 -27
  91. package/dist/components/Dropdown/Dropdown.js.map +1 -1
  92. package/dist/components/Epic/Epic.js +1 -4
  93. package/dist/components/Epic/Epic.js.map +1 -1
  94. package/dist/components/FocusTrap/FocusTrap.d.ts +1 -1
  95. package/dist/components/FocusTrap/FocusTrap.js +9 -9
  96. package/dist/components/FocusTrap/FocusTrap.js.map +1 -1
  97. package/dist/components/HorizontalCell/HorizontalCell.js +3 -5
  98. package/dist/components/HorizontalCell/HorizontalCell.js.map +1 -1
  99. package/dist/components/MiniInfoCell/MiniInfoCell.js +2 -2
  100. package/dist/components/MiniInfoCell/MiniInfoCell.js.map +1 -1
  101. package/dist/components/ModalRoot/ModalRoot.d.ts +1 -1
  102. package/dist/components/ModalRoot/ModalRootDesktop.d.ts +1 -1
  103. package/dist/components/Popper/Popper.d.ts +18 -1
  104. package/dist/components/Popper/Popper.js +10 -19
  105. package/dist/components/Popper/Popper.js.map +1 -1
  106. package/dist/components/PopperArrow/PopperArrow.d.ts +8 -0
  107. package/dist/components/PopperArrow/PopperArrow.js +27 -0
  108. package/dist/components/PopperArrow/PopperArrow.js.map +1 -0
  109. package/dist/components/RichTooltip/RichTooltip.d.ts +7 -2
  110. package/dist/components/RichTooltip/RichTooltip.js +5 -10
  111. package/dist/components/RichTooltip/RichTooltip.js.map +1 -1
  112. package/dist/components/SimpleCell/SimpleCell.js +18 -28
  113. package/dist/components/SimpleCell/SimpleCell.js.map +1 -1
  114. package/dist/components/Snackbar/Snackbar.d.ts +5 -1
  115. package/dist/components/Snackbar/Snackbar.js +8 -11
  116. package/dist/components/Snackbar/Snackbar.js.map +1 -1
  117. package/dist/components/SplitCol/SplitCol.d.ts +1 -0
  118. package/dist/components/SplitCol/SplitCol.js +3 -0
  119. package/dist/components/SplitCol/SplitCol.js.map +1 -1
  120. package/dist/components/SplitLayout/SplitLayout.js +4 -7
  121. package/dist/components/SplitLayout/SplitLayout.js.map +1 -1
  122. package/dist/components/Tabbar/Tabbar.d.ts +8 -1
  123. package/dist/components/Tabbar/Tabbar.js +15 -14
  124. package/dist/components/Tabbar/Tabbar.js.map +1 -1
  125. package/dist/components/TabbarItem/TabbarItem.js +7 -9
  126. package/dist/components/TabbarItem/TabbarItem.js.map +1 -1
  127. package/dist/components/Tabs/Tabs.d.ts +13 -2
  128. package/dist/components/Tabs/Tabs.js +23 -5
  129. package/dist/components/Tabs/Tabs.js.map +1 -1
  130. package/dist/components/TabsItem/TabsItem.d.ts +22 -1
  131. package/dist/components/TabsItem/TabsItem.js +40 -21
  132. package/dist/components/TabsItem/TabsItem.js.map +1 -1
  133. package/dist/components/TextTooltip/TextTooltip.d.ts +5 -1
  134. package/dist/components/TextTooltip/TextTooltip.js +5 -7
  135. package/dist/components/TextTooltip/TextTooltip.js.map +1 -1
  136. package/dist/components/Tooltip/Tooltip.d.ts +18 -1
  137. package/dist/components/Tooltip/Tooltip.js +89 -68
  138. package/dist/components/Tooltip/Tooltip.js.map +1 -1
  139. package/dist/components/Typography/Headline/Headline.d.ts +3 -3
  140. package/dist/components/Typography/Headline/Headline.js +10 -2
  141. package/dist/components/Typography/Headline/Headline.js.map +1 -1
  142. package/dist/components/View/View.d.ts +2 -18
  143. package/dist/components/View/View.js +384 -462
  144. package/dist/components/View/View.js.map +1 -1
  145. package/dist/components/View/ViewInfinite.d.ts +1 -1
  146. package/dist/components/WriteBar/WriteBar.d.ts +5 -1
  147. package/dist/components/WriteBar/WriteBar.js +10 -5
  148. package/dist/components/WriteBar/WriteBar.js.map +1 -1
  149. package/dist/components/WriteBarIcon/WriteBarIcon.js +3 -6
  150. package/dist/components/WriteBarIcon/WriteBarIcon.js.map +1 -1
  151. package/dist/components.css +143 -127
  152. package/dist/components.css.map +1 -1
  153. package/dist/cssm/components/ActionSheet/ActionSheet.css +1 -1
  154. package/dist/cssm/components/ActionSheetItem/ActionSheetItem.css +1 -1
  155. package/dist/cssm/components/Alert/Alert.css +1 -1
  156. package/dist/cssm/components/AppRoot/AppRoot.css +1 -1
  157. package/dist/cssm/components/Avatar/Avatar.css +3 -5
  158. package/dist/cssm/components/Badge/Badge.css +3 -3
  159. package/dist/cssm/components/Banner/Banner.css +5 -5
  160. package/dist/cssm/components/BaseGallery/BaseGallery.css +1 -1
  161. package/dist/cssm/components/Button/Button.css +53 -35
  162. package/dist/cssm/components/Calendar/Calendar.css +1 -1
  163. package/dist/cssm/components/CalendarDay/CalendarDay.css +1 -1
  164. package/dist/cssm/components/CalendarDays/CalendarDays.css +1 -1
  165. package/dist/cssm/components/CalendarHeader/CalendarHeader.css +1 -1
  166. package/dist/cssm/components/CalendarRange/CalendarRange.css +1 -1
  167. package/dist/cssm/components/CalendarTime/CalendarTime.css +1 -1
  168. package/dist/cssm/components/Card/Card.css +5 -6
  169. package/dist/cssm/components/CardGrid/CardGrid.css +1 -1
  170. package/dist/cssm/components/CardScroll/CardScroll.css +1 -1
  171. package/dist/cssm/components/CardScroll/CardScroll.js +3 -1
  172. package/dist/cssm/components/CardScroll/CardScroll.js.map +1 -1
  173. package/dist/cssm/components/Cell/Cell.css +3 -3
  174. package/dist/cssm/components/Cell/CellCheckbox/CellCheckbox.css +1 -1
  175. package/dist/cssm/components/Cell/CellDragger/CellDragger.css +1 -1
  176. package/dist/cssm/components/CellButton/CellButton.css +1 -1
  177. package/dist/cssm/components/Checkbox/Checkbox.css +1 -1
  178. package/dist/cssm/components/Chip/Chip.css +1 -1
  179. package/dist/cssm/components/ChipsInput/ChipsInput.css +1 -1
  180. package/dist/cssm/components/ChipsSelect/ChipsSelect.css +1 -1
  181. package/dist/cssm/components/ConfigProvider/ConfigProviderContext.d.ts +1 -0
  182. package/dist/cssm/components/ConfigProvider/ConfigProviderContext.js +3 -0
  183. package/dist/cssm/components/ConfigProvider/ConfigProviderContext.js.map +1 -1
  184. package/dist/cssm/components/ContentCard/ContentCard.css +1 -1
  185. package/dist/cssm/components/Counter/Counter.css +31 -31
  186. package/dist/cssm/components/CustomScrollView/CustomScrollView.css +1 -1
  187. package/dist/cssm/components/CustomSelect/CustomSelect.css +1 -1
  188. package/dist/cssm/components/CustomSelect/CustomSelect.d.ts +1 -1
  189. package/dist/cssm/components/CustomSelect/CustomSelect.js +473 -580
  190. package/dist/cssm/components/CustomSelect/CustomSelect.js.map +1 -1
  191. package/dist/cssm/components/CustomSelectDropdown/CustomSelectDropdown.css +3 -3
  192. package/dist/cssm/components/CustomSelectOption/CustomSelectOption.css +3 -3
  193. package/dist/cssm/components/DateInput/DateInput.css +1 -1
  194. package/dist/cssm/components/DatePicker/DatePicker.css +1 -1
  195. package/dist/cssm/components/DateRangeInput/DateRangeInput.css +1 -1
  196. package/dist/cssm/components/Dropdown/Dropdown.css +1 -1
  197. package/dist/cssm/components/Dropdown/Dropdown.d.ts +46 -5
  198. package/dist/cssm/components/Dropdown/Dropdown.js +137 -27
  199. package/dist/cssm/components/Dropdown/Dropdown.js.map +1 -1
  200. package/dist/cssm/components/Epic/Epic.css +1 -1
  201. package/dist/cssm/components/Epic/Epic.js +1 -4
  202. package/dist/cssm/components/Epic/Epic.js.map +1 -1
  203. package/dist/cssm/components/FixedLayout/FixedLayout.css +1 -1
  204. package/dist/cssm/components/FocusTrap/FocusTrap.d.ts +1 -1
  205. package/dist/cssm/components/FocusTrap/FocusTrap.js +9 -9
  206. package/dist/cssm/components/FocusTrap/FocusTrap.js.map +1 -1
  207. package/dist/cssm/components/FocusVisible/FocusVisible.css +1 -1
  208. package/dist/cssm/components/Footer/Footer.css +1 -1
  209. package/dist/cssm/components/FormField/FormField.css +9 -9
  210. package/dist/cssm/components/FormItem/FormItem.css +1 -1
  211. package/dist/cssm/components/FormLayout/FormLayout.css +1 -1
  212. package/dist/cssm/components/FormLayoutGroup/FormLayoutGroup.css +1 -1
  213. package/dist/cssm/components/FormStatus/FormStatus.css +1 -1
  214. package/dist/cssm/components/Gradient/Gradient.css +1 -1
  215. package/dist/cssm/components/GridAvatar/GridAvatar.css +1 -1
  216. package/dist/cssm/components/Group/Group.css +1 -1
  217. package/dist/cssm/components/Header/Header.css +1 -1
  218. package/dist/cssm/components/HorizontalCell/HorizontalCell.css +1 -1
  219. package/dist/cssm/components/HorizontalCell/HorizontalCell.js +3 -5
  220. package/dist/cssm/components/HorizontalCell/HorizontalCell.js.map +1 -1
  221. package/dist/cssm/components/HorizontalScroll/HorizontalScroll.css +1 -1
  222. package/dist/cssm/components/HorizontalScroll/HorizontalScrollArrow.css +3 -3
  223. package/dist/cssm/components/IconButton/IconButton.css +1 -1
  224. package/dist/cssm/components/InfoRow/InfoRow.css +1 -1
  225. package/dist/cssm/components/InitialsAvatar/InitialsAvatar.css +1 -1
  226. package/dist/cssm/components/Input/Input.css +1 -1
  227. package/dist/cssm/components/InputLike/InputLike.css +1 -1
  228. package/dist/cssm/components/InputLike/InputLikeDivider.css +1 -1
  229. package/dist/cssm/components/Link/Link.css +1 -1
  230. package/dist/cssm/components/MiniInfoCell/MiniInfoCell.css +1 -1
  231. package/dist/cssm/components/MiniInfoCell/MiniInfoCell.js +2 -2
  232. package/dist/cssm/components/MiniInfoCell/MiniInfoCell.js.map +1 -1
  233. package/dist/cssm/components/ModalCard/ModalCard.css +1 -1
  234. package/dist/cssm/components/ModalCardBase/ModalCardBase.css +3 -3
  235. package/dist/cssm/components/ModalDismissButton/ModalDismissButton.css +1 -1
  236. package/dist/cssm/components/ModalPage/ModalPage.css +1 -1
  237. package/dist/cssm/components/ModalPageHeader/ModalPageHeader.css +1 -1
  238. package/dist/cssm/components/ModalRoot/ModalRoot.css +1 -1
  239. package/dist/cssm/components/ModalRoot/ModalRoot.d.ts +1 -1
  240. package/dist/cssm/components/ModalRoot/ModalRootDesktop.d.ts +1 -1
  241. package/dist/cssm/components/Pagination/Pagination.css +1 -1
  242. package/dist/cssm/components/Panel/Panel.css +1 -1
  243. package/dist/cssm/components/PanelHeader/PanelHeader.css +1 -1
  244. package/dist/cssm/components/PanelHeaderButton/PanelHeaderButton.css +1 -1
  245. package/dist/cssm/components/PanelHeaderContent/PanelHeaderContent.css +1 -1
  246. package/dist/cssm/components/PanelHeaderContext/PanelHeaderContext.css +1 -1
  247. package/dist/cssm/components/Placeholder/Placeholder.css +3 -3
  248. package/dist/cssm/components/PopoutRoot/PopoutRoot.css +1 -1
  249. package/dist/cssm/components/PopoutWrapper/PopoutWrapper.css +1 -1
  250. package/dist/cssm/components/Popper/Popper.css +1 -1
  251. package/dist/cssm/components/Popper/Popper.d.ts +18 -1
  252. package/dist/cssm/components/Popper/Popper.js +10 -19
  253. package/dist/cssm/components/Popper/Popper.js.map +1 -1
  254. package/dist/cssm/components/PopperArrow/PopperArrow.css +1 -0
  255. package/dist/cssm/components/PopperArrow/PopperArrow.d.ts +8 -0
  256. package/dist/cssm/components/PopperArrow/PopperArrow.js +28 -0
  257. package/dist/cssm/components/PopperArrow/PopperArrow.js.map +1 -0
  258. package/dist/cssm/components/Progress/Progress.css +1 -1
  259. package/dist/cssm/components/PromoBanner/PromoBanner.css +1 -1
  260. package/dist/cssm/components/PullToRefresh/PullToRefresh.css +3 -3
  261. package/dist/cssm/components/Radio/Radio.css +1 -1
  262. package/dist/cssm/components/RadioGroup/RadioGroup.css +1 -1
  263. package/dist/cssm/components/Removable/Removable.css +1 -1
  264. package/dist/cssm/components/RichCell/RichCell.css +3 -3
  265. package/dist/cssm/components/RichTooltip/RichTooltip.css +3 -1
  266. package/dist/cssm/components/RichTooltip/RichTooltip.d.ts +7 -2
  267. package/dist/cssm/components/RichTooltip/RichTooltip.js +5 -10
  268. package/dist/cssm/components/RichTooltip/RichTooltip.js.map +1 -1
  269. package/dist/cssm/components/Root/Root.css +1 -1
  270. package/dist/cssm/components/ScreenSpinner/ScreenSpinner.css +1 -1
  271. package/dist/cssm/components/Search/Search.css +1 -1
  272. package/dist/cssm/components/SegmentedControl/SegmentedControl.css +1 -1
  273. package/dist/cssm/components/SegmentedControl/SegmentedControlOption/SegmentedControlOption.css +1 -1
  274. package/dist/cssm/components/Select/Select.css +1 -1
  275. package/dist/cssm/components/Separator/Separator.css +1 -1
  276. package/dist/cssm/components/SimpleCell/SimpleCell.css +1 -1
  277. package/dist/cssm/components/SimpleCell/SimpleCell.js +18 -28
  278. package/dist/cssm/components/SimpleCell/SimpleCell.js.map +1 -1
  279. package/dist/cssm/components/SimpleCheckbox/SimpleCheckbox.css +1 -1
  280. package/dist/cssm/components/Slider/Slider.css +3 -3
  281. package/dist/cssm/components/SliderSwitch/SliderSwitch.css +1 -1
  282. package/dist/cssm/components/Snackbar/Snackbar.css +1 -1
  283. package/dist/cssm/components/Snackbar/Snackbar.d.ts +5 -1
  284. package/dist/cssm/components/Snackbar/Snackbar.js +8 -11
  285. package/dist/cssm/components/Snackbar/Snackbar.js.map +1 -1
  286. package/dist/cssm/components/Spacing/Spacing.css +1 -1
  287. package/dist/cssm/components/Spinner/Spinner.css +1 -1
  288. package/dist/cssm/components/SplitCol/SplitCol.css +1 -1
  289. package/dist/cssm/components/SplitCol/SplitCol.d.ts +1 -0
  290. package/dist/cssm/components/SplitCol/SplitCol.js +3 -0
  291. package/dist/cssm/components/SplitCol/SplitCol.js.map +1 -1
  292. package/dist/cssm/components/SplitLayout/SplitLayout.css +1 -1
  293. package/dist/cssm/components/SplitLayout/SplitLayout.js +4 -7
  294. package/dist/cssm/components/SplitLayout/SplitLayout.js.map +1 -1
  295. package/dist/cssm/components/SubnavigationBar/SubnavigationBar.css +1 -1
  296. package/dist/cssm/components/SubnavigationButton/SubnavigationButton.css +1 -1
  297. package/dist/cssm/components/Switch/Switch.css +3 -3
  298. package/dist/cssm/components/Tabbar/Tabbar.css +5 -3
  299. package/dist/cssm/components/Tabbar/Tabbar.d.ts +8 -1
  300. package/dist/cssm/components/Tabbar/Tabbar.js +15 -14
  301. package/dist/cssm/components/Tabbar/Tabbar.js.map +1 -1
  302. package/dist/cssm/components/TabbarItem/TabbarItem.css +1 -1
  303. package/dist/cssm/components/TabbarItem/TabbarItem.js +7 -9
  304. package/dist/cssm/components/TabbarItem/TabbarItem.js.map +1 -1
  305. package/dist/cssm/components/Tabs/Tabs.css +1 -1
  306. package/dist/cssm/components/Tabs/Tabs.d.ts +13 -2
  307. package/dist/cssm/components/Tabs/Tabs.js +23 -5
  308. package/dist/cssm/components/Tabs/Tabs.js.map +1 -1
  309. package/dist/cssm/components/TabsItem/TabsItem.css +5 -1
  310. package/dist/cssm/components/TabsItem/TabsItem.d.ts +22 -1
  311. package/dist/cssm/components/TabsItem/TabsItem.js +40 -21
  312. package/dist/cssm/components/TabsItem/TabsItem.js.map +1 -1
  313. package/dist/cssm/components/Tappable/Tappable.css +5 -5
  314. package/dist/cssm/components/TextTooltip/TextTooltip.css +1 -1
  315. package/dist/cssm/components/TextTooltip/TextTooltip.d.ts +5 -1
  316. package/dist/cssm/components/TextTooltip/TextTooltip.js +5 -7
  317. package/dist/cssm/components/TextTooltip/TextTooltip.js.map +1 -1
  318. package/dist/cssm/components/Textarea/Textarea.css +1 -1
  319. package/dist/cssm/components/Tooltip/Tooltip.css +1 -1
  320. package/dist/cssm/components/Tooltip/Tooltip.d.ts +18 -1
  321. package/dist/cssm/components/Tooltip/Tooltip.js +89 -68
  322. package/dist/cssm/components/Tooltip/Tooltip.js.map +1 -1
  323. package/dist/cssm/components/Typography/Caption/Caption.css +1 -1
  324. package/dist/cssm/components/Typography/Footnote/Footnote.css +1 -1
  325. package/dist/cssm/components/Typography/Headline/Headline.css +1 -1
  326. package/dist/cssm/components/Typography/Headline/Headline.d.ts +3 -3
  327. package/dist/cssm/components/Typography/Headline/Headline.js +10 -2
  328. package/dist/cssm/components/Typography/Headline/Headline.js.map +1 -1
  329. package/dist/cssm/components/Typography/Paragraph/Paragraph.css +1 -1
  330. package/dist/cssm/components/Typography/Subhead/Subhead.css +1 -1
  331. package/dist/cssm/components/Typography/Text/Text.css +1 -1
  332. package/dist/cssm/components/Typography/Title/Title.css +1 -1
  333. package/dist/cssm/components/UsersStack/UsersStack.css +5 -5
  334. package/dist/cssm/components/View/View.css +1 -1
  335. package/dist/cssm/components/View/View.d.ts +2 -18
  336. package/dist/cssm/components/View/View.js +384 -462
  337. package/dist/cssm/components/View/View.js.map +1 -1
  338. package/dist/cssm/components/View/ViewIOS.css +1 -1
  339. package/dist/cssm/components/View/ViewInfinite.d.ts +1 -1
  340. package/dist/cssm/components/VisuallyHiddenInput/VisuallyHiddenInput.css +1 -1
  341. package/dist/cssm/components/WriteBar/WriteBar.css +3 -1
  342. package/dist/cssm/components/WriteBar/WriteBar.d.ts +5 -1
  343. package/dist/cssm/components/WriteBar/WriteBar.js +10 -5
  344. package/dist/cssm/components/WriteBar/WriteBar.js.map +1 -1
  345. package/dist/cssm/components/WriteBarIcon/WriteBarIcon.css +1 -1
  346. package/dist/cssm/components/WriteBarIcon/WriteBarIcon.js +3 -6
  347. package/dist/cssm/components/WriteBarIcon/WriteBarIcon.js.map +1 -1
  348. package/dist/cssm/fonts/fonts.css +1 -1
  349. package/dist/cssm/hooks/useOrientationChange.js +2 -1
  350. package/dist/cssm/hooks/useOrientationChange.js.map +1 -1
  351. package/dist/cssm/lib/calendar.d.ts +2 -2
  352. package/dist/cssm/styles/animations.css +1 -1
  353. package/dist/cssm/styles/bright_light.css +1 -1
  354. package/dist/cssm/styles/common.css +1 -1
  355. package/dist/cssm/styles/components.css +143 -127
  356. package/dist/cssm/styles/constants.css +3 -10
  357. package/dist/cssm/styles/space_gray.css +1 -1
  358. package/dist/cssm/styles/themes.css +1 -16
  359. package/dist/cssm/styles/unstable.css +3 -1
  360. package/dist/cssm/styles/vkcom_dark.css +1 -6
  361. package/dist/cssm/styles/vkcom_light.css +1 -11
  362. package/dist/cssm/tokenized/index.d.ts +26 -0
  363. package/dist/cssm/tokenized/index.js +13 -0
  364. package/dist/cssm/tokenized/index.js.map +1 -1
  365. package/dist/default_scheme.css +1 -1
  366. package/dist/default_scheme.css.map +1 -1
  367. package/dist/fonts.css +1 -1
  368. package/dist/fonts.css.map +1 -1
  369. package/dist/hooks/useOrientationChange.js +2 -1
  370. package/dist/hooks/useOrientationChange.js.map +1 -1
  371. package/dist/lib/calendar.d.ts +2 -2
  372. package/dist/tokenized/index.d.ts +26 -0
  373. package/dist/tokenized/index.js +13 -0
  374. package/dist/tokenized/index.js.map +1 -1
  375. package/dist/unstable.css +3 -1
  376. package/dist/unstable.css.map +1 -1
  377. package/dist/vkui.css +144 -143
  378. package/dist/vkui.css.map +1 -1
  379. package/package.json +6 -5
  380. package/src/components/Badge/Badge.css +0 -5
  381. package/src/components/CardScroll/CardScroll.tsx +1 -1
  382. package/src/components/Cell/Cell.css +3 -2
  383. package/src/components/ChipsInput/ChipsInput.css +2 -0
  384. package/src/components/ConfigProvider/ConfigProviderContext.tsx +2 -0
  385. package/src/components/Counter/Counter.css +30 -0
  386. package/src/components/CustomScrollView/CustomScrollView.css +10 -5
  387. package/src/components/CustomSelect/CustomSelect.tsx +543 -574
  388. package/src/components/Dropdown/Dropdown.css +12 -0
  389. package/src/components/Dropdown/Dropdown.tsx +174 -20
  390. package/src/components/Dropdown/Readme.md +1 -0
  391. package/src/components/Epic/Epic.tsx +1 -4
  392. package/src/components/FixedLayout/Readme.md +103 -109
  393. package/src/components/FocusTrap/FocusTrap.tsx +10 -10
  394. package/src/components/Group/Group.css +1 -1
  395. package/src/components/HorizontalCell/HorizontalCell.css +25 -43
  396. package/src/components/HorizontalCell/HorizontalCell.tsx +3 -9
  397. package/src/components/HorizontalScroll/HorizontalScroll.css +23 -0
  398. package/src/components/Input/Input.css +2 -0
  399. package/src/components/MiniInfoCell/MiniInfoCell.css +13 -3
  400. package/src/components/MiniInfoCell/MiniInfoCell.tsx +3 -3
  401. package/src/components/Popper/Popper.css +0 -35
  402. package/src/components/Popper/Popper.tsx +29 -23
  403. package/src/components/PopperArrow/PopperArrow.css +34 -0
  404. package/src/components/PopperArrow/PopperArrow.tsx +40 -0
  405. package/src/components/RichTooltip/RichTooltip.css +44 -4
  406. package/src/components/RichTooltip/RichTooltip.tsx +9 -11
  407. package/src/components/SimpleCell/Readme.md +115 -129
  408. package/src/components/SimpleCell/SimpleCell.css +30 -68
  409. package/src/components/SimpleCell/SimpleCell.tsx +21 -25
  410. package/src/components/Snackbar/Readme.md +95 -123
  411. package/src/components/Snackbar/Snackbar.css +18 -27
  412. package/src/components/Snackbar/Snackbar.tsx +17 -11
  413. package/src/components/SplitCol/SplitCol.tsx +2 -0
  414. package/src/components/SplitLayout/SplitLayout.css +3 -7
  415. package/src/components/SplitLayout/SplitLayout.tsx +9 -6
  416. package/src/components/Tabbar/Tabbar.css +4 -1
  417. package/src/components/Tabbar/Tabbar.tsx +23 -12
  418. package/src/components/TabbarItem/TabbarItem.css +7 -5
  419. package/src/components/TabbarItem/TabbarItem.tsx +13 -7
  420. package/src/components/Tabs/Readme.md +191 -251
  421. package/src/components/Tabs/Tabs.css +27 -80
  422. package/src/components/Tabs/Tabs.tsx +45 -7
  423. package/src/components/TabsItem/Readme.md +1 -0
  424. package/src/components/TabsItem/TabsItem.css +191 -106
  425. package/src/components/TabsItem/TabsItem.tsx +72 -20
  426. package/src/components/TextTooltip/TextTooltip.css +41 -11
  427. package/src/components/TextTooltip/TextTooltip.tsx +9 -13
  428. package/src/components/Textarea/Textarea.css +2 -0
  429. package/src/components/Tooltip/Readme.md +128 -101
  430. package/src/components/Tooltip/Tooltip.css +29 -40
  431. package/src/components/Tooltip/Tooltip.tsx +98 -66
  432. package/src/components/Typography/Headline/Headline.tsx +15 -1
  433. package/src/components/View/Readme.md +2 -0
  434. package/src/components/View/View.tsx +451 -514
  435. package/src/components/WriteBar/WriteBar.css +27 -33
  436. package/src/components/WriteBar/WriteBar.tsx +16 -5
  437. package/src/components/WriteBarIcon/WriteBarIcon.css +6 -19
  438. package/src/components/WriteBarIcon/WriteBarIcon.tsx +6 -6
  439. package/src/hooks/useOrientationChange.ts +1 -0
  440. package/src/styles/components.css +1 -0
  441. package/src/styles/constants.css +8 -0
  442. package/src/tokenized/index.ts +39 -0
  443. package/tsconfig.json +1 -1
  444. package/.cache/ts/src/components/ClickPopper/ClickPopper.d.ts +0 -21
  445. package/dist/cjs/components/ClickPopper/ClickPopper.js +0 -96
  446. package/dist/cjs/components/ClickPopper/ClickPopper.js.map +0 -1
  447. package/dist/components/ClickPopper/ClickPopper.d.ts +0 -21
  448. package/dist/components/ClickPopper/ClickPopper.js +0 -71
  449. package/dist/components/ClickPopper/ClickPopper.js.map +0 -1
  450. package/dist/cssm/components/ClickPopper/ClickPopper.d.ts +0 -21
  451. package/dist/cssm/components/ClickPopper/ClickPopper.js +0 -71
  452. package/dist/cssm/components/ClickPopper/ClickPopper.js.map +0 -1
  453. package/src/components/ClickPopper/ClickPopper.tsx +0 -86
@@ -1,20 +1,13 @@
1
1
  import * as React from "react";
2
2
  import { SelectMimicry } from "../SelectMimicry/SelectMimicry";
3
- import {
4
- debounce,
5
- setRef,
6
- multiRef,
7
- getTitleFromChildren,
8
- } from "../../lib/utils";
3
+ import { debounce, multiRef, getTitleFromChildren } from "../../lib/utils";
9
4
  import { classNames } from "../../lib/classNames";
10
5
  import { NativeSelectProps } from "../NativeSelect/NativeSelect";
11
6
  import { withAdaptivity } from "../../hoc/withAdaptivity";
12
- import { withPlatform } from "../../hoc/withPlatform";
13
7
  import {
14
8
  CustomSelectOption,
15
9
  CustomSelectOptionProps,
16
10
  } from "../CustomSelectOption/CustomSelectOption";
17
- import { getClassName } from "../../helpers/getClassName";
18
11
  import { FormFieldProps } from "../FormField/FormField";
19
12
  import { HasPlatform } from "../../types";
20
13
  import { Input } from "../Input/Input";
@@ -25,11 +18,11 @@ import {
25
18
  defaultFilterFn,
26
19
  getFormFieldModeFromSelectType,
27
20
  } from "../../lib/select";
28
- import { is } from "../../lib/is";
29
21
  import { Placement } from "../Popper/Popper";
30
22
  import { CustomSelectDropdown } from "../CustomSelectDropdown/CustomSelectDropdown";
31
23
  import { TrackerOptionsProps } from "../CustomScrollView/useTrackerVisibility";
32
24
  import { SelectType } from "../Select/Select";
25
+ import { useIsomorphicLayoutEffect } from "../../lib/useIsomorphicLayoutEffect";
33
26
  import "./CustomSelect.css";
34
27
 
35
28
  const findIndexAfter = (
@@ -72,6 +65,44 @@ const checkOptionsValueType = (options: CustomSelectOptionInterface[]) => {
72
65
  }
73
66
  };
74
67
 
68
+ function defaultRenderOptionFn({
69
+ option,
70
+ ...props
71
+ }: CustomSelectOptionProps): React.ReactNode {
72
+ return <CustomSelectOption {...props} />;
73
+ }
74
+
75
+ const handleOptionDown: MouseEventHandler = (
76
+ e: React.MouseEvent<HTMLElement>
77
+ ) => {
78
+ e.preventDefault();
79
+ };
80
+
81
+ function findSelectedIndex(
82
+ options: CustomSelectOptionInterface[],
83
+ value: SelectValue
84
+ ) {
85
+ return (
86
+ options.findIndex((item) => {
87
+ value = typeof item.value === "number" ? Number(value) : value;
88
+ return item.value === value;
89
+ }) ?? -1
90
+ );
91
+ }
92
+
93
+ const filter = (
94
+ options: CustomSelectProps["options"],
95
+ inputValue: string,
96
+ filterFn: CustomSelectProps["filterFn"]
97
+ ) => {
98
+ return typeof filterFn === "function"
99
+ ? options.filter((option) => filterFn(inputValue, option))
100
+ : options;
101
+ };
102
+
103
+ const defaultOptions: CustomSelectOptionInterface[] = [];
104
+ const defaultIcon = <DropdownIcon />;
105
+
75
106
  type SelectValue = React.SelectHTMLAttributes<HTMLSelectElement>["value"];
76
107
 
77
108
  export interface CustomSelectOptionInterface {
@@ -81,16 +112,6 @@ export interface CustomSelectOptionInterface {
81
112
  [index: string]: any;
82
113
  }
83
114
 
84
- interface CustomSelectState {
85
- inputValue?: string;
86
- opened?: boolean;
87
- focusedOptionIndex?: number;
88
- selectedOptionIndex?: number;
89
- nativeSelectValue?: SelectValue;
90
- options?: CustomSelectOptionInterface[];
91
- popperPlacement?: Placement;
92
- }
93
-
94
115
  export interface CustomSelectProps
95
116
  extends NativeSelectProps,
96
117
  HasPlatform,
@@ -153,178 +174,111 @@ export interface CustomSelectProps
153
174
 
154
175
  type MouseEventHandler = (event: React.MouseEvent<HTMLElement>) => void;
155
176
 
156
- class CustomSelectComponent extends React.Component<
157
- CustomSelectProps,
158
- CustomSelectState
159
- > {
160
- static defaultProps: Partial<CustomSelectProps> = {
161
- searchable: false,
162
- renderOption({ option, ...props }): React.ReactNode {
163
- return <CustomSelectOption {...props} />;
164
- },
165
- options: [],
166
- emptyText: "Ничего не найдено",
167
- filterFn: defaultFilterFn,
168
- icon: <DropdownIcon />,
169
- dropdownOffsetDistance: 0,
170
- fixDropdownWidth: true,
171
- };
172
-
173
- public constructor(props: CustomSelectProps) {
174
- super(props);
175
-
176
- const { value, defaultValue } = props;
177
-
178
- const initialValue = value !== undefined ? value : defaultValue;
179
-
180
- this.keyboardInput = "";
181
-
182
- if (process.env.NODE_ENV === "development") {
183
- checkOptionsValueType(props.options);
184
- }
185
-
186
- this.state = {
187
- opened: false,
188
- focusedOptionIndex: -1,
189
- selectedOptionIndex: this.findSelectedIndex(props.options, initialValue),
190
- nativeSelectValue: initialValue,
191
- options: props.options,
192
- inputValue: "",
193
- };
194
-
195
- if (props.value !== undefined) {
196
- this.isControlledOutside = true;
197
- }
177
+ function CustomSelectComponent(props: CustomSelectProps) {
178
+ const {
179
+ before,
180
+ name,
181
+ className,
182
+ getRef,
183
+ getRootRef,
184
+ popupDirection,
185
+ sizeY,
186
+ platform,
187
+ style,
188
+ onChange,
189
+ children,
190
+ onInputChange: onInputChangeProp,
191
+ renderDropdown,
192
+ onOpen,
193
+ onClose,
194
+ fetching,
195
+ forceDropdownPortal,
196
+ selectType = SelectType.default,
197
+ autoHideScrollbar,
198
+ autoHideScrollbarDelay,
199
+ searchable = false,
200
+ renderOption: renderOptionProp = defaultRenderOptionFn,
201
+ options: optionsProp = defaultOptions,
202
+ emptyText = "Ничего не найдено",
203
+ filterFn = defaultFilterFn,
204
+ icon = defaultIcon,
205
+ dropdownOffsetDistance = 0,
206
+ fixDropdownWidth = true,
207
+ ...restProps
208
+ } = props;
209
+
210
+ if (process.env.NODE_ENV === "development") {
211
+ checkOptionsValueType(optionsProp);
198
212
  }
199
213
 
200
- private keyboardInput: string;
201
- private isControlledOutside = false;
202
- private selectEl: HTMLSelectElement | null = null;
203
- private readonly scrollBoxRef = React.createRef<HTMLDivElement>();
204
- private readonly containerRef = React.createRef<HTMLLabelElement>();
214
+ const containerRef = React.useRef<HTMLLabelElement>(null);
215
+ const scrollBoxRef = React.useRef<HTMLDivElement>(null);
216
+ const selectElRef = React.useRef<HTMLSelectElement>(null);
217
+
218
+ const [focusedOptionIndex, setFocusedOptionIndex] = React.useState<
219
+ number | undefined
220
+ >(-1);
221
+ const [isControlledOutside, setIsControlledOutside] = React.useState(
222
+ props.value !== undefined
223
+ );
224
+ const [inputValue, setInputValue] = React.useState("");
225
+ const [nativeSelectValue, setNativeSelectValue] = React.useState(
226
+ props.value ?? props.defaultValue
227
+ );
228
+ const [keyboardInput, setKeyboardInput] = React.useState("");
229
+ const [popperPlacement, setPopperPlacement] = React.useState<
230
+ Placement | undefined
231
+ >(undefined);
232
+ const [options, setOptions] = React.useState(optionsProp);
233
+ const [selectedOptionIndex, setSelectedOptionIndex] = React.useState<
234
+ number | undefined
235
+ >(findSelectedIndex(optionsProp, props.value ?? props.defaultValue));
236
+ const [opened, setOpened] = React.useState(false);
237
+
238
+ React.useEffect(() => {
239
+ setIsControlledOutside(props.value !== undefined);
240
+ setNativeSelectValue(
241
+ (nativeSelectValue) => props.value ?? nativeSelectValue
242
+ );
243
+ }, [props.value]);
205
244
 
206
- private readonly resetKeyboardInput = () => {
207
- this.keyboardInput = "";
208
- };
245
+ useIsomorphicLayoutEffect(() => {
246
+ if (nativeSelectValue) {
247
+ const event = new Event("change", { bubbles: true });
209
248
 
210
- private readonly getSelectedItem = () => {
211
- const { selectedOptionIndex, options } = this.state;
249
+ selectElRef.current?.dispatchEvent(event);
250
+ }
251
+ }, [nativeSelectValue]);
212
252
 
213
- if (!options?.length) {
253
+ const selected = React.useMemo(() => {
254
+ if (!options.length) {
214
255
  return null;
215
256
  }
216
257
 
217
258
  return selectedOptionIndex !== undefined
218
259
  ? options[selectedOptionIndex]
219
260
  : undefined;
220
- };
221
-
222
- get areOptionsShown() {
223
- return this.scrollBoxRef.current !== null;
224
- }
225
-
226
- filter = (
227
- options: CustomSelectProps["options"],
228
- inputValue: string,
229
- filterFn: CustomSelectProps["filterFn"]
230
- ) => {
231
- return typeof filterFn === "function"
232
- ? options.filter((option) => filterFn(inputValue, option))
233
- : options;
234
- };
235
-
236
- findSelectedIndex(
237
- options: CustomSelectOptionInterface[] | undefined,
238
- value: SelectValue
239
- ) {
240
- return (
241
- options?.findIndex((item) => {
242
- value = typeof item.value === "number" ? Number(value) : value;
243
- return item.value === value;
244
- }) ?? -1
245
- );
246
- }
247
-
248
- open = () => {
249
- this.setState(
250
- ({ selectedOptionIndex }) => ({
251
- opened: true,
252
- focusedOptionIndex: selectedOptionIndex,
253
- }),
254
- () => {
255
- const { selectedOptionIndex } = this.state;
256
-
257
- if (
258
- selectedOptionIndex !== undefined &&
259
- this.isValidIndex(selectedOptionIndex)
260
- ) {
261
- this.scrollToElement(selectedOptionIndex, true);
262
- }
263
- }
264
- );
265
- typeof this.props.onOpen === "function" && this.props.onOpen();
266
- };
267
-
268
- close = () => {
269
- this.resetKeyboardInput();
270
-
271
- this.setState(() => ({
272
- inputValue: "",
273
- opened: false,
274
- focusedOptionIndex: -1,
275
- options: this.props.options,
276
- }));
277
- typeof this.props.onClose === "function" && this.props.onClose();
278
- };
279
-
280
- private isValidIndex(index: number) {
281
- return index >= 0 && index < (this.state.options?.length ?? 0);
282
- }
283
-
284
- selectFocused = () => {
285
- const { focusedOptionIndex } = this.state;
286
-
287
- if (focusedOptionIndex !== undefined) {
288
- this.select(focusedOptionIndex);
289
- }
290
- };
291
-
292
- select = (index: number) => {
293
- if (!this.isValidIndex(index)) {
294
- return;
295
- }
296
-
297
- const item = this.state.options?.[index];
298
-
299
- this.setState(
300
- {
301
- nativeSelectValue: item?.value,
302
- },
303
- () => {
304
- const event = new Event("change", { bubbles: true });
305
- this.selectEl?.dispatchEvent(event);
306
- }
307
- );
308
- this.close();
309
- };
310
-
311
- onClick = () => {
312
- this.state.opened ? this.close() : this.open();
313
- };
261
+ }, [options, selectedOptionIndex]);
262
+
263
+ const openedClassNames = React.useMemo(
264
+ () =>
265
+ classNames(
266
+ opened && "Select--open",
267
+ opened &&
268
+ dropdownOffsetDistance === 0 &&
269
+ (popperPlacement?.includes("top")
270
+ ? "Select--pop-up"
271
+ : "Select--pop-down")
272
+ ),
273
+ [dropdownOffsetDistance, opened, popperPlacement]
274
+ );
314
275
 
315
- onFocus = () => {
316
- const event = new Event("focus");
317
- this.selectEl?.dispatchEvent(event);
318
- };
276
+ const resetKeyboardInput = React.useCallback(() => {
277
+ setKeyboardInput("");
278
+ }, []);
319
279
 
320
- onBlur = () => {
321
- this.close();
322
- const event = new Event("blur");
323
- this.selectEl?.dispatchEvent(event);
324
- };
325
-
326
- private scrollToElement(index: number, center = false) {
327
- const dropdown = this.scrollBoxRef.current;
280
+ const scrollToElement = React.useCallback((index: number, center = false) => {
281
+ const dropdown = scrollBoxRef.current;
328
282
  const item = dropdown ? (dropdown.children[index] as HTMLElement) : null;
329
283
 
330
284
  if (!item || !dropdown) {
@@ -343,450 +297,465 @@ class CustomSelectComponent extends React.Component<
343
297
  } else if (itemTop < scrollTop) {
344
298
  dropdown.scrollTop = itemTop;
345
299
  }
346
- }
300
+ }, []);
347
301
 
348
- focusOptionByIndex = (index: number | undefined, scrollTo = true) => {
349
- if (
350
- index === undefined ||
351
- index < 0 ||
352
- index > (this.state.options?.length ?? 0) - 1
353
- ) {
354
- return;
355
- }
302
+ const isValidIndex = React.useCallback(
303
+ (index: number) => {
304
+ return index >= 0 && index < (options.length ?? 0);
305
+ },
306
+ [options.length]
307
+ );
308
+
309
+ const focusOptionByIndex = React.useCallback(
310
+ (index: number | undefined, scrollTo = true) => {
311
+ if (
312
+ index === undefined ||
313
+ index < 0 ||
314
+ index > (options.length ?? 0) - 1
315
+ ) {
316
+ return;
317
+ }
356
318
 
357
- const option = this.state.options?.[index];
319
+ const option = options[index];
358
320
 
359
- if (option?.disabled) {
360
- return;
361
- }
321
+ if (option?.disabled) {
322
+ return;
323
+ }
362
324
 
363
- scrollTo && this.scrollToElement(index);
325
+ if (scrollTo) {
326
+ scrollToElement(index);
327
+ }
364
328
 
365
- this.setState((prevState) =>
366
329
  // Это оптимизация, прежде всего, под `onMouseOver`
367
- prevState.focusedOptionIndex !== index
368
- ? {
369
- focusedOptionIndex: index,
370
- }
371
- : null
372
- );
373
- };
374
-
375
- focusOption = (type: "next" | "prev") => {
376
- const { focusedOptionIndex } = this.state;
377
- let index = focusedOptionIndex;
378
-
379
- if (type === "next") {
380
- const nextIndex = findIndexAfter(this.state.options, index);
381
- index = nextIndex === -1 ? findIndexAfter(this.state.options) : nextIndex; // Следующий за index или первый валидный до index
382
- } else if (type === "prev") {
383
- const beforeIndex = findIndexBefore(this.state.options, index);
384
- index =
385
- beforeIndex === -1 ? findIndexBefore(this.state.options) : beforeIndex; // Предшествующий index или последний валидный после index
386
- }
330
+ setFocusedOptionIndex((focusedOptionIndex) =>
331
+ focusedOptionIndex !== index ? index : focusedOptionIndex
332
+ );
333
+ },
334
+ [options, scrollToElement]
335
+ );
387
336
 
388
- this.focusOptionByIndex(index);
389
- };
337
+ const areOptionsShown = React.useCallback(() => {
338
+ return scrollBoxRef.current !== null;
339
+ }, []);
390
340
 
391
- handleOptionHover: MouseEventHandler = (e: React.MouseEvent<HTMLElement>) => {
392
- this.focusOptionByIndex(
393
- Array.prototype.indexOf.call(
394
- e.currentTarget.parentNode?.children,
395
- e.currentTarget
396
- ),
397
- false
398
- );
399
- };
341
+ const onKeyboardInput = React.useCallback(
342
+ (key: string) => {
343
+ const fullInput = keyboardInput + key;
400
344
 
401
- handleOptionDown: MouseEventHandler = (e: React.MouseEvent<HTMLElement>) => {
402
- e.preventDefault();
403
- };
345
+ const optionIndex = options.findIndex((option) => {
346
+ return getTitleFromChildren(option.label)
347
+ .toLowerCase()
348
+ .includes(fullInput);
349
+ });
404
350
 
405
- handleOptionClick: MouseEventHandler = (e: React.MouseEvent<HTMLElement>) => {
406
- const index = Array.prototype.indexOf.call(
407
- e.currentTarget.parentNode?.children,
408
- e.currentTarget
409
- );
410
- const option = this.state.options?.[index];
351
+ if (optionIndex !== undefined && optionIndex > -1) {
352
+ focusOptionByIndex(optionIndex);
353
+ }
411
354
 
412
- if (option && !option.disabled) {
413
- this.selectFocused();
414
- }
415
- };
355
+ setKeyboardInput(fullInput);
356
+ },
357
+ [focusOptionByIndex, keyboardInput, options]
358
+ );
416
359
 
417
- resetFocusedOption = () => {
418
- this.setState({ focusedOptionIndex: -1 });
419
- };
360
+ const close = React.useCallback(() => {
361
+ resetKeyboardInput();
420
362
 
421
- onKeyboardInput = (key: string) => {
422
- const fullInput = this.keyboardInput + key;
363
+ setInputValue("");
364
+ setOpened(false);
365
+ setFocusedOptionIndex(-1);
366
+ setOptions(optionsProp);
367
+ onClose?.();
368
+ }, [onClose, optionsProp, resetKeyboardInput]);
423
369
 
424
- const optionIndex = this.state.options?.findIndex((option) => {
425
- return getTitleFromChildren(option.label)
426
- .toLowerCase()
427
- .includes(fullInput);
428
- });
370
+ const selectFocused = React.useCallback(() => {
371
+ if (focusedOptionIndex !== undefined && isValidIndex(focusedOptionIndex)) {
372
+ const item = options[focusedOptionIndex];
429
373
 
430
- if (optionIndex !== undefined && optionIndex > -1) {
431
- this.focusOptionByIndex(optionIndex);
374
+ setNativeSelectValue(item?.value);
375
+ close();
432
376
  }
377
+ }, [close, focusedOptionIndex, isValidIndex, options]);
433
378
 
434
- this.keyboardInput = fullInput;
435
- };
379
+ const open = React.useCallback(() => {
380
+ setOpened(true);
381
+ setFocusedOptionIndex(selectedOptionIndex);
436
382
 
437
- /**
438
- * Нужен для правильного поведения обработчика onClick на select. Фильтрует клики, которые были сделаны по
439
- * выпадающему списку.
440
- */
441
- onLabelClick = (e: React.MouseEvent<HTMLLabelElement>) => {
442
- if (this.scrollBoxRef.current?.contains(e.target as Node)) {
443
- e.preventDefault();
383
+ if (typeof onOpen === "function") {
384
+ onOpen();
444
385
  }
445
- };
446
-
447
- onNativeSelectChange: React.ChangeEventHandler<HTMLSelectElement> = (e) => {
448
- const newSelectedOptionIndex = this.findSelectedIndex(
449
- this.state.options,
450
- e.currentTarget.value
451
- );
386
+ }, [onOpen, selectedOptionIndex]);
452
387
 
453
- if (this.state.selectedOptionIndex !== newSelectedOptionIndex) {
454
- if (!this.isControlledOutside) {
455
- this.setState({
456
- selectedOptionIndex: newSelectedOptionIndex,
457
- });
458
- }
459
- this.props.onChange?.(e);
388
+ React.useEffect(() => {
389
+ if (
390
+ opened &&
391
+ selectedOptionIndex !== undefined &&
392
+ isValidIndex(selectedOptionIndex)
393
+ ) {
394
+ scrollToElement(selectedOptionIndex, true);
460
395
  }
461
- };
462
-
463
- onInputChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
464
- if (this.props.onInputChange) {
465
- const options = this.props.onInputChange(e, this.props.options);
466
- if (options) {
467
- if (process.env.NODE_ENV === "development") {
468
- warn(
469
- "Этот метод фильтрации устарел. Возвращаемое значение onInputChange будет " +
470
- "проигнорировано в v5.0.0. Для фильтрации обновляйте props.options самостоятельно или используйте свойство filterFn."
471
- );
472
- }
473
- this.setState({
474
- options,
475
- selectedOptionIndex: this.findSelectedIndex(
476
- options,
477
- this.state.nativeSelectValue
478
- ),
479
- inputValue: e.target.value,
480
- });
481
- } else {
482
- this.setState({ inputValue: e.target.value });
483
- }
396
+ }, [isValidIndex, opened, scrollToElement, selectedOptionIndex]);
397
+
398
+ const onBlur = React.useCallback(() => {
399
+ close();
400
+ const event = new Event("blur");
401
+ selectElRef.current?.dispatchEvent(event);
402
+ }, [close]);
403
+
404
+ const resetFocusedOption = React.useCallback(() => {
405
+ setFocusedOptionIndex(-1);
406
+ }, []);
407
+
408
+ const onFocus = React.useCallback(() => {
409
+ const event = new Event("focus");
410
+ selectElRef.current?.dispatchEvent(event);
411
+ }, []);
412
+
413
+ const onClick = React.useCallback(() => {
414
+ if (opened) {
415
+ close();
484
416
  } else {
485
- const options = this.filter(
486
- this.props.options,
487
- e.target.value,
488
- this.props.filterFn
489
- );
490
- this.setState({
491
- options,
492
- selectedOptionIndex: this.findSelectedIndex(
493
- options,
494
- this.state.nativeSelectValue
495
- ),
496
- inputValue: e.target.value,
497
- });
498
- }
499
- };
500
-
501
- onInputKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (event) => {
502
- ["ArrowUp", "ArrowDown", "Escape", "Enter"].includes(event.key) &&
503
- this.areOptionsShown &&
504
- event.preventDefault();
505
-
506
- switch (event.key) {
507
- case "ArrowUp":
508
- this.areOptionsShown && this.focusOption("prev");
509
- break;
510
- case "ArrowDown":
511
- this.areOptionsShown && this.focusOption("next");
512
- break;
513
- case "Escape":
514
- this.close();
515
- break;
516
- case "Enter":
517
- this.areOptionsShown && this.selectFocused();
518
- break;
417
+ open();
519
418
  }
520
- };
419
+ }, [close, open, opened]);
420
+
421
+ const handleKeyUp = React.useMemo(
422
+ () => debounce(resetKeyboardInput, 1000),
423
+ [resetKeyboardInput]
424
+ );
425
+
426
+ const focusOption = React.useCallback(
427
+ (type: "next" | "prev") => {
428
+ let index = focusedOptionIndex;
429
+
430
+ if (type === "next") {
431
+ const nextIndex = findIndexAfter(options, index);
432
+ index = nextIndex === -1 ? findIndexAfter(options) : nextIndex; // Следующий за index или первый валидный до index
433
+ } else if (type === "prev") {
434
+ const beforeIndex = findIndexBefore(options, index);
435
+ index = beforeIndex === -1 ? findIndexBefore(options) : beforeIndex; // Предшествующий index или последний валидный после index
436
+ }
521
437
 
522
- handleKeyDownSelect = (event: React.KeyboardEvent) => {
523
- const { opened } = this.state;
438
+ focusOptionByIndex(index);
439
+ },
440
+ [focusOptionByIndex, focusedOptionIndex, options]
441
+ );
442
+
443
+ React.useEffect(() => {
444
+ const value = props.value ?? nativeSelectValue ?? props.defaultValue;
445
+
446
+ const options =
447
+ searchable && inputValue !== undefined
448
+ ? filter(optionsProp, inputValue, filterFn)
449
+ : optionsProp;
450
+
451
+ setOptions(options);
452
+ setSelectedOptionIndex(findSelectedIndex(options, value));
453
+ }, [
454
+ filterFn,
455
+ inputValue,
456
+ nativeSelectValue,
457
+ optionsProp,
458
+ props.defaultValue,
459
+ props.value,
460
+ searchable,
461
+ ]);
524
462
 
525
- if (event.key.length === 1 && event.key !== " ") {
526
- this.onKeyboardInput(event.key);
527
- return;
528
- }
463
+ /**
464
+ * Нужен для правильного поведения обработчика onClick на select. Фильтрует клики, которые были сделаны по
465
+ * выпадающему списку.
466
+ */
467
+ const onLabelClick = React.useCallback(
468
+ (e: React.MouseEvent<HTMLLabelElement>) => {
469
+ if (scrollBoxRef.current?.contains(e.target as Node)) {
470
+ e.preventDefault();
471
+ }
472
+ },
473
+ []
474
+ );
529
475
 
530
- ["ArrowUp", "ArrowDown", "Escape", "Enter"].includes(event.key) &&
531
- this.areOptionsShown &&
532
- event.preventDefault();
476
+ const onNativeSelectChange: React.ChangeEventHandler<HTMLSelectElement> =
477
+ React.useCallback(
478
+ (e) => {
479
+ const newSelectedOptionIndex = findSelectedIndex(
480
+ options,
481
+ e.currentTarget.value
482
+ );
533
483
 
534
- switch (event.key) {
535
- case "ArrowUp":
536
- if (opened) {
537
- this.areOptionsShown && this.focusOption("prev");
538
- } else {
539
- this.open();
484
+ if (selectedOptionIndex !== newSelectedOptionIndex) {
485
+ if (!isControlledOutside) {
486
+ setSelectedOptionIndex(newSelectedOptionIndex);
487
+ }
488
+ onChange?.(e);
540
489
  }
541
- break;
542
- case "ArrowDown":
543
- if (opened) {
544
- this.areOptionsShown && this.focusOption("next");
545
- } else {
546
- this.open();
490
+ },
491
+ [isControlledOutside, onChange, options, selectedOptionIndex]
492
+ );
493
+
494
+ const onInputKeyDown: React.KeyboardEventHandler<HTMLInputElement> =
495
+ React.useCallback(
496
+ (event) => {
497
+ ["ArrowUp", "ArrowDown", "Escape", "Enter"].includes(event.key) &&
498
+ areOptionsShown() &&
499
+ event.preventDefault();
500
+
501
+ switch (event.key) {
502
+ case "ArrowUp":
503
+ areOptionsShown() && focusOption("prev");
504
+ break;
505
+ case "ArrowDown":
506
+ areOptionsShown() && focusOption("next");
507
+ break;
508
+ case "Escape":
509
+ close();
510
+ break;
511
+ case "Enter":
512
+ areOptionsShown() && selectFocused();
513
+ break;
547
514
  }
548
- break;
549
- case "Escape":
550
- this.close();
551
- break;
552
- case "Enter":
553
- case "Spacebar":
554
- case " ":
555
- if (opened) {
556
- this.areOptionsShown && this.selectFocused();
515
+ },
516
+ [areOptionsShown, close, focusOption, selectFocused]
517
+ );
518
+
519
+ const onInputChange: React.ChangeEventHandler<HTMLInputElement> =
520
+ React.useCallback(
521
+ (e) => {
522
+ if (onInputChangeProp) {
523
+ const options = onInputChangeProp(e, optionsProp);
524
+ if (options) {
525
+ if (process.env.NODE_ENV === "development") {
526
+ warn(
527
+ "Этот метод фильтрации устарел. Возвращаемое значение onInputChange будет " +
528
+ "проигнорировано в v5.0.0. Для фильтрации обновляйте props.options самостоятельно или используйте свойство filterFn."
529
+ );
530
+ }
531
+ setOptions(options);
532
+ setSelectedOptionIndex(
533
+ findSelectedIndex(options, nativeSelectValue)
534
+ );
535
+ }
557
536
  } else {
558
- this.open();
537
+ const options = filter(optionsProp, e.target.value, filterFn);
538
+ setOptions(options);
539
+ setSelectedOptionIndex(findSelectedIndex(options, nativeSelectValue));
559
540
  }
560
- break;
561
- }
562
- };
563
-
564
- handleKeyUp = debounce(this.resetKeyboardInput, 1000);
541
+ setInputValue(e.target.value);
542
+ },
543
+ [filterFn, nativeSelectValue, onInputChangeProp, optionsProp]
544
+ );
565
545
 
566
- componentDidUpdate(prevProps: CustomSelectProps) {
567
- // Внутри useEffect и так is, можно убрать
568
- if (
569
- !is(prevProps.value, this.props.value) ||
570
- prevProps.options !== this.props.options
571
- ) {
572
- if (process.env.NODE_ENV === "development") {
573
- checkOptionsValueType(this.props.options);
546
+ const handleKeyDownSelect = React.useCallback(
547
+ (event: React.KeyboardEvent) => {
548
+ if (event.key.length === 1 && event.key !== " ") {
549
+ onKeyboardInput(event.key);
550
+ return;
574
551
  }
575
552
 
576
- this.isControlledOutside = this.props.value !== undefined;
577
- const value =
578
- this.props.value === undefined
579
- ? this.state.nativeSelectValue
580
- : this.props.value;
581
- const options =
582
- this.props.searchable && this.state.inputValue !== undefined
583
- ? this.filter(
584
- this.props.options,
585
- this.state.inputValue,
586
- this.props.filterFn
587
- )
588
- : this.props.options;
589
- this.setState({
590
- nativeSelectValue: value,
591
- selectedOptionIndex: this.findSelectedIndex(options, value),
592
- options,
593
- });
594
- }
595
- }
596
-
597
- renderOption = (option: CustomSelectOptionInterface, index: number) => {
598
- const { focusedOptionIndex, selectedOptionIndex } = this.state;
599
- const { renderOption } = this.props;
600
- const hovered = index === focusedOptionIndex;
601
- const selected = index === selectedOptionIndex;
602
-
603
- return (
604
- <React.Fragment key={`${option.value}`}>
605
- {renderOption!({
606
- option,
607
- hovered,
608
- children: option.label,
609
- selected,
610
- disabled: option.disabled,
611
- onClick: this.handleOptionClick,
612
- onMouseDown: this.handleOptionDown,
613
- // Используем `onMouseOver` вместо `onMouseEnter`.
614
- // При параметре `searchable`, обновляется "ребёнок", из-за чего `onMouseEnter` не срабатывает в следующих кейсах:
615
- // 1. До загрузки выпадающего списка, курсор мышки находится над произвольным элементом этого списка.
616
- // > Лечение: только увод курсора мыши и возвращении его обратно вызывает событие `onMouseEnter` на этот элемент.
617
- // 2. Если это тач-устройство.
618
- // > Лечение: нужно нажать на какой-нибудь произвольный элемент списка, после чего `onMouseEnter` будет работать на соседние элементы,
619
- // но не на тот, на который нажали в первый раз.
620
- // Более подробно по ссылке https://github.com/facebook/react/issues/13956#issuecomment-1082055744
621
- onMouseOver: this.handleOptionHover,
622
- })}
623
- </React.Fragment>
624
- );
625
- };
553
+ ["ArrowUp", "ArrowDown", "Escape", "Enter"].includes(event.key) &&
554
+ areOptionsShown() &&
555
+ event.preventDefault();
626
556
 
627
- selectRef = (element: HTMLSelectElement) => {
628
- this.selectEl = element;
629
- if (this.props.getRef) {
630
- setRef(element, this.props.getRef);
631
- }
632
- };
633
-
634
- onPlacementChange = (placement?: Placement) => {
635
- this.setState(() => ({
636
- popperPlacement: placement,
637
- }));
638
- };
639
-
640
- render() {
641
- const { opened, nativeSelectValue, options: stateOptions } = this.state;
642
- const {
643
- before,
644
- searchable,
645
- name,
646
- className,
647
- getRef,
648
- getRootRef,
649
- popupDirection,
650
- options,
651
- sizeY,
652
- platform,
653
- style,
654
- onChange,
655
- onBlur,
656
- onFocus,
657
- onClick,
658
- renderOption,
659
- children,
660
- emptyText,
661
- onInputChange,
662
- filterFn,
663
- renderDropdown,
664
- onOpen,
665
- onClose,
666
- fetching,
667
- icon,
668
- dropdownOffsetDistance,
669
- fixDropdownWidth,
670
- forceDropdownPortal,
671
- selectType = SelectType.default,
672
- autoHideScrollbar,
673
- autoHideScrollbarDelay,
674
- ...restProps
675
- } = this.props;
676
- const selected = this.getSelectedItem();
677
- const label = selected ? selected.label : undefined;
557
+ switch (event.key) {
558
+ case "ArrowUp":
559
+ if (opened) {
560
+ areOptionsShown() && focusOption("prev");
561
+ } else {
562
+ open();
563
+ }
564
+ break;
565
+ case "ArrowDown":
566
+ if (opened) {
567
+ areOptionsShown() && focusOption("next");
568
+ } else {
569
+ open();
570
+ }
571
+ break;
572
+ case "Escape":
573
+ close();
574
+ break;
575
+ case "Enter":
576
+ case "Spacebar":
577
+ case " ":
578
+ if (opened) {
579
+ areOptionsShown() && selectFocused();
580
+ } else {
581
+ open();
582
+ }
583
+ break;
584
+ }
585
+ },
586
+ [
587
+ areOptionsShown,
588
+ close,
589
+ focusOption,
590
+ onKeyboardInput,
591
+ open,
592
+ opened,
593
+ selectFocused,
594
+ ]
595
+ );
596
+
597
+ const handleOptionClick = React.useCallback(
598
+ (e: React.MouseEvent<HTMLElement>) => {
599
+ const index = Array.prototype.indexOf.call(
600
+ e.currentTarget.parentNode?.children,
601
+ e.currentTarget
602
+ );
603
+ const option = options[index];
678
604
 
605
+ if (option && !option.disabled) {
606
+ selectFocused();
607
+ }
608
+ },
609
+ [options, selectFocused]
610
+ );
611
+
612
+ const handleOptionHover = React.useCallback(
613
+ (e: React.MouseEvent<HTMLElement>) => {
614
+ focusOptionByIndex(
615
+ Array.prototype.indexOf.call(
616
+ e.currentTarget.parentNode?.children,
617
+ e.currentTarget
618
+ ),
619
+ false
620
+ );
621
+ },
622
+ [focusOptionByIndex]
623
+ );
624
+
625
+ const renderOption = React.useCallback(
626
+ (option: CustomSelectOptionInterface, index: number) => {
627
+ const hovered = index === focusedOptionIndex;
628
+ const selected = index === selectedOptionIndex;
629
+
630
+ return (
631
+ <React.Fragment key={`${option.value}`}>
632
+ {renderOptionProp({
633
+ option,
634
+ hovered,
635
+ children: option.label,
636
+ selected,
637
+ disabled: option.disabled,
638
+ onClick: handleOptionClick,
639
+ onMouseDown: handleOptionDown,
640
+ // Используем `onMouseOver` вместо `onMouseEnter`.
641
+ // При параметре `searchable`, обновляется "ребёнок", из-за чего `onMouseEnter` не срабатывает в следующих кейсах:
642
+ // 1. До загрузки выпадающего списка, курсор мышки находится над произвольным элементом этого списка.
643
+ // > Лечение: только увод курсора мыши и возвращении его обратно вызывает событие `onMouseEnter` на этот элемент.
644
+ // 2. Если это тач-устройство.
645
+ // > Лечение: нужно нажать на какой-нибудь произвольный элемент списка, после чего `onMouseEnter` будет работать на соседние элементы,
646
+ // но не на тот, на который нажали в первый раз.
647
+ // Более подробно по ссылке https://github.com/facebook/react/issues/13956#issuecomment-1082055744
648
+ onMouseOver: handleOptionHover,
649
+ })}
650
+ </React.Fragment>
651
+ );
652
+ },
653
+ [
654
+ focusedOptionIndex,
655
+ handleOptionClick,
656
+ handleOptionHover,
657
+ renderOptionProp,
658
+ selectedOptionIndex,
659
+ ]
660
+ );
661
+
662
+ const resolvedContent = React.useMemo(() => {
679
663
  const defaultDropdownContent =
680
- stateOptions !== undefined && stateOptions.length > 0 ? (
681
- stateOptions.map(this.renderOption)
664
+ options?.length > 0 ? (
665
+ options.map(renderOption)
682
666
  ) : (
683
- <Caption vkuiClass="CustomSelect__empty">
684
- {this.props.emptyText}
685
- </Caption>
667
+ <Caption vkuiClass="CustomSelect__empty">{emptyText}</Caption>
686
668
  );
687
669
 
688
- let resolvedContent;
689
-
690
670
  if (typeof renderDropdown === "function") {
691
- resolvedContent = renderDropdown({ defaultDropdownContent });
671
+ return renderDropdown({ defaultDropdownContent });
692
672
  } else {
693
- resolvedContent = defaultDropdownContent;
673
+ return defaultDropdownContent;
694
674
  }
695
-
696
- const openedClassNames = classNames(
697
- opened && "Select--open",
698
- opened &&
699
- (dropdownOffsetDistance as number) === 0 &&
700
- (this.state.popperPlacement?.includes("top")
701
- ? "Select--pop-up"
702
- : "Select--pop-down")
703
- );
704
-
705
- return (
706
- <label
707
- vkuiClass={getClassName("CustomSelect", platform)}
708
- className={className}
709
- style={style}
710
- ref={multiRef(this.containerRef, getRootRef)}
711
- onClick={this.onLabelClick}
712
- >
713
- {opened && searchable ? (
714
- <Input
715
- {...restProps}
716
- autoFocus
717
- onBlur={this.onBlur}
718
- vkuiClass={openedClassNames}
719
- value={this.state.inputValue}
720
- onKeyDown={this.onInputKeyDown}
721
- onChange={this.onInputChange}
722
- // TODO Ожидается, что клик поймает нативный select, но его перехватывает Input. К сожалению, это приводит к конфликтам типизации.
723
- // TODO Нужно перестать пытаться превратить CustomSelect в select. Тогда эта проблема уйдёт.
724
- // @ts-ignore
725
- onClick={onClick}
726
- before={before}
727
- after={icon}
728
- placeholder={restProps.placeholder}
729
- mode={getFormFieldModeFromSelectType(selectType)}
730
- />
731
- ) : (
732
- <SelectMimicry
733
- {...restProps}
734
- aria-hidden={true}
735
- onClick={this.onClick}
736
- onKeyDown={this.handleKeyDownSelect}
737
- onKeyUp={this.handleKeyUp}
738
- onFocus={this.onFocus}
739
- onBlur={this.onBlur}
740
- vkuiClass={openedClassNames}
741
- after={icon}
742
- selectType={selectType}
743
- >
744
- {label}
745
- </SelectMimicry>
746
- )}
747
- <select
748
- ref={this.selectRef}
749
- name={name}
750
- onChange={this.onNativeSelectChange}
675
+ }, [emptyText, options, renderDropdown, renderOption]);
676
+
677
+ return (
678
+ <label
679
+ vkuiClass="CustomSelect"
680
+ className={className}
681
+ style={style}
682
+ ref={multiRef(containerRef, getRootRef)}
683
+ onClick={onLabelClick}
684
+ >
685
+ {opened && searchable ? (
686
+ <Input
687
+ {...restProps}
688
+ autoFocus
751
689
  onBlur={onBlur}
752
- onFocus={onFocus}
753
- onClick={onClick}
754
- value={nativeSelectValue}
690
+ vkuiClass={openedClassNames}
691
+ value={inputValue}
692
+ onKeyDown={onInputKeyDown}
693
+ onChange={onInputChange}
694
+ // TODO Ожидается, что клик поймает нативный select, но его перехватывает Input. К сожалению, это приводит к конфликтам типизации.
695
+ // TODO Нужно перестать пытаться превратить CustomSelect в select. Тогда эта проблема уйдёт.
696
+ // @ts-ignore
697
+ onClick={props.onClick}
698
+ before={before}
699
+ after={icon}
700
+ placeholder={restProps.placeholder}
701
+ mode={getFormFieldModeFromSelectType(selectType)}
702
+ />
703
+ ) : (
704
+ <SelectMimicry
705
+ {...restProps}
755
706
  aria-hidden={true}
756
- vkuiClass="CustomSelect__control"
707
+ onClick={onClick}
708
+ onKeyDown={handleKeyDownSelect}
709
+ onKeyUp={handleKeyUp}
710
+ onFocus={onFocus}
711
+ onBlur={onBlur}
712
+ vkuiClass={openedClassNames}
713
+ after={icon}
714
+ selectType={selectType}
757
715
  >
758
- {options.map((item) => (
759
- <option key={`${item.value}`} value={item.value} />
760
- ))}
761
- </select>
762
- {opened && (
763
- <CustomSelectDropdown
764
- targetRef={this.containerRef}
765
- placement={popupDirection}
766
- scrollBoxRef={this.scrollBoxRef}
767
- onPlacementChange={this.onPlacementChange}
768
- onMouseLeave={this.resetFocusedOption}
769
- fetching={fetching}
770
- offsetDistance={dropdownOffsetDistance}
771
- sameWidth={fixDropdownWidth}
772
- forcePortal={forceDropdownPortal}
773
- autoHideScrollbar={autoHideScrollbar}
774
- autoHideScrollbarDelay={autoHideScrollbarDelay}
775
- observableRefs={this.scrollBoxRef}
776
- >
777
- {resolvedContent}
778
- </CustomSelectDropdown>
779
- )}
780
- </label>
781
- );
782
- }
716
+ {selected?.label}
717
+ </SelectMimicry>
718
+ )}
719
+ <select
720
+ ref={selectElRef}
721
+ name={name}
722
+ onChange={onNativeSelectChange}
723
+ onBlur={props.onBlur}
724
+ onFocus={props.onFocus}
725
+ onClick={props.onClick}
726
+ value={nativeSelectValue}
727
+ aria-hidden={true}
728
+ vkuiClass="CustomSelect__control"
729
+ >
730
+ {optionsProp.map((item) => (
731
+ <option key={`${item.value}`} value={item.value} />
732
+ ))}
733
+ </select>
734
+ {opened && (
735
+ <CustomSelectDropdown
736
+ targetRef={containerRef}
737
+ placement={popupDirection}
738
+ scrollBoxRef={scrollBoxRef}
739
+ onPlacementChange={setPopperPlacement}
740
+ onMouseLeave={resetFocusedOption}
741
+ fetching={fetching}
742
+ offsetDistance={dropdownOffsetDistance}
743
+ sameWidth={fixDropdownWidth}
744
+ forcePortal={forceDropdownPortal}
745
+ autoHideScrollbar={autoHideScrollbar}
746
+ autoHideScrollbarDelay={autoHideScrollbarDelay}
747
+ observableRefs={scrollBoxRef}
748
+ >
749
+ {resolvedContent}
750
+ </CustomSelectDropdown>
751
+ )}
752
+ </label>
753
+ );
783
754
  }
784
755
 
785
756
  /**
786
757
  * @see https://vkcom.github.io/VKUI/#/CustomSelect
787
758
  */
788
- export const CustomSelect = withPlatform(
789
- withAdaptivity(CustomSelectComponent, {
790
- sizeY: true,
791
- })
792
- );
759
+ export const CustomSelect = withAdaptivity(CustomSelectComponent, {
760
+ sizeY: true,
761
+ });