@vkontakte/vkui 7.8.2 → 7.9.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 (282) hide show
  1. package/dist/components/Box/Box.d.ts +11 -0
  2. package/dist/components/Box/Box.d.ts.map +1 -0
  3. package/dist/components/Box/Box.js +25 -0
  4. package/dist/components/Box/Box.js.map +1 -0
  5. package/dist/components/CarouselBase/CarouselBase.d.ts +1 -1
  6. package/dist/components/CarouselBase/CarouselBase.d.ts.map +1 -1
  7. package/dist/components/CarouselBase/CarouselBase.js +6 -4
  8. package/dist/components/CarouselBase/CarouselBase.js.map +1 -1
  9. package/dist/components/CarouselBase/constants.d.ts +1 -1
  10. package/dist/components/CarouselBase/constants.d.ts.map +1 -1
  11. package/dist/components/CarouselBase/constants.js +1 -1
  12. package/dist/components/CarouselBase/constants.js.map +1 -1
  13. package/dist/components/CarouselBase/hooks.d.ts +3 -1
  14. package/dist/components/CarouselBase/hooks.d.ts.map +1 -1
  15. package/dist/components/CarouselBase/hooks.js +46 -6
  16. package/dist/components/CarouselBase/hooks.js.map +1 -1
  17. package/dist/components/CarouselBase/types.d.ts +12 -0
  18. package/dist/components/CarouselBase/types.d.ts.map +1 -1
  19. package/dist/components/CarouselBase/types.js.map +1 -1
  20. package/dist/components/Checkbox/Checkbox.d.ts +11 -2
  21. package/dist/components/Checkbox/Checkbox.d.ts.map +1 -1
  22. package/dist/components/Checkbox/Checkbox.js +44 -10
  23. package/dist/components/Checkbox/Checkbox.js.map +1 -1
  24. package/dist/components/Checkbox/CheckboxInput/CheckboxInput.d.ts +16 -3
  25. package/dist/components/Checkbox/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  26. package/dist/components/Checkbox/CheckboxInput/CheckboxInput.js +32 -19
  27. package/dist/components/Checkbox/CheckboxInput/CheckboxInput.js.map +1 -1
  28. package/dist/components/Checkbox/CheckboxSimple/CheckboxSimple.d.ts +1 -1
  29. package/dist/components/Checkbox/CheckboxSimple/CheckboxSimple.d.ts.map +1 -1
  30. package/dist/components/Checkbox/CheckboxSimple/CheckboxSimple.js +39 -10
  31. package/dist/components/Checkbox/CheckboxSimple/CheckboxSimple.js.map +1 -1
  32. package/dist/components/ChipsInput/ChipsInput.d.ts +1 -1
  33. package/dist/components/ChipsInput/ChipsInput.d.ts.map +1 -1
  34. package/dist/components/ChipsInput/ChipsInput.js +32 -13
  35. package/dist/components/ChipsInput/ChipsInput.js.map +1 -1
  36. package/dist/components/ChipsInputBase/ChipsInputBase.d.ts +1 -1
  37. package/dist/components/ChipsInputBase/ChipsInputBase.d.ts.map +1 -1
  38. package/dist/components/ChipsInputBase/ChipsInputBase.js +52 -26
  39. package/dist/components/ChipsInputBase/ChipsInputBase.js.map +1 -1
  40. package/dist/components/ChipsInputBase/types.d.ts +13 -4
  41. package/dist/components/ChipsInputBase/types.d.ts.map +1 -1
  42. package/dist/components/ChipsInputBase/types.js.map +1 -1
  43. package/dist/components/ChipsSelect/ChipsSelect.d.ts +1 -1
  44. package/dist/components/ChipsSelect/ChipsSelect.d.ts.map +1 -1
  45. package/dist/components/ChipsSelect/ChipsSelect.js +67 -38
  46. package/dist/components/ChipsSelect/ChipsSelect.js.map +1 -1
  47. package/dist/components/CustomSelect/CustomSelect.d.ts +16 -2
  48. package/dist/components/CustomSelect/CustomSelect.d.ts.map +1 -1
  49. package/dist/components/CustomSelect/CustomSelect.js +99 -50
  50. package/dist/components/CustomSelect/CustomSelect.js.map +1 -1
  51. package/dist/components/CustomSelect/CustomSelectInput/CustomSelectInput.d.ts +6 -2
  52. package/dist/components/CustomSelect/CustomSelectInput/CustomSelectInput.d.ts.map +1 -1
  53. package/dist/components/CustomSelect/CustomSelectInput/CustomSelectInput.js +38 -20
  54. package/dist/components/CustomSelect/CustomSelectInput/CustomSelectInput.js.map +1 -1
  55. package/dist/components/CustomSelect/helpers.d.ts +1 -0
  56. package/dist/components/CustomSelect/helpers.d.ts.map +1 -1
  57. package/dist/components/CustomSelect/helpers.js +11 -0
  58. package/dist/components/CustomSelect/helpers.js.map +1 -1
  59. package/dist/components/Div/Div.d.ts +3 -0
  60. package/dist/components/Div/Div.d.ts.map +1 -1
  61. package/dist/components/Div/Div.js +11 -1
  62. package/dist/components/Div/Div.js.map +1 -1
  63. package/dist/components/File/File.d.ts +16 -3
  64. package/dist/components/File/File.d.ts.map +1 -1
  65. package/dist/components/File/File.js +29 -17
  66. package/dist/components/File/File.js.map +1 -1
  67. package/dist/components/Input/Input.d.ts +16 -3
  68. package/dist/components/Input/Input.d.ts.map +1 -1
  69. package/dist/components/Input/Input.js +28 -13
  70. package/dist/components/Input/Input.js.map +1 -1
  71. package/dist/components/NativeSelect/NativeSelect.d.ts +17 -3
  72. package/dist/components/NativeSelect/NativeSelect.d.ts.map +1 -1
  73. package/dist/components/NativeSelect/NativeSelect.js +37 -14
  74. package/dist/components/NativeSelect/NativeSelect.js.map +1 -1
  75. package/dist/components/Radio/Radio.d.ts +18 -3
  76. package/dist/components/Radio/Radio.d.ts.map +1 -1
  77. package/dist/components/Radio/Radio.js +31 -11
  78. package/dist/components/Radio/Radio.js.map +1 -1
  79. package/dist/components/Radio/RadioInput/RadioInput.d.ts +16 -3
  80. package/dist/components/Radio/RadioInput/RadioInput.d.ts.map +1 -1
  81. package/dist/components/Radio/RadioInput/RadioInput.js +22 -11
  82. package/dist/components/Radio/RadioInput/RadioInput.js.map +1 -1
  83. package/dist/components/Search/Search.d.ts +16 -3
  84. package/dist/components/Search/Search.d.ts.map +1 -1
  85. package/dist/components/Search/Search.js +50 -28
  86. package/dist/components/Search/Search.js.map +1 -1
  87. package/dist/components/Select/Select.d.ts.map +1 -1
  88. package/dist/components/Select/Select.js +10 -4
  89. package/dist/components/Select/Select.js.map +1 -1
  90. package/dist/components/SelectionControl/SelectionControl.d.ts +2 -2
  91. package/dist/components/SelectionControl/SelectionControl.d.ts.map +1 -1
  92. package/dist/components/SelectionControl/SelectionControl.js.map +1 -1
  93. package/dist/components/Snackbar/Snackbar.d.ts +10 -1
  94. package/dist/components/Snackbar/Snackbar.d.ts.map +1 -1
  95. package/dist/components/Snackbar/Snackbar.js +20 -6
  96. package/dist/components/Snackbar/Snackbar.js.map +1 -1
  97. package/dist/components/SplitLayout/SplitLayout.d.ts +16 -3
  98. package/dist/components/SplitLayout/SplitLayout.d.ts.map +1 -1
  99. package/dist/components/SplitLayout/SplitLayout.js +24 -9
  100. package/dist/components/SplitLayout/SplitLayout.js.map +1 -1
  101. package/dist/components/Switch/Switch.d.ts +16 -3
  102. package/dist/components/Switch/Switch.d.ts.map +1 -1
  103. package/dist/components/Switch/Switch.js +32 -20
  104. package/dist/components/Switch/Switch.js.map +1 -1
  105. package/dist/components/Textarea/Textarea.d.ts +16 -3
  106. package/dist/components/Textarea/Textarea.d.ts.map +1 -1
  107. package/dist/components/Textarea/Textarea.js +36 -18
  108. package/dist/components/Textarea/Textarea.js.map +1 -1
  109. package/dist/components/WriteBar/WriteBar.d.ts +16 -3
  110. package/dist/components/WriteBar/WriteBar.d.ts.map +1 -1
  111. package/dist/components/WriteBar/WriteBar.js +28 -11
  112. package/dist/components/WriteBar/WriteBar.js.map +1 -1
  113. package/dist/components.css +1 -1
  114. package/dist/components.css.map +1 -1
  115. package/dist/cssm/components/Box/Box.js +19 -0
  116. package/dist/cssm/components/Box/Box.js.map +1 -0
  117. package/dist/cssm/components/CarouselBase/CarouselBase.js +4 -4
  118. package/dist/cssm/components/CarouselBase/CarouselBase.js.map +1 -1
  119. package/dist/cssm/components/CarouselBase/constants.js +1 -1
  120. package/dist/cssm/components/CarouselBase/constants.js.map +1 -1
  121. package/dist/cssm/components/CarouselBase/hooks.js +46 -6
  122. package/dist/cssm/components/CarouselBase/hooks.js.map +1 -1
  123. package/dist/cssm/components/CarouselBase/types.js.map +1 -1
  124. package/dist/cssm/components/Checkbox/Checkbox.js +29 -6
  125. package/dist/cssm/components/Checkbox/Checkbox.js.map +1 -1
  126. package/dist/cssm/components/Checkbox/CheckboxInput/CheckboxInput.js +24 -13
  127. package/dist/cssm/components/Checkbox/CheckboxInput/CheckboxInput.js.map +1 -1
  128. package/dist/cssm/components/Checkbox/CheckboxSimple/CheckboxSimple.js +24 -6
  129. package/dist/cssm/components/Checkbox/CheckboxSimple/CheckboxSimple.js.map +1 -1
  130. package/dist/cssm/components/ChipsInput/ChipsInput.js +25 -11
  131. package/dist/cssm/components/ChipsInput/ChipsInput.js.map +1 -1
  132. package/dist/cssm/components/ChipsInputBase/ChipsInputBase.js +30 -12
  133. package/dist/cssm/components/ChipsInputBase/ChipsInputBase.js.map +1 -1
  134. package/dist/cssm/components/ChipsInputBase/types.js.map +1 -1
  135. package/dist/cssm/components/ChipsSelect/ChipsSelect.js +49 -30
  136. package/dist/cssm/components/ChipsSelect/ChipsSelect.js.map +1 -1
  137. package/dist/cssm/components/CustomSelect/CustomSelect.js +73 -41
  138. package/dist/cssm/components/CustomSelect/CustomSelect.js.map +1 -1
  139. package/dist/cssm/components/CustomSelect/CustomSelectInput/CustomSelectInput.js +20 -9
  140. package/dist/cssm/components/CustomSelect/CustomSelectInput/CustomSelectInput.js.map +1 -1
  141. package/dist/cssm/components/CustomSelect/helpers.js +11 -0
  142. package/dist/cssm/components/CustomSelect/helpers.js.map +1 -1
  143. package/dist/cssm/components/Div/Div.js +11 -1
  144. package/dist/cssm/components/Div/Div.js.map +1 -1
  145. package/dist/cssm/components/File/File.js +20 -7
  146. package/dist/cssm/components/File/File.js.map +1 -1
  147. package/dist/cssm/components/Input/Input.js +20 -7
  148. package/dist/cssm/components/Input/Input.js.map +1 -1
  149. package/dist/cssm/components/MiniInfoCell/MiniInfoCell.module.css +1 -1
  150. package/dist/cssm/components/NativeSelect/NativeSelect.js +25 -8
  151. package/dist/cssm/components/NativeSelect/NativeSelect.js.map +1 -1
  152. package/dist/cssm/components/Radio/Radio.js +28 -8
  153. package/dist/cssm/components/Radio/Radio.js.map +1 -1
  154. package/dist/cssm/components/Radio/RadioInput/RadioInput.js +18 -6
  155. package/dist/cssm/components/Radio/RadioInput/RadioInput.js.map +1 -1
  156. package/dist/cssm/components/Search/Search.js +34 -17
  157. package/dist/cssm/components/Search/Search.js.map +1 -1
  158. package/dist/cssm/components/Select/Select.js +9 -1
  159. package/dist/cssm/components/Select/Select.js.map +1 -1
  160. package/dist/cssm/components/SelectionControl/SelectionControl.js.map +1 -1
  161. package/dist/cssm/components/Snackbar/Snackbar.js +11 -2
  162. package/dist/cssm/components/Snackbar/Snackbar.js.map +1 -1
  163. package/dist/cssm/components/SplitLayout/SplitLayout.js +22 -8
  164. package/dist/cssm/components/SplitLayout/SplitLayout.js.map +1 -1
  165. package/dist/cssm/components/Switch/Switch.js +29 -17
  166. package/dist/cssm/components/Switch/Switch.js.map +1 -1
  167. package/dist/cssm/components/Textarea/Textarea.js +22 -8
  168. package/dist/cssm/components/Textarea/Textarea.js.map +1 -1
  169. package/dist/cssm/components/WriteBar/WriteBar.js +24 -9
  170. package/dist/cssm/components/WriteBar/WriteBar.js.map +1 -1
  171. package/dist/cssm/hooks/useMergeProps.js +38 -0
  172. package/dist/cssm/hooks/useMergeProps.js.map +1 -0
  173. package/dist/cssm/index.js +2 -0
  174. package/dist/cssm/index.js.map +1 -1
  175. package/dist/cssm/lib/animation/useCSSTransition.js +1 -1
  176. package/dist/cssm/lib/animation/useCSSTransition.js.map +1 -1
  177. package/dist/cssm/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js +1 -1
  178. package/dist/cssm/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js.map +1 -1
  179. package/dist/cssm/lib/fx.js +55 -8
  180. package/dist/cssm/lib/fx.js.map +1 -1
  181. package/dist/cssm/lib/layouts/gaps.js.map +1 -1
  182. package/dist/cssm/lib/layouts/helpers.js +21 -0
  183. package/dist/cssm/lib/layouts/helpers.js.map +1 -0
  184. package/dist/cssm/lib/layouts/index.js +1 -0
  185. package/dist/cssm/lib/layouts/index.js.map +1 -1
  186. package/dist/cssm/lib/layouts/layoutProps.js +89 -0
  187. package/dist/cssm/lib/layouts/layoutProps.js.map +1 -0
  188. package/dist/cssm/lib/layouts/resolveLayoutProps.js +36 -0
  189. package/dist/cssm/lib/layouts/resolveLayoutProps.js.map +1 -0
  190. package/dist/cssm/lib/layouts/types.js +3 -0
  191. package/dist/cssm/lib/layouts/types.js.map +1 -0
  192. package/dist/cssm/lib/warnOnce.js +1 -1
  193. package/dist/cssm/lib/warnOnce.js.map +1 -1
  194. package/dist/cssm/styles/layout.css +922 -0
  195. package/dist/hooks/useMergeProps.d.ts +6 -0
  196. package/dist/hooks/useMergeProps.d.ts.map +1 -0
  197. package/dist/hooks/useMergeProps.js +42 -0
  198. package/dist/hooks/useMergeProps.js.map +1 -0
  199. package/dist/index.d.ts +3 -0
  200. package/dist/index.d.ts.map +1 -1
  201. package/dist/index.js +1 -0
  202. package/dist/index.js.map +1 -1
  203. package/dist/lib/animation/useCSSTransition.js +1 -1
  204. package/dist/lib/animation/useCSSTransition.js.map +1 -1
  205. package/dist/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js +1 -1
  206. package/dist/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js.map +1 -1
  207. package/dist/lib/fx.d.ts +8 -1
  208. package/dist/lib/fx.d.ts.map +1 -1
  209. package/dist/lib/fx.js +55 -8
  210. package/dist/lib/fx.js.map +1 -1
  211. package/dist/lib/layouts/gaps.d.ts +4 -5
  212. package/dist/lib/layouts/gaps.d.ts.map +1 -1
  213. package/dist/lib/layouts/gaps.js.map +1 -1
  214. package/dist/lib/layouts/helpers.d.ts +17 -0
  215. package/dist/lib/layouts/helpers.d.ts.map +1 -0
  216. package/dist/lib/layouts/helpers.js +21 -0
  217. package/dist/lib/layouts/helpers.js.map +1 -0
  218. package/dist/lib/layouts/index.d.ts +2 -0
  219. package/dist/lib/layouts/index.d.ts.map +1 -1
  220. package/dist/lib/layouts/index.js +1 -0
  221. package/dist/lib/layouts/index.js.map +1 -1
  222. package/dist/lib/layouts/layoutProps.d.ts +33 -0
  223. package/dist/lib/layouts/layoutProps.d.ts.map +1 -0
  224. package/dist/lib/layouts/layoutProps.js +89 -0
  225. package/dist/lib/layouts/layoutProps.js.map +1 -0
  226. package/dist/lib/layouts/resolveLayoutProps.d.ts +18 -0
  227. package/dist/lib/layouts/resolveLayoutProps.d.ts.map +1 -0
  228. package/dist/lib/layouts/resolveLayoutProps.js +35 -0
  229. package/dist/lib/layouts/resolveLayoutProps.js.map +1 -0
  230. package/dist/lib/layouts/types.d.ts +123 -0
  231. package/dist/lib/layouts/types.d.ts.map +1 -0
  232. package/dist/lib/layouts/types.js +3 -0
  233. package/dist/lib/layouts/types.js.map +1 -0
  234. package/dist/lib/warnOnce.js +1 -1
  235. package/dist/lib/warnOnce.js.map +1 -1
  236. package/dist/vkui.css +1 -1
  237. package/dist/vkui.css.map +1 -1
  238. package/package.json +2 -2
  239. package/src/components/Box/Box.tsx +26 -0
  240. package/src/components/CarouselBase/CarouselBase.tsx +11 -4
  241. package/src/components/CarouselBase/constants.ts +1 -1
  242. package/src/components/CarouselBase/hooks.ts +31 -6
  243. package/src/components/CarouselBase/types.ts +13 -0
  244. package/src/components/Checkbox/Checkbox.tsx +57 -7
  245. package/src/components/Checkbox/CheckboxInput/CheckboxInput.tsx +51 -18
  246. package/src/components/Checkbox/CheckboxSimple/CheckboxSimple.tsx +36 -6
  247. package/src/components/ChipsInput/ChipsInput.tsx +38 -11
  248. package/src/components/ChipsInputBase/ChipsInputBase.tsx +60 -17
  249. package/src/components/ChipsInputBase/types.ts +15 -4
  250. package/src/components/ChipsSelect/ChipsSelect.tsx +71 -33
  251. package/src/components/CustomSelect/CustomSelect.tsx +135 -45
  252. package/src/components/CustomSelect/CustomSelectInput/CustomSelectInput.tsx +48 -17
  253. package/src/components/CustomSelect/helpers.ts +23 -0
  254. package/src/components/Div/Div.tsx +13 -3
  255. package/src/components/File/File.tsx +48 -11
  256. package/src/components/Input/Input.tsx +51 -14
  257. package/src/components/MiniInfoCell/MiniInfoCell.module.css +1 -1
  258. package/src/components/NativeSelect/NativeSelect.tsx +57 -18
  259. package/src/components/Radio/Radio.tsx +51 -8
  260. package/src/components/Radio/RadioInput/RadioInput.tsx +35 -11
  261. package/src/components/Search/Search.tsx +80 -29
  262. package/src/components/Select/Select.tsx +22 -3
  263. package/src/components/SelectionControl/SelectionControl.tsx +2 -1
  264. package/src/components/Snackbar/Snackbar.tsx +35 -5
  265. package/src/components/SplitLayout/SplitLayout.tsx +46 -12
  266. package/src/components/Switch/Switch.tsx +62 -31
  267. package/src/components/Textarea/Textarea.tsx +58 -14
  268. package/src/components/WriteBar/WriteBar.tsx +59 -13
  269. package/src/hooks/useMergeProps.ts +66 -0
  270. package/src/index.ts +3 -0
  271. package/src/lib/animation/useCSSTransition.ts +1 -1
  272. package/src/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.ts +1 -1
  273. package/src/lib/fx.ts +63 -8
  274. package/src/lib/layouts/gaps.ts +4 -5
  275. package/src/lib/layouts/helpers.ts +24 -0
  276. package/src/lib/layouts/index.ts +13 -0
  277. package/src/lib/layouts/layoutProps.ts +75 -0
  278. package/src/lib/layouts/resolveLayoutProps.ts +51 -0
  279. package/src/lib/layouts/types.ts +142 -0
  280. package/src/lib/warnOnce.ts +1 -1
  281. package/src/styles/layout.css +1 -0
  282. package/src/styles/layout.css.d.ts.map +1 -0
@@ -5,20 +5,27 @@ import { classNames } from '@vkontakte/vkjs';
5
5
  import { getRequiredValueByKey } from '../../helpers/getValueByKey';
6
6
  import { useAdaptivity } from '../../hooks/useAdaptivity';
7
7
  import { useExternRef } from '../../hooks/useExternRef';
8
+ import { useMergeProps } from '../../hooks/useMergeProps';
8
9
  import { callMultiple } from '../../lib/callMultiple';
9
10
  import { useDOM } from '../../lib/dom';
10
11
  import type { Placement } from '../../lib/floating';
11
12
  import { defaultFilterFn, type FilterFn } from '../../lib/select';
12
13
  import { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';
13
14
  import { preventDefault } from '../../lib/utils';
15
+ import { type HasDataAttribute, type HasRootRef } from '../../types';
14
16
  import {
15
17
  CustomSelectDropdown,
16
18
  type CustomSelectDropdownProps,
17
19
  } from '../CustomSelectDropdown/CustomSelectDropdown';
18
20
  import { CustomSelectOption } from '../CustomSelectOption/CustomSelectOption';
19
21
  import type { FormFieldProps } from '../FormField/FormField';
20
- import type { NativeSelectProps, SelectValue } from '../NativeSelect/NativeSelect';
21
- import { NOT_SELECTED, remapFromNativeValueToSelectValue } from '../NativeSelect/NativeSelect';
22
+ import {
23
+ type NativeSelectProps,
24
+ NOT_SELECTED,
25
+ remapFromNativeValueToSelectValue,
26
+ type SelectValue,
27
+ } from '../NativeSelect/NativeSelect';
28
+ import { RootComponent } from '../RootComponent/RootComponent';
22
29
  import type { SelectType } from '../Select/Select';
23
30
  import { Footnote } from '../Typography/Footnote/Footnote';
24
31
  import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden';
@@ -28,6 +35,7 @@ import {
28
35
  type CustomSelectInputProps,
29
36
  } from './CustomSelectInput/CustomSelectInput';
30
37
  import {
38
+ checkDeprecatedProps,
31
39
  checkMixControlledAndUncontrolledState,
32
40
  checkOptionsValueType,
33
41
  filter,
@@ -110,11 +118,24 @@ export type { CustomSelectClearButtonProps };
110
118
 
111
119
  export interface SelectProps<
112
120
  OptionInterfaceT extends CustomSelectOptionInterface = CustomSelectOptionInterface,
113
- > extends NativeSelectProps,
121
+ > extends Omit<NativeSelectProps, 'slotProps'>,
114
122
  Omit<FormFieldProps, 'maxHeight'>,
115
123
  Pick<CustomSelectDropdownProps, 'overscrollBehavior'>,
116
124
  Pick<CustomSelectInputProps, 'minLength' | 'maxLength' | 'pattern' | 'readOnly'> {
117
125
  /**
126
+ * Свойства, которые можно прокинуть внутрь компонента:
127
+ * - `root`: свойства для прокидывания в корень компонента;
128
+ * - `select`: свойства для прокидывания в нативный `select`;
129
+ * - `input`: свойства для прокидывания в нативный `input`.
130
+ */
131
+ slotProps?: NativeSelectProps['slotProps'] & {
132
+ input?: React.InputHTMLAttributes<HTMLInputElement> &
133
+ HasDataAttribute &
134
+ HasRootRef<HTMLInputElement>;
135
+ };
136
+ /**
137
+ * @deprecated Since 7.9.0. Вместо этого используйте `slotProps={ input: { getRootRef: ... } }`.
138
+ *
118
139
  * Ref на внутрений компонент input.
119
140
  */
120
141
  getSelectInputRef?: React.Ref<HTMLInputElement>;
@@ -216,6 +237,8 @@ export interface SelectProps<
216
237
  */
217
238
  labelTextTestId?: string;
218
239
  /**
240
+ * @deprecated Since 7.9.0. Вместо этого используйте `slotProps={ select: { 'data-testid': ... } }`.
241
+ *
219
242
  * Передает атрибут `data-testid` для нативного элемента `select`.
220
243
  */
221
244
  nativeSelectTestId?: string;
@@ -245,13 +268,13 @@ export function CustomSelect<OptionInterfaceT extends CustomSelectOptionInterfac
245
268
  props: SelectProps<OptionInterfaceT>,
246
269
  ): React.ReactNode {
247
270
  const {
271
+ style,
272
+ className,
273
+ getRootRef,
248
274
  before,
249
275
  name,
250
- className,
251
276
  getRef,
252
- getRootRef,
253
277
  popupDirection = 'bottom',
254
- style,
255
278
  onChange,
256
279
  children,
257
280
  'onInputChange': onInputChangeProp,
@@ -259,7 +282,12 @@ export function CustomSelect<OptionInterfaceT extends CustomSelectOptionInterfac
259
282
  onOpen,
260
283
  onClose,
261
284
  fetching,
285
+ labelTextTestId,
286
+ multiline,
287
+ placeholder,
288
+ status,
262
289
  forceDropdownPortal,
290
+ align,
263
291
  selectType = 'default',
264
292
  searchable = false,
265
293
  'renderOption': renderOptionProp = defaultRenderOptionFn,
@@ -280,32 +308,80 @@ export function CustomSelect<OptionInterfaceT extends CustomSelectOptionInterfac
280
308
  getSelectInputRef,
281
309
  overscrollBehavior,
282
310
  'onInputKeyDown': onInputKeyDownProp,
283
- readOnly,
284
311
  accessible = false,
285
312
  fetchingInProgressLabel,
286
313
  fetchingCompletedLabel,
314
+ 'value': selectValue,
315
+
316
+ slotProps,
287
317
  ...restProps
288
318
  } = props;
289
319
 
290
320
  if (process.env.NODE_ENV === 'development') {
291
321
  checkOptionsValueType(options);
322
+ checkDeprecatedProps(props);
292
323
  }
293
324
 
294
325
  const { sizeY = 'none' } = useAdaptivity();
295
326
 
327
+ const {
328
+ onClick: onRootClick,
329
+ onMouseMove: onRootMouseMove,
330
+ onMouseDown: onRootMouseDown,
331
+ getRootRef: rootRef,
332
+ ...rootRest
333
+ } = useMergeProps(
334
+ {
335
+ style,
336
+ className,
337
+ getRootRef,
338
+ },
339
+ slotProps?.root,
340
+ );
341
+
342
+ const { getRootRef: getSelectRef, ...selectRest } = useMergeProps(
343
+ {
344
+ getRootRef: getRef,
345
+ onBlur: props.onBlur,
346
+ onFocus: props.onFocus,
347
+ onClick: props.onClick,
348
+ },
349
+ slotProps?.select,
350
+ );
351
+
352
+ const {
353
+ getRootRef: getInputRef,
354
+ onChange: onChangeInput,
355
+ onFocus: onInputFocus,
356
+ onBlur: onInputBlur,
357
+ onKeyDown: onNativeInputKeyDown,
358
+ onClick: onNativeInputClick,
359
+ readOnly,
360
+ ...inputRest
361
+ } = useMergeProps(
362
+ {
363
+ getRootRef: getSelectInputRef,
364
+ onChange: onInputChangeProp,
365
+ // Приводим типы так как в CustomSelect типы в rest определены как React.SelectHTMLAttributes<HTMLSelectElement>
366
+ // Хотя эти свойства прокидываются в input
367
+ ...(restProps as React.InputHTMLAttributes<HTMLInputElement>),
368
+ },
369
+ slotProps?.input,
370
+ );
371
+
296
372
  const containerRef = React.useRef<HTMLDivElement>(null);
297
- const handleRootRef = useExternRef(containerRef, getRootRef);
298
- const selectElRef = useExternRef(getRef);
299
- const selectInputRef = useExternRef(getSelectInputRef);
373
+ const handleRootRef = useExternRef(containerRef, rootRef);
374
+ const selectElRef = useExternRef(getSelectRef);
375
+ const selectInputRef = useExternRef(getInputRef);
300
376
 
301
377
  const propsValue = React.useMemo<SelectValue | undefined>(() => {
302
- if (props.value === undefined) {
378
+ if (selectValue === undefined) {
303
379
  return undefined;
304
380
  }
305
- return getOptionByValue(options, props.value)?.value ?? null;
306
- }, [options, props.value]);
381
+ return getOptionByValue(options, selectValue)?.value ?? null;
382
+ }, [options, selectValue]);
307
383
 
308
- const [isControlledOutside, setIsControlledOutside] = React.useState(props.value !== undefined);
384
+ const [isControlledOutside, setIsControlledOutside] = React.useState(selectValue !== undefined);
309
385
  const [popperPlacement, setPopperPlacement] = React.useState<Placement>(popupDirection);
310
386
 
311
387
  const {
@@ -332,7 +408,7 @@ export function CustomSelect<OptionInterfaceT extends CustomSelectOptionInterfac
332
408
  options,
333
409
  accessible,
334
410
  selectedValue: selectedOptionValue,
335
- onInputChange: onInputChangeProp,
411
+ onInputChange: onChangeInput,
336
412
  });
337
413
 
338
414
  const filteredOptions = React.useMemo(
@@ -433,7 +509,7 @@ export function CustomSelect<OptionInterfaceT extends CustomSelectOptionInterfac
433
509
  selectOption(focusedOptionValue);
434
510
  }, [focusedOptionValue, selectOption]);
435
511
 
436
- const onInputKeyDown = useInputKeyboardController({
512
+ const handleInputKeyDown = useInputKeyboardController({
437
513
  opened,
438
514
  open,
439
515
  close,
@@ -623,39 +699,54 @@ export function CustomSelect<OptionInterfaceT extends CustomSelectOptionInterfac
623
699
  [resetFocusedOption],
624
700
  );
625
701
 
702
+ const updateLastMousePosition = (e: React.MouseEvent) => {
703
+ lastMousePositionRef.current = { x: e.clientX, y: e.clientY };
704
+ };
705
+
626
706
  return (
627
- <div
628
- className={classNames(styles.host, sizeY !== 'regular' && sizeYClassNames[sizeY], className)}
629
- style={style}
630
- ref={handleRootRef}
631
- onClick={passClickAndFocusToInputOnClick}
632
- onMouseDown={preventInputBlurWhenClickInsideFocusedSelectArea}
633
- onMouseMove={function updateLastMousePosition(e) {
634
- lastMousePositionRef.current = { x: e.clientX, y: e.clientY };
635
- }}
707
+ <RootComponent
708
+ baseClassName={classNames(styles.host, sizeY !== 'regular' && sizeYClassNames[sizeY])}
709
+ getRootRef={handleRootRef}
710
+ onClick={callMultiple(onRootClick, passClickAndFocusToInputOnClick)}
711
+ onMouseDown={callMultiple(onRootMouseDown, preventInputBlurWhenClickInsideFocusedSelectArea)}
712
+ onMouseMove={callMultiple(onRootMouseMove, updateLastMousePosition)}
713
+ {...rootRest}
636
714
  >
637
715
  <CustomSelectInput
638
716
  autoComplete="off"
639
717
  autoCapitalize="none"
640
718
  autoCorrect="off"
641
719
  spellCheck="false"
642
- {...restProps}
643
- {...selectInputAriaProps}
644
- getRef={selectInputRef}
645
- onFocus={onFocus}
646
- onBlur={onBlur}
647
- className={openedClassNames}
648
- readOnly={readOnly || !searchable}
649
720
  fetching={fetching}
650
721
  searchable={searchable}
651
722
  accessible={accessible}
652
- value={inputValue}
653
- onKeyDown={!readOnly ? onInputKeyDown : undefined}
654
- onChange={onInputChange}
655
- onClick={!readOnly ? toggleOpened : undefined}
656
723
  before={before}
657
724
  after={afterItems}
658
725
  selectType={selectType}
726
+ align={align}
727
+ status={status}
728
+ placeholder={placeholder}
729
+ multiline={multiline}
730
+ labelTextTestId={labelTextTestId}
731
+ slotProps={{
732
+ root: { className: openedClassNames },
733
+ input: {
734
+ getRootRef: selectInputRef,
735
+ onChange: onInputChange,
736
+ onFocus: callMultiple(onFocus, onInputFocus),
737
+ onBlur: callMultiple(onBlur, onInputFocus),
738
+ onKeyDown: !readOnly
739
+ ? callMultiple(handleInputKeyDown, onNativeInputKeyDown)
740
+ : onNativeInputKeyDown,
741
+ onClick: !readOnly
742
+ ? callMultiple(toggleOpened, onNativeInputClick)
743
+ : onNativeInputClick,
744
+ value: inputValue,
745
+ readOnly: readOnly || !searchable,
746
+ ...selectInputAriaProps,
747
+ ...inputRest,
748
+ },
749
+ }}
659
750
  >
660
751
  {selected?.label}
661
752
  </CustomSelectInput>
@@ -666,19 +757,18 @@ export function CustomSelect<OptionInterfaceT extends CustomSelectOptionInterfac
666
757
  fetchingInProgressLabel={fetchingInProgressLabel}
667
758
  fetchingCompletedLabel={fetchingCompletedLabel}
668
759
  />
669
- <select
760
+ <RootComponent
761
+ Component="select"
762
+ baseClassName={styles.control}
670
763
  tabIndex={-1}
671
- ref={selectElRef}
672
764
  name={name}
673
- onChange={onNativeSelectChange}
674
- onBlur={props.onBlur}
675
- onFocus={props.onFocus}
676
- onClick={props.onClick}
677
765
  value={nativeSelectValue}
678
766
  aria-hidden
679
- className={styles.control}
680
767
  data-testid={nativeSelectTestId}
681
768
  required={required}
769
+ onChange={onNativeSelectChange}
770
+ getRootRef={selectElRef}
771
+ {...selectRest}
682
772
  >
683
773
  {(allowClearButton || nativeSelectValue === NOT_SELECTED.NATIVE) && (
684
774
  <option key={NOT_SELECTED.NATIVE} value={NOT_SELECTED.NATIVE} />
@@ -686,7 +776,7 @@ export function CustomSelect<OptionInterfaceT extends CustomSelectOptionInterfac
686
776
  {options.map((item) => (
687
777
  <option key={`${item.value}`} value={item.value} />
688
778
  ))}
689
- </select>
779
+ </RootComponent>
690
780
  {opened && (
691
781
  <CustomSelectDropdown
692
782
  targetRef={containerRef}
@@ -708,6 +798,6 @@ export function CustomSelect<OptionInterfaceT extends CustomSelectOptionInterfac
708
798
  {resolvedContent}
709
799
  </CustomSelectDropdown>
710
800
  )}
711
- </div>
801
+ </RootComponent>
712
802
  );
713
803
  }
@@ -6,9 +6,10 @@ import { classNames } from '@vkontakte/vkjs';
6
6
  import { useAdaptivity } from '../../../hooks/useAdaptivity';
7
7
  import { useExternRef } from '../../../hooks/useExternRef';
8
8
  import { useFocusWithin } from '../../../hooks/useFocusWithin';
9
+ import { useMergeProps } from '../../../hooks/useMergeProps';
9
10
  import { usePlatform } from '../../../hooks/usePlatform';
10
11
  import { getFormFieldModeFromSelectType } from '../../../lib/select';
11
- import type { HasAlign, HasRef, HasRootRef } from '../../../types';
12
+ import type { HasAlign, HasDataAttribute, HasRef, HasRootRef } from '../../../types';
12
13
  import { FormField, type FormFieldProps } from '../../FormField/FormField';
13
14
  import type { SelectType } from '../../Select/Select';
14
15
  import { SelectTypography } from '../../SelectTypography/SelectTypography';
@@ -27,6 +28,14 @@ export interface CustomSelectInputProps
27
28
  HasRootRef<HTMLDivElement>,
28
29
  HasAlign,
29
30
  Omit<FormFieldProps, 'mode' | 'type' | 'maxHeight'> {
31
+ slotProps?: {
32
+ input?: React.InputHTMLAttributes<HTMLInputElement> &
33
+ HasRootRef<HTMLInputElement> &
34
+ HasDataAttribute;
35
+ root?: Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> &
36
+ HasRootRef<HTMLDivElement> &
37
+ HasDataAttribute;
38
+ };
30
39
  selectType?: SelectType;
31
40
  multiline?: boolean;
32
41
  labelTextTestId?: string;
@@ -40,11 +49,11 @@ export interface CustomSelectInputProps
40
49
  * @private
41
50
  */
42
51
  export const CustomSelectInput = ({
52
+ style: rootStyle,
53
+ className: rootClassName,
54
+ getRootRef: rootGetRootRef,
43
55
  align = 'left',
44
56
  getRef,
45
- className,
46
- getRootRef,
47
- style,
48
57
  before,
49
58
  after,
50
59
  status,
@@ -52,37 +61,62 @@ export const CustomSelectInput = ({
52
61
  placeholder,
53
62
  selectType = 'default',
54
63
  multiline,
55
- disabled,
56
64
  fetching,
57
65
  labelTextTestId,
58
66
  searchable,
59
67
  accessible,
68
+
69
+ slotProps,
60
70
  ...restProps
61
71
  }: CustomSelectInputProps): React.ReactNode => {
62
72
  const { sizeY = 'none' } = useAdaptivity();
63
73
 
74
+ const { style, className, getRootRef, ...rootRest } = useMergeProps(
75
+ {
76
+ style: rootStyle,
77
+ className: rootClassName,
78
+ getRootRef: rootGetRootRef,
79
+ },
80
+ slotProps?.root,
81
+ );
82
+
83
+ const {
84
+ className: inputClassName,
85
+ value,
86
+ readOnly,
87
+ disabled,
88
+ ...inputProps
89
+ } = useMergeProps(
90
+ {
91
+ getRootRef: getRef,
92
+ ...restProps,
93
+ },
94
+ slotProps?.input,
95
+ );
96
+
64
97
  const title = children || placeholder;
65
- const showLabelOrPlaceholder = !Boolean(restProps.value);
98
+ const showLabelOrPlaceholder = !Boolean(value);
66
99
 
67
100
  const handleRootRef = useExternRef(getRootRef);
68
101
  const focusWithin = useFocusWithin(handleRootRef);
69
102
 
70
- const inputReadonly = restProps.readOnly || (disabled && fetching);
103
+ const inputReadonly = readOnly || (disabled && fetching);
71
104
 
72
105
  const input = (
73
106
  <Text
74
107
  type="text"
75
- {...restProps}
76
108
  disabled={disabled && !fetching}
77
109
  readOnly={inputReadonly}
78
110
  Component="input"
79
111
  normalize={false}
112
+ placeholder={children ? '' : placeholder}
80
113
  className={classNames(
81
114
  styles.el,
82
- (restProps.readOnly || (showLabelOrPlaceholder && !focusWithin)) && styles.elCursorPointer,
115
+ (readOnly || (showLabelOrPlaceholder && !focusWithin)) && styles.elCursorPointer,
116
+ inputClassName,
83
117
  )}
84
- getRootRef={getRef}
85
- placeholder={children ? '' : placeholder}
118
+ value={value}
119
+ {...inputProps}
86
120
  />
87
121
  );
88
122
 
@@ -116,7 +150,7 @@ export const CustomSelectInput = ({
116
150
  inputHidden && styles.inputHidden,
117
151
  labelHidden && styles.labelHidden,
118
152
  accessible && styles.accessible,
119
- restProps.value && styles.hasInputValue,
153
+ value && styles.hasInputValue,
120
154
  className,
121
155
  )}
122
156
  getRootRef={handleRootRef}
@@ -125,6 +159,7 @@ export const CustomSelectInput = ({
125
159
  disabled={disabled}
126
160
  mode={getFormFieldModeFromSelectType(selectType)}
127
161
  status={status}
162
+ {...rootRest}
128
163
  >
129
164
  <div className={styles.inputGroup}>
130
165
  <div
@@ -146,11 +181,7 @@ export const CustomSelectInput = ({
146
181
  * Делаем это только для режима read-only. Потому что проблема именно в режиме read-only.
147
182
  * Обертка вокруг инпута обрабатывает клики и передаёт фокус, так что на взаимодействии с инпутом это никак не скажется.
148
183
  **/}
149
- {restProps.readOnly && platform === 'ios' ? (
150
- <VisuallyHidden>{input}</VisuallyHidden>
151
- ) : (
152
- input
153
- )}
184
+ {readOnly && platform === 'ios' ? <VisuallyHidden>{input}</VisuallyHidden> : input}
154
185
  </div>
155
186
  </FormField>
156
187
  );
@@ -31,6 +31,29 @@ export const findIndexBefore = (
31
31
  };
32
32
  const warn = warnOnce('CustomSelect');
33
33
 
34
+ export const checkDeprecatedProps = ({
35
+ getRef,
36
+ getSelectInputRef,
37
+ nativeSelectTestId,
38
+ }: Pick<SelectProps, 'getRef' | 'getSelectInputRef' | 'nativeSelectTestId' | 'onInputChange'>) => {
39
+ /* istanbul ignore if: не проверяем в тестах */
40
+ if (getRef) {
41
+ warn('Свойство `getRef` устаревшее, используйте `slotProps={ select: { getRootRef: ... } }`');
42
+ }
43
+ /* istanbul ignore if: не проверяем в тестах */
44
+ if (getSelectInputRef) {
45
+ warn(
46
+ 'Свойство `getSelectInputRef` устаревшее, используйте `slotProps={ input: { getRootRef: ... } }`',
47
+ );
48
+ }
49
+ /* istanbul ignore if: не проверяем в тестах */
50
+ if (nativeSelectTestId) {
51
+ warn(
52
+ "Свойство `nativeSelectTestId` устаревшее, используйте `slotProps={ select: { 'data-testid': ... } }`",
53
+ );
54
+ }
55
+ };
56
+
34
57
  export const checkOptionsValueType = <T extends CustomSelectOptionInterface>(options: T[]) => {
35
58
  if (new Set(options.map((item) => typeof item.value)).size > 1) {
36
59
  warn(
@@ -1,13 +1,23 @@
1
1
  import * as React from 'react';
2
+ import { warnOnce } from '../../lib/warnOnce';
2
3
  import type { HTMLAttributesWithRootRef } from '../../types';
3
4
  import { RootComponent } from '../RootComponent/RootComponent';
4
5
  import styles from './Div.module.css';
5
6
 
6
7
  export type DivProps = HTMLAttributesWithRootRef<HTMLDivElement>;
7
8
 
9
+ const warn = warnOnce('Div');
10
+
8
11
  /**
9
12
  * @see https://vkui.io/components/div
13
+ *
14
+ * @deprecated Since 7.9.0. Будет удалено в **VKUI v9**.
15
+ * Используйте компонент `Box`.
10
16
  */
11
- export const Div = (props: DivProps): React.ReactNode => (
12
- <RootComponent baseClassName={styles.host} {...props} />
13
- );
17
+ export const Div = (props: DivProps): React.ReactNode => {
18
+ if (process.env.NODE_ENV === 'development') {
19
+ warn('Компонент Div устарел, используйте компонент Box в качестве альтернативы.');
20
+ }
21
+
22
+ return <RootComponent baseClassName={styles.host} {...props} />;
23
+ };
@@ -1,18 +1,44 @@
1
+ 'use client';
2
+
1
3
  import * as React from 'react';
2
- import type { HasRef, HasRootRef } from '../../types';
4
+ import { useMergeProps } from '../../hooks/useMergeProps';
5
+ import { warnOnce } from '../../lib/warnOnce';
6
+ import type { HasDataAttribute, HasRootRef } from '../../types';
3
7
  import { Button, type VKUIButtonProps } from '../Button/Button';
4
8
  import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden';
5
9
 
10
+ const warn = warnOnce('File');
11
+
6
12
  export interface FileProps
7
13
  extends Omit<VKUIButtonProps, 'type'>,
8
14
  Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'>,
9
- HasRef<HTMLInputElement>,
10
- HasRootRef<HTMLElement> {}
15
+ HasRootRef<HTMLElement> {
16
+ /**
17
+ * @deprecated Since 7.9.0. Вместо этого используйте `slotProps={ input: { getRootRef: ... } }`.
18
+ */
19
+ getRef?: React.Ref<HTMLInputElement>;
20
+ /**
21
+ * Свойства, которые можно прокинуть внутрь компонента:
22
+ * - `root`: свойства для прокидывания в корень компонента;
23
+ * - `input`: свойства для прокидывания в скрытый `input`.
24
+ */
25
+ slotProps?: {
26
+ root?: Omit<React.LabelHTMLAttributes<HTMLLabelElement>, 'children'> &
27
+ HasRootRef<HTMLLabelElement> &
28
+ HasDataAttribute;
29
+ input?: Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'> &
30
+ HasRootRef<HTMLInputElement> &
31
+ HasDataAttribute;
32
+ };
33
+ }
11
34
 
12
35
  /**
13
36
  * @see https://vkui.io/components/file
14
37
  */
15
38
  export const File = ({
39
+ getRootRef,
40
+ className,
41
+ style,
16
42
  children = 'Выберите файл',
17
43
  align = 'left',
18
44
  size,
@@ -21,18 +47,30 @@ export const File = ({
21
47
  before,
22
48
  after,
23
49
  loading,
24
- className,
25
- style,
26
50
  getRef,
27
- getRootRef,
28
51
  appearance,
52
+ slotProps,
29
53
  ...restProps
30
54
  }: FileProps): React.ReactNode => {
55
+ /* istanbul ignore if: не проверяем в тестах */
56
+ if (process.env.NODE_ENV === 'development' && getRef) {
57
+ warn('Свойство `getRef` устаревшее, используйте `slotProps={ input: { getRootRef: ... } }`');
58
+ }
59
+
60
+ const rootProps = useMergeProps(
61
+ {
62
+ className,
63
+ style,
64
+ getRootRef: getRootRef as React.Ref<HTMLLabelElement>,
65
+ },
66
+ slotProps?.root,
67
+ );
68
+ const inputRest = useMergeProps({ getRootRef: getRef, ...restProps }, slotProps?.input);
69
+
31
70
  return (
32
71
  <Button
33
72
  Component="label"
34
73
  align={align}
35
- className={className}
36
74
  stretched={stretched}
37
75
  mode={mode}
38
76
  appearance={appearance}
@@ -40,11 +78,10 @@ export const File = ({
40
78
  before={before}
41
79
  after={after}
42
80
  loading={loading}
43
- style={style}
44
- getRootRef={getRootRef}
45
- disabled={restProps.disabled}
81
+ disabled={inputRest.disabled}
82
+ {...rootProps}
46
83
  >
47
- <VisuallyHidden title="" {...restProps} Component="input" type="file" getRootRef={getRef} />
84
+ <VisuallyHidden title="" Component="input" type="file" {...inputRest} />
48
85
  {children}
49
86
  </Button>
50
87
  );