@vkontakte/vkui 6.5.3 → 6.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/CustomSelect/CustomSelect.d.ts +12 -2
- package/dist/cjs/components/CustomSelect/CustomSelect.d.ts.map +1 -1
- package/dist/cjs/components/CustomSelect/CustomSelect.js +72 -52
- package/dist/cjs/components/CustomSelect/CustomSelect.js.map +1 -1
- package/dist/cjs/components/CustomSelect/CustomSelectInput.d.ts +1 -3
- package/dist/cjs/components/CustomSelect/CustomSelectInput.d.ts.map +1 -1
- package/dist/cjs/components/CustomSelect/CustomSelectInput.js +24 -19
- package/dist/cjs/components/CustomSelect/CustomSelectInput.js.map +1 -1
- package/dist/components/CustomSelect/CustomSelect.d.ts +12 -2
- package/dist/components/CustomSelect/CustomSelect.d.ts.map +1 -1
- package/dist/components/CustomSelect/CustomSelect.js +64 -44
- package/dist/components/CustomSelect/CustomSelect.js.map +1 -1
- package/dist/components/CustomSelect/CustomSelectInput.d.ts +1 -3
- package/dist/components/CustomSelect/CustomSelectInput.d.ts.map +1 -1
- package/dist/components/CustomSelect/CustomSelectInput.js +24 -19
- package/dist/components/CustomSelect/CustomSelectInput.js.map +1 -1
- package/dist/components.css +1 -1
- package/dist/components.css.map +1 -1
- package/dist/components.js.tmp +101 -156
- package/dist/cssm/components/CustomSelect/CustomSelect.d.ts +12 -2
- package/dist/cssm/components/CustomSelect/CustomSelect.d.ts.map +1 -1
- package/dist/cssm/components/CustomSelect/CustomSelect.js +60 -41
- package/dist/cssm/components/CustomSelect/CustomSelect.js.map +1 -1
- package/dist/cssm/components/CustomSelect/CustomSelectInput.d.ts +1 -3
- package/dist/cssm/components/CustomSelect/CustomSelectInput.d.ts.map +1 -1
- package/dist/cssm/components/CustomSelect/CustomSelectInput.js +21 -16
- package/dist/cssm/components/CustomSelect/CustomSelectInput.js.map +1 -1
- package/dist/cssm/components/CustomSelect/CustomSelectInput.module.css +40 -74
- package/dist/vkui.css +1 -1
- package/dist/vkui.css.map +1 -1
- package/dist/vkui.js.tmp +101 -156
- package/package.json +1 -1
- package/src/components/CustomSelect/CustomSelect.tsx +101 -53
- package/src/components/CustomSelect/CustomSelectInput.module.css +35 -55
- package/src/components/CustomSelect/CustomSelectInput.tsx +35 -24
- package/dist/cjs/components/CustomSelect/helpers.d.ts +0 -8
- package/dist/cjs/components/CustomSelect/helpers.d.ts.map +0 -1
- package/dist/cjs/components/CustomSelect/helpers.js +0 -76
- package/dist/cjs/components/CustomSelect/helpers.js.map +0 -1
- package/dist/cjs/components/CustomSelect/types.d.ts +0 -12
- package/dist/cjs/components/CustomSelect/types.d.ts.map +0 -1
- package/dist/cjs/components/CustomSelect/types.js +0 -6
- package/dist/cjs/components/CustomSelect/types.js.map +0 -1
- package/dist/components/CustomSelect/helpers.d.ts +0 -8
- package/dist/components/CustomSelect/helpers.d.ts.map +0 -1
- package/dist/components/CustomSelect/helpers.js +0 -48
- package/dist/components/CustomSelect/helpers.js.map +0 -1
- package/dist/components/CustomSelect/types.d.ts +0 -12
- package/dist/components/CustomSelect/types.d.ts.map +0 -1
- package/dist/components/CustomSelect/types.js +0 -3
- package/dist/components/CustomSelect/types.js.map +0 -1
- package/dist/cssm/components/CustomSelect/helpers.d.ts +0 -8
- package/dist/cssm/components/CustomSelect/helpers.d.ts.map +0 -1
- package/dist/cssm/components/CustomSelect/helpers.js +0 -44
- package/dist/cssm/components/CustomSelect/helpers.js.map +0 -1
- package/dist/cssm/components/CustomSelect/types.d.ts +0 -12
- package/dist/cssm/components/CustomSelect/types.d.ts.map +0 -1
- package/dist/cssm/components/CustomSelect/types.js +0 -3
- package/dist/cssm/components/CustomSelect/types.js.map +0 -1
- package/src/components/CustomSelect/helpers.tsx +0 -61
- package/src/components/CustomSelect/types.ts +0 -15
|
@@ -17,17 +17,19 @@ const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
|
|
|
17
17
|
const _vkjs = require("@vkontakte/vkjs");
|
|
18
18
|
const _useAdaptivity = require("../../hooks/useAdaptivity");
|
|
19
19
|
const _useExternRef = require("../../hooks/useExternRef");
|
|
20
|
+
const _useFocusWithin = require("../../hooks/useFocusWithin");
|
|
20
21
|
const _usePlatform = require("../../hooks/usePlatform");
|
|
21
22
|
const _select = require("../../lib/select");
|
|
22
23
|
const _FormField = require("../FormField/FormField");
|
|
23
24
|
const _SelectTypography = require("../SelectTypography/SelectTypography");
|
|
25
|
+
const _Text = require("../Typography/Text/Text");
|
|
24
26
|
const _VisuallyHidden = require("../VisuallyHidden/VisuallyHidden");
|
|
25
27
|
const sizeYClassNames = {
|
|
26
28
|
none: "vkuiCustomSelectInput--sizeY-none",
|
|
27
29
|
compact: "vkuiCustomSelectInput--sizeY-compact"
|
|
28
30
|
};
|
|
29
31
|
const CustomSelectInput = (_param)=>{
|
|
30
|
-
var { align = 'left', getRef, className, getRootRef, style, before, after, status,
|
|
32
|
+
var { align = 'left', getRef, className, getRootRef, style, before, after, status, children, placeholder, selectType = 'default', multiline, disabled, fetching, labelTextTestId } = _param, restProps = _object_without_properties._(_param, [
|
|
31
33
|
"align",
|
|
32
34
|
"getRef",
|
|
33
35
|
"className",
|
|
@@ -36,32 +38,35 @@ const CustomSelectInput = (_param)=>{
|
|
|
36
38
|
"before",
|
|
37
39
|
"after",
|
|
38
40
|
"status",
|
|
39
|
-
"
|
|
41
|
+
"children",
|
|
42
|
+
"placeholder",
|
|
40
43
|
"selectType",
|
|
41
44
|
"multiline",
|
|
42
45
|
"disabled",
|
|
43
46
|
"fetching",
|
|
44
|
-
"labelTextTestId"
|
|
45
|
-
"searchable"
|
|
47
|
+
"labelTextTestId"
|
|
46
48
|
]);
|
|
47
49
|
const { sizeY = 'none' } = (0, _useAdaptivity.useAdaptivity)();
|
|
50
|
+
const title = children || placeholder;
|
|
51
|
+
const showLabelOrPlaceholder = !Boolean(restProps.value);
|
|
48
52
|
const handleRootRef = (0, _useExternRef.useExternRef)(getRootRef);
|
|
49
|
-
const
|
|
50
|
-
const input = /*#__PURE__*/ (0, _jsxruntime.jsx)(
|
|
51
|
-
selectType: selectType,
|
|
53
|
+
const focusWithin = (0, _useFocusWithin.useFocusWithin)(handleRootRef);
|
|
54
|
+
const input = /*#__PURE__*/ (0, _jsxruntime.jsx)(_Text.Text, _object_spread_props._(_object_spread._({
|
|
52
55
|
type: "text"
|
|
53
|
-
},
|
|
56
|
+
}, restProps), {
|
|
54
57
|
disabled: disabled && !fetching,
|
|
55
|
-
readOnly:
|
|
58
|
+
readOnly: restProps.readOnly || disabled && fetching,
|
|
56
59
|
Component: "input",
|
|
57
60
|
normalize: false,
|
|
58
|
-
className: "
|
|
59
|
-
getRootRef: getRef
|
|
61
|
+
className: (0, _vkjs.classNames)("vkuiCustomSelectInput__el", (restProps.readOnly || showLabelOrPlaceholder && !focusWithin) && "vkuiCustomSelectInput__el--cursor-pointer"),
|
|
62
|
+
getRootRef: getRef,
|
|
63
|
+
placeholder: children ? '' : placeholder
|
|
60
64
|
}));
|
|
65
|
+
const platform = (0, _usePlatform.usePlatform)();
|
|
61
66
|
return /*#__PURE__*/ (0, _jsxruntime.jsx)(_FormField.FormField, {
|
|
62
67
|
Component: "div",
|
|
63
68
|
style: style,
|
|
64
|
-
className: (0, _vkjs.classNames)("vkuiCustomSelectInput", align === 'right' && "vkuiCustomSelectInput--align-right", align === 'center' && "vkuiCustomSelectInput--align-center", !
|
|
69
|
+
className: (0, _vkjs.classNames)("vkuiCustomSelectInput", align === 'right' && "vkuiCustomSelectInput--align-right", align === 'center' && "vkuiCustomSelectInput--align-center", !children && "vkuiCustomSelectInput--empty", multiline && "vkuiCustomSelectInput--multiline", sizeY !== 'regular' && sizeYClassNames[sizeY], before && "vkuiCustomSelectInput--hasBefore", after && "vkuiCustomSelectInput--hasAfter", className),
|
|
65
70
|
getRootRef: handleRootRef,
|
|
66
71
|
before: before,
|
|
67
72
|
after: after,
|
|
@@ -71,20 +76,20 @@ const CustomSelectInput = (_param)=>{
|
|
|
71
76
|
children: /*#__PURE__*/ (0, _jsxruntime.jsxs)("div", {
|
|
72
77
|
className: "vkuiCustomSelectInput__input-group",
|
|
73
78
|
children: [
|
|
74
|
-
!searchable && platform === 'ios' ? /*#__PURE__*/ (0, _jsxruntime.jsx)(_VisuallyHidden.VisuallyHidden, {
|
|
75
|
-
children: input
|
|
76
|
-
}) : input,
|
|
77
79
|
/*#__PURE__*/ (0, _jsxruntime.jsx)("div", {
|
|
78
|
-
className: (0, _vkjs.classNames)("
|
|
80
|
+
className: (0, _vkjs.classNames)("vkuiCustomSelectInput__container", className),
|
|
79
81
|
tabIndex: -1,
|
|
80
82
|
"aria-hidden": true,
|
|
81
83
|
"data-testid": labelTextTestId,
|
|
82
84
|
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_SelectTypography.SelectTypography, {
|
|
83
85
|
selectType: selectType,
|
|
84
|
-
className: "
|
|
85
|
-
children:
|
|
86
|
+
className: "vkuiCustomSelectInput__title",
|
|
87
|
+
children: showLabelOrPlaceholder && title
|
|
86
88
|
})
|
|
87
|
-
})
|
|
89
|
+
}),
|
|
90
|
+
restProps.readOnly && platform === 'ios' ? /*#__PURE__*/ (0, _jsxruntime.jsx)(_VisuallyHidden.VisuallyHidden, {
|
|
91
|
+
children: input
|
|
92
|
+
}) : input
|
|
88
93
|
]
|
|
89
94
|
})
|
|
90
95
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/CustomSelect/CustomSelectInput.tsx"],"sourcesContent":["import * as React from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { usePlatform } from '../../hooks/usePlatform';\nimport { getFormFieldModeFromSelectType } from '../../lib/select';\nimport { HasAlign, HasRef, HasRootRef } from '../../types';\nimport { FormField, FormFieldProps } from '../FormField/FormField';\nimport type { SelectType } from '../Select/Select';\nimport { SelectTypography } from '../SelectTypography/SelectTypography';\nimport { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden';\nimport styles from './CustomSelectInput.module.css';\n\nconst sizeYClassNames = {\n none: styles['CustomSelectInput--sizeY-none'],\n compact: styles['CustomSelectInput--sizeY-compact'],\n};\n\nexport interface CustomSelectInputProps\n extends React.InputHTMLAttributes<HTMLInputElement>,\n HasRef<HTMLInputElement>,\n HasRootRef<HTMLDivElement>,\n HasAlign,\n Omit<FormFieldProps, 'mode' | 'type' | 'maxHeight'> {\n selectType?: SelectType;\n multiline?: boolean;\n labelTextTestId?: string;\n fetching?: boolean;\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/CustomSelect/CustomSelectInput.tsx"],"sourcesContent":["import * as React from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { useFocusWithin } from '../../hooks/useFocusWithin';\nimport { usePlatform } from '../../hooks/usePlatform';\nimport { getFormFieldModeFromSelectType } from '../../lib/select';\nimport { HasAlign, HasRef, HasRootRef } from '../../types';\nimport { FormField, FormFieldProps } from '../FormField/FormField';\nimport type { SelectType } from '../Select/Select';\nimport { SelectTypography } from '../SelectTypography/SelectTypography';\nimport { Text } from '../Typography/Text/Text';\nimport { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden';\nimport styles from './CustomSelectInput.module.css';\n\nconst sizeYClassNames = {\n none: styles['CustomSelectInput--sizeY-none'],\n compact: styles['CustomSelectInput--sizeY-compact'],\n};\n\nexport interface CustomSelectInputProps\n extends React.InputHTMLAttributes<HTMLInputElement>,\n HasRef<HTMLInputElement>,\n HasRootRef<HTMLDivElement>,\n HasAlign,\n Omit<FormFieldProps, 'mode' | 'type' | 'maxHeight'> {\n selectType?: SelectType;\n multiline?: boolean;\n labelTextTestId?: string;\n fetching?: boolean;\n}\n\n/**\n * @since 5.10.0\n * @private\n */\nexport const CustomSelectInput = ({\n align = 'left',\n getRef,\n className,\n getRootRef,\n style,\n before,\n after,\n status,\n children,\n placeholder,\n selectType = 'default',\n multiline,\n disabled,\n fetching,\n labelTextTestId,\n ...restProps\n}: CustomSelectInputProps): React.ReactNode => {\n const { sizeY = 'none' } = useAdaptivity();\n\n const title = children || placeholder;\n const showLabelOrPlaceholder = !Boolean(restProps.value);\n\n const handleRootRef = useExternRef(getRootRef);\n const focusWithin = useFocusWithin(handleRootRef);\n\n const input = (\n <Text\n type=\"text\"\n {...restProps}\n disabled={disabled && !fetching}\n readOnly={restProps.readOnly || (disabled && fetching)}\n Component=\"input\"\n normalize={false}\n className={classNames(\n styles['CustomSelectInput__el'],\n (restProps.readOnly || (showLabelOrPlaceholder && !focusWithin)) &&\n styles['CustomSelectInput__el--cursor-pointer'],\n )}\n getRootRef={getRef}\n placeholder={children ? '' : placeholder}\n />\n );\n\n const platform = usePlatform();\n return (\n <FormField\n Component=\"div\"\n style={style}\n className={classNames(\n styles['CustomSelectInput'],\n align === 'right' && styles['CustomSelectInput--align-right'],\n align === 'center' && styles['CustomSelectInput--align-center'],\n !children && styles['CustomSelectInput--empty'],\n multiline && styles['CustomSelectInput--multiline'],\n sizeY !== 'regular' && sizeYClassNames[sizeY],\n before && styles['CustomSelectInput--hasBefore'],\n after && styles['CustomSelectInput--hasAfter'],\n className,\n )}\n getRootRef={handleRootRef}\n before={before}\n after={after}\n disabled={disabled}\n mode={getFormFieldModeFromSelectType(selectType)}\n status={status}\n >\n <div className={styles['CustomSelectInput__input-group']}>\n <div\n className={classNames(styles['CustomSelectInput__container'], className)}\n tabIndex={-1}\n aria-hidden\n data-testid={labelTextTestId}\n >\n <SelectTypography selectType={selectType} className={styles['CustomSelectInput__title']}>\n {showLabelOrPlaceholder && title}\n </SelectTypography>\n </div>\n {/* Чтобы отключить autosuggestion в iOS, тултипы которого начинают всплывать даже когда input\n * в режиме readonly, мы оборачиваем инпут в VisuallyHidden.\n * Тултипы появляются при каждом клике на input.\n * смотри: https://github.com/VKCOM/VKUI/issues/6205\n *\n * Достаточно не дать пользователю кликнуть по инпуту.\n * Делаем это только для режима read-only. Потому что проблема именно в режиме read-only.\n * Обертка вокруг инпута обрабатывает клики и передаёт фокус, так что на взаимодействии с инпутом это никак не скажется.\n **/}\n {restProps.readOnly && platform === 'ios' ? (\n <VisuallyHidden>{input}</VisuallyHidden>\n ) : (\n input\n )}\n </div>\n </FormField>\n );\n};\n"],"names":["CustomSelectInput","sizeYClassNames","none","compact","align","getRef","className","getRootRef","style","before","after","status","children","placeholder","selectType","multiline","disabled","fetching","labelTextTestId","restProps","sizeY","useAdaptivity","title","showLabelOrPlaceholder","Boolean","value","handleRootRef","useExternRef","focusWithin","useFocusWithin","input","Text","type","readOnly","Component","normalize","classNames","platform","usePlatform","FormField","mode","getFormFieldModeFromSelectType","div","tabIndex","aria-hidden","data-testid","SelectTypography","VisuallyHidden"],"mappings":";;;;+BAoCaA;;;eAAAA;;;;;;;;iEApCU;sBACI;+BACG;8BACD;gCACE;6BACH;wBACmB;2BAEL;kCAET;sBACZ;gCACU;AAG/B,MAAMC,kBAAkB;IACtBC,IAAI;IACJC,OAAO;AACT;AAkBO,MAAMH,oBAAoB;QAAC,EAChCI,QAAQ,MAAM,EACdC,MAAM,EACNC,SAAS,EACTC,UAAU,EACVC,KAAK,EACLC,MAAM,EACNC,KAAK,EACLC,MAAM,EACNC,QAAQ,EACRC,WAAW,EACXC,aAAa,SAAS,EACtBC,SAAS,EACTC,QAAQ,EACRC,QAAQ,EACRC,eAAe,EAEQ,WADpBC;QAfHf;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;;IAGA,MAAM,EAAEE,QAAQ,MAAM,EAAE,GAAGC,IAAAA,4BAAa;IAExC,MAAMC,QAAQV,YAAYC;IAC1B,MAAMU,yBAAyB,CAACC,QAAQL,UAAUM,KAAK;IAEvD,MAAMC,gBAAgBC,IAAAA,0BAAY,EAACpB;IACnC,MAAMqB,cAAcC,IAAAA,8BAAc,EAACH;IAEnC,MAAMI,sBACJ,qBAACC,UAAI;QACHC,MAAK;OACDb;QACJH,UAAUA,YAAY,CAACC;QACvBgB,UAAUd,UAAUc,QAAQ,IAAKjB,YAAYC;QAC7CiB,WAAU;QACVC,WAAW;QACX7B,WAAW8B,IAAAA,gBAAU,+BAEnB,AAACjB,CAAAA,UAAUc,QAAQ,IAAKV,0BAA0B,CAACK,WAAW;QAGhErB,YAAYF;QACZQ,aAAaD,WAAW,KAAKC;;IAIjC,MAAMwB,WAAWC,IAAAA,wBAAW;IAC5B,qBACE,qBAACC,oBAAS;QACRL,WAAU;QACV1B,OAAOA;QACPF,WAAW8B,IAAAA,gBAAU,2BAEnBhC,UAAU,iDACVA,UAAU,mDACV,CAACQ,4CACDG,iDACAK,UAAU,aAAanB,eAAe,CAACmB,MAAM,EAC7CX,8CACAC,4CACAJ;QAEFC,YAAYmB;QACZjB,QAAQA;QACRC,OAAOA;QACPM,UAAUA;QACVwB,MAAMC,IAAAA,sCAA8B,EAAC3B;QACrCH,QAAQA;kBAER,cAAA,sBAAC+B;YAAIpC,SAAS;;8BACZ,qBAACoC;oBACCpC,WAAW8B,IAAAA,gBAAU,sCAAyC9B;oBAC9DqC,UAAU,CAAC;oBACXC,aAAW;oBACXC,eAAa3B;8BAEb,cAAA,qBAAC4B,kCAAgB;wBAAChC,YAAYA;wBAAYR,SAAS;kCAChDiB,0BAA0BD;;;gBAY9BH,UAAUc,QAAQ,IAAII,aAAa,sBAClC,qBAACU,8BAAc;8BAAEjB;qBAEjBA;;;;AAKV"}
|
|
@@ -2,12 +2,22 @@ import * as React from 'react';
|
|
|
2
2
|
import { type FilterFn } from '../../lib/select';
|
|
3
3
|
import { TrackerOptionsProps } from '../CustomScrollView/useTrackerVisibility';
|
|
4
4
|
import { CustomSelectDropdownProps } from '../CustomSelectDropdown/CustomSelectDropdown';
|
|
5
|
+
import { type CustomSelectOptionProps } from '../CustomSelectOption/CustomSelectOption';
|
|
5
6
|
import { FormFieldProps } from '../FormField/FormField';
|
|
6
7
|
import { NativeSelectProps } from '../NativeSelect/NativeSelect';
|
|
7
8
|
import { SelectType } from '../Select/Select';
|
|
8
9
|
import { type CustomSelectClearButtonProps } from './CustomSelectClearButton';
|
|
9
|
-
|
|
10
|
-
export
|
|
10
|
+
type SelectValue = React.SelectHTMLAttributes<HTMLSelectElement>['value'];
|
|
11
|
+
export interface CustomSelectOptionInterface {
|
|
12
|
+
value: SelectValue;
|
|
13
|
+
label: React.ReactElement | string;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
[index: string]: any;
|
|
16
|
+
}
|
|
17
|
+
export interface CustomSelectRenderOption<T extends CustomSelectOptionInterface> extends CustomSelectOptionProps {
|
|
18
|
+
option: T;
|
|
19
|
+
}
|
|
20
|
+
export type { CustomSelectClearButtonProps };
|
|
11
21
|
export interface SelectProps<OptionInterfaceT extends CustomSelectOptionInterface = CustomSelectOptionInterface> extends NativeSelectProps, Omit<FormFieldProps, 'maxHeight'>, TrackerOptionsProps, Pick<CustomSelectDropdownProps, 'overscrollBehavior' | 'autoHideScrollbar' | 'autoHideScrollbarDelay'> {
|
|
12
22
|
/**
|
|
13
23
|
* ref на внутрений компонент input
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CustomSelect.d.ts","sourceRoot":"","sources":["../../../src/components/CustomSelect/CustomSelect.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"CustomSelect.d.ts","sourceRoot":"","sources":["../../../src/components/CustomSelect/CustomSelect.tsx"],"names":[],"mappings":"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"}
|
|
@@ -6,29 +6,67 @@ import * as React from 'react';
|
|
|
6
6
|
import { classNames, debounce } from '@vkontakte/vkjs';
|
|
7
7
|
import { useAdaptivity } from '../../hooks/useAdaptivity';
|
|
8
8
|
import { useExternRef } from '../../hooks/useExternRef';
|
|
9
|
+
import { useFocusWithin } from '../../hooks/useFocusWithin';
|
|
9
10
|
import { useDOM } from '../../lib/dom';
|
|
10
11
|
import { defaultFilterFn } from '../../lib/select';
|
|
11
12
|
import { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';
|
|
12
13
|
import { warnOnce } from '../../lib/warnOnce';
|
|
13
14
|
import { CustomSelectDropdown } from '../CustomSelectDropdown/CustomSelectDropdown';
|
|
15
|
+
import { CustomSelectOption } from '../CustomSelectOption/CustomSelectOption';
|
|
14
16
|
import { DropdownIcon } from '../DropdownIcon/DropdownIcon';
|
|
15
17
|
import { Footnote } from '../Typography/Footnote/Footnote';
|
|
18
|
+
import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden';
|
|
16
19
|
import { CustomSelectClearButton } from './CustomSelectClearButton';
|
|
17
20
|
import { CustomSelectInput } from './CustomSelectInput';
|
|
18
|
-
import { calculateInputValueFromOptions, defaultRenderOptionFn, findIndexAfter, findIndexBefore, findSelectedIndex } from './helpers';
|
|
19
21
|
const sizeYClassNames = {
|
|
20
22
|
none: "vkuiCustomSelect--sizeY-none",
|
|
21
23
|
['compact']: "vkuiCustomSelect--sizeY-compact"
|
|
22
24
|
};
|
|
25
|
+
const findIndexAfter = (options = [], startIndex = -1)=>{
|
|
26
|
+
if (startIndex >= options.length - 1) {
|
|
27
|
+
return -1;
|
|
28
|
+
}
|
|
29
|
+
return options.findIndex((option, i)=>i > startIndex && !option.disabled);
|
|
30
|
+
};
|
|
31
|
+
const findIndexBefore = (options = [], endIndex = options.length)=>{
|
|
32
|
+
let result = -1;
|
|
33
|
+
if (endIndex <= 0) {
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
for(let i = endIndex - 1; i >= 0; i--){
|
|
37
|
+
let option = options[i];
|
|
38
|
+
if (!option.disabled) {
|
|
39
|
+
result = i;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
};
|
|
23
45
|
const warn = warnOnce('CustomSelect');
|
|
24
46
|
const checkOptionsValueType = (options)=>{
|
|
25
47
|
if (new Set(options.map((item)=>typeof item.value)).size > 1) {
|
|
26
48
|
warn('Некоторые значения ваших опций имеют разные типы. onChange всегда возвращает строковый тип.', 'error');
|
|
27
49
|
}
|
|
28
50
|
};
|
|
51
|
+
function defaultRenderOptionFn(_param) {
|
|
52
|
+
var { option } = _param, props = _object_without_properties(_param, [
|
|
53
|
+
"option"
|
|
54
|
+
]);
|
|
55
|
+
return /*#__PURE__*/ _jsx(CustomSelectOption, _object_spread({}, props));
|
|
56
|
+
}
|
|
29
57
|
const handleOptionDown = (e)=>{
|
|
30
58
|
e.preventDefault();
|
|
31
59
|
};
|
|
60
|
+
function findSelectedIndex(options = [], value, withClear) {
|
|
61
|
+
if (withClear && value === '') {
|
|
62
|
+
return -1;
|
|
63
|
+
}
|
|
64
|
+
var _options_findIndex;
|
|
65
|
+
return (_options_findIndex = options.findIndex((item)=>{
|
|
66
|
+
value = typeof item.value === 'number' ? Number(value) : value;
|
|
67
|
+
return item.value === value;
|
|
68
|
+
})) !== null && _options_findIndex !== void 0 ? _options_findIndex : -1;
|
|
69
|
+
}
|
|
32
70
|
const filter = (options, inputValue, filterFn)=>{
|
|
33
71
|
return typeof filterFn === 'function' ? options.filter((option)=>filterFn(inputValue, option)) : options;
|
|
34
72
|
};
|
|
@@ -83,14 +121,13 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
83
121
|
const scrollBoxRef = React.useRef(null);
|
|
84
122
|
const selectElRef = useExternRef(getRef);
|
|
85
123
|
const optionsWrapperRef = React.useRef(null);
|
|
86
|
-
const selectInputRef = useExternRef(getSelectInputRef);
|
|
87
124
|
const [focusedOptionIndex, setFocusedOptionIndex] = React.useState(-1);
|
|
88
125
|
const [isControlledOutside, setIsControlledOutside] = React.useState(props.value !== undefined);
|
|
126
|
+
const [inputValue, setInputValue] = React.useState('');
|
|
89
127
|
const [nativeSelectValue, setNativeSelectValue] = React.useState(()=>{
|
|
90
128
|
var _props_value, _ref;
|
|
91
129
|
return (_ref = (_props_value = props.value) !== null && _props_value !== void 0 ? _props_value : defaultValue) !== null && _ref !== void 0 ? _ref : allowClearButton ? '' : undefined;
|
|
92
130
|
});
|
|
93
|
-
const [inputValue, setInputValue] = React.useState(()=>calculateInputValueFromOptions(optionsProp, nativeSelectValue));
|
|
94
131
|
const [popperPlacement, setPopperPlacement] = React.useState(popupDirection);
|
|
95
132
|
const [options, setOptions] = React.useState(optionsProp);
|
|
96
133
|
var _props_value;
|
|
@@ -208,6 +245,7 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
208
245
|
* Сброс происходит в одном из эффекте `updateOptionsAndSelectedOptionIndex()`.
|
|
209
246
|
*/ const close = React.useCallback(()=>{
|
|
210
247
|
resetKeyboardInput();
|
|
248
|
+
setInputValue('');
|
|
211
249
|
setOpened(false);
|
|
212
250
|
resetFocusedOption();
|
|
213
251
|
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
@@ -218,8 +256,8 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
218
256
|
]);
|
|
219
257
|
const selectOption = React.useCallback((index)=>{
|
|
220
258
|
const item = options[index];
|
|
221
|
-
close();
|
|
222
259
|
setNativeSelectValue(item === null || item === void 0 ? void 0 : item.value);
|
|
260
|
+
close();
|
|
223
261
|
const shouldTriggerOnChangeWhenControlledAndInnerValueIsOutOfSync = isControlledOutside && props.value !== nativeSelectValue && nativeSelectValue === (item === null || item === void 0 ? void 0 : item.value);
|
|
224
262
|
if (shouldTriggerOnChangeWhenControlledAndInnerValueIsOutOfSync) {
|
|
225
263
|
var _selectElRef_current;
|
|
@@ -263,23 +301,18 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
263
301
|
bubbles: true
|
|
264
302
|
});
|
|
265
303
|
(_selectElRef_current = selectElRef.current) === null || _selectElRef_current === void 0 ? void 0 : _selectElRef_current.dispatchEvent(event);
|
|
266
|
-
setInputValue(calculateInputValueFromOptions(optionsProp, nativeSelectValue));
|
|
267
304
|
}, [
|
|
268
305
|
close,
|
|
269
|
-
selectElRef
|
|
270
|
-
optionsProp,
|
|
271
|
-
nativeSelectValue
|
|
306
|
+
selectElRef
|
|
272
307
|
]);
|
|
273
308
|
const onFocus = React.useCallback(()=>{
|
|
274
|
-
var _selectElRef_current
|
|
309
|
+
var _selectElRef_current;
|
|
275
310
|
const event = new Event('focusin', {
|
|
276
311
|
bubbles: true
|
|
277
312
|
});
|
|
278
313
|
(_selectElRef_current = selectElRef.current) === null || _selectElRef_current === void 0 ? void 0 : _selectElRef_current.dispatchEvent(event);
|
|
279
|
-
(_selectInputRef_current = selectInputRef.current) === null || _selectInputRef_current === void 0 ? void 0 : _selectInputRef_current.select();
|
|
280
314
|
}, [
|
|
281
|
-
selectElRef
|
|
282
|
-
selectInputRef
|
|
315
|
+
selectElRef
|
|
283
316
|
]);
|
|
284
317
|
const onClick = React.useCallback(()=>{
|
|
285
318
|
if (opened) {
|
|
@@ -310,38 +343,21 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
310
343
|
focusedOptionIndex,
|
|
311
344
|
options
|
|
312
345
|
]);
|
|
313
|
-
React.useEffect(function
|
|
346
|
+
React.useEffect(function updateOptionsAndSelectedOptionIndex() {
|
|
347
|
+
var _props_value, _ref;
|
|
348
|
+
const value = (_ref = (_props_value = props.value) !== null && _props_value !== void 0 ? _props_value : nativeSelectValue) !== null && _ref !== void 0 ? _ref : defaultValue;
|
|
314
349
|
const options = searchable && inputValue !== undefined ? filter(optionsProp, inputValue, filterFn) : optionsProp;
|
|
315
350
|
setOptions(options);
|
|
351
|
+
setSelectedOptionIndex(findSelectedIndex(options, value, allowClearButton));
|
|
316
352
|
}, [
|
|
317
353
|
filterFn,
|
|
318
354
|
inputValue,
|
|
355
|
+
nativeSelectValue,
|
|
319
356
|
optionsProp,
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
React.useEffect(function updateSelectedOptionIndexOnValueChange() {
|
|
325
|
-
setSelectedOptionIndex(findSelectedIndex(options, selectValue, allowClearButton));
|
|
326
|
-
}, [
|
|
327
|
-
selectValue,
|
|
328
|
-
allowClearButton,
|
|
329
|
-
options
|
|
330
|
-
]);
|
|
331
|
-
const prevSelectValueRef = React.useRef(selectValue);
|
|
332
|
-
React.useEffect(function updateInputValueOnSelectValueChange() {
|
|
333
|
-
if (prevSelectValueRef.current === selectValue) {
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
setInputValue(calculateInputValueFromOptions(optionsProp, selectValue));
|
|
337
|
-
}, [
|
|
338
|
-
selectValue,
|
|
339
|
-
optionsProp
|
|
340
|
-
]);
|
|
341
|
-
React.useEffect(function updatePrevSelectValue() {
|
|
342
|
-
prevSelectValueRef.current = selectValue;
|
|
343
|
-
}, [
|
|
344
|
-
selectValue
|
|
357
|
+
defaultValue,
|
|
358
|
+
props.value,
|
|
359
|
+
searchable,
|
|
360
|
+
allowClearButton
|
|
345
361
|
]);
|
|
346
362
|
const onNativeSelectChange = (e)=>{
|
|
347
363
|
const newSelectedOptionIndex = findSelectedIndex(options, e.currentTarget.value, allowClearButton);
|
|
@@ -506,6 +522,7 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
506
522
|
renderDropdown,
|
|
507
523
|
renderOption
|
|
508
524
|
]);
|
|
525
|
+
const selectInputRef = useExternRef(getSelectInputRef);
|
|
509
526
|
const focusOnInputTimerRef = React.useRef();
|
|
510
527
|
const focusOnInput = React.useCallback(()=>{
|
|
511
528
|
clearTimeout(focusOnInputTimerRef.current);
|
|
@@ -591,14 +608,11 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
591
608
|
selectInputRef
|
|
592
609
|
]);
|
|
593
610
|
const preventInputBlurWhenClickInsideFocusedSelectArea = (e)=>{
|
|
594
|
-
var _selectInputRef_current;
|
|
595
611
|
// Так как инпут больше не оборачивается пустым лэйблом, то клик внутри обертки,
|
|
596
612
|
// но вне инпута (например по иконке дропдауна), будет убирать фокус с инпута.
|
|
597
613
|
// Чтобы в такой ситуации отключить blur инпута мы превентим mousedown событие обёртки
|
|
598
614
|
const isInputFocused = document && document.activeElement === selectInputRef.current;
|
|
599
|
-
|
|
600
|
-
const inputClicked = (_selectInputRef_current = selectInputRef.current) === null || _selectInputRef_current === void 0 ? void 0 : _selectInputRef_current.contains(clickTarget);
|
|
601
|
-
if (isInputFocused && !inputClicked) {
|
|
615
|
+
if (isInputFocused) {
|
|
602
616
|
e.preventDefault();
|
|
603
617
|
}
|
|
604
618
|
};
|
|
@@ -607,12 +621,14 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
607
621
|
const selectInputAriaProps = {
|
|
608
622
|
'role': 'combobox',
|
|
609
623
|
'aria-controls': popupAriaId,
|
|
624
|
+
'aria-owns': popupAriaId,
|
|
610
625
|
'aria-expanded': opened,
|
|
611
626
|
['aria-activedescendant']: ariaActiveDescendantId && opened ? `${popupAriaId}-${ariaActiveDescendantId}` : undefined,
|
|
612
627
|
'aria-labelledby': ariaLabelledBy,
|
|
613
628
|
'aria-haspopup': 'listbox',
|
|
614
629
|
'aria-autocomplete': 'none'
|
|
615
630
|
};
|
|
631
|
+
const focusWithin = useFocusWithin(handleRootRef);
|
|
616
632
|
return /*#__PURE__*/ _jsxs("div", {
|
|
617
633
|
className: classNames("vkuiCustomSelect", sizeY !== 'regular' && sizeYClassNames[sizeY], className),
|
|
618
634
|
style: style,
|
|
@@ -620,6 +636,10 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
620
636
|
onClick: passClickAndFocusToInputOnClick,
|
|
621
637
|
onMouseDown: preventInputBlurWhenClickInsideFocusedSelectArea,
|
|
622
638
|
children: [
|
|
639
|
+
focusWithin && selected && !opened && /*#__PURE__*/ _jsx(VisuallyHidden, {
|
|
640
|
+
"aria-live": "polite",
|
|
641
|
+
children: selected.label
|
|
642
|
+
}),
|
|
623
643
|
/*#__PURE__*/ _jsx(CustomSelectInput, _object_spread_props(_object_spread({
|
|
624
644
|
autoComplete: "off",
|
|
625
645
|
autoCapitalize: "none",
|
|
@@ -630,7 +650,7 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
630
650
|
onFocus: onFocus,
|
|
631
651
|
onBlur: onBlur,
|
|
632
652
|
className: openedClassNames,
|
|
633
|
-
|
|
653
|
+
readOnly: !searchable,
|
|
634
654
|
fetching: fetching,
|
|
635
655
|
value: inputValue,
|
|
636
656
|
onKeyUp: handleKeyUp,
|
|
@@ -640,7 +660,7 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
640
660
|
before: before,
|
|
641
661
|
after: afterIcons,
|
|
642
662
|
selectType: selectType,
|
|
643
|
-
|
|
663
|
+
children: selected === null || selected === void 0 ? void 0 : selected.label
|
|
644
664
|
})),
|
|
645
665
|
/*#__PURE__*/ _jsxs("select", {
|
|
646
666
|
ref: selectElRef,
|