@vkontakte/vkui 6.5.2 → 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 +68 -43
- 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/cjs/components/ImageBase/ImageBase.js +4 -1
- package/dist/cjs/components/ImageBase/ImageBase.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 +60 -35
- 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/ImageBase/ImageBase.js +4 -1
- package/dist/components/ImageBase/ImageBase.js.map +1 -1
- package/dist/components.css +2 -2
- package/dist/components.css.map +1 -1
- package/dist/components.js.tmp +100 -148
- 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 +57 -34
- 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/cssm/components/ImageBase/ImageBase.js +4 -1
- package/dist/cssm/components/ImageBase/ImageBase.js.map +1 -1
- package/dist/cssm/components/ImageBase/ImageBase.module.css +13 -2
- package/dist/vkui.css +2 -2
- package/dist/vkui.css.map +1 -1
- package/dist/vkui.js.tmp +100 -148
- package/package.json +1 -1
- package/src/components/CustomSelect/CustomSelect.tsx +98 -47
- package/src/components/CustomSelect/CustomSelectInput.module.css +35 -55
- package/src/components/CustomSelect/CustomSelectInput.tsx +35 -24
- package/src/components/ImageBase/ImageBase.module.css +13 -2
- package/src/components/ImageBase/ImageBase.tsx +1 -1
- 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"}
|
|
@@ -182,7 +182,10 @@ const ImageBase = (_param)=>{
|
|
|
182
182
|
className: "vkuiImageBase__fallback",
|
|
183
183
|
children: fallbackIcon
|
|
184
184
|
}),
|
|
185
|
-
children,
|
|
185
|
+
children && /*#__PURE__*/ (0, _jsxruntime.jsx)("div", {
|
|
186
|
+
className: "vkuiImageBase__children",
|
|
187
|
+
children: children
|
|
188
|
+
}),
|
|
186
189
|
!noBorder && /*#__PURE__*/ (0, _jsxruntime.jsx)("div", {
|
|
187
190
|
"aria-hidden": true,
|
|
188
191
|
className: "vkuiImageBase__border"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/ImageBase/ImageBase.tsx"],"sourcesContent":["import * as React from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { minOr } from '../../lib/comparing';\nimport { getFetchPriorityProp } from '../../lib/utils';\nimport type { AnchorHTMLAttributesOnly, HasRef, HasRootRef, LiteralUnion } from '../../types';\nimport { Clickable } from '../Clickable/Clickable';\nimport { ImageBaseBadge, type ImageBaseBadgeProps } from './ImageBaseBadge/ImageBaseBadge';\nimport { ImageBaseOverlay, type ImageBaseOverlayProps } from './ImageBaseOverlay/ImageBaseOverlay';\nimport { ImageBaseContext } from './context';\nimport type { ImageBaseContextProps, ImageBaseExpectedIconProps, ImageBaseSize } from './types';\nimport { validateFallbackIcon, validateSize } from './validators';\nimport styles from './ImageBase.module.css';\n\nexport type {\n ImageBaseSize,\n ImageBaseExpectedIconProps,\n ImageBaseBadgeProps,\n ImageBaseOverlayProps,\n ImageBaseContextProps,\n};\n\nexport {\n getBadgeIconSizeByImageBaseSize,\n getFallbackIconSizeByImageBaseSize,\n getOverlayIconSizeByImageBaseSize,\n} from './helpers';\n\nexport { ImageBaseContext };\n\n/**\n * Размер по умолчанию.\n */\nconst defaultSize = 24;\n\nexport interface ImageBaseProps\n extends React.ImgHTMLAttributes<HTMLElement>,\n AnchorHTMLAttributesOnly,\n HasRootRef<HTMLDivElement>,\n HasRef<HTMLImageElement> {\n /**\n * Задаёт размер картинки.\n *\n * Используйте размеры заданные дизайн-системой `16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 56 | 64 | 72 | 80 | 88 | 96`.\n *\n * > ⚠️ Использование кастомного размера – это пограничный кейс.\n */\n size?: LiteralUnion<ImageBaseSize, number>;\n /**\n * Ширина изображения\n */\n widthSize?: number | string;\n /**\n * Высота изображения\n */\n heightSize?: number | string;\n /**\n * Отключает обводку.\n */\n noBorder?: boolean;\n /**\n * Фолбек на случай, если картинка не прогрузилась.\n *\n * > 📝 Нужный для `<ImageBase size={...} />` размер можно узнать из функции `getFallbackIconSizeByImageBaseSize()`.\n *\n * > Предпочтительней использовать иконки из `@vkontakte/icons`.\n *\n * > 📊️ Если вы хотите передать кастомную иконку, то следует именовать её по шаблону `Icon<size><name>`. Или же\n * > чтобы в неё был передан параметр `width`. Тогда мы сможем выводить в консоль подсказку правильного ли размера вы\n * > использовали иконку.\n *\n * > ⚠️ Может перекрывать `children`.\n */\n fallbackIcon?: React.ReactElement<ImageBaseExpectedIconProps>;\n /**\n * Отключает фон, заданный по умолчанию. Полезен для отображения картинок с прозрачностью.\n * @since 5.10.0\n */\n withTransparentBackground?: boolean;\n /**\n * Пользовательское значения стиля object-fit\n * Подробнее можно почитать в [документации](https://developer.mozilla.org/ru/docs/Web/CSS/object-fit)\n */\n objectFit?: React.CSSProperties['objectFit'];\n /**\n * Флаг для сохранения пропорций картинки.\n * Для корректной работы необходимо задать размеры хотя бы одной стороны картинки\n */\n keepAspectRatio?: boolean;\n}\n\nconst getObjectFitClassName = (objectFit: React.CSSProperties['objectFit']) => {\n switch (objectFit) {\n case 'contain':\n return styles['ImageBase__img--objectFit-contain'];\n case 'cover':\n return styles['ImageBase__img--objectFit-cover'];\n case 'none':\n return styles['ImageBase__img--objectFit-none'];\n case 'scale-down':\n return styles['ImageBase__img--objectFit-scaleDown'];\n }\n return undefined;\n};\n\nconst parsePx = (value: string): number | undefined => {\n if (value.endsWith('px')) {\n return parseInt(value);\n }\n return undefined;\n};\n\nconst sizeToNumber = (size: number | string | undefined): number | undefined => {\n if (typeof size === 'string') {\n return parsePx(size);\n }\n return size;\n};\n\n/**\n * @see https://vkcom.github.io/VKUI/#/ImageBase\n */\nexport const ImageBase: React.FC<ImageBaseProps> & {\n Badge: typeof ImageBaseBadge;\n Overlay: typeof ImageBaseOverlay;\n} = ({\n alt,\n crossOrigin,\n decoding,\n loading,\n referrerPolicy,\n sizes,\n src,\n srcSet,\n useMap,\n fetchPriority,\n getRef,\n size: sizeProp,\n width: widthImg,\n height: heightImg,\n widthSize,\n heightSize,\n style,\n noBorder = false,\n fallbackIcon: fallbackIconProp,\n children,\n onLoad,\n onError,\n withTransparentBackground,\n objectFit = 'cover',\n keepAspectRatio = false,\n ...restProps\n}: ImageBaseProps) => {\n const size = sizeProp ?? minOr([sizeToNumber(widthSize), sizeToNumber(heightSize)], defaultSize);\n\n const width = widthSize ?? (keepAspectRatio ? undefined : size);\n const height = heightSize ?? (keepAspectRatio ? undefined : size);\n\n const [loaded, setLoaded] = React.useState(false);\n const [failed, setFailed] = React.useState(false);\n\n const hasSrc = src || srcSet;\n const needShowFallbackIcon = (failed || !hasSrc) && React.isValidElement(fallbackIconProp);\n\n const fallbackIcon = needShowFallbackIcon ? fallbackIconProp : null;\n\n if (process.env.NODE_ENV === 'development') {\n validateSize(size);\n if (fallbackIcon) {\n validateFallbackIcon(size, { name: 'fallbackIcon', value: fallbackIcon });\n }\n }\n\n const handleImageLoad = (event: React.SyntheticEvent<HTMLImageElement>) => {\n if (loaded) {\n return;\n }\n\n setLoaded(true);\n setFailed(false);\n onLoad?.(event);\n };\n\n const handleImageError = (event: React.SyntheticEvent<HTMLImageElement>) => {\n setLoaded(false);\n setFailed(true);\n onError?.(event);\n };\n\n const imgRef = useExternRef(getRef);\n const isOnLoadStatusCheckedRef = React.useRef(false);\n React.useEffect(\n function dispatchLoadEventForAlreadyLoadedResourceIfReactInitializedLater() {\n if (isOnLoadStatusCheckedRef.current) {\n return;\n }\n isOnLoadStatusCheckedRef.current = true;\n\n if (imgRef.current && imgRef.current.complete && !loaded) {\n const event = new Event('load');\n imgRef.current.dispatchEvent(event);\n }\n },\n [imgRef, loaded],\n );\n\n return (\n <ImageBaseContext.Provider value={{ size }}>\n <Clickable\n style={{ width, height, ...style }}\n baseClassName={classNames(\n styles['ImageBase'],\n loaded && styles['ImageBase--loaded'],\n withTransparentBackground && styles['ImageBase--transparent-background'],\n )}\n {...restProps}\n >\n {hasSrc && (\n <img\n ref={imgRef}\n alt={alt}\n className={classNames(\n styles['ImageBase__img'],\n getObjectFitClassName(objectFit),\n keepAspectRatio && styles['ImageBase__img--keepRatio'],\n )}\n crossOrigin={crossOrigin}\n decoding={decoding}\n loading={loading}\n referrerPolicy={referrerPolicy}\n style={\n keepAspectRatio\n ? {\n width: widthImg || width,\n height: heightImg || height,\n }\n : undefined\n }\n sizes={sizes}\n src={src}\n srcSet={srcSet}\n useMap={useMap}\n width={widthImg}\n height={heightImg}\n onLoad={handleImageLoad}\n onError={handleImageError}\n {...getFetchPriorityProp(fetchPriority)}\n />\n )}\n {fallbackIcon && <div className={styles['ImageBase__fallback']}>{fallbackIcon}</div>}\n {children}\n {!noBorder && <div aria-hidden className={styles['ImageBase__border']} />}\n </Clickable>\n </ImageBaseContext.Provider>\n );\n};\n\nImageBase.displayName = 'ImageBase';\n\nImageBase.Badge = ImageBaseBadge;\nImageBase.Badge.displayName = 'ImageBase.Badge';\n\nImageBase.Overlay = ImageBaseOverlay;\nImageBase.Overlay.displayName = 'ImageBase.Overlay';\n"],"names":["ImageBase","ImageBaseContext","getBadgeIconSizeByImageBaseSize","getFallbackIconSizeByImageBaseSize","getOverlayIconSizeByImageBaseSize","defaultSize","getObjectFitClassName","objectFit","undefined","parsePx","value","endsWith","parseInt","sizeToNumber","size","alt","crossOrigin","decoding","loading","referrerPolicy","sizes","src","srcSet","useMap","fetchPriority","getRef","sizeProp","width","widthImg","height","heightImg","widthSize","heightSize","style","noBorder","fallbackIcon","fallbackIconProp","children","onLoad","onError","withTransparentBackground","keepAspectRatio","restProps","minOr","loaded","setLoaded","React","useState","failed","setFailed","hasSrc","needShowFallbackIcon","isValidElement","process","env","NODE_ENV","validateSize","validateFallbackIcon","name","handleImageLoad","event","handleImageError","imgRef","useExternRef","isOnLoadStatusCheckedRef","useRef","useEffect","dispatchLoadEventForAlreadyLoadedResourceIfReactInitializedLater","current","complete","Event","dispatchEvent","Provider","Clickable","baseClassName","classNames","img","ref","className","getFetchPriorityProp","div","aria-hidden","displayName","Badge","ImageBaseBadge","Overlay","ImageBaseOverlay"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/ImageBase/ImageBase.tsx"],"sourcesContent":["import * as React from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { minOr } from '../../lib/comparing';\nimport { getFetchPriorityProp } from '../../lib/utils';\nimport type { AnchorHTMLAttributesOnly, HasRef, HasRootRef, LiteralUnion } from '../../types';\nimport { Clickable } from '../Clickable/Clickable';\nimport { ImageBaseBadge, type ImageBaseBadgeProps } from './ImageBaseBadge/ImageBaseBadge';\nimport { ImageBaseOverlay, type ImageBaseOverlayProps } from './ImageBaseOverlay/ImageBaseOverlay';\nimport { ImageBaseContext } from './context';\nimport type { ImageBaseContextProps, ImageBaseExpectedIconProps, ImageBaseSize } from './types';\nimport { validateFallbackIcon, validateSize } from './validators';\nimport styles from './ImageBase.module.css';\n\nexport type {\n ImageBaseSize,\n ImageBaseExpectedIconProps,\n ImageBaseBadgeProps,\n ImageBaseOverlayProps,\n ImageBaseContextProps,\n};\n\nexport {\n getBadgeIconSizeByImageBaseSize,\n getFallbackIconSizeByImageBaseSize,\n getOverlayIconSizeByImageBaseSize,\n} from './helpers';\n\nexport { ImageBaseContext };\n\n/**\n * Размер по умолчанию.\n */\nconst defaultSize = 24;\n\nexport interface ImageBaseProps\n extends React.ImgHTMLAttributes<HTMLElement>,\n AnchorHTMLAttributesOnly,\n HasRootRef<HTMLDivElement>,\n HasRef<HTMLImageElement> {\n /**\n * Задаёт размер картинки.\n *\n * Используйте размеры заданные дизайн-системой `16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 56 | 64 | 72 | 80 | 88 | 96`.\n *\n * > ⚠️ Использование кастомного размера – это пограничный кейс.\n */\n size?: LiteralUnion<ImageBaseSize, number>;\n /**\n * Ширина изображения\n */\n widthSize?: number | string;\n /**\n * Высота изображения\n */\n heightSize?: number | string;\n /**\n * Отключает обводку.\n */\n noBorder?: boolean;\n /**\n * Фолбек на случай, если картинка не прогрузилась.\n *\n * > 📝 Нужный для `<ImageBase size={...} />` размер можно узнать из функции `getFallbackIconSizeByImageBaseSize()`.\n *\n * > Предпочтительней использовать иконки из `@vkontakte/icons`.\n *\n * > 📊️ Если вы хотите передать кастомную иконку, то следует именовать её по шаблону `Icon<size><name>`. Или же\n * > чтобы в неё был передан параметр `width`. Тогда мы сможем выводить в консоль подсказку правильного ли размера вы\n * > использовали иконку.\n *\n * > ⚠️ Может перекрывать `children`.\n */\n fallbackIcon?: React.ReactElement<ImageBaseExpectedIconProps>;\n /**\n * Отключает фон, заданный по умолчанию. Полезен для отображения картинок с прозрачностью.\n * @since 5.10.0\n */\n withTransparentBackground?: boolean;\n /**\n * Пользовательское значения стиля object-fit\n * Подробнее можно почитать в [документации](https://developer.mozilla.org/ru/docs/Web/CSS/object-fit)\n */\n objectFit?: React.CSSProperties['objectFit'];\n /**\n * Флаг для сохранения пропорций картинки.\n * Для корректной работы необходимо задать размеры хотя бы одной стороны картинки\n */\n keepAspectRatio?: boolean;\n}\n\nconst getObjectFitClassName = (objectFit: React.CSSProperties['objectFit']) => {\n switch (objectFit) {\n case 'contain':\n return styles['ImageBase__img--objectFit-contain'];\n case 'cover':\n return styles['ImageBase__img--objectFit-cover'];\n case 'none':\n return styles['ImageBase__img--objectFit-none'];\n case 'scale-down':\n return styles['ImageBase__img--objectFit-scaleDown'];\n }\n return undefined;\n};\n\nconst parsePx = (value: string): number | undefined => {\n if (value.endsWith('px')) {\n return parseInt(value);\n }\n return undefined;\n};\n\nconst sizeToNumber = (size: number | string | undefined): number | undefined => {\n if (typeof size === 'string') {\n return parsePx(size);\n }\n return size;\n};\n\n/**\n * @see https://vkcom.github.io/VKUI/#/ImageBase\n */\nexport const ImageBase: React.FC<ImageBaseProps> & {\n Badge: typeof ImageBaseBadge;\n Overlay: typeof ImageBaseOverlay;\n} = ({\n alt,\n crossOrigin,\n decoding,\n loading,\n referrerPolicy,\n sizes,\n src,\n srcSet,\n useMap,\n fetchPriority,\n getRef,\n size: sizeProp,\n width: widthImg,\n height: heightImg,\n widthSize,\n heightSize,\n style,\n noBorder = false,\n fallbackIcon: fallbackIconProp,\n children,\n onLoad,\n onError,\n withTransparentBackground,\n objectFit = 'cover',\n keepAspectRatio = false,\n ...restProps\n}: ImageBaseProps) => {\n const size = sizeProp ?? minOr([sizeToNumber(widthSize), sizeToNumber(heightSize)], defaultSize);\n\n const width = widthSize ?? (keepAspectRatio ? undefined : size);\n const height = heightSize ?? (keepAspectRatio ? undefined : size);\n\n const [loaded, setLoaded] = React.useState(false);\n const [failed, setFailed] = React.useState(false);\n\n const hasSrc = src || srcSet;\n const needShowFallbackIcon = (failed || !hasSrc) && React.isValidElement(fallbackIconProp);\n\n const fallbackIcon = needShowFallbackIcon ? fallbackIconProp : null;\n\n if (process.env.NODE_ENV === 'development') {\n validateSize(size);\n if (fallbackIcon) {\n validateFallbackIcon(size, { name: 'fallbackIcon', value: fallbackIcon });\n }\n }\n\n const handleImageLoad = (event: React.SyntheticEvent<HTMLImageElement>) => {\n if (loaded) {\n return;\n }\n\n setLoaded(true);\n setFailed(false);\n onLoad?.(event);\n };\n\n const handleImageError = (event: React.SyntheticEvent<HTMLImageElement>) => {\n setLoaded(false);\n setFailed(true);\n onError?.(event);\n };\n\n const imgRef = useExternRef(getRef);\n const isOnLoadStatusCheckedRef = React.useRef(false);\n React.useEffect(\n function dispatchLoadEventForAlreadyLoadedResourceIfReactInitializedLater() {\n if (isOnLoadStatusCheckedRef.current) {\n return;\n }\n isOnLoadStatusCheckedRef.current = true;\n\n if (imgRef.current && imgRef.current.complete && !loaded) {\n const event = new Event('load');\n imgRef.current.dispatchEvent(event);\n }\n },\n [imgRef, loaded],\n );\n\n return (\n <ImageBaseContext.Provider value={{ size }}>\n <Clickable\n style={{ width, height, ...style }}\n baseClassName={classNames(\n styles['ImageBase'],\n loaded && styles['ImageBase--loaded'],\n withTransparentBackground && styles['ImageBase--transparent-background'],\n )}\n {...restProps}\n >\n {hasSrc && (\n <img\n ref={imgRef}\n alt={alt}\n className={classNames(\n styles['ImageBase__img'],\n getObjectFitClassName(objectFit),\n keepAspectRatio && styles['ImageBase__img--keepRatio'],\n )}\n crossOrigin={crossOrigin}\n decoding={decoding}\n loading={loading}\n referrerPolicy={referrerPolicy}\n style={\n keepAspectRatio\n ? {\n width: widthImg || width,\n height: heightImg || height,\n }\n : undefined\n }\n sizes={sizes}\n src={src}\n srcSet={srcSet}\n useMap={useMap}\n width={widthImg}\n height={heightImg}\n onLoad={handleImageLoad}\n onError={handleImageError}\n {...getFetchPriorityProp(fetchPriority)}\n />\n )}\n {fallbackIcon && <div className={styles['ImageBase__fallback']}>{fallbackIcon}</div>}\n {children && <div className={styles['ImageBase__children']}>{children}</div>}\n {!noBorder && <div aria-hidden className={styles['ImageBase__border']} />}\n </Clickable>\n </ImageBaseContext.Provider>\n );\n};\n\nImageBase.displayName = 'ImageBase';\n\nImageBase.Badge = ImageBaseBadge;\nImageBase.Badge.displayName = 'ImageBase.Badge';\n\nImageBase.Overlay = ImageBaseOverlay;\nImageBase.Overlay.displayName = 'ImageBase.Overlay';\n"],"names":["ImageBase","ImageBaseContext","getBadgeIconSizeByImageBaseSize","getFallbackIconSizeByImageBaseSize","getOverlayIconSizeByImageBaseSize","defaultSize","getObjectFitClassName","objectFit","undefined","parsePx","value","endsWith","parseInt","sizeToNumber","size","alt","crossOrigin","decoding","loading","referrerPolicy","sizes","src","srcSet","useMap","fetchPriority","getRef","sizeProp","width","widthImg","height","heightImg","widthSize","heightSize","style","noBorder","fallbackIcon","fallbackIconProp","children","onLoad","onError","withTransparentBackground","keepAspectRatio","restProps","minOr","loaded","setLoaded","React","useState","failed","setFailed","hasSrc","needShowFallbackIcon","isValidElement","process","env","NODE_ENV","validateSize","validateFallbackIcon","name","handleImageLoad","event","handleImageError","imgRef","useExternRef","isOnLoadStatusCheckedRef","useRef","useEffect","dispatchLoadEventForAlreadyLoadedResourceIfReactInitializedLater","current","complete","Event","dispatchEvent","Provider","Clickable","baseClassName","classNames","img","ref","className","getFetchPriorityProp","div","aria-hidden","displayName","Badge","ImageBaseBadge","Overlay","ImageBaseOverlay"],"mappings":"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"}
|
|
@@ -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
|
};
|
|
@@ -85,11 +123,11 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
85
123
|
const optionsWrapperRef = React.useRef(null);
|
|
86
124
|
const [focusedOptionIndex, setFocusedOptionIndex] = React.useState(-1);
|
|
87
125
|
const [isControlledOutside, setIsControlledOutside] = React.useState(props.value !== undefined);
|
|
126
|
+
const [inputValue, setInputValue] = React.useState('');
|
|
88
127
|
const [nativeSelectValue, setNativeSelectValue] = React.useState(()=>{
|
|
89
128
|
var _props_value, _ref;
|
|
90
129
|
return (_ref = (_props_value = props.value) !== null && _props_value !== void 0 ? _props_value : defaultValue) !== null && _ref !== void 0 ? _ref : allowClearButton ? '' : undefined;
|
|
91
130
|
});
|
|
92
|
-
const [inputValue, setInputValue] = React.useState(()=>calculateInputValueFromOptions(optionsProp, nativeSelectValue));
|
|
93
131
|
const [popperPlacement, setPopperPlacement] = React.useState(popupDirection);
|
|
94
132
|
const [options, setOptions] = React.useState(optionsProp);
|
|
95
133
|
var _props_value;
|
|
@@ -207,6 +245,7 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
207
245
|
* Сброс происходит в одном из эффекте `updateOptionsAndSelectedOptionIndex()`.
|
|
208
246
|
*/ const close = React.useCallback(()=>{
|
|
209
247
|
resetKeyboardInput();
|
|
248
|
+
setInputValue('');
|
|
210
249
|
setOpened(false);
|
|
211
250
|
resetFocusedOption();
|
|
212
251
|
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
@@ -217,8 +256,8 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
217
256
|
]);
|
|
218
257
|
const selectOption = React.useCallback((index)=>{
|
|
219
258
|
const item = options[index];
|
|
220
|
-
close();
|
|
221
259
|
setNativeSelectValue(item === null || item === void 0 ? void 0 : item.value);
|
|
260
|
+
close();
|
|
222
261
|
const shouldTriggerOnChangeWhenControlledAndInnerValueIsOutOfSync = isControlledOutside && props.value !== nativeSelectValue && nativeSelectValue === (item === null || item === void 0 ? void 0 : item.value);
|
|
223
262
|
if (shouldTriggerOnChangeWhenControlledAndInnerValueIsOutOfSync) {
|
|
224
263
|
var _selectElRef_current;
|
|
@@ -262,12 +301,9 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
262
301
|
bubbles: true
|
|
263
302
|
});
|
|
264
303
|
(_selectElRef_current = selectElRef.current) === null || _selectElRef_current === void 0 ? void 0 : _selectElRef_current.dispatchEvent(event);
|
|
265
|
-
setInputValue(calculateInputValueFromOptions(optionsProp, nativeSelectValue));
|
|
266
304
|
}, [
|
|
267
305
|
close,
|
|
268
|
-
selectElRef
|
|
269
|
-
optionsProp,
|
|
270
|
-
nativeSelectValue
|
|
306
|
+
selectElRef
|
|
271
307
|
]);
|
|
272
308
|
const onFocus = React.useCallback(()=>{
|
|
273
309
|
var _selectElRef_current;
|
|
@@ -307,38 +343,21 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
307
343
|
focusedOptionIndex,
|
|
308
344
|
options
|
|
309
345
|
]);
|
|
310
|
-
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;
|
|
311
349
|
const options = searchable && inputValue !== undefined ? filter(optionsProp, inputValue, filterFn) : optionsProp;
|
|
312
350
|
setOptions(options);
|
|
351
|
+
setSelectedOptionIndex(findSelectedIndex(options, value, allowClearButton));
|
|
313
352
|
}, [
|
|
314
353
|
filterFn,
|
|
315
354
|
inputValue,
|
|
355
|
+
nativeSelectValue,
|
|
316
356
|
optionsProp,
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
React.useEffect(function updateSelectedOptionIndexOnValueChange() {
|
|
322
|
-
setSelectedOptionIndex(findSelectedIndex(options, selectValue, allowClearButton));
|
|
323
|
-
}, [
|
|
324
|
-
selectValue,
|
|
325
|
-
allowClearButton,
|
|
326
|
-
options
|
|
327
|
-
]);
|
|
328
|
-
const prevSelectValueRef = React.useRef(selectValue);
|
|
329
|
-
React.useEffect(function updateInputValueOnSelectValueChange() {
|
|
330
|
-
if (prevSelectValueRef.current === selectValue) {
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
333
|
-
setInputValue(calculateInputValueFromOptions(optionsProp, selectValue));
|
|
334
|
-
}, [
|
|
335
|
-
selectValue,
|
|
336
|
-
optionsProp
|
|
337
|
-
]);
|
|
338
|
-
React.useEffect(function updatePrevSelectValue() {
|
|
339
|
-
prevSelectValueRef.current = selectValue;
|
|
340
|
-
}, [
|
|
341
|
-
selectValue
|
|
357
|
+
defaultValue,
|
|
358
|
+
props.value,
|
|
359
|
+
searchable,
|
|
360
|
+
allowClearButton
|
|
342
361
|
]);
|
|
343
362
|
const onNativeSelectChange = (e)=>{
|
|
344
363
|
const newSelectedOptionIndex = findSelectedIndex(options, e.currentTarget.value, allowClearButton);
|
|
@@ -602,12 +621,14 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
602
621
|
const selectInputAriaProps = {
|
|
603
622
|
'role': 'combobox',
|
|
604
623
|
'aria-controls': popupAriaId,
|
|
624
|
+
'aria-owns': popupAriaId,
|
|
605
625
|
'aria-expanded': opened,
|
|
606
626
|
['aria-activedescendant']: ariaActiveDescendantId && opened ? `${popupAriaId}-${ariaActiveDescendantId}` : undefined,
|
|
607
627
|
'aria-labelledby': ariaLabelledBy,
|
|
608
628
|
'aria-haspopup': 'listbox',
|
|
609
629
|
'aria-autocomplete': 'none'
|
|
610
630
|
};
|
|
631
|
+
const focusWithin = useFocusWithin(handleRootRef);
|
|
611
632
|
return /*#__PURE__*/ _jsxs("div", {
|
|
612
633
|
className: classNames("vkuiCustomSelect", sizeY !== 'regular' && sizeYClassNames[sizeY], className),
|
|
613
634
|
style: style,
|
|
@@ -615,6 +636,10 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
615
636
|
onClick: passClickAndFocusToInputOnClick,
|
|
616
637
|
onMouseDown: preventInputBlurWhenClickInsideFocusedSelectArea,
|
|
617
638
|
children: [
|
|
639
|
+
focusWithin && selected && !opened && /*#__PURE__*/ _jsx(VisuallyHidden, {
|
|
640
|
+
"aria-live": "polite",
|
|
641
|
+
children: selected.label
|
|
642
|
+
}),
|
|
618
643
|
/*#__PURE__*/ _jsx(CustomSelectInput, _object_spread_props(_object_spread({
|
|
619
644
|
autoComplete: "off",
|
|
620
645
|
autoCapitalize: "none",
|
|
@@ -625,7 +650,7 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
625
650
|
onFocus: onFocus,
|
|
626
651
|
onBlur: onBlur,
|
|
627
652
|
className: openedClassNames,
|
|
628
|
-
|
|
653
|
+
readOnly: !searchable,
|
|
629
654
|
fetching: fetching,
|
|
630
655
|
value: inputValue,
|
|
631
656
|
onKeyUp: handleKeyUp,
|
|
@@ -635,7 +660,7 @@ const filter = (options, inputValue, filterFn)=>{
|
|
|
635
660
|
before: before,
|
|
636
661
|
after: afterIcons,
|
|
637
662
|
selectType: selectType,
|
|
638
|
-
|
|
663
|
+
children: selected === null || selected === void 0 ? void 0 : selected.label
|
|
639
664
|
})),
|
|
640
665
|
/*#__PURE__*/ _jsxs("select", {
|
|
641
666
|
ref: selectElRef,
|