@hh.ru/magritte-ui-suggest 3.1.20 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Suggest.js +18 -7
- package/Suggest.js.map +1 -1
- package/SuggestPicker.d.ts +9 -2
- package/SuggestPicker.js +10 -8
- package/SuggestPicker.js.map +1 -1
- package/dataProvider.d.ts +2 -0
- package/dataProvider.js +4 -2
- package/dataProvider.js.map +1 -1
- package/index.css +25 -9
- package/index.d.ts +1 -1
- package/index.js +3 -1
- package/index.js.map +1 -1
- package/package.json +4 -2
- package/{sectionRenderers-859b79db.js → sectionRenderers-1c26595e.js} +12 -8
- package/sectionRenderers-1c26595e.js.map +1 -0
- package/sectionRenderers.d.ts +1 -1
- package/sectionRenderers.js +2 -1
- package/sectionRenderers.js.map +1 -1
- package/types.d.ts +13 -1
- package/sectionRenderers-859b79db.js.map +0 -1
package/Suggest.js
CHANGED
|
@@ -4,19 +4,25 @@ import { forwardRef, useState, useRef, useCallback, useEffect } from 'react';
|
|
|
4
4
|
import { useMultipleRefs } from '@hh.ru/magritte-common-use-multiple-refs';
|
|
5
5
|
import { useBreakpoint } from '@hh.ru/magritte-ui-breakpoint';
|
|
6
6
|
import { SuggestPicker } from './SuggestPicker.js';
|
|
7
|
+
import { DataProviderError } from './dataProvider.js';
|
|
7
8
|
import { useSuggestKeyboardNav } from './useSuggestKeyboardNav.js';
|
|
8
|
-
import { s as styles } from './sectionRenderers-
|
|
9
|
+
import { s as styles } from './sectionRenderers-1c26595e.js';
|
|
9
10
|
import 'classnames';
|
|
10
11
|
import '@hh.ru/magritte-ui-bottom-sheet';
|
|
12
|
+
import '@hh.ru/magritte-ui-button';
|
|
11
13
|
import '@hh.ru/magritte-ui-drop';
|
|
14
|
+
import '@hh.ru/magritte-ui-icon/icon';
|
|
12
15
|
import '@hh.ru/magritte-ui-navigation-bar';
|
|
16
|
+
import 'axios';
|
|
17
|
+
import '@hh.ru/magritte-common-func-utils';
|
|
18
|
+
import '@hh.ru/magritte-common-fuzzy-search';
|
|
13
19
|
import '@hh.ru/magritte-common-keyboard';
|
|
14
20
|
import '@hh.ru/magritte-ui-card';
|
|
15
21
|
import '@hh.ru/magritte-ui-cell';
|
|
16
22
|
import '@hh.ru/magritte-ui-chips';
|
|
17
23
|
import '@hh.ru/magritte-ui-typography';
|
|
18
24
|
|
|
19
|
-
const SuggestComponent = function ({ dataProvider, input, inputValue, onSelectValidator = () => true, navigationBarProps, maxHeight = 460, itemsGap = 4, dropHost, onBlur, }, ref) {
|
|
25
|
+
const SuggestComponent = function ({ dataProvider, input, inputValue, onSelectValidator = () => true, navigationBarProps, maxHeight = 460, itemsGap = 4, dropHost, onBlur, topContent, bottomContent, maxWidth, errorPlaceholder, trls, }, ref) {
|
|
20
26
|
const { component: InputComponent, props: inputProps } = input;
|
|
21
27
|
const [inputValueState, setInputValueState] = useState(inputProps.value || '');
|
|
22
28
|
const { onChange: onInputChange, onFocus: onInputFocus, onKeyDown: onInputKeyDown } = inputProps;
|
|
@@ -30,6 +36,7 @@ const SuggestComponent = function ({ dataProvider, input, inputValue, onSelectVa
|
|
|
30
36
|
const onBlurRef = useRef(onBlur);
|
|
31
37
|
onBlurRef.current = onBlur; // update actual callback
|
|
32
38
|
const { isMobile } = useBreakpoint();
|
|
39
|
+
const [isError, setIsError] = useState(false);
|
|
33
40
|
const currentRequestRef = useRef();
|
|
34
41
|
const actualInputValue = inputValue === undefined ? inputValueState : inputValue;
|
|
35
42
|
const { focused, onKeyDown, onFocus, onBottomSheetClose } = useSuggestKeyboardNav(suggestContainerRef, inputContainerRef, setValueSelectedFromSuggest, actualInputValue, inputRef, onBlurRef);
|
|
@@ -40,15 +47,17 @@ const SuggestComponent = function ({ dataProvider, input, inputValue, onSelectVa
|
|
|
40
47
|
onInputChange?.(value);
|
|
41
48
|
}, [inputValue, setInputValueState, onInputChange]);
|
|
42
49
|
const requestData = useCallback((query) => {
|
|
50
|
+
setIsError(false);
|
|
43
51
|
currentRequestRef.current?.cancel();
|
|
44
52
|
const request = dataProvider(query);
|
|
45
53
|
request.then((result) => {
|
|
46
54
|
setRequestResult({ query, result });
|
|
47
|
-
}, (
|
|
48
|
-
|
|
49
|
-
if (
|
|
50
|
-
|
|
55
|
+
}, (event) => {
|
|
56
|
+
// включаем error state если это НЕ ошибка, вызванная `minCharsCount` или отменненым запросом
|
|
57
|
+
if (!(event instanceof DataProviderError)) {
|
|
58
|
+
setIsError(true);
|
|
51
59
|
}
|
|
60
|
+
setRequestResult(null);
|
|
52
61
|
});
|
|
53
62
|
currentRequestRef.current = request;
|
|
54
63
|
}, [dataProvider]);
|
|
@@ -97,7 +106,9 @@ const SuggestComponent = function ({ dataProvider, input, inputValue, onSelectVa
|
|
|
97
106
|
wrapperRef: wrapperInputRef,
|
|
98
107
|
autoComplete: 'off',
|
|
99
108
|
};
|
|
100
|
-
return (jsxs(Fragment, { children: [jsx("div", { ref: inputContainerRef, className: styles.suggestInputContainer, children: jsx(InputComponent, { ...actualInputProps }) }), jsx(SuggestPicker, { data: requestResult?.result, activatorRef: wrapperInputRef, inputRef: inputRef, inputFocused: focused, dropHost: dropHost, currentInputValueSelectedFromSuggest: valueSelectedFromSuggest !== false, onValueSelect: onValueSelectHandler, maxHeight: maxHeight, navigationBarProps: navigationBarProps, suggestContainerRef: suggestContainerRef, itemsGap: itemsGap, onBottomSheetClose: onBottomSheetClose, inputValue: actualInputValue,
|
|
109
|
+
return (jsxs(Fragment, { children: [jsx("div", { ref: inputContainerRef, className: styles.suggestInputContainer, children: jsx(InputComponent, { ...actualInputProps }) }), jsx(SuggestPicker, { data: requestResult?.result, activatorRef: wrapperInputRef, inputRef: inputRef, inputFocused: focused, dropHost: dropHost, currentInputValueSelectedFromSuggest: valueSelectedFromSuggest !== false, onValueSelect: onValueSelectHandler, maxHeight: maxHeight, navigationBarProps: navigationBarProps, suggestContainerRef: suggestContainerRef, itemsGap: itemsGap, onBottomSheetClose: onBottomSheetClose, inputValue: actualInputValue, topContent: topContent, bottomContent: bottomContent, maxWidth: maxWidth, isError: isError, trls: trls, errorPlaceholder: errorPlaceholder, onClickReload: () => {
|
|
110
|
+
requestData(actualInputValue);
|
|
111
|
+
}, input: {
|
|
101
112
|
component: InputComponent,
|
|
102
113
|
props: {
|
|
103
114
|
...input.props,
|
package/Suggest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Suggest.js","sources":["../src/Suggest.tsx"],"sourcesContent":["import {\n FocusEventHandler,\n ReactElement,\n useCallback,\n useEffect,\n useRef,\n useState,\n KeyboardEventHandler,\n forwardRef,\n ForwardedRef,\n} from 'react';\n\nimport { useMultipleRefs } from '@hh.ru/magritte-common-use-multiple-refs';\nimport { useBreakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { SuggestPicker } from '@hh.ru/magritte-ui-suggest/SuggestPicker';\nimport {\n DataProviderRequest,\n DataProviderResult,\n SuggestProps,\n SuggestInputComponent,\n InputProp,\n ControlledInputProps,\n NativeFocusEventHandler,\n} from '@hh.ru/magritte-ui-suggest/types';\nimport { useSuggestKeyboardNav } from '@hh.ru/magritte-ui-suggest/useSuggestKeyboardNav';\n\nimport styles from './suggest.less';\n\nconst SuggestComponent = function <K, T extends SuggestInputComponent>(\n {\n dataProvider,\n input,\n inputValue,\n onSelectValidator = () => true,\n navigationBarProps,\n maxHeight = 460,\n itemsGap = 4,\n dropHost,\n onBlur,\n }: SuggestProps<K, T>,\n ref: ForwardedRef<HTMLElement>\n): ReactElement | null {\n const { component: InputComponent, props: inputProps } = input;\n const [inputValueState, setInputValueState] = useState(inputProps.value || '');\n const { onChange: onInputChange, onFocus: onInputFocus, onKeyDown: onInputKeyDown } = inputProps;\n const [requestResult, setRequestResult] = useState<{ query: string; result: DataProviderResult<K> } | null>(null);\n const [valueSelectedFromSuggest, setValueSelectedFromSuggest] = useState<string | false>(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const wrapperInputRef = useRef<HTMLInputElement>(null);\n const suggestContainerRef = useRef<HTMLElement>(null);\n const inputContainerRef = useRef<HTMLDivElement>(null);\n const inputRefMulti = useMultipleRefs(inputRef, ref);\n const onBlurRef = useRef<NativeFocusEventHandler | undefined>(onBlur);\n onBlurRef.current = onBlur; // update actual callback\n const { isMobile } = useBreakpoint();\n\n const currentRequestRef = useRef<DataProviderRequest>();\n const actualInputValue = inputValue === undefined ? inputValueState : inputValue;\n\n const { focused, onKeyDown, onFocus, onBottomSheetClose } = useSuggestKeyboardNav(\n suggestContainerRef,\n inputContainerRef,\n setValueSelectedFromSuggest,\n actualInputValue,\n inputRef,\n onBlurRef\n );\n\n const onChangeHandler = useCallback(\n (value: string) => {\n if (inputValue === undefined) {\n setInputValueState(value);\n }\n\n onInputChange?.(value);\n },\n [inputValue, setInputValueState, onInputChange]\n );\n\n const requestData = useCallback(\n (query: string) => {\n currentRequestRef.current?.cancel();\n const request = dataProvider(query);\n request.then(\n (result) => {\n setRequestResult({ query, result });\n },\n (error) => {\n setRequestResult(null);\n if (error) {\n throw error;\n }\n }\n );\n currentRequestRef.current = request;\n },\n [dataProvider]\n );\n\n useEffect(() => {\n if (valueSelectedFromSuggest !== false && requestResult?.query !== actualInputValue) {\n setRequestResult(null);\n }\n if (valueSelectedFromSuggest !== actualInputValue.trim()) {\n setValueSelectedFromSuggest(false);\n if (focused) {\n requestData(actualInputValue);\n }\n }\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [actualInputValue, requestData, focused]);\n\n const onFocusHandler = useCallback<FocusEventHandler<HTMLElement>>(\n (event) => {\n setValueSelectedFromSuggest(false);\n if (actualInputValue !== requestResult?.query) {\n setRequestResult(null);\n requestData(actualInputValue);\n }\n\n onInputFocus?.(event);\n onFocus(event);\n },\n [actualInputValue, requestResult?.query, onInputFocus, onFocus, requestData]\n );\n\n const onValueSelectHandler = useCallback(\n (value: string, data: K | undefined) => {\n if (!onSelectValidator(value, data)) {\n return;\n }\n if (!isMobile) {\n inputRef.current?.focus();\n }\n onChangeHandler(value);\n setValueSelectedFromSuggest(value);\n },\n [onSelectValidator, isMobile, onChangeHandler]\n );\n\n const onKeyDownHandler = useCallback<KeyboardEventHandler<HTMLInputElement>>(\n (event) => {\n onKeyDown(event);\n onInputKeyDown?.(event);\n },\n [onInputKeyDown, onKeyDown]\n );\n\n const actualInputProps = {\n ...inputProps,\n value: actualInputValue,\n onFocus: onFocusHandler,\n onChange: onChangeHandler,\n onKeyDown: onKeyDownHandler,\n ref: inputRefMulti,\n wrapperRef: wrapperInputRef,\n autoComplete: 'off',\n } as unknown as JSX.IntrinsicAttributes & JSX.LibraryManagedAttributes<T, ControlledInputProps>;\n\n return (\n <>\n <div ref={inputContainerRef} className={styles.suggestInputContainer}>\n <InputComponent {...actualInputProps} />\n </div>\n <SuggestPicker\n data={requestResult?.result}\n activatorRef={wrapperInputRef}\n inputRef={inputRef}\n inputFocused={focused}\n dropHost={dropHost}\n currentInputValueSelectedFromSuggest={valueSelectedFromSuggest !== false}\n onValueSelect={onValueSelectHandler}\n maxHeight={maxHeight}\n navigationBarProps={navigationBarProps}\n suggestContainerRef={suggestContainerRef}\n itemsGap={itemsGap}\n onBottomSheetClose={onBottomSheetClose}\n inputValue={actualInputValue}\n input={\n {\n component: InputComponent,\n props: {\n ...input.props,\n onFocus: onFocusHandler,\n onChange: onChangeHandler,\n value: actualInputValue,\n onKeyDown: onKeyDownHandler,\n },\n } as InputProp<T>\n }\n />\n </>\n );\n};\n\nconst Suggest = forwardRef(SuggestComponent) as (<K, T extends SuggestInputComponent>(\n props: SuggestProps<K, T> & { ref?: ForwardedRef<HTMLElement> }\n) => ReactElement | null) & { displayName: string };\n\nSuggest.displayName = 'Suggest';\n\nexport { Suggest };\n"],"names":["_jsxs","_Fragment","_jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Suggest.js","sources":["../src/Suggest.tsx"],"sourcesContent":["import {\n FocusEventHandler,\n ReactElement,\n useCallback,\n useEffect,\n useRef,\n useState,\n KeyboardEventHandler,\n forwardRef,\n ForwardedRef,\n} from 'react';\n\nimport { useMultipleRefs } from '@hh.ru/magritte-common-use-multiple-refs';\nimport { useBreakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { SuggestPicker } from '@hh.ru/magritte-ui-suggest/SuggestPicker';\nimport { DataProviderError } from '@hh.ru/magritte-ui-suggest/dataProvider';\nimport {\n DataProviderRequest,\n DataProviderResult,\n SuggestProps,\n SuggestInputComponent,\n InputProp,\n ControlledInputProps,\n NativeFocusEventHandler,\n} from '@hh.ru/magritte-ui-suggest/types';\nimport { useSuggestKeyboardNav } from '@hh.ru/magritte-ui-suggest/useSuggestKeyboardNav';\n\nimport styles from './suggest.less';\n\nconst SuggestComponent = function <K, T extends SuggestInputComponent>(\n {\n dataProvider,\n input,\n inputValue,\n onSelectValidator = () => true,\n navigationBarProps,\n maxHeight = 460,\n itemsGap = 4,\n dropHost,\n onBlur,\n topContent,\n bottomContent,\n maxWidth,\n errorPlaceholder,\n trls,\n }: SuggestProps<K, T>,\n ref: ForwardedRef<HTMLElement>\n): ReactElement | null {\n const { component: InputComponent, props: inputProps } = input;\n const [inputValueState, setInputValueState] = useState(inputProps.value || '');\n const { onChange: onInputChange, onFocus: onInputFocus, onKeyDown: onInputKeyDown } = inputProps;\n const [requestResult, setRequestResult] = useState<{ query: string; result: DataProviderResult<K> } | null>(null);\n const [valueSelectedFromSuggest, setValueSelectedFromSuggest] = useState<string | false>(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const wrapperInputRef = useRef<HTMLInputElement>(null);\n const suggestContainerRef = useRef<HTMLElement>(null);\n const inputContainerRef = useRef<HTMLDivElement>(null);\n const inputRefMulti = useMultipleRefs(inputRef, ref);\n const onBlurRef = useRef<NativeFocusEventHandler | undefined>(onBlur);\n onBlurRef.current = onBlur; // update actual callback\n const { isMobile } = useBreakpoint();\n const [isError, setIsError] = useState(false);\n\n const currentRequestRef = useRef<DataProviderRequest>();\n const actualInputValue = inputValue === undefined ? inputValueState : inputValue;\n\n const { focused, onKeyDown, onFocus, onBottomSheetClose } = useSuggestKeyboardNav(\n suggestContainerRef,\n inputContainerRef,\n setValueSelectedFromSuggest,\n actualInputValue,\n inputRef,\n onBlurRef\n );\n\n const onChangeHandler = useCallback(\n (value: string) => {\n if (inputValue === undefined) {\n setInputValueState(value);\n }\n\n onInputChange?.(value);\n },\n [inputValue, setInputValueState, onInputChange]\n );\n\n const requestData = useCallback(\n (query: string) => {\n setIsError(false);\n currentRequestRef.current?.cancel();\n const request = dataProvider(query);\n request.then(\n (result) => {\n setRequestResult({ query, result });\n },\n (event) => {\n // включаем error state если это НЕ ошибка, вызванная `minCharsCount` или отменненым запросом\n if (!(event instanceof DataProviderError)) {\n setIsError(true);\n }\n setRequestResult(null);\n }\n );\n currentRequestRef.current = request;\n },\n [dataProvider]\n );\n\n useEffect(() => {\n if (valueSelectedFromSuggest !== false && requestResult?.query !== actualInputValue) {\n setRequestResult(null);\n }\n if (valueSelectedFromSuggest !== actualInputValue.trim()) {\n setValueSelectedFromSuggest(false);\n if (focused) {\n requestData(actualInputValue);\n }\n }\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [actualInputValue, requestData, focused]);\n\n const onFocusHandler = useCallback<FocusEventHandler<HTMLElement>>(\n (event) => {\n setValueSelectedFromSuggest(false);\n if (actualInputValue !== requestResult?.query) {\n setRequestResult(null);\n requestData(actualInputValue);\n }\n\n onInputFocus?.(event);\n onFocus(event);\n },\n [actualInputValue, requestResult?.query, onInputFocus, onFocus, requestData]\n );\n\n const onValueSelectHandler = useCallback(\n (value: string, data: K | undefined) => {\n if (!onSelectValidator(value, data)) {\n return;\n }\n if (!isMobile) {\n inputRef.current?.focus();\n }\n onChangeHandler(value);\n setValueSelectedFromSuggest(value);\n },\n [onSelectValidator, isMobile, onChangeHandler]\n );\n\n const onKeyDownHandler = useCallback<KeyboardEventHandler<HTMLInputElement>>(\n (event) => {\n onKeyDown(event);\n onInputKeyDown?.(event);\n },\n [onInputKeyDown, onKeyDown]\n );\n\n const actualInputProps = {\n ...inputProps,\n value: actualInputValue,\n onFocus: onFocusHandler,\n onChange: onChangeHandler,\n onKeyDown: onKeyDownHandler,\n ref: inputRefMulti,\n wrapperRef: wrapperInputRef,\n autoComplete: 'off',\n } as unknown as JSX.IntrinsicAttributes & JSX.LibraryManagedAttributes<T, ControlledInputProps>;\n\n return (\n <>\n <div ref={inputContainerRef} className={styles.suggestInputContainer}>\n <InputComponent {...actualInputProps} />\n </div>\n <SuggestPicker\n data={requestResult?.result}\n activatorRef={wrapperInputRef}\n inputRef={inputRef}\n inputFocused={focused}\n dropHost={dropHost}\n currentInputValueSelectedFromSuggest={valueSelectedFromSuggest !== false}\n onValueSelect={onValueSelectHandler}\n maxHeight={maxHeight}\n navigationBarProps={navigationBarProps}\n suggestContainerRef={suggestContainerRef}\n itemsGap={itemsGap}\n onBottomSheetClose={onBottomSheetClose}\n inputValue={actualInputValue}\n topContent={topContent}\n bottomContent={bottomContent}\n maxWidth={maxWidth}\n isError={isError}\n trls={trls}\n errorPlaceholder={errorPlaceholder}\n onClickReload={() => {\n requestData(actualInputValue);\n }}\n input={\n {\n component: InputComponent,\n props: {\n ...input.props,\n onFocus: onFocusHandler,\n onChange: onChangeHandler,\n value: actualInputValue,\n onKeyDown: onKeyDownHandler,\n },\n } as InputProp<T>\n }\n />\n </>\n );\n};\n\nconst Suggest = forwardRef(SuggestComponent) as (<K, T extends SuggestInputComponent>(\n props: SuggestProps<K, T> & { ref?: ForwardedRef<HTMLElement> }\n) => ReactElement | null) & { displayName: string };\n\nSuggest.displayName = 'Suggest';\n\nexport { Suggest };\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
package/SuggestPicker.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RefObject, ReactElement } from 'react';
|
|
1
|
+
import { RefObject, ReactElement, ReactNode } from 'react';
|
|
2
2
|
import { type TokenBaseCoreSpace } from '@hh.ru/magritte-design-tokens/types';
|
|
3
3
|
import { DataProviderResult, SuggestProps, SuggestInputComponent, InputProp } from './types';
|
|
4
4
|
interface SuggestPickerProps<K, P extends SuggestInputComponent = SuggestInputComponent> {
|
|
@@ -16,9 +16,16 @@ interface SuggestPickerProps<K, P extends SuggestInputComponent = SuggestInputCo
|
|
|
16
16
|
onBottomSheetClose: VoidFunction;
|
|
17
17
|
dropHost?: RefObject<HTMLElement>;
|
|
18
18
|
inputValue: string;
|
|
19
|
+
topContent?: ReactNode;
|
|
20
|
+
bottomContent?: ReactNode;
|
|
21
|
+
maxWidth?: number;
|
|
22
|
+
isError: boolean;
|
|
23
|
+
trls: SuggestProps<unknown, SuggestInputComponent>['trls'];
|
|
24
|
+
errorPlaceholder: ReactNode;
|
|
25
|
+
onClickReload: VoidFunction;
|
|
19
26
|
}
|
|
20
27
|
export declare const SuggestPicker: {
|
|
21
|
-
<K, P extends SuggestInputComponent>({ data, activatorRef, inputRef, onValueSelect, maxHeight, navigationBarProps, input, inputFocused, currentInputValueSelectedFromSuggest, suggestContainerRef, itemsGap, onBottomSheetClose, dropHost, inputValue, }: SuggestPickerProps<K, P>): ReactElement | null;
|
|
28
|
+
<K, P extends SuggestInputComponent>({ data, activatorRef, inputRef, onValueSelect, maxHeight, navigationBarProps, input, inputFocused, currentInputValueSelectedFromSuggest, suggestContainerRef, itemsGap, onBottomSheetClose, dropHost, inputValue, topContent, bottomContent, maxWidth, isError, trls, errorPlaceholder, onClickReload, }: SuggestPickerProps<K, P>): ReactElement | null;
|
|
22
29
|
displayName: string;
|
|
23
30
|
};
|
|
24
31
|
export {};
|
package/SuggestPicker.js
CHANGED
|
@@ -2,17 +2,19 @@ import './index.css';
|
|
|
2
2
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import { useState, useRef, useEffect, useMemo } from 'react';
|
|
4
4
|
import classnames from 'classnames';
|
|
5
|
-
import { BottomSheet } from '@hh.ru/magritte-ui-bottom-sheet';
|
|
5
|
+
import { BottomSheet, BottomSheetFooter } from '@hh.ru/magritte-ui-bottom-sheet';
|
|
6
6
|
import { useBreakpoint } from '@hh.ru/magritte-ui-breakpoint';
|
|
7
|
+
import { Button } from '@hh.ru/magritte-ui-button';
|
|
7
8
|
import { Drop } from '@hh.ru/magritte-ui-drop';
|
|
9
|
+
import { ArrowPathOutlinedSize24 } from '@hh.ru/magritte-ui-icon/icon';
|
|
8
10
|
import { NavigationBar } from '@hh.ru/magritte-ui-navigation-bar';
|
|
9
|
-
import { r as renderSection, s as styles } from './sectionRenderers-
|
|
11
|
+
import { r as renderSection, s as styles } from './sectionRenderers-1c26595e.js';
|
|
10
12
|
import '@hh.ru/magritte-ui-card';
|
|
11
13
|
import '@hh.ru/magritte-ui-cell';
|
|
12
14
|
import '@hh.ru/magritte-ui-chips';
|
|
13
15
|
import '@hh.ru/magritte-ui-typography';
|
|
14
16
|
|
|
15
|
-
const SuggestPicker = function ({ data, activatorRef, inputRef, onValueSelect, maxHeight, navigationBarProps, input, inputFocused, currentInputValueSelectedFromSuggest, suggestContainerRef, itemsGap, onBottomSheetClose, dropHost, inputValue, }) {
|
|
17
|
+
const SuggestPicker = function ({ data, activatorRef, inputRef, onValueSelect, maxHeight, navigationBarProps, input, inputFocused, currentInputValueSelectedFromSuggest, suggestContainerRef, itemsGap, onBottomSheetClose, dropHost, inputValue, topContent, bottomContent, maxWidth, isError, trls, errorPlaceholder, onClickReload, }) {
|
|
16
18
|
const { isMobile, breakpoint } = useBreakpoint();
|
|
17
19
|
const [showBottomSheet, setShowBottomSheet] = useState(false);
|
|
18
20
|
const [showDrop, setShowDrop] = useState(true);
|
|
@@ -44,11 +46,11 @@ const SuggestPicker = function ({ data, activatorRef, inputRef, onValueSelect, m
|
|
|
44
46
|
return null;
|
|
45
47
|
}
|
|
46
48
|
return data.reduce((result, section, index) => {
|
|
47
|
-
const renderResult = renderSection(section, index, onValueSelect, breakpoint);
|
|
49
|
+
const renderResult = renderSection(section, index, onValueSelect, breakpoint, data.length, Boolean(bottomContent));
|
|
48
50
|
result.push(...renderResult);
|
|
49
51
|
return result;
|
|
50
52
|
}, []);
|
|
51
|
-
}, [data, onValueSelect, breakpoint]);
|
|
53
|
+
}, [data, onValueSelect, breakpoint, bottomContent]);
|
|
52
54
|
const InputComponent = input.component;
|
|
53
55
|
const processInput = (ref) => (event) => {
|
|
54
56
|
const hasPrintableRepresentation = event.key.replace(/\s/g, '').length === 1;
|
|
@@ -59,7 +61,7 @@ const SuggestPicker = function ({ data, activatorRef, inputRef, onValueSelect, m
|
|
|
59
61
|
const newEvent = new KeyboardEvent('keydown', event.nativeEvent);
|
|
60
62
|
ref.current?.dispatchEvent(newEvent);
|
|
61
63
|
};
|
|
62
|
-
return (jsxs(Fragment, { children: [
|
|
64
|
+
return (jsxs(Fragment, { children: [jsxs(BottomSheet, { visible: showBottomSheet, height: "full-screen", keyboardOverlaysContent: false, header: jsx(NavigationBar, { ...navigationBarProps, options: jsx("div", { className: classnames({
|
|
63
65
|
[styles.bottomSheetInputHideCaret]: !caretVisible,
|
|
64
66
|
}), children: jsx(InputComponent, { ...{
|
|
65
67
|
...input.props,
|
|
@@ -75,11 +77,11 @@ const SuggestPicker = function ({ data, activatorRef, inputRef, onValueSelect, m
|
|
|
75
77
|
}, onClose: () => {
|
|
76
78
|
setShowBottomSheet(false);
|
|
77
79
|
onBottomSheetClose();
|
|
78
|
-
}, ref: suggestContainerRef, allowScrollWhileFocused: true, children:
|
|
80
|
+
}, footer: isError && (jsx(BottomSheetFooter, { children: jsx(Button, { mode: "secondary", style: "negative", icon: jsx(ArrowPathOutlinedSize24, {}), onClick: onClickReload, "data-qa": "suggest-reload-button", stretched: true, children: trls.resetButton }) })), ref: suggestContainerRef, allowScrollWhileFocused: true, children: [!isError && (jsxs("div", { onKeyDown: processInput(bottomSheetInputRef), className: styles.suggestItemsContainer, style: { gap: itemsGap }, children: [topContent, suggestContent, bottomContent] })), isError && jsx("div", { className: styles.errorWrapper, children: errorPlaceholder })] }), jsx(Drop, { direction: "bottom", alignment: "left", visible: suggestContent !== null &&
|
|
79
81
|
suggestContent.length > 0 &&
|
|
80
82
|
!currentInputValueSelectedFromSuggest &&
|
|
81
83
|
inputFocused &&
|
|
82
|
-
showDrop, onClose: () => setShowDrop(false), host: dropHost, activatorRef: activatorRef, role: "status", space: 400, widthEqualToActivator:
|
|
84
|
+
showDrop, onClose: () => setShowDrop(false), host: dropHost, activatorRef: activatorRef, role: "status", space: 400, widthEqualToActivator: !maxWidth, maxWidth: maxWidth, forcePosition: true, arrowNavigation: true, "data-qa": "suggest-drop", ref: suggestContainerRef, children: jsx("div", { onKeyDown: processInput(inputRef), className: styles.suggestItemsContainer, style: { maxHeight }, children: jsxs("div", { className: styles.suggestItemsContainerWrapper, style: { gap: itemsGap }, children: [topContent, suggestContent, bottomContent] }) }) })] }));
|
|
83
85
|
};
|
|
84
86
|
SuggestPicker.displayName = 'SuggestPicker';
|
|
85
87
|
|
package/SuggestPicker.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SuggestPicker.js","sources":["../src/SuggestPicker.tsx"],"sourcesContent":["import { RefObject, useMemo, useEffect, useRef, useState, ReactElement, KeyboardEventHandler } from 'react';\nimport classnames from 'classnames';\n\nimport { type TokenBaseCoreSpace } from '@hh.ru/magritte-design-tokens/types';\nimport { BottomSheet } from '@hh.ru/magritte-ui-bottom-sheet';\nimport { useBreakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { Drop } from '@hh.ru/magritte-ui-drop';\nimport { ControlledInputProps } from '@hh.ru/magritte-ui-input/src';\nimport { NavigationBar } from '@hh.ru/magritte-ui-navigation-bar';\nimport { renderSection } from '@hh.ru/magritte-ui-suggest/sectionRenderers';\nimport { DataProviderResult, SuggestProps, SuggestInputComponent, InputProp } from '@hh.ru/magritte-ui-suggest/types';\n\nimport styles from './suggest.less';\n\ninterface SuggestPickerProps<K, P extends SuggestInputComponent = SuggestInputComponent> {\n data: DataProviderResult<K> | null | undefined;\n activatorRef: RefObject<HTMLElement>;\n inputRef: RefObject<HTMLElement>;\n onValueSelect: (value: string, data: K | undefined) => void;\n maxHeight: number;\n navigationBarProps: SuggestProps<unknown, SuggestInputComponent>['navigationBarProps'];\n input: InputProp<P>;\n inputFocused: boolean;\n currentInputValueSelectedFromSuggest: boolean;\n suggestContainerRef: RefObject<HTMLElement>;\n itemsGap: TokenBaseCoreSpace;\n onBottomSheetClose: VoidFunction;\n dropHost?: RefObject<HTMLElement>;\n inputValue: string;\n}\n\nexport const SuggestPicker = function <K, P extends SuggestInputComponent>({\n data,\n activatorRef,\n inputRef,\n onValueSelect,\n maxHeight,\n navigationBarProps,\n input,\n inputFocused,\n currentInputValueSelectedFromSuggest,\n suggestContainerRef,\n itemsGap,\n onBottomSheetClose,\n dropHost,\n inputValue,\n}: SuggestPickerProps<K, P>): ReactElement | null {\n const { isMobile, breakpoint } = useBreakpoint();\n const [showBottomSheet, setShowBottomSheet] = useState(false);\n const [showDrop, setShowDrop] = useState(true);\n const bottomSheetInputRef = useRef<HTMLInputElement>(null);\n const [caretVisible, setCaretVisible] = useState(false);\n\n useEffect(() => {\n if (inputFocused) {\n setShowBottomSheet(true);\n } else if (!isMobile) {\n setShowBottomSheet(false);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [inputFocused, setShowBottomSheet]);\n\n useEffect(() => {\n if (currentInputValueSelectedFromSuggest) {\n setShowBottomSheet(false);\n if (isMobile) {\n onBottomSheetClose();\n }\n }\n }, [currentInputValueSelectedFromSuggest, onBottomSheetClose, isMobile]);\n\n // если скрыли дроп из-за скрытия активатора под скроллом, то при следующем изменении данных нужно его показать\n useEffect(() => {\n setShowDrop(true);\n }, [inputValue, inputFocused]);\n\n const suggestContent = useMemo(() => {\n if (!data) {\n return null;\n }\n\n return data.reduce<Array<JSX.Element>>((result, section, index) => {\n const renderResult = renderSection(section, index, onValueSelect, breakpoint);\n result.push(...renderResult);\n return result;\n }, []);\n }, [data, onValueSelect, breakpoint]);\n\n const InputComponent = input.component;\n const processInput =\n (ref: RefObject<HTMLElement>): KeyboardEventHandler<HTMLElement> =>\n (event) => {\n const hasPrintableRepresentation = event.key.replace(/\\s/g, '').length === 1;\n if (!hasPrintableRepresentation) {\n return;\n }\n ref.current?.focus();\n const newEvent = new KeyboardEvent('keydown', event.nativeEvent);\n ref.current?.dispatchEvent(newEvent);\n };\n\n return (\n <>\n <BottomSheet\n visible={showBottomSheet}\n height=\"full-screen\"\n keyboardOverlaysContent={false}\n header={\n <NavigationBar\n {...navigationBarProps}\n options={\n <div\n className={classnames({\n [styles.bottomSheetInputHideCaret]: !caretVisible,\n })}\n >\n <InputComponent\n {...({\n ...input.props,\n invalid: false,\n ref: bottomSheetInputRef,\n autoComplete: 'off',\n } as unknown as JSX.IntrinsicAttributes &\n JSX.LibraryManagedAttributes<P, ControlledInputProps>)}\n />\n </div>\n }\n />\n }\n onAppear={() => {\n bottomSheetInputRef?.current?.focus();\n setCaretVisible(true);\n }}\n onBeforeExit={() => {\n bottomSheetInputRef?.current?.blur();\n setCaretVisible(false);\n }}\n onClose={() => {\n setShowBottomSheet(false);\n onBottomSheetClose();\n }}\n ref={suggestContainerRef}\n allowScrollWhileFocused\n >\n <div\n onKeyDown={processInput(bottomSheetInputRef)}\n className={styles.suggestItemsContainer}\n style={{ gap: itemsGap }}\n >\n {suggestContent}\n </div>\n </BottomSheet>\n <Drop\n direction=\"bottom\"\n alignment=\"left\"\n visible={\n suggestContent !== null &&\n suggestContent.length > 0 &&\n !currentInputValueSelectedFromSuggest &&\n inputFocused &&\n showDrop\n }\n onClose={() => setShowDrop(false)}\n host={dropHost}\n activatorRef={activatorRef}\n role=\"status\"\n space={400}\n widthEqualToActivator\n forcePosition\n arrowNavigation\n data-qa=\"suggest-drop\"\n ref={suggestContainerRef}\n >\n <div onKeyDown={processInput(inputRef)} className={styles.suggestItemsContainer} style={{ maxHeight }}>\n <div className={styles.suggestItemsContainerWrapper} style={{ gap: itemsGap }}>\n {suggestContent}\n </div>\n </div>\n </Drop>\n </>\n );\n};\n\nSuggestPicker.displayName = 'SuggestPicker';\n"],"names":["_jsxs","_Fragment","_jsx"],"mappings":";;;;;;;;;;;;;AA+BO,MAAM,aAAa,GAAG,UAA8C,EACvE,IAAI,EACJ,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,SAAS,EACT,kBAAkB,EAClB,KAAK,EACL,YAAY,EACZ,oCAAoC,EACpC,mBAAmB,EACnB,QAAQ,EACR,kBAAkB,EAClB,QAAQ,EACR,UAAU,GACa,EAAA;IACvB,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,aAAa,EAAE,CAAC;IACjD,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9D,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC/C,IAAA,MAAM,mBAAmB,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAC;IAC3D,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAExD,SAAS,CAAC,MAAK;AACX,QAAA,IAAI,YAAY,EAAE;YACd,kBAAkB,CAAC,IAAI,CAAC,CAAC;AAC5B,SAAA;aAAM,IAAI,CAAC,QAAQ,EAAE;YAClB,kBAAkB,CAAC,KAAK,CAAC,CAAC;AAC7B,SAAA;;AAEL,KAAC,EAAE,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAEvC,SAAS,CAAC,MAAK;AACX,QAAA,IAAI,oCAAoC,EAAE;YACtC,kBAAkB,CAAC,KAAK,CAAC,CAAC;AAC1B,YAAA,IAAI,QAAQ,EAAE;AACV,gBAAA,kBAAkB,EAAE,CAAC;AACxB,aAAA;AACJ,SAAA;KACJ,EAAE,CAAC,oCAAoC,EAAE,kBAAkB,EAAE,QAAQ,CAAC,CAAC,CAAC;;IAGzE,SAAS,CAAC,MAAK;QACX,WAAW,CAAC,IAAI,CAAC,CAAC;AACtB,KAAC,EAAE,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC;AAE/B,IAAA,MAAM,cAAc,GAAG,OAAO,CAAC,MAAK;QAChC,IAAI,CAAC,IAAI,EAAE;AACP,YAAA,OAAO,IAAI,CAAC;AACf,SAAA;QAED,OAAO,IAAI,CAAC,MAAM,CAAqB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,KAAI;AAC9D,YAAA,MAAM,YAAY,GAAG,aAAa,CAAC,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;AAC9E,YAAA,MAAM,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC;AAC7B,YAAA,OAAO,MAAM,CAAC;SACjB,EAAE,EAAE,CAAC,CAAC;KACV,EAAE,CAAC,IAAI,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC;AAEtC,IAAA,MAAM,cAAc,GAAG,KAAK,CAAC,SAAS,CAAC;IACvC,MAAM,YAAY,GACd,CAAC,GAA2B,KAC5B,CAAC,KAAK,KAAI;AACN,QAAA,MAAM,0BAA0B,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;QAC7E,IAAI,CAAC,0BAA0B,EAAE;YAC7B,OAAO;AACV,SAAA;AACD,QAAA,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;QACrB,MAAM,QAAQ,GAAG,IAAI,aAAa,CAAC,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;AACjE,QAAA,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;AACzC,KAAC,CAAC;AAEN,IAAA,QACIA,IAAA,CAAAC,QAAA,EAAA,EAAA,QAAA,EAAA,CACIC,GAAC,CAAA,WAAW,EACR,EAAA,OAAO,EAAE,eAAe,EACxB,MAAM,EAAC,aAAa,EACpB,uBAAuB,EAAE,KAAK,EAC9B,MAAM,EACFA,GAAC,CAAA,aAAa,EACN,EAAA,GAAA,kBAAkB,EACtB,OAAO,EACHA,GAAA,CAAA,KAAA,EAAA,EACI,SAAS,EAAE,UAAU,CAAC;AAClB,4BAAA,CAAC,MAAM,CAAC,yBAAyB,GAAG,CAAC,YAAY;yBACpD,CAAC,EAAA,QAAA,EAEFA,GAAC,CAAA,cAAc,EACN,EAAA,GAAA;gCACD,GAAG,KAAK,CAAC,KAAK;AACd,gCAAA,OAAO,EAAE,KAAK;AACd,gCAAA,GAAG,EAAE,mBAAmB;AACxB,gCAAA,YAAY,EAAE,KAAK;AAEmC,6BAAA,EAAA,CAC5D,GACA,EAEZ,CAAA,EAEN,QAAQ,EAAE,MAAK;AACX,oBAAA,mBAAmB,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;oBACtC,eAAe,CAAC,IAAI,CAAC,CAAC;AAC1B,iBAAC,EACD,YAAY,EAAE,MAAK;AACf,oBAAA,mBAAmB,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;oBACrC,eAAe,CAAC,KAAK,CAAC,CAAC;AAC3B,iBAAC,EACD,OAAO,EAAE,MAAK;oBACV,kBAAkB,CAAC,KAAK,CAAC,CAAC;AAC1B,oBAAA,kBAAkB,EAAE,CAAC;iBACxB,EACD,GAAG,EAAE,mBAAmB,EACxB,uBAAuB,EAAA,IAAA,EAAA,QAAA,EAEvBA,GACI,CAAA,KAAA,EAAA,EAAA,SAAS,EAAE,YAAY,CAAC,mBAAmB,CAAC,EAC5C,SAAS,EAAE,MAAM,CAAC,qBAAqB,EACvC,KAAK,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,EAEvB,QAAA,EAAA,cAAc,GACb,EACI,CAAA,EACdA,GAAC,CAAA,IAAI,EACD,EAAA,SAAS,EAAC,QAAQ,EAClB,SAAS,EAAC,MAAM,EAChB,OAAO,EACH,cAAc,KAAK,IAAI;oBACvB,cAAc,CAAC,MAAM,GAAG,CAAC;AACzB,oBAAA,CAAC,oCAAoC;oBACrC,YAAY;AACZ,oBAAA,QAAQ,EAEZ,OAAO,EAAE,MAAM,WAAW,CAAC,KAAK,CAAC,EACjC,IAAI,EAAE,QAAQ,EACd,YAAY,EAAE,YAAY,EAC1B,IAAI,EAAC,QAAQ,EACb,KAAK,EAAE,GAAG,EACV,qBAAqB,EAAA,IAAA,EACrB,aAAa,EAAA,IAAA,EACb,eAAe,EACP,IAAA,EAAA,SAAA,EAAA,cAAc,EACtB,GAAG,EAAE,mBAAmB,EAExB,QAAA,EAAAA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,YAAY,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,qBAAqB,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,YACjGA,GAAK,CAAA,KAAA,EAAA,EAAA,SAAS,EAAE,MAAM,CAAC,4BAA4B,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,YACxE,cAAc,EAAA,CACb,GACJ,EACH,CAAA,CAAA,EAAA,CACR,EACL;AACN,EAAE;AAEF,aAAa,CAAC,WAAW,GAAG,eAAe;;;;"}
|
|
1
|
+
{"version":3,"file":"SuggestPicker.js","sources":["../src/SuggestPicker.tsx"],"sourcesContent":["import { RefObject, useMemo, useEffect, useRef, useState, ReactElement, KeyboardEventHandler, ReactNode } from 'react';\nimport classnames from 'classnames';\n\nimport { type TokenBaseCoreSpace } from '@hh.ru/magritte-design-tokens/types';\nimport { BottomSheet, BottomSheetFooter } from '@hh.ru/magritte-ui-bottom-sheet';\nimport { useBreakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { Button } from '@hh.ru/magritte-ui-button';\nimport { Drop } from '@hh.ru/magritte-ui-drop';\nimport { ArrowPathOutlinedSize24 } from '@hh.ru/magritte-ui-icon/icon';\nimport { ControlledInputProps } from '@hh.ru/magritte-ui-input/src';\nimport { NavigationBar } from '@hh.ru/magritte-ui-navigation-bar';\nimport { renderSection } from '@hh.ru/magritte-ui-suggest/sectionRenderers';\nimport { DataProviderResult, SuggestProps, SuggestInputComponent, InputProp } from '@hh.ru/magritte-ui-suggest/types';\n\nimport styles from './suggest.less';\n\ninterface SuggestPickerProps<K, P extends SuggestInputComponent = SuggestInputComponent> {\n data: DataProviderResult<K> | null | undefined;\n activatorRef: RefObject<HTMLElement>;\n inputRef: RefObject<HTMLElement>;\n onValueSelect: (value: string, data: K | undefined) => void;\n maxHeight: number;\n navigationBarProps: SuggestProps<unknown, SuggestInputComponent>['navigationBarProps'];\n input: InputProp<P>;\n inputFocused: boolean;\n currentInputValueSelectedFromSuggest: boolean;\n suggestContainerRef: RefObject<HTMLElement>;\n itemsGap: TokenBaseCoreSpace;\n onBottomSheetClose: VoidFunction;\n dropHost?: RefObject<HTMLElement>;\n inputValue: string;\n topContent?: ReactNode;\n bottomContent?: ReactNode;\n maxWidth?: number;\n isError: boolean;\n trls: SuggestProps<unknown, SuggestInputComponent>['trls'];\n errorPlaceholder: ReactNode;\n onClickReload: VoidFunction;\n}\n\nexport const SuggestPicker = function <K, P extends SuggestInputComponent>({\n data,\n activatorRef,\n inputRef,\n onValueSelect,\n maxHeight,\n navigationBarProps,\n input,\n inputFocused,\n currentInputValueSelectedFromSuggest,\n suggestContainerRef,\n itemsGap,\n onBottomSheetClose,\n dropHost,\n inputValue,\n topContent,\n bottomContent,\n maxWidth,\n isError,\n trls,\n errorPlaceholder,\n onClickReload,\n}: SuggestPickerProps<K, P>): ReactElement | null {\n const { isMobile, breakpoint } = useBreakpoint();\n const [showBottomSheet, setShowBottomSheet] = useState(false);\n const [showDrop, setShowDrop] = useState(true);\n const bottomSheetInputRef = useRef<HTMLInputElement>(null);\n const [caretVisible, setCaretVisible] = useState(false);\n\n useEffect(() => {\n if (inputFocused) {\n setShowBottomSheet(true);\n } else if (!isMobile) {\n setShowBottomSheet(false);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [inputFocused, setShowBottomSheet]);\n\n useEffect(() => {\n if (currentInputValueSelectedFromSuggest) {\n setShowBottomSheet(false);\n if (isMobile) {\n onBottomSheetClose();\n }\n }\n }, [currentInputValueSelectedFromSuggest, onBottomSheetClose, isMobile]);\n\n // если скрыли дроп из-за скрытия активатора под скроллом, то при следующем изменении данных нужно его показать\n useEffect(() => {\n setShowDrop(true);\n }, [inputValue, inputFocused]);\n\n const suggestContent = useMemo(() => {\n if (!data) {\n return null;\n }\n\n return data.reduce<Array<JSX.Element>>((result, section, index) => {\n const renderResult = renderSection(\n section,\n index,\n onValueSelect,\n breakpoint,\n data.length,\n Boolean(bottomContent)\n );\n result.push(...renderResult);\n return result;\n }, []);\n }, [data, onValueSelect, breakpoint, bottomContent]);\n\n const InputComponent = input.component;\n const processInput =\n (ref: RefObject<HTMLElement>): KeyboardEventHandler<HTMLElement> =>\n (event) => {\n const hasPrintableRepresentation = event.key.replace(/\\s/g, '').length === 1;\n if (!hasPrintableRepresentation) {\n return;\n }\n ref.current?.focus();\n const newEvent = new KeyboardEvent('keydown', event.nativeEvent);\n ref.current?.dispatchEvent(newEvent);\n };\n\n return (\n <>\n <BottomSheet\n visible={showBottomSheet}\n height=\"full-screen\"\n keyboardOverlaysContent={false}\n header={\n <NavigationBar\n {...navigationBarProps}\n options={\n <div\n className={classnames({\n [styles.bottomSheetInputHideCaret]: !caretVisible,\n })}\n >\n <InputComponent\n {...({\n ...input.props,\n invalid: false,\n ref: bottomSheetInputRef,\n autoComplete: 'off',\n } as unknown as JSX.IntrinsicAttributes &\n JSX.LibraryManagedAttributes<P, ControlledInputProps>)}\n />\n </div>\n }\n />\n }\n onAppear={() => {\n bottomSheetInputRef?.current?.focus();\n setCaretVisible(true);\n }}\n onBeforeExit={() => {\n bottomSheetInputRef?.current?.blur();\n setCaretVisible(false);\n }}\n onClose={() => {\n setShowBottomSheet(false);\n onBottomSheetClose();\n }}\n footer={\n isError && (\n <BottomSheetFooter>\n <Button\n mode=\"secondary\"\n style=\"negative\"\n icon={<ArrowPathOutlinedSize24 />}\n onClick={onClickReload}\n data-qa=\"suggest-reload-button\"\n stretched\n >\n {trls.resetButton}\n </Button>\n </BottomSheetFooter>\n )\n }\n ref={suggestContainerRef}\n allowScrollWhileFocused\n >\n {!isError && (\n <div\n onKeyDown={processInput(bottomSheetInputRef)}\n className={styles.suggestItemsContainer}\n style={{ gap: itemsGap }}\n >\n {topContent}\n {suggestContent}\n {bottomContent}\n </div>\n )}\n {isError && <div className={styles.errorWrapper}>{errorPlaceholder}</div>}\n </BottomSheet>\n <Drop\n direction=\"bottom\"\n alignment=\"left\"\n visible={\n suggestContent !== null &&\n suggestContent.length > 0 &&\n !currentInputValueSelectedFromSuggest &&\n inputFocused &&\n showDrop\n }\n onClose={() => setShowDrop(false)}\n host={dropHost}\n activatorRef={activatorRef}\n role=\"status\"\n space={400}\n widthEqualToActivator={!maxWidth}\n maxWidth={maxWidth}\n forcePosition\n arrowNavigation\n data-qa=\"suggest-drop\"\n ref={suggestContainerRef}\n >\n <div onKeyDown={processInput(inputRef)} className={styles.suggestItemsContainer} style={{ maxHeight }}>\n <div className={styles.suggestItemsContainerWrapper} style={{ gap: itemsGap }}>\n {topContent}\n {suggestContent}\n {bottomContent}\n </div>\n </div>\n </Drop>\n </>\n );\n};\n\nSuggestPicker.displayName = 'SuggestPicker';\n"],"names":["_jsxs","_Fragment","_jsx"],"mappings":"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"}
|
package/dataProvider.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export declare const decorateWithQueryTransofrmer: <K, T>(fetcher: AsyncDataFetc
|
|
|
10
10
|
export declare const decorateWithResponseFormatter: <T, F, K = never>(fetcher: AsyncDataFetcher<F, T>, formatter: FetcherResultProducer<K, T>) => AsyncDataFetcher<K, DataProviderResult<K>>;
|
|
11
11
|
export declare const combineProviders: <T>(providers: DataProvider<T>[]) => DataProvider<T>;
|
|
12
12
|
export declare const defaultFetcher: <T>(url: string, onCancel: CancelCallback) => Promise<T | null>;
|
|
13
|
+
export declare class DataProviderError extends Error {
|
|
14
|
+
}
|
|
13
15
|
export declare const createDataProvider: <K>({ fetcher, debounceTimeout, minCharsCount, }: {
|
|
14
16
|
fetcher: AsyncDataFetcher<K, DataProviderResult<K>>;
|
|
15
17
|
debounceTimeout?: number | undefined;
|
package/dataProvider.js
CHANGED
|
@@ -43,10 +43,12 @@ const defaultFetcher = (url, onCancel) => {
|
|
|
43
43
|
return null;
|
|
44
44
|
});
|
|
45
45
|
};
|
|
46
|
+
class DataProviderError extends Error {
|
|
47
|
+
}
|
|
46
48
|
const createDataProvider = ({ fetcher, debounceTimeout = 300, minCharsCount = 3, }) => {
|
|
47
49
|
const makeQuery = debounce(({ query, resolve, reject, cancelation, }) => {
|
|
48
50
|
if (query.length < minCharsCount || cancelation.isCanceled) {
|
|
49
|
-
reject();
|
|
51
|
+
reject(new DataProviderError());
|
|
50
52
|
return;
|
|
51
53
|
}
|
|
52
54
|
fetcher(query, cancelation.onCancel).then(resolve, reject);
|
|
@@ -68,5 +70,5 @@ const createDataProvider = ({ fetcher, debounceTimeout = 300, minCharsCount = 3,
|
|
|
68
70
|
};
|
|
69
71
|
const createStaticDataFetcher = (data) => (query) => Promise.resolve(data.filter(({ text }) => match(query, text)));
|
|
70
72
|
|
|
71
|
-
export { combineProviders, createDataProvider, createStaticDataFetcher, decorateWithQueryTransofrmer, decorateWithResponseFormatter, defaultFetcher };
|
|
73
|
+
export { DataProviderError, combineProviders, createDataProvider, createStaticDataFetcher, decorateWithQueryTransofrmer, decorateWithResponseFormatter, defaultFetcher };
|
|
72
74
|
//# sourceMappingURL=dataProvider.js.map
|
package/dataProvider.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataProvider.js","sources":["../src/dataProvider.ts"],"sourcesContent":["import axios from 'axios';\n\nimport { debounce } from '@hh.ru/magritte-common-func-utils';\nimport { match } from '@hh.ru/magritte-common-fuzzy-search';\nimport { DataProvider, DataProviderResult } from '@hh.ru/magritte-ui-suggest/types';\n\ntype CancelCallback = (callback: VoidFunction) => void;\n\nexport interface FetcherResultProducer<R = never, I = undefined> {\n (data: I | null, query: string): DataProviderResult<R>;\n}\nexport interface AsyncDataFetcher<R = never, T = DataProviderResult<R>> {\n (url: string, onCancel: CancelCallback): Promise<T | null>;\n}\n\nexport const decorateWithQueryTransofrmer =\n <K, T>(fetcher: AsyncDataFetcher<K, T>, decorator: (query: string) => string): AsyncDataFetcher<K, T> =>\n (query, onCancel) =>\n fetcher(decorator(query), onCancel);\n\nexport const decorateWithResponseFormatter =\n <T, F, K = never>(fetcher: AsyncDataFetcher<F, T>, formatter: FetcherResultProducer<K, T>): AsyncDataFetcher<K> =>\n async (url, onCancel) =>\n formatter(await fetcher(url, onCancel), url);\n\nexport const combineProviders = <T>(providers: Array<DataProvider<T>>): DataProvider<T> => {\n const provider = (query: string) => {\n const provider = providers.find((provider) => query.length >= provider.minCharsCount) || providers[0];\n return provider(query);\n };\n\n provider.minCharsCount = Math.min(...providers.map((provider) => provider.minCharsCount));\n return provider;\n};\n\ninterface ResolverCallback<T> {\n (arg: { resolve: (result: T | null) => void; reject: (err?: unknown) => void }): VoidFunction | void;\n}\n\nconst createCancelablePromise = <T>(callback: ResolverCallback<T>) => {\n let isCanceled = false;\n let cancelHandler: VoidFunction | void;\n\n const promise = new Promise<T | null>((resolve, reject) => {\n cancelHandler = callback({\n resolve: (data: T | null) => {\n !isCanceled && resolve(data);\n },\n reject: (err: unknown) => !isCanceled && reject(err),\n });\n }) as Promise<T> & { cancel: VoidFunction };\n\n promise.cancel = () => {\n isCanceled = true;\n cancelHandler?.();\n };\n return promise;\n};\n\nexport const defaultFetcher = <T>(url: string, onCancel: CancelCallback): Promise<T | null> => {\n const controller = new AbortController();\n onCancel(() => controller.abort());\n\n return axios\n .get<T>(url, { signal: controller.signal })\n .then((response) => response.data)\n .catch((error) => {\n if (!axios.isCancel(error)) {\n throw error;\n }\n return null;\n });\n};\n\nexport const createDataProvider = <K>({\n fetcher,\n debounceTimeout = 300,\n minCharsCount = 3,\n}: {\n fetcher: AsyncDataFetcher<K>;\n debounceTimeout?: number;\n minCharsCount?: number;\n}): DataProvider<K> => {\n const makeQuery = debounce(\n ({\n query,\n resolve,\n reject,\n cancelation,\n }: Parameters<ResolverCallback<DataProviderResult<K>>>[0] & {\n query: string;\n cancelation: { isCanceled: boolean; onCancel: CancelCallback };\n }) => {\n if (query.length < minCharsCount || cancelation.isCanceled) {\n reject();\n return;\n }\n fetcher(query, cancelation.onCancel).then(resolve, reject);\n },\n debounceTimeout\n );\n\n const provider = (query: string) =>\n createCancelablePromise<DataProviderResult<K>>(({ resolve, reject }) => {\n const cancelCallbacks: VoidFunction[] = [];\n const cancelation = {\n isCanceled: false,\n onCancel: (callback: VoidFunction) => cancelCallbacks.push(callback),\n };\n makeQuery({ query, resolve, reject, cancelation });\n return () => {\n cancelation.isCanceled = true;\n cancelCallbacks.forEach((callback) => callback());\n };\n });\n\n provider.minCharsCount = minCharsCount;\n return provider;\n};\n\nexport const createStaticDataFetcher =\n <T extends { text: string }>(data: Array<T>): AsyncDataFetcher<never, T[]> =>\n (query) =>\n Promise.resolve(data.filter(({ text }) => match(query, text)));\n"],"names":[],"mappings":";;;;AAea,MAAA,4BAA4B,GACrC,CAAO,OAA+B,EAAE,SAAoC,KAC5E,CAAC,KAAK,EAAE,QAAQ,KACZ,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE;AAErC,MAAM,6BAA6B,GACtC,CAAkB,OAA+B,EAAE,SAAsC,KACzF,OAAO,GAAG,EAAE,QAAQ,KAChB,SAAS,CAAC,MAAM,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE;AAExC,MAAA,gBAAgB,GAAG,CAAI,SAAiC,KAAqB;AACtF,IAAA,MAAM,QAAQ,GAAG,CAAC,KAAa,KAAI;QAC/B,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,KAAK,CAAC,MAAM,IAAI,QAAQ,CAAC,aAAa,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC;AACtG,QAAA,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC3B,KAAC,CAAC;IAEF,QAAQ,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;AAC1F,IAAA,OAAO,QAAQ,CAAC;AACpB,EAAE;AAMF,MAAM,uBAAuB,GAAG,CAAI,QAA6B,KAAI;IACjE,IAAI,UAAU,GAAG,KAAK,CAAC;AACvB,IAAA,IAAI,aAAkC,CAAC;IAEvC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAW,CAAC,OAAO,EAAE,MAAM,KAAI;QACtD,aAAa,GAAG,QAAQ,CAAC;AACrB,YAAA,OAAO,EAAE,CAAC,IAAc,KAAI;AACxB,gBAAA,CAAC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;aAChC;AACD,YAAA,MAAM,EAAE,CAAC,GAAY,KAAK,CAAC,UAAU,IAAI,MAAM,CAAC,GAAG,CAAC;AACvD,SAAA,CAAC,CAAC;AACP,KAAC,CAA0C,CAAC;AAE5C,IAAA,OAAO,CAAC,MAAM,GAAG,MAAK;QAClB,UAAU,GAAG,IAAI,CAAC;QAClB,aAAa,IAAI,CAAC;AACtB,KAAC,CAAC;AACF,IAAA,OAAO,OAAO,CAAC;AACnB,CAAC,CAAC;MAEW,cAAc,GAAG,CAAI,GAAW,EAAE,QAAwB,KAAuB;AAC1F,IAAA,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC;AAEnC,IAAA,OAAO,KAAK;SACP,GAAG,CAAI,GAAG,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC;SAC1C,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,IAAI,CAAC;AACjC,SAAA,KAAK,CAAC,CAAC,KAAK,KAAI;AACb,QAAA,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;AACxB,YAAA,MAAM,KAAK,CAAC;AACf,SAAA;AACD,QAAA,OAAO,IAAI,CAAC;AAChB,KAAC,CAAC,CAAC;AACX,EAAE;
|
|
1
|
+
{"version":3,"file":"dataProvider.js","sources":["../src/dataProvider.ts"],"sourcesContent":["import axios from 'axios';\n\nimport { debounce } from '@hh.ru/magritte-common-func-utils';\nimport { match } from '@hh.ru/magritte-common-fuzzy-search';\nimport { DataProvider, DataProviderResult } from '@hh.ru/magritte-ui-suggest/types';\n\ntype CancelCallback = (callback: VoidFunction) => void;\n\nexport interface FetcherResultProducer<R = never, I = undefined> {\n (data: I | null, query: string): DataProviderResult<R>;\n}\nexport interface AsyncDataFetcher<R = never, T = DataProviderResult<R>> {\n (url: string, onCancel: CancelCallback): Promise<T | null>;\n}\n\nexport const decorateWithQueryTransofrmer =\n <K, T>(fetcher: AsyncDataFetcher<K, T>, decorator: (query: string) => string): AsyncDataFetcher<K, T> =>\n (query, onCancel) =>\n fetcher(decorator(query), onCancel);\n\nexport const decorateWithResponseFormatter =\n <T, F, K = never>(fetcher: AsyncDataFetcher<F, T>, formatter: FetcherResultProducer<K, T>): AsyncDataFetcher<K> =>\n async (url, onCancel) =>\n formatter(await fetcher(url, onCancel), url);\n\nexport const combineProviders = <T>(providers: Array<DataProvider<T>>): DataProvider<T> => {\n const provider = (query: string) => {\n const provider = providers.find((provider) => query.length >= provider.minCharsCount) || providers[0];\n return provider(query);\n };\n\n provider.minCharsCount = Math.min(...providers.map((provider) => provider.minCharsCount));\n return provider;\n};\n\ninterface ResolverCallback<T> {\n (arg: { resolve: (result: T | null) => void; reject: (err?: unknown) => void }): VoidFunction | void;\n}\n\nconst createCancelablePromise = <T>(callback: ResolverCallback<T>) => {\n let isCanceled = false;\n let cancelHandler: VoidFunction | void;\n\n const promise = new Promise<T | null>((resolve, reject) => {\n cancelHandler = callback({\n resolve: (data: T | null) => {\n !isCanceled && resolve(data);\n },\n reject: (err: unknown) => !isCanceled && reject(err),\n });\n }) as Promise<T> & { cancel: VoidFunction };\n\n promise.cancel = () => {\n isCanceled = true;\n cancelHandler?.();\n };\n return promise;\n};\n\nexport const defaultFetcher = <T>(url: string, onCancel: CancelCallback): Promise<T | null> => {\n const controller = new AbortController();\n onCancel(() => controller.abort());\n\n return axios\n .get<T>(url, { signal: controller.signal })\n .then((response) => response.data)\n .catch((error) => {\n if (!axios.isCancel(error)) {\n throw error;\n }\n return null;\n });\n};\n\nexport class DataProviderError extends Error {}\n\nexport const createDataProvider = <K>({\n fetcher,\n debounceTimeout = 300,\n minCharsCount = 3,\n}: {\n fetcher: AsyncDataFetcher<K>;\n debounceTimeout?: number;\n minCharsCount?: number;\n}): DataProvider<K> => {\n const makeQuery = debounce(\n ({\n query,\n resolve,\n reject,\n cancelation,\n }: Parameters<ResolverCallback<DataProviderResult<K>>>[0] & {\n query: string;\n cancelation: { isCanceled: boolean; onCancel: CancelCallback };\n }) => {\n if (query.length < minCharsCount || cancelation.isCanceled) {\n reject(new DataProviderError());\n return;\n }\n fetcher(query, cancelation.onCancel).then(resolve, reject);\n },\n debounceTimeout\n );\n\n const provider = (query: string) =>\n createCancelablePromise<DataProviderResult<K>>(({ resolve, reject }) => {\n const cancelCallbacks: VoidFunction[] = [];\n const cancelation = {\n isCanceled: false,\n onCancel: (callback: VoidFunction) => cancelCallbacks.push(callback),\n };\n makeQuery({ query, resolve, reject, cancelation });\n return () => {\n cancelation.isCanceled = true;\n cancelCallbacks.forEach((callback) => callback());\n };\n });\n\n provider.minCharsCount = minCharsCount;\n return provider;\n};\n\nexport const createStaticDataFetcher =\n <T extends { text: string }>(data: Array<T>): AsyncDataFetcher<never, T[]> =>\n (query) =>\n Promise.resolve(data.filter(({ text }) => match(query, text)));\n"],"names":[],"mappings":"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"}
|
package/index.css
CHANGED
|
@@ -2,47 +2,63 @@
|
|
|
2
2
|
--magritte-color-text-primary-v18-1-1:#000000;
|
|
3
3
|
}
|
|
4
4
|
:root{
|
|
5
|
+
--magritte-static-space-300-v18-1-1:12px;
|
|
5
6
|
--magritte-static-space-400-v18-1-1:16px;
|
|
6
7
|
}
|
|
7
8
|
.magritte-night-theme{
|
|
8
9
|
--magritte-color-text-primary-v18-1-1:#ffffff;
|
|
9
10
|
}
|
|
10
|
-
.magritte-chips-section-container___Z7N-
|
|
11
|
+
.magritte-chips-section-container___Z7N-E_4-0-0{
|
|
11
12
|
display:flex;
|
|
12
13
|
gap:12px;
|
|
13
|
-
padding-bottom:16px;
|
|
14
14
|
flex:1 1;
|
|
15
15
|
flex-wrap:wrap;
|
|
16
16
|
}
|
|
17
|
-
.magritte-
|
|
17
|
+
.magritte-chips-section-container_with-other-items___eJZAr_4-0-0{
|
|
18
|
+
padding-bottom:16px;
|
|
19
|
+
}
|
|
20
|
+
.magritte-suggest-items-container___SKj-g_4-0-0{
|
|
18
21
|
display:flex;
|
|
19
22
|
flex-direction:column;
|
|
20
23
|
}
|
|
21
|
-
.magritte-suggest-items-container___SKj-
|
|
24
|
+
.magritte-suggest-items-container___SKj-g_4-0-0 .focus-visible{
|
|
22
25
|
z-index:1;
|
|
23
26
|
position:relative;
|
|
24
27
|
}
|
|
25
|
-
.magritte-suggest-items-container-
|
|
28
|
+
.magritte-suggest-items-container-wrapper___T2L5U_4-0-0{
|
|
26
29
|
padding:var(--magritte-static-space-400-v18-1-1);
|
|
27
30
|
margin:calc(-1 * var(--magritte-static-space-400-v18-1-1));
|
|
28
31
|
display:flex;
|
|
29
32
|
flex-direction:column;
|
|
30
33
|
}
|
|
31
|
-
|
|
34
|
+
@media (min-width: 1020px){
|
|
35
|
+
body.magritte-old-layout .magritte-suggest-items-container-wrapper___T2L5U_4-0-0{
|
|
36
|
+
padding:var(--magritte-static-space-300-v18-1-1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
@media (min-width: 1024px){
|
|
40
|
+
body:not(.magritte-old-layout) .magritte-suggest-items-container-wrapper___T2L5U_4-0-0{
|
|
41
|
+
padding:var(--magritte-static-space-300-v18-1-1);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
.magritte-suggest-input-container___l3OkM_4-0-0{
|
|
32
45
|
--magritte-ui-input-caret-color-override:transparent;
|
|
33
46
|
display:inline-block;
|
|
34
47
|
width:100%;
|
|
35
48
|
}
|
|
36
49
|
@media (min-width: 700px){
|
|
37
|
-
body.magritte-old-layout .magritte-suggest-input-
|
|
50
|
+
body.magritte-old-layout .magritte-suggest-input-container___l3OkM_4-0-0{
|
|
38
51
|
--magritte-ui-input-caret-color-override:var(--magritte-color-text-primary-v18-1-1);
|
|
39
52
|
}
|
|
40
53
|
}
|
|
41
54
|
@media (min-width: 600px){
|
|
42
|
-
body:not(.magritte-old-layout) .magritte-suggest-input-
|
|
55
|
+
body:not(.magritte-old-layout) .magritte-suggest-input-container___l3OkM_4-0-0{
|
|
43
56
|
--magritte-ui-input-caret-color-override:var(--magritte-color-text-primary-v18-1-1);
|
|
44
57
|
}
|
|
45
58
|
}
|
|
46
|
-
.magritte-bottom-sheet-input-hide-
|
|
59
|
+
.magritte-bottom-sheet-input-hide-caret___ikoig_4-0-0{
|
|
47
60
|
--magritte-ui-input-caret-color-override:transparent;
|
|
48
61
|
}
|
|
62
|
+
.magritte-error-wrapper___Ui4xt_4-0-0{
|
|
63
|
+
height:100%;
|
|
64
|
+
}
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export * from '@hh.ru/magritte-ui-theme-provider';
|
|
2
2
|
export * from './Suggest';
|
|
3
3
|
export { createDataProvider, decorateWithQueryTransofrmer, decorateWithResponseFormatter, defaultFetcher, createStaticDataFetcher, combineProviders, type AsyncDataFetcher, } from './dataProvider';
|
|
4
|
-
export type { DataSection, DataSectionOfType, DataProviderResult, DataProvider, SuggestInputProps, } from './types';
|
|
4
|
+
export type { DataSection, DataSectionOfType, DataProviderResult, DataProvider, SuggestInputProps, SuggestProps, SuggestInputComponent, } from './types';
|
package/index.js
CHANGED
|
@@ -9,9 +9,11 @@ import '@hh.ru/magritte-ui-breakpoint';
|
|
|
9
9
|
import './SuggestPicker.js';
|
|
10
10
|
import 'classnames';
|
|
11
11
|
import '@hh.ru/magritte-ui-bottom-sheet';
|
|
12
|
+
import '@hh.ru/magritte-ui-button';
|
|
12
13
|
import '@hh.ru/magritte-ui-drop';
|
|
14
|
+
import '@hh.ru/magritte-ui-icon/icon';
|
|
13
15
|
import '@hh.ru/magritte-ui-navigation-bar';
|
|
14
|
-
import './sectionRenderers-
|
|
16
|
+
import './sectionRenderers-1c26595e.js';
|
|
15
17
|
import '@hh.ru/magritte-ui-card';
|
|
16
18
|
import '@hh.ru/magritte-ui-cell';
|
|
17
19
|
import '@hh.ru/magritte-ui-chips';
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hh.ru/magritte-ui-suggest",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"types": "index.d.ts",
|
|
6
6
|
"sideEffects": [
|
|
@@ -26,10 +26,12 @@
|
|
|
26
26
|
"@hh.ru/magritte-design-tokens": "18.1.1",
|
|
27
27
|
"@hh.ru/magritte-ui-bottom-sheet": "4.1.22",
|
|
28
28
|
"@hh.ru/magritte-ui-breakpoint": "4.0.1",
|
|
29
|
+
"@hh.ru/magritte-ui-button": "3.1.14",
|
|
29
30
|
"@hh.ru/magritte-ui-card": "6.0.2",
|
|
30
31
|
"@hh.ru/magritte-ui-cell": "2.2.4",
|
|
31
32
|
"@hh.ru/magritte-ui-chips": "3.0.23",
|
|
32
33
|
"@hh.ru/magritte-ui-drop": "5.0.8",
|
|
34
|
+
"@hh.ru/magritte-ui-icon": "7.1.3",
|
|
33
35
|
"@hh.ru/magritte-ui-input": "5.0.12",
|
|
34
36
|
"@hh.ru/magritte-ui-mock-component": "1.0.10",
|
|
35
37
|
"@hh.ru/magritte-ui-navigation-bar": "4.1.8",
|
|
@@ -44,5 +46,5 @@
|
|
|
44
46
|
"publishConfig": {
|
|
45
47
|
"access": "public"
|
|
46
48
|
},
|
|
47
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "e9fcf9c4b642e0d40df69405709ae8ca9a399cf3"
|
|
48
50
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import './index.css';
|
|
2
2
|
import { createElement } from 'react';
|
|
3
3
|
import { jsx } from 'react/jsx-runtime';
|
|
4
|
+
import classnames from 'classnames';
|
|
4
5
|
import { Breakpoint } from '@hh.ru/magritte-ui-breakpoint';
|
|
5
6
|
import { Card } from '@hh.ru/magritte-ui-card';
|
|
6
7
|
import { Cell } from '@hh.ru/magritte-ui-cell';
|
|
7
8
|
import { CustomChip } from '@hh.ru/magritte-ui-chips';
|
|
8
9
|
import { Text } from '@hh.ru/magritte-ui-typography';
|
|
9
10
|
|
|
10
|
-
var styles = {"chips-section-container":"magritte-chips-section-container___Z7N-
|
|
11
|
+
var styles = {"chips-section-container":"magritte-chips-section-container___Z7N-E_4-0-0","chipsSectionContainer":"magritte-chips-section-container___Z7N-E_4-0-0","chips-section-container_with-other-items":"magritte-chips-section-container_with-other-items___eJZAr_4-0-0","chipsSectionContainerWithOtherItems":"magritte-chips-section-container_with-other-items___eJZAr_4-0-0","suggest-items-container":"magritte-suggest-items-container___SKj-g_4-0-0","suggestItemsContainer":"magritte-suggest-items-container___SKj-g_4-0-0","suggest-items-container-wrapper":"magritte-suggest-items-container-wrapper___T2L5U_4-0-0","suggestItemsContainerWrapper":"magritte-suggest-items-container-wrapper___T2L5U_4-0-0","suggest-input-container":"magritte-suggest-input-container___l3OkM_4-0-0","suggestInputContainer":"magritte-suggest-input-container___l3OkM_4-0-0","bottom-sheet-input-hide-caret":"magritte-bottom-sheet-input-hide-caret___ikoig_4-0-0","bottomSheetInputHideCaret":"magritte-bottom-sheet-input-hide-caret___ikoig_4-0-0","error-wrapper":"magritte-error-wrapper___Ui4xt_4-0-0","errorWrapper":"magritte-error-wrapper___Ui4xt_4-0-0"};
|
|
11
12
|
|
|
12
13
|
const cellSectionRenderer = (section, sectionId, onValueSelect, breakpoint) => {
|
|
13
14
|
return section.items.map((item) => {
|
|
@@ -16,17 +17,20 @@ const cellSectionRenderer = (section, sectionId, onValueSelect, breakpoint) => {
|
|
|
16
17
|
}, onClick: (event) => {
|
|
17
18
|
event.preventDefault();
|
|
18
19
|
onValueSelect(item.value, item.data);
|
|
19
|
-
}, actionCard: true, padding: [Breakpoint.XS, Breakpoint.S].includes(breakpoint) ? 0 :
|
|
20
|
+
}, actionCard: true, padding: [Breakpoint.XS, Breakpoint.S].includes(breakpoint) ? 0 : 12, paddingTop: 12, paddingBottom: 12, borderRadius: 12, "data-qa": "suggest-item-cell", children: jsx(Cell, { ...item.componentProps, onClick: undefined }) }, `cell_${sectionId}_${item.value}`));
|
|
20
21
|
});
|
|
21
22
|
};
|
|
22
|
-
const chipsSectionRenderer = (section, sectionId, onValueSelect) => {
|
|
23
|
-
return (jsx("div", { className: styles.chipsSectionContainer,
|
|
23
|
+
const chipsSectionRenderer = (section, sectionId, onValueSelect, _, length, haveBottomContent) => {
|
|
24
|
+
return (jsx("div", { className: classnames(styles.chipsSectionContainer, {
|
|
25
|
+
// чипсы - не последний элемент или есть нижний контент
|
|
26
|
+
[styles.chipsSectionContainerWithOtherItems]: sectionId !== length - 1 || haveBottomContent,
|
|
27
|
+
}), children: section.items.map((item) => {
|
|
24
28
|
return (createElement(CustomChip, { ...(item.componentProps || {}), key: `chips_${sectionId}_${item.value}`, onMouseDown: (event) => event.preventDefault(), onClick: () => onValueSelect(item.value, item.data), "data-qa": "suggest-item-chips" }, item.value));
|
|
25
29
|
}) }, `chips_section_${sectionId}`));
|
|
26
30
|
};
|
|
27
31
|
const delimiterSectionRenderer = (section, _, __, breakpoint) => {
|
|
28
32
|
return [
|
|
29
|
-
jsx(Card, { style: "blank", stretched: true, padding: [Breakpoint.XS, Breakpoint.S].includes(breakpoint) ? 0 :
|
|
33
|
+
jsx(Card, { style: "blank", stretched: true, padding: [Breakpoint.XS, Breakpoint.S].includes(breakpoint) ? 0 : 12, paddingTop: 8, paddingBottom: 8, "data-qa": "suggest-item-delimiter", children: jsx(Text, { style: "secondary", typography: "label-3-regular", children: section.text }) }, `delimiter_${section.text}`),
|
|
30
34
|
];
|
|
31
35
|
};
|
|
32
36
|
const SECTION_TYPE_TO_RENDERER_MAP = {
|
|
@@ -34,11 +38,11 @@ const SECTION_TYPE_TO_RENDERER_MAP = {
|
|
|
34
38
|
chips: chipsSectionRenderer,
|
|
35
39
|
delimiter: delimiterSectionRenderer,
|
|
36
40
|
};
|
|
37
|
-
const renderSection = (section, sectionId, onValueSelect, breakpoint) => {
|
|
41
|
+
const renderSection = (section, sectionId, onValueSelect, breakpoint, length, haveBottomContent) => {
|
|
38
42
|
const renderer = SECTION_TYPE_TO_RENDERER_MAP[section.type];
|
|
39
|
-
const result = renderer(section, sectionId, onValueSelect, breakpoint);
|
|
43
|
+
const result = renderer(section, sectionId, onValueSelect, breakpoint, length, haveBottomContent);
|
|
40
44
|
return Array.isArray(result) ? result : [result];
|
|
41
45
|
};
|
|
42
46
|
|
|
43
47
|
export { renderSection as r, styles as s };
|
|
44
|
-
//# sourceMappingURL=sectionRenderers-
|
|
48
|
+
//# sourceMappingURL=sectionRenderers-1c26595e.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sectionRenderers-1c26595e.js","sources":["../src/sectionRenderers.tsx"],"sourcesContent":["import classnames from 'classnames';\n\nimport { Breakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { Card } from '@hh.ru/magritte-ui-card';\nimport { Cell } from '@hh.ru/magritte-ui-cell';\nimport { CustomChip } from '@hh.ru/magritte-ui-chips';\nimport { DataSection, DataSectionOfType } from '@hh.ru/magritte-ui-suggest/types';\nimport { Text } from '@hh.ru/magritte-ui-typography';\n\nimport styles from './suggest.less';\n\ninterface ValueSelectHandler<K> {\n (value: string, data: K | undefined): void;\n}\n\ninterface SectionRenderer<T extends DataSection['type'], K = unknown> {\n (\n section: DataSectionOfType<T>,\n sectionId: number,\n onValueSelect: ValueSelectHandler<K>,\n breakpoint: Breakpoint,\n length: number,\n haveBottomContent: boolean\n ): JSX.Element[] | JSX.Element;\n}\n\nconst cellSectionRenderer: SectionRenderer<'cells'> = (section, sectionId, onValueSelect, breakpoint) => {\n return section.items.map((item) => {\n return (\n <Card\n style=\"blank\"\n stretched\n hoverStyle=\"neutral\"\n onMouseDown={(event) => {\n event.preventDefault();\n }}\n onClick={(event) => {\n event.preventDefault();\n onValueSelect(item.value, item.data);\n }}\n actionCard\n padding={[Breakpoint.XS, Breakpoint.S].includes(breakpoint) ? 0 : 12}\n paddingTop={12}\n paddingBottom={12}\n borderRadius={12}\n key={`cell_${sectionId}_${item.value}`}\n data-qa=\"suggest-item-cell\"\n >\n <Cell {...item.componentProps} onClick={undefined} />\n </Card>\n );\n });\n};\n\nconst chipsSectionRenderer: SectionRenderer<'chips'> = (\n section,\n sectionId,\n onValueSelect,\n _,\n length,\n haveBottomContent\n) => {\n return (\n <div\n className={classnames(styles.chipsSectionContainer, {\n // чипсы - не последний элемент или есть нижний контент\n [styles.chipsSectionContainerWithOtherItems]: sectionId !== length - 1 || haveBottomContent,\n })}\n key={`chips_section_${sectionId}`}\n >\n {section.items.map((item) => {\n return (\n <CustomChip\n {...(item.componentProps || {})}\n key={`chips_${sectionId}_${item.value}`}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onValueSelect(item.value, item.data)}\n data-qa=\"suggest-item-chips\"\n >\n {item.value}\n </CustomChip>\n );\n })}\n </div>\n );\n};\n\nconst delimiterSectionRenderer: SectionRenderer<'delimiter'> = (section, _, __, breakpoint) => {\n return [\n <Card\n style=\"blank\"\n stretched\n padding={[Breakpoint.XS, Breakpoint.S].includes(breakpoint) ? 0 : 12}\n paddingTop={8}\n paddingBottom={8}\n key={`delimiter_${section.text}`}\n data-qa=\"suggest-item-delimiter\"\n >\n <Text style=\"secondary\" typography=\"label-3-regular\">\n {section.text}\n </Text>\n </Card>,\n ];\n};\n\nconst SECTION_TYPE_TO_RENDERER_MAP: { [K in DataSection['type']]: SectionRenderer<K> } = {\n cells: cellSectionRenderer,\n chips: chipsSectionRenderer,\n delimiter: delimiterSectionRenderer,\n};\n\nexport const renderSection = <T, K extends DataSection['type']>(\n section: DataSectionOfType<K>,\n sectionId: number,\n onValueSelect: ValueSelectHandler<T>,\n breakpoint: Breakpoint,\n length: number,\n haveBottomContent: boolean\n): JSX.Element[] => {\n const renderer = SECTION_TYPE_TO_RENDERER_MAP[section.type];\n const result = renderer(\n section,\n sectionId,\n onValueSelect as ValueSelectHandler<unknown>,\n breakpoint,\n length,\n haveBottomContent\n );\n return Array.isArray(result) ? result : [result];\n};\n"],"names":["_jsx","_createElement"],"mappings":"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"}
|
package/sectionRenderers.d.ts
CHANGED
|
@@ -3,5 +3,5 @@ import { DataSectionOfType } from './types';
|
|
|
3
3
|
interface ValueSelectHandler<K> {
|
|
4
4
|
(value: string, data: K | undefined): void;
|
|
5
5
|
}
|
|
6
|
-
export declare const renderSection: <T, K extends "cells" | "chips" | "delimiter">(section: DataSectionOfType<K, unknown>, sectionId: number, onValueSelect: ValueSelectHandler<T>, breakpoint: Breakpoint) => JSX.Element[];
|
|
6
|
+
export declare const renderSection: <T, K extends "cells" | "chips" | "delimiter">(section: DataSectionOfType<K, unknown>, sectionId: number, onValueSelect: ValueSelectHandler<T>, breakpoint: Breakpoint, length: number, haveBottomContent: boolean) => JSX.Element[];
|
|
7
7
|
export {};
|
package/sectionRenderers.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import './index.css';
|
|
2
2
|
import 'react';
|
|
3
3
|
import 'react/jsx-runtime';
|
|
4
|
+
import 'classnames';
|
|
4
5
|
import '@hh.ru/magritte-ui-breakpoint';
|
|
5
6
|
import '@hh.ru/magritte-ui-card';
|
|
6
7
|
import '@hh.ru/magritte-ui-cell';
|
|
7
8
|
import '@hh.ru/magritte-ui-chips';
|
|
8
9
|
import '@hh.ru/magritte-ui-typography';
|
|
9
|
-
export { r as renderSection } from './sectionRenderers-
|
|
10
|
+
export { r as renderSection } from './sectionRenderers-1c26595e.js';
|
|
10
11
|
//# sourceMappingURL=sectionRenderers.js.map
|
package/sectionRenderers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sectionRenderers.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sectionRenderers.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
|
package/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FocusEventHandler, ForwardRefExoticComponent, FunctionComponent, KeyboardEventHandler, Ref, RefObject } from 'react';
|
|
1
|
+
import { FocusEventHandler, ForwardRefExoticComponent, FunctionComponent, KeyboardEventHandler, Ref, RefObject, ReactNode } from 'react';
|
|
2
2
|
import { type TokenBaseCoreSpace } from '@hh.ru/magritte-design-tokens/types';
|
|
3
3
|
import { type CellProps } from '@hh.ru/magritte-ui-cell';
|
|
4
4
|
import { type CustomChipProps } from '@hh.ru/magritte-ui-chips';
|
|
@@ -84,5 +84,17 @@ export interface SuggestProps<K, P extends SuggestInputComponent = SuggestInputC
|
|
|
84
84
|
dropHost?: RefObject<HTMLElement>;
|
|
85
85
|
/** Обработчик события потери фокуса садджестом */
|
|
86
86
|
onBlur?: NativeFocusEventHandler;
|
|
87
|
+
/** Верхний произвольный контент */
|
|
88
|
+
topContent?: ReactNode;
|
|
89
|
+
/** Нижний произвольный контент */
|
|
90
|
+
bottomContent?: ReactNode;
|
|
91
|
+
/** Максимальная ширина выпадающего списка Drop */
|
|
92
|
+
maxWidth?: number;
|
|
93
|
+
/** placeholder при возникновении ошибки сети */
|
|
94
|
+
errorPlaceholder: ReactNode;
|
|
95
|
+
/** Перевод для кнопки в error состоянии */
|
|
96
|
+
trls: {
|
|
97
|
+
resetButton: ReactNode;
|
|
98
|
+
};
|
|
87
99
|
}
|
|
88
100
|
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sectionRenderers-859b79db.js","sources":["../src/sectionRenderers.tsx"],"sourcesContent":["import { Breakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { Card } from '@hh.ru/magritte-ui-card';\nimport { Cell } from '@hh.ru/magritte-ui-cell';\nimport { CustomChip } from '@hh.ru/magritte-ui-chips';\nimport { DataSection, DataSectionOfType } from '@hh.ru/magritte-ui-suggest/types';\nimport { Text } from '@hh.ru/magritte-ui-typography';\n\nimport styles from './suggest.less';\n\ninterface ValueSelectHandler<K> {\n (value: string, data: K | undefined): void;\n}\n\ninterface SectionRenderer<T extends DataSection['type'], K = unknown> {\n (section: DataSectionOfType<T>, sectionId: number, onValueSelect: ValueSelectHandler<K>, breakpoint: Breakpoint):\n | JSX.Element[]\n | JSX.Element;\n}\n\nconst cellSectionRenderer: SectionRenderer<'cells'> = (section, sectionId, onValueSelect, breakpoint) => {\n return section.items.map((item) => {\n return (\n <Card\n style=\"blank\"\n stretched\n hoverStyle=\"neutral\"\n onMouseDown={(event) => {\n event.preventDefault();\n }}\n onClick={(event) => {\n event.preventDefault();\n onValueSelect(item.value, item.data);\n }}\n actionCard\n padding={[Breakpoint.XS, Breakpoint.S].includes(breakpoint) ? 0 : 16}\n paddingTop={12}\n paddingBottom={12}\n borderRadius={12}\n key={`cell_${sectionId}_${item.value}`}\n data-qa=\"suggest-item-cell\"\n >\n <Cell {...item.componentProps} onClick={undefined} />\n </Card>\n );\n });\n};\n\nconst chipsSectionRenderer: SectionRenderer<'chips'> = (section, sectionId, onValueSelect) => {\n return (\n <div className={styles.chipsSectionContainer} key={`chips_section_${sectionId}`}>\n {section.items.map((item) => {\n return (\n <CustomChip\n {...(item.componentProps || {})}\n key={`chips_${sectionId}_${item.value}`}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onValueSelect(item.value, item.data)}\n data-qa=\"suggest-item-chips\"\n >\n {item.value}\n </CustomChip>\n );\n })}\n </div>\n );\n};\n\nconst delimiterSectionRenderer: SectionRenderer<'delimiter'> = (section, _, __, breakpoint) => {\n return [\n <Card\n style=\"blank\"\n stretched\n padding={[Breakpoint.XS, Breakpoint.S].includes(breakpoint) ? 0 : 16}\n paddingTop={8}\n paddingBottom={8}\n key={`delimiter_${section.text}`}\n data-qa=\"suggest-item-delimiter\"\n >\n <Text style=\"secondary\" typography=\"label-3-regular\">\n {section.text}\n </Text>\n </Card>,\n ];\n};\n\nconst SECTION_TYPE_TO_RENDERER_MAP: { [K in DataSection['type']]: SectionRenderer<K> } = {\n cells: cellSectionRenderer,\n chips: chipsSectionRenderer,\n delimiter: delimiterSectionRenderer,\n};\n\nexport const renderSection = <T, K extends DataSection['type']>(\n section: DataSectionOfType<K>,\n sectionId: number,\n onValueSelect: ValueSelectHandler<T>,\n breakpoint: Breakpoint\n): JSX.Element[] => {\n const renderer = SECTION_TYPE_TO_RENDERER_MAP[section.type];\n const result = renderer(section, sectionId, onValueSelect as ValueSelectHandler<unknown>, breakpoint);\n return Array.isArray(result) ? result : [result];\n};\n"],"names":["_jsx","_createElement"],"mappings":"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"}
|