@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.
- package/dist/components/Box/Box.d.ts +11 -0
- package/dist/components/Box/Box.d.ts.map +1 -0
- package/dist/components/Box/Box.js +25 -0
- package/dist/components/Box/Box.js.map +1 -0
- package/dist/components/CarouselBase/CarouselBase.d.ts +1 -1
- package/dist/components/CarouselBase/CarouselBase.d.ts.map +1 -1
- package/dist/components/CarouselBase/CarouselBase.js +6 -4
- package/dist/components/CarouselBase/CarouselBase.js.map +1 -1
- package/dist/components/CarouselBase/constants.d.ts +1 -1
- package/dist/components/CarouselBase/constants.d.ts.map +1 -1
- package/dist/components/CarouselBase/constants.js +1 -1
- package/dist/components/CarouselBase/constants.js.map +1 -1
- package/dist/components/CarouselBase/hooks.d.ts +3 -1
- package/dist/components/CarouselBase/hooks.d.ts.map +1 -1
- package/dist/components/CarouselBase/hooks.js +46 -6
- package/dist/components/CarouselBase/hooks.js.map +1 -1
- package/dist/components/CarouselBase/types.d.ts +12 -0
- package/dist/components/CarouselBase/types.d.ts.map +1 -1
- package/dist/components/CarouselBase/types.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.d.ts +11 -2
- package/dist/components/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox/Checkbox.js +44 -10
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/Checkbox/CheckboxInput/CheckboxInput.d.ts +16 -3
- package/dist/components/Checkbox/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/components/Checkbox/CheckboxInput/CheckboxInput.js +32 -19
- package/dist/components/Checkbox/CheckboxInput/CheckboxInput.js.map +1 -1
- package/dist/components/Checkbox/CheckboxSimple/CheckboxSimple.d.ts +1 -1
- package/dist/components/Checkbox/CheckboxSimple/CheckboxSimple.d.ts.map +1 -1
- package/dist/components/Checkbox/CheckboxSimple/CheckboxSimple.js +39 -10
- package/dist/components/Checkbox/CheckboxSimple/CheckboxSimple.js.map +1 -1
- package/dist/components/ChipsInput/ChipsInput.d.ts +1 -1
- package/dist/components/ChipsInput/ChipsInput.d.ts.map +1 -1
- package/dist/components/ChipsInput/ChipsInput.js +32 -13
- package/dist/components/ChipsInput/ChipsInput.js.map +1 -1
- package/dist/components/ChipsInputBase/ChipsInputBase.d.ts +1 -1
- package/dist/components/ChipsInputBase/ChipsInputBase.d.ts.map +1 -1
- package/dist/components/ChipsInputBase/ChipsInputBase.js +52 -26
- package/dist/components/ChipsInputBase/ChipsInputBase.js.map +1 -1
- package/dist/components/ChipsInputBase/types.d.ts +13 -4
- package/dist/components/ChipsInputBase/types.d.ts.map +1 -1
- package/dist/components/ChipsInputBase/types.js.map +1 -1
- package/dist/components/ChipsSelect/ChipsSelect.d.ts +1 -1
- package/dist/components/ChipsSelect/ChipsSelect.d.ts.map +1 -1
- package/dist/components/ChipsSelect/ChipsSelect.js +67 -38
- package/dist/components/ChipsSelect/ChipsSelect.js.map +1 -1
- package/dist/components/CustomSelect/CustomSelect.d.ts +16 -2
- package/dist/components/CustomSelect/CustomSelect.d.ts.map +1 -1
- package/dist/components/CustomSelect/CustomSelect.js +99 -50
- package/dist/components/CustomSelect/CustomSelect.js.map +1 -1
- package/dist/components/CustomSelect/CustomSelectInput/CustomSelectInput.d.ts +6 -2
- package/dist/components/CustomSelect/CustomSelectInput/CustomSelectInput.d.ts.map +1 -1
- package/dist/components/CustomSelect/CustomSelectInput/CustomSelectInput.js +38 -20
- package/dist/components/CustomSelect/CustomSelectInput/CustomSelectInput.js.map +1 -1
- package/dist/components/CustomSelect/helpers.d.ts +1 -0
- package/dist/components/CustomSelect/helpers.d.ts.map +1 -1
- package/dist/components/CustomSelect/helpers.js +11 -0
- package/dist/components/CustomSelect/helpers.js.map +1 -1
- package/dist/components/Div/Div.d.ts +3 -0
- package/dist/components/Div/Div.d.ts.map +1 -1
- package/dist/components/Div/Div.js +11 -1
- package/dist/components/Div/Div.js.map +1 -1
- package/dist/components/File/File.d.ts +16 -3
- package/dist/components/File/File.d.ts.map +1 -1
- package/dist/components/File/File.js +29 -17
- package/dist/components/File/File.js.map +1 -1
- package/dist/components/Input/Input.d.ts +16 -3
- package/dist/components/Input/Input.d.ts.map +1 -1
- package/dist/components/Input/Input.js +28 -13
- package/dist/components/Input/Input.js.map +1 -1
- package/dist/components/NativeSelect/NativeSelect.d.ts +17 -3
- package/dist/components/NativeSelect/NativeSelect.d.ts.map +1 -1
- package/dist/components/NativeSelect/NativeSelect.js +37 -14
- package/dist/components/NativeSelect/NativeSelect.js.map +1 -1
- package/dist/components/Radio/Radio.d.ts +18 -3
- package/dist/components/Radio/Radio.d.ts.map +1 -1
- package/dist/components/Radio/Radio.js +31 -11
- package/dist/components/Radio/Radio.js.map +1 -1
- package/dist/components/Radio/RadioInput/RadioInput.d.ts +16 -3
- package/dist/components/Radio/RadioInput/RadioInput.d.ts.map +1 -1
- package/dist/components/Radio/RadioInput/RadioInput.js +22 -11
- package/dist/components/Radio/RadioInput/RadioInput.js.map +1 -1
- package/dist/components/Search/Search.d.ts +16 -3
- package/dist/components/Search/Search.d.ts.map +1 -1
- package/dist/components/Search/Search.js +50 -28
- package/dist/components/Search/Search.js.map +1 -1
- package/dist/components/Select/Select.d.ts.map +1 -1
- package/dist/components/Select/Select.js +10 -4
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/SelectionControl/SelectionControl.d.ts +2 -2
- package/dist/components/SelectionControl/SelectionControl.d.ts.map +1 -1
- package/dist/components/SelectionControl/SelectionControl.js.map +1 -1
- package/dist/components/Snackbar/Snackbar.d.ts +10 -1
- package/dist/components/Snackbar/Snackbar.d.ts.map +1 -1
- package/dist/components/Snackbar/Snackbar.js +20 -6
- package/dist/components/Snackbar/Snackbar.js.map +1 -1
- package/dist/components/SplitLayout/SplitLayout.d.ts +16 -3
- package/dist/components/SplitLayout/SplitLayout.d.ts.map +1 -1
- package/dist/components/SplitLayout/SplitLayout.js +24 -9
- package/dist/components/SplitLayout/SplitLayout.js.map +1 -1
- package/dist/components/Switch/Switch.d.ts +16 -3
- package/dist/components/Switch/Switch.d.ts.map +1 -1
- package/dist/components/Switch/Switch.js +32 -20
- package/dist/components/Switch/Switch.js.map +1 -1
- package/dist/components/Textarea/Textarea.d.ts +16 -3
- package/dist/components/Textarea/Textarea.d.ts.map +1 -1
- package/dist/components/Textarea/Textarea.js +36 -18
- package/dist/components/Textarea/Textarea.js.map +1 -1
- package/dist/components/WriteBar/WriteBar.d.ts +16 -3
- package/dist/components/WriteBar/WriteBar.d.ts.map +1 -1
- package/dist/components/WriteBar/WriteBar.js +28 -11
- package/dist/components/WriteBar/WriteBar.js.map +1 -1
- package/dist/components.css +1 -1
- package/dist/components.css.map +1 -1
- package/dist/cssm/components/Box/Box.js +19 -0
- package/dist/cssm/components/Box/Box.js.map +1 -0
- package/dist/cssm/components/CarouselBase/CarouselBase.js +4 -4
- package/dist/cssm/components/CarouselBase/CarouselBase.js.map +1 -1
- package/dist/cssm/components/CarouselBase/constants.js +1 -1
- package/dist/cssm/components/CarouselBase/constants.js.map +1 -1
- package/dist/cssm/components/CarouselBase/hooks.js +46 -6
- package/dist/cssm/components/CarouselBase/hooks.js.map +1 -1
- package/dist/cssm/components/CarouselBase/types.js.map +1 -1
- package/dist/cssm/components/Checkbox/Checkbox.js +29 -6
- package/dist/cssm/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/cssm/components/Checkbox/CheckboxInput/CheckboxInput.js +24 -13
- package/dist/cssm/components/Checkbox/CheckboxInput/CheckboxInput.js.map +1 -1
- package/dist/cssm/components/Checkbox/CheckboxSimple/CheckboxSimple.js +24 -6
- package/dist/cssm/components/Checkbox/CheckboxSimple/CheckboxSimple.js.map +1 -1
- package/dist/cssm/components/ChipsInput/ChipsInput.js +25 -11
- package/dist/cssm/components/ChipsInput/ChipsInput.js.map +1 -1
- package/dist/cssm/components/ChipsInputBase/ChipsInputBase.js +30 -12
- package/dist/cssm/components/ChipsInputBase/ChipsInputBase.js.map +1 -1
- package/dist/cssm/components/ChipsInputBase/types.js.map +1 -1
- package/dist/cssm/components/ChipsSelect/ChipsSelect.js +49 -30
- package/dist/cssm/components/ChipsSelect/ChipsSelect.js.map +1 -1
- package/dist/cssm/components/CustomSelect/CustomSelect.js +73 -41
- package/dist/cssm/components/CustomSelect/CustomSelect.js.map +1 -1
- package/dist/cssm/components/CustomSelect/CustomSelectInput/CustomSelectInput.js +20 -9
- package/dist/cssm/components/CustomSelect/CustomSelectInput/CustomSelectInput.js.map +1 -1
- package/dist/cssm/components/CustomSelect/helpers.js +11 -0
- package/dist/cssm/components/CustomSelect/helpers.js.map +1 -1
- package/dist/cssm/components/Div/Div.js +11 -1
- package/dist/cssm/components/Div/Div.js.map +1 -1
- package/dist/cssm/components/File/File.js +20 -7
- package/dist/cssm/components/File/File.js.map +1 -1
- package/dist/cssm/components/Input/Input.js +20 -7
- package/dist/cssm/components/Input/Input.js.map +1 -1
- package/dist/cssm/components/MiniInfoCell/MiniInfoCell.module.css +1 -1
- package/dist/cssm/components/NativeSelect/NativeSelect.js +25 -8
- package/dist/cssm/components/NativeSelect/NativeSelect.js.map +1 -1
- package/dist/cssm/components/Radio/Radio.js +28 -8
- package/dist/cssm/components/Radio/Radio.js.map +1 -1
- package/dist/cssm/components/Radio/RadioInput/RadioInput.js +18 -6
- package/dist/cssm/components/Radio/RadioInput/RadioInput.js.map +1 -1
- package/dist/cssm/components/Search/Search.js +34 -17
- package/dist/cssm/components/Search/Search.js.map +1 -1
- package/dist/cssm/components/Select/Select.js +9 -1
- package/dist/cssm/components/Select/Select.js.map +1 -1
- package/dist/cssm/components/SelectionControl/SelectionControl.js.map +1 -1
- package/dist/cssm/components/Snackbar/Snackbar.js +11 -2
- package/dist/cssm/components/Snackbar/Snackbar.js.map +1 -1
- package/dist/cssm/components/SplitLayout/SplitLayout.js +22 -8
- package/dist/cssm/components/SplitLayout/SplitLayout.js.map +1 -1
- package/dist/cssm/components/Switch/Switch.js +29 -17
- package/dist/cssm/components/Switch/Switch.js.map +1 -1
- package/dist/cssm/components/Textarea/Textarea.js +22 -8
- package/dist/cssm/components/Textarea/Textarea.js.map +1 -1
- package/dist/cssm/components/WriteBar/WriteBar.js +24 -9
- package/dist/cssm/components/WriteBar/WriteBar.js.map +1 -1
- package/dist/cssm/hooks/useMergeProps.js +38 -0
- package/dist/cssm/hooks/useMergeProps.js.map +1 -0
- package/dist/cssm/index.js +2 -0
- package/dist/cssm/index.js.map +1 -1
- package/dist/cssm/lib/animation/useCSSTransition.js +1 -1
- package/dist/cssm/lib/animation/useCSSTransition.js.map +1 -1
- package/dist/cssm/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js +1 -1
- package/dist/cssm/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js.map +1 -1
- package/dist/cssm/lib/fx.js +55 -8
- package/dist/cssm/lib/fx.js.map +1 -1
- package/dist/cssm/lib/layouts/gaps.js.map +1 -1
- package/dist/cssm/lib/layouts/helpers.js +21 -0
- package/dist/cssm/lib/layouts/helpers.js.map +1 -0
- package/dist/cssm/lib/layouts/index.js +1 -0
- package/dist/cssm/lib/layouts/index.js.map +1 -1
- package/dist/cssm/lib/layouts/layoutProps.js +89 -0
- package/dist/cssm/lib/layouts/layoutProps.js.map +1 -0
- package/dist/cssm/lib/layouts/resolveLayoutProps.js +36 -0
- package/dist/cssm/lib/layouts/resolveLayoutProps.js.map +1 -0
- package/dist/cssm/lib/layouts/types.js +3 -0
- package/dist/cssm/lib/layouts/types.js.map +1 -0
- package/dist/cssm/lib/warnOnce.js +1 -1
- package/dist/cssm/lib/warnOnce.js.map +1 -1
- package/dist/cssm/styles/layout.css +922 -0
- package/dist/hooks/useMergeProps.d.ts +6 -0
- package/dist/hooks/useMergeProps.d.ts.map +1 -0
- package/dist/hooks/useMergeProps.js +42 -0
- package/dist/hooks/useMergeProps.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/animation/useCSSTransition.js +1 -1
- package/dist/lib/animation/useCSSTransition.js.map +1 -1
- package/dist/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js +1 -1
- package/dist/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js.map +1 -1
- package/dist/lib/fx.d.ts +8 -1
- package/dist/lib/fx.d.ts.map +1 -1
- package/dist/lib/fx.js +55 -8
- package/dist/lib/fx.js.map +1 -1
- package/dist/lib/layouts/gaps.d.ts +4 -5
- package/dist/lib/layouts/gaps.d.ts.map +1 -1
- package/dist/lib/layouts/gaps.js.map +1 -1
- package/dist/lib/layouts/helpers.d.ts +17 -0
- package/dist/lib/layouts/helpers.d.ts.map +1 -0
- package/dist/lib/layouts/helpers.js +21 -0
- package/dist/lib/layouts/helpers.js.map +1 -0
- package/dist/lib/layouts/index.d.ts +2 -0
- package/dist/lib/layouts/index.d.ts.map +1 -1
- package/dist/lib/layouts/index.js +1 -0
- package/dist/lib/layouts/index.js.map +1 -1
- package/dist/lib/layouts/layoutProps.d.ts +33 -0
- package/dist/lib/layouts/layoutProps.d.ts.map +1 -0
- package/dist/lib/layouts/layoutProps.js +89 -0
- package/dist/lib/layouts/layoutProps.js.map +1 -0
- package/dist/lib/layouts/resolveLayoutProps.d.ts +18 -0
- package/dist/lib/layouts/resolveLayoutProps.d.ts.map +1 -0
- package/dist/lib/layouts/resolveLayoutProps.js +35 -0
- package/dist/lib/layouts/resolveLayoutProps.js.map +1 -0
- package/dist/lib/layouts/types.d.ts +123 -0
- package/dist/lib/layouts/types.d.ts.map +1 -0
- package/dist/lib/layouts/types.js +3 -0
- package/dist/lib/layouts/types.js.map +1 -0
- package/dist/lib/warnOnce.js +1 -1
- package/dist/lib/warnOnce.js.map +1 -1
- package/dist/vkui.css +1 -1
- package/dist/vkui.css.map +1 -1
- package/package.json +2 -2
- package/src/components/Box/Box.tsx +26 -0
- package/src/components/CarouselBase/CarouselBase.tsx +11 -4
- package/src/components/CarouselBase/constants.ts +1 -1
- package/src/components/CarouselBase/hooks.ts +31 -6
- package/src/components/CarouselBase/types.ts +13 -0
- package/src/components/Checkbox/Checkbox.tsx +57 -7
- package/src/components/Checkbox/CheckboxInput/CheckboxInput.tsx +51 -18
- package/src/components/Checkbox/CheckboxSimple/CheckboxSimple.tsx +36 -6
- package/src/components/ChipsInput/ChipsInput.tsx +38 -11
- package/src/components/ChipsInputBase/ChipsInputBase.tsx +60 -17
- package/src/components/ChipsInputBase/types.ts +15 -4
- package/src/components/ChipsSelect/ChipsSelect.tsx +71 -33
- package/src/components/CustomSelect/CustomSelect.tsx +135 -45
- package/src/components/CustomSelect/CustomSelectInput/CustomSelectInput.tsx +48 -17
- package/src/components/CustomSelect/helpers.ts +23 -0
- package/src/components/Div/Div.tsx +13 -3
- package/src/components/File/File.tsx +48 -11
- package/src/components/Input/Input.tsx +51 -14
- package/src/components/MiniInfoCell/MiniInfoCell.module.css +1 -1
- package/src/components/NativeSelect/NativeSelect.tsx +57 -18
- package/src/components/Radio/Radio.tsx +51 -8
- package/src/components/Radio/RadioInput/RadioInput.tsx +35 -11
- package/src/components/Search/Search.tsx +80 -29
- package/src/components/Select/Select.tsx +22 -3
- package/src/components/SelectionControl/SelectionControl.tsx +2 -1
- package/src/components/Snackbar/Snackbar.tsx +35 -5
- package/src/components/SplitLayout/SplitLayout.tsx +46 -12
- package/src/components/Switch/Switch.tsx +62 -31
- package/src/components/Textarea/Textarea.tsx +58 -14
- package/src/components/WriteBar/WriteBar.tsx +59 -13
- package/src/hooks/useMergeProps.ts +66 -0
- package/src/index.ts +3 -0
- package/src/lib/animation/useCSSTransition.ts +1 -1
- package/src/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.ts +1 -1
- package/src/lib/fx.ts +63 -8
- package/src/lib/layouts/gaps.ts +4 -5
- package/src/lib/layouts/helpers.ts +24 -0
- package/src/lib/layouts/index.ts +13 -0
- package/src/lib/layouts/layoutProps.ts +75 -0
- package/src/lib/layouts/resolveLayoutProps.ts +51 -0
- package/src/lib/layouts/types.ts +142 -0
- package/src/lib/warnOnce.ts +1 -1
- package/src/styles/layout.css +1 -0
- 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
|
|
21
|
-
|
|
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,
|
|
298
|
-
const selectElRef = useExternRef(
|
|
299
|
-
const selectInputRef = useExternRef(
|
|
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 (
|
|
378
|
+
if (selectValue === undefined) {
|
|
303
379
|
return undefined;
|
|
304
380
|
}
|
|
305
|
-
return getOptionByValue(options,
|
|
306
|
-
}, [options,
|
|
381
|
+
return getOptionByValue(options, selectValue)?.value ?? null;
|
|
382
|
+
}, [options, selectValue]);
|
|
307
383
|
|
|
308
|
-
const [isControlledOutside, setIsControlledOutside] = React.useState(
|
|
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:
|
|
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
|
|
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
|
-
<
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
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
|
-
<
|
|
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
|
-
</
|
|
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
|
-
</
|
|
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(
|
|
98
|
+
const showLabelOrPlaceholder = !Boolean(value);
|
|
66
99
|
|
|
67
100
|
const handleRootRef = useExternRef(getRootRef);
|
|
68
101
|
const focusWithin = useFocusWithin(handleRootRef);
|
|
69
102
|
|
|
70
|
-
const inputReadonly =
|
|
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
|
-
(
|
|
115
|
+
(readOnly || (showLabelOrPlaceholder && !focusWithin)) && styles.elCursorPointer,
|
|
116
|
+
inputClassName,
|
|
83
117
|
)}
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
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
|
-
{
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
10
|
-
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
disabled={restProps.disabled}
|
|
81
|
+
disabled={inputRest.disabled}
|
|
82
|
+
{...rootProps}
|
|
46
83
|
>
|
|
47
|
-
<VisuallyHidden title=""
|
|
84
|
+
<VisuallyHidden title="" Component="input" type="file" {...inputRest} />
|
|
48
85
|
{children}
|
|
49
86
|
</Button>
|
|
50
87
|
);
|