@hh.ru/magritte-ui-new-select 1.0.1 → 1.1.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.
Files changed (57) hide show
  1. package/Select.d.ts +4 -1
  2. package/Select.js +19 -6
  3. package/Select.js.map +1 -1
  4. package/SelectSearchTrigger.d.ts +3 -0
  5. package/SelectSearchTrigger.js +61 -0
  6. package/SelectSearchTrigger.js.map +1 -0
  7. package/SelectTrigger.d.ts +3 -0
  8. package/SelectTrigger.js +42 -0
  9. package/SelectTrigger.js.map +1 -0
  10. package/dataProviderTypes.js +1 -0
  11. package/index.css +25 -0
  12. package/index.d.ts +1 -0
  13. package/index.js +17 -5
  14. package/index.js.map +1 -1
  15. package/internal/ConfigContext.d.ts +1 -3
  16. package/internal/ConfigContext.js +3 -4
  17. package/internal/ConfigContext.js.map +1 -1
  18. package/internal/NavigationManagement.d.ts +8 -0
  19. package/internal/NavigationManagement.js +29 -0
  20. package/internal/NavigationManagement.js.map +1 -0
  21. package/internal/SearchStateContext.d.ts +10 -0
  22. package/internal/SearchStateContext.js +21 -0
  23. package/internal/SearchStateContext.js.map +1 -0
  24. package/internal/SelectDataProvider.d.ts +2 -2
  25. package/internal/SelectDataProvider.js +6 -4
  26. package/internal/SelectDataProvider.js.map +1 -1
  27. package/internal/SelectStateContext.d.ts +1 -1
  28. package/internal/SelectStateContext.js +1 -0
  29. package/internal/SelectStateContext.js.map +1 -1
  30. package/internal/VisibilityContext.js +1 -0
  31. package/internal/focusOrchestrator.d.ts +35 -0
  32. package/internal/focusOrchestrator.js +93 -0
  33. package/internal/focusOrchestrator.js.map +1 -0
  34. package/internal/slots.js +1 -0
  35. package/internal/useDataProvider.d.ts +8 -0
  36. package/internal/{useSearch.js → useDataProvider.js} +11 -31
  37. package/internal/useDataProvider.js.map +1 -0
  38. package/internal/useFocusWithin.d.ts +11 -0
  39. package/internal/useFocusWithin.js +87 -0
  40. package/internal/useFocusWithin.js.map +1 -0
  41. package/internal/useSelectState.d.ts +1 -1
  42. package/internal/useSelectState.js +1 -0
  43. package/internal/useSelectState.js.map +1 -1
  44. package/internal/utils.d.ts +1 -0
  45. package/internal/utils.js +1 -0
  46. package/internal/utils.js.map +1 -1
  47. package/package.json +4 -2
  48. package/types.d.ts +9 -5
  49. package/types.js +1 -0
  50. package/useSelectTrigger.d.ts +6 -0
  51. package/useSelectTrigger.js +111 -0
  52. package/useSelectTrigger.js.map +1 -0
  53. package/internal/NavigationContext.d.ts +0 -17
  54. package/internal/NavigationContext.js +0 -30
  55. package/internal/NavigationContext.js.map +0 -1
  56. package/internal/useSearch.d.ts +0 -8
  57. package/internal/useSearch.js.map +0 -1
@@ -0,0 +1,111 @@
1
+ import './index.css';
2
+ import { useRef, useEffect, useCallback } from 'react';
3
+ import { keyboardMatches, keyboardKeys, keyboardMatch } from '@hh.ru/magritte-common-keyboard';
4
+ import { useDataProvider } from './internal/SelectDataProvider.js';
5
+ import { useSelectState } from './internal/SelectStateContext.js';
6
+ import { useVisibility } from './internal/VisibilityContext.js';
7
+ import { useFocusOrchestrator } from './internal/focusOrchestrator.js';
8
+ import { useSelectElementsValue, useRegisterSelectElementsSlot } from './internal/slots.js';
9
+ import { useSelectedLabels } from './internal/utils.js';
10
+ import 'react/jsx-runtime';
11
+ import '@hh.ru/magritte-common-data-provider';
12
+ import './internal/useDataProvider.js';
13
+ import './internal/SearchStateContext.js';
14
+ import './internal/useSelectState.js';
15
+ import './internal/ConfigContext.js';
16
+ import '@hh.ru/magritte-internal-slot-registry';
17
+
18
+ // TODO заводил под тест, хук только получает триггер, но нерегает его в сторе
19
+ const useGetTriggerRef = () => {
20
+ const activatorRef = useSelectElementsValue('activatorRef');
21
+ return activatorRef;
22
+ };
23
+ const useTriggerRef = () => {
24
+ const activatorRef = useRef(null);
25
+ useRegisterSelectElementsSlot('activatorRef', activatorRef);
26
+ return activatorRef;
27
+ };
28
+ const useSelectTrigger = (disabled) => {
29
+ const showedByFocus = useRef(false);
30
+ const focusedByPointer = useRef(false);
31
+ const { showOptions, toggleListVisibility } = useVisibility();
32
+ const { optionList } = useDataProvider();
33
+ const orchestrator = useFocusOrchestrator();
34
+ const { committedValues, clearSelectedValuesByTrigger } = useSelectState();
35
+ const selectedLabels = useSelectedLabels(committedValues);
36
+ // определяем источник фокуса - pointer или keyboard
37
+ useEffect(() => {
38
+ const onPointerDownDocument = () => {
39
+ focusedByPointer.current = true;
40
+ };
41
+ const onKeyDownDocument = () => {
42
+ focusedByPointer.current = false;
43
+ };
44
+ document.addEventListener('pointerdown', onPointerDownDocument, true);
45
+ document.addEventListener('keydown', onKeyDownDocument, true);
46
+ return () => {
47
+ document.removeEventListener('pointerdown', onPointerDownDocument, true);
48
+ document.removeEventListener('keydown', onKeyDownDocument, true);
49
+ };
50
+ }, []);
51
+ // клавиатурная навигация вокруг тригера и списка
52
+ const onKeyDown = useCallback((event) => {
53
+ // не хотим скролить дроп при использовании пробела
54
+ if (!showOptions && keyboardMatches(event.nativeEvent, [keyboardKeys.Space])) {
55
+ event.preventDefault();
56
+ return;
57
+ }
58
+ // закрытие и переброс фокуса на тригер
59
+ if (showOptions && keyboardMatch(event.nativeEvent, keyboardKeys.Escape)) {
60
+ showedByFocus.current = false;
61
+ orchestrator.yieldFocus();
62
+ toggleListVisibility();
63
+ return;
64
+ }
65
+ // TODO использовать orchestrator и отправлять фокус по стрелкам в дроп
66
+ // после закрытия пользователь решил что-то поделать опять
67
+ if (!showOptions &&
68
+ !keyboardMatches(event.nativeEvent, [keyboardKeys.Tab, keyboardKeys.Escape, keyboardKeys.Space])) {
69
+ toggleListVisibility();
70
+ }
71
+ }, [showOptions, orchestrator, toggleListVisibility]);
72
+ // открытие/закрытие тригера
73
+ const onChange = useCallback(() => {
74
+ if (disabled) {
75
+ return;
76
+ }
77
+ if (showedByFocus.current) {
78
+ showedByFocus.current = false;
79
+ return;
80
+ }
81
+ toggleListVisibility();
82
+ }, [disabled, toggleListVisibility]);
83
+ const onBlur = useCallback(() => {
84
+ // TODO тут что-то про подсказки было
85
+ if (showOptions && optionList.length === 0) {
86
+ toggleListVisibility();
87
+ }
88
+ }, [showOptions, optionList.length, toggleListVisibility]);
89
+ const onClear = useCallback(() => clearSelectedValuesByTrigger(), [clearSelectedValuesByTrigger]);
90
+ const onFocus = useCallback(() => {
91
+ if (disabled || showOptions) {
92
+ return;
93
+ }
94
+ if (focusedByPointer.current) {
95
+ showedByFocus.current = true;
96
+ toggleListVisibility();
97
+ }
98
+ }, [disabled, showOptions, toggleListVisibility]);
99
+ return {
100
+ expanded: showOptions,
101
+ onBlur,
102
+ onChange,
103
+ onClear,
104
+ onKeyDown,
105
+ onFocus,
106
+ values: selectedLabels,
107
+ };
108
+ };
109
+
110
+ export { useGetTriggerRef, useSelectTrigger, useTriggerRef };
111
+ //# sourceMappingURL=useSelectTrigger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSelectTrigger.js","sources":["src/useSelectTrigger.ts"],"sourcesContent":["import { KeyboardEventHandler, RefObject, useCallback, useRef, useEffect } from 'react';\n\nimport { StaticDataFetcherItem } from '@hh.ru/magritte-common-data-provider';\nimport { keyboardKeys, keyboardMatch, keyboardMatches } from '@hh.ru/magritte-common-keyboard';\nimport { useDataProvider } from '@hh.ru/magritte-ui-new-select/internal/SelectDataProvider';\nimport { useSelectState } from '@hh.ru/magritte-ui-new-select/internal/SelectStateContext';\nimport { useVisibility } from '@hh.ru/magritte-ui-new-select/internal/VisibilityContext';\nimport { useFocusOrchestrator } from '@hh.ru/magritte-ui-new-select/internal/focusOrchestrator';\nimport { useRegisterSelectElementsSlot, useSelectElementsValue } from '@hh.ru/magritte-ui-new-select/internal/slots';\nimport { useSelectedLabels } from '@hh.ru/magritte-ui-new-select/internal/utils';\nimport { SelectControlledTriggerProps } from '@hh.ru/magritte-ui-new-select/types';\n\n// TODO заводил под тест, хук только получает триггер, но нерегает его в сторе\nexport const useGetTriggerRef = (): RefObject<HTMLElement> | undefined => {\n const activatorRef = useSelectElementsValue('activatorRef');\n return activatorRef;\n};\n\nexport const useTriggerRef = (): RefObject<HTMLElement> => {\n const activatorRef = useRef<HTMLElement>(null);\n useRegisterSelectElementsSlot('activatorRef', activatorRef);\n\n return activatorRef;\n};\n\nexport const useSelectTrigger = <MultipleType extends boolean, DataType extends StaticDataFetcherItem>(\n disabled?: boolean\n): SelectControlledTriggerProps => {\n const showedByFocus = useRef(false);\n const focusedByPointer = useRef<boolean>(false);\n const { showOptions, toggleListVisibility } = useVisibility();\n const { optionList } = useDataProvider<DataType>();\n const orchestrator = useFocusOrchestrator();\n const { committedValues, clearSelectedValuesByTrigger } = useSelectState<MultipleType, DataType>();\n const selectedLabels = useSelectedLabels(committedValues);\n\n // определяем источник фокуса - pointer или keyboard\n useEffect(() => {\n const onPointerDownDocument = () => {\n focusedByPointer.current = true;\n };\n const onKeyDownDocument = () => {\n focusedByPointer.current = false;\n };\n document.addEventListener('pointerdown', onPointerDownDocument, true);\n document.addEventListener('keydown', onKeyDownDocument, true);\n return () => {\n document.removeEventListener('pointerdown', onPointerDownDocument, true);\n document.removeEventListener('keydown', onKeyDownDocument, true);\n };\n }, []);\n\n // клавиатурная навигация вокруг тригера и списка\n const onKeyDown = useCallback<KeyboardEventHandler>(\n (event) => {\n // не хотим скролить дроп при использовании пробела\n if (!showOptions && keyboardMatches(event.nativeEvent, [keyboardKeys.Space])) {\n event.preventDefault();\n return;\n }\n\n // закрытие и переброс фокуса на тригер\n if (showOptions && keyboardMatch(event.nativeEvent, keyboardKeys.Escape)) {\n showedByFocus.current = false;\n orchestrator.yieldFocus();\n toggleListVisibility();\n return;\n }\n\n // TODO использовать orchestrator и отправлять фокус по стрелкам в дроп\n\n // после закрытия пользователь решил что-то поделать опять\n if (\n !showOptions &&\n !keyboardMatches(event.nativeEvent, [keyboardKeys.Tab, keyboardKeys.Escape, keyboardKeys.Space])\n ) {\n toggleListVisibility();\n }\n },\n [showOptions, orchestrator, toggleListVisibility]\n );\n\n // открытие/закрытие тригера\n const onChange = useCallback(() => {\n if (disabled) {\n return;\n }\n if (showedByFocus.current) {\n showedByFocus.current = false;\n return;\n }\n toggleListVisibility();\n }, [disabled, toggleListVisibility]);\n\n const onBlur = useCallback(() => {\n // TODO тут что-то про подсказки было\n if (showOptions && optionList.length === 0) {\n toggleListVisibility();\n }\n }, [showOptions, optionList.length, toggleListVisibility]);\n\n const onClear = useCallback(() => clearSelectedValuesByTrigger(), [clearSelectedValuesByTrigger]);\n\n const onFocus = useCallback(() => {\n if (disabled || showOptions) {\n return;\n }\n if (focusedByPointer.current) {\n showedByFocus.current = true;\n toggleListVisibility();\n }\n }, [disabled, showOptions, toggleListVisibility]);\n\n return {\n expanded: showOptions,\n onBlur,\n onChange,\n onClear,\n onKeyDown,\n onFocus,\n values: selectedLabels,\n };\n};\n"],"names":[],"mappings":"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"}
@@ -1,17 +0,0 @@
1
- import { type ReactNode, type ReactElement, Dispatch, MutableRefObject, SetStateAction } from 'react';
2
- export type FocusStateType = 'focus' | 'focusAndSelect' | null;
3
- export interface UseNavigation {
4
- forcedState: FocusStateType;
5
- requestFocus: VoidFunction;
6
- requestFocusAndSelect: VoidFunction;
7
- clearFocusIntent: VoidFunction;
8
- committedByKeyboardRef: MutableRefObject<boolean>;
9
- }
10
- export declare const useNavigation: () => UseNavigation;
11
- interface NavigationProviderProps {
12
- children: ReactNode;
13
- forcedState: FocusStateType;
14
- setForcedState: Dispatch<SetStateAction<FocusStateType>>;
15
- }
16
- export declare const NavigationProvider: ({ children, forcedState, setForcedState, }: NavigationProviderProps) => ReactElement;
17
- export {};
@@ -1,30 +0,0 @@
1
- import { jsx } from 'react/jsx-runtime';
2
- import { createContext, useContext, useCallback, useRef, useMemo } from 'react';
3
- import { assertSelectContext } from './utils.js';
4
- import '@hh.ru/magritte-common-keyboard';
5
-
6
- const SelectNavigationContext = createContext(null);
7
- const useNavigation = () => {
8
- return assertSelectContext(useContext(SelectNavigationContext), 'useNavigation');
9
- };
10
- // фокус/клавиатура (самый нижний в цепочке — читает все что выше)
11
- const NavigationProvider = ({ children, forcedState, setForcedState, }) => {
12
- const requestFocus = useCallback(() => setForcedState('focus'), [setForcedState]);
13
- const requestFocusAndSelect = useCallback(() => setForcedState('focusAndSelect'), [setForcedState]);
14
- const clearFocusIntent = useCallback(() => setForcedState(null), [setForcedState]);
15
- // надо перебросить фокус на тригер
16
- // при выборе опции/использовании кнопок с клавиатуры
17
- // реф обрабатывается в опции/кнопках/дропе
18
- const committedByKeyboardRef = useRef(false);
19
- const contextValue = useMemo(() => ({
20
- forcedState,
21
- requestFocus,
22
- requestFocusAndSelect,
23
- clearFocusIntent,
24
- committedByKeyboardRef,
25
- }), [forcedState, requestFocus, requestFocusAndSelect, clearFocusIntent]);
26
- return jsx(SelectNavigationContext.Provider, { value: contextValue, children: children });
27
- };
28
-
29
- export { NavigationProvider, useNavigation };
30
- //# sourceMappingURL=NavigationContext.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"NavigationContext.js","sources":["src/internal/NavigationContext.tsx"],"sourcesContent":["import {\n createContext,\n useContext,\n type ReactNode,\n type ReactElement,\n Dispatch,\n useMemo,\n MutableRefObject,\n useCallback,\n useRef,\n SetStateAction,\n} from 'react';\n\nimport { assertSelectContext } from '@hh.ru/magritte-ui-new-select/internal/utils';\n\nexport type FocusStateType = 'focus' | 'focusAndSelect' | null;\n\nexport interface UseNavigation {\n forcedState: FocusStateType;\n requestFocus: VoidFunction;\n requestFocusAndSelect: VoidFunction;\n clearFocusIntent: VoidFunction;\n committedByKeyboardRef: MutableRefObject<boolean>;\n}\n\nconst SelectNavigationContext = createContext<UseNavigation | null>(null);\n\nexport const useNavigation = (): UseNavigation => {\n return assertSelectContext(useContext(SelectNavigationContext), 'useNavigation');\n};\n\ninterface NavigationProviderProps {\n children: ReactNode;\n forcedState: FocusStateType;\n setForcedState: Dispatch<SetStateAction<FocusStateType>>;\n}\n\n// фокус/клавиатура (самый нижний в цепочке — читает все что выше)\nexport const NavigationProvider = ({\n children,\n forcedState,\n setForcedState,\n}: NavigationProviderProps): ReactElement => {\n const requestFocus = useCallback(() => setForcedState('focus'), [setForcedState]);\n const requestFocusAndSelect = useCallback(() => setForcedState('focusAndSelect'), [setForcedState]);\n const clearFocusIntent = useCallback(() => setForcedState(null), [setForcedState]);\n\n // надо перебросить фокус на тригер\n // при выборе опции/использовании кнопок с клавиатуры\n // реф обрабатывается в опции/кнопках/дропе\n const committedByKeyboardRef = useRef(false);\n\n const contextValue = useMemo(\n () => ({\n forcedState,\n requestFocus,\n requestFocusAndSelect,\n clearFocusIntent,\n committedByKeyboardRef,\n }),\n [forcedState, requestFocus, requestFocusAndSelect, clearFocusIntent]\n );\n return <SelectNavigationContext.Provider value={contextValue}>{children}</SelectNavigationContext.Provider>;\n};\n"],"names":["_jsx"],"mappings":";;;;;AAyBA,MAAM,uBAAuB,GAAG,aAAa,CAAuB,IAAI,CAAC,CAAC;AAEnE,MAAM,aAAa,GAAG,MAAoB;IAC7C,OAAO,mBAAmB,CAAC,UAAU,CAAC,uBAAuB,CAAC,EAAE,eAAe,CAAC,CAAC;AACrF,EAAE;AAQF;AACO,MAAM,kBAAkB,GAAG,CAAC,EAC/B,QAAQ,EACR,WAAW,EACX,cAAc,GACQ,KAAkB;AACxC,IAAA,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC;AAClF,IAAA,MAAM,qBAAqB,GAAG,WAAW,CAAC,MAAM,cAAc,CAAC,gBAAgB,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC;AACpG,IAAA,MAAM,gBAAgB,GAAG,WAAW,CAAC,MAAM,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC;;;;AAKnF,IAAA,MAAM,sBAAsB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;AAE7C,IAAA,MAAM,YAAY,GAAG,OAAO,CACxB,OAAO;QACH,WAAW;QACX,YAAY;QACZ,qBAAqB;QACrB,gBAAgB;QAChB,sBAAsB;KACzB,CAAC,EACF,CAAC,WAAW,EAAE,YAAY,EAAE,qBAAqB,EAAE,gBAAgB,CAAC,CACvE,CAAC;IACF,OAAOA,GAAA,CAAC,uBAAuB,CAAC,QAAQ,EAAA,EAAC,KAAK,EAAE,YAAY,EAAA,QAAA,EAAG,QAAQ,EAAA,CAAoC,CAAC;AAChH;;;;"}
@@ -1,8 +0,0 @@
1
- import { StaticDataFetcherItem, DataProvider as DataProviderType } from '@hh.ru/magritte-common-data-provider';
2
- import { OnOptionsChangeCallback, SelectOption, SearchValue, SetSearchValue } from '@hh.ru/magritte-ui-new-select/types';
3
- export interface UseSelectSearch<DataType extends StaticDataFetcherItem> extends SearchValue, SetSearchValue {
4
- internalError?: boolean;
5
- internalLoading?: boolean;
6
- optionList: SelectOption<DataType>[];
7
- }
8
- export declare const useSearch: <DataType extends StaticDataFetcherItem>(dataProvider: DataProviderType<DataType>, onOptionsChangeExternal?: OnOptionsChangeCallback<DataType>) => UseSelectSearch<DataType>;
@@ -1 +0,0 @@
1
- {"version":3,"file":"useSearch.js","sources":["src/internal/useSearch.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport {\n StaticDataFetcherItem,\n DataProvider as DataProviderType,\n DataProviderError,\n} from '@hh.ru/magritte-common-data-provider';\nimport { DataProviderRequest } from '@hh.ru/magritte-common-data-provider/types';\nimport { useVisibility } from '@hh.ru/magritte-ui-new-select/internal/VisibilityContext';\nimport {\n OnOptionsChangeCallback,\n SelectOption,\n SearchValue,\n SetSearchValue,\n} from '@hh.ru/magritte-ui-new-select/types';\n\nconst EMPTY_OPTION_LIST: never[] = [];\n\nexport interface UseSelectSearch<DataType extends StaticDataFetcherItem> extends SearchValue, SetSearchValue {\n internalError?: boolean;\n internalLoading?: boolean;\n optionList: SelectOption<DataType>[];\n}\n\nexport const useSearch = <DataType extends StaticDataFetcherItem>(\n dataProvider: DataProviderType<DataType>,\n onOptionsChangeExternal?: OnOptionsChangeCallback<DataType>\n): UseSelectSearch<DataType> => {\n const { showOptions } = useVisibility();\n const [searchValue, setSearchValue] = useState('');\n const [optionList, setOptionList] = useState<SelectOption<DataType>[]>(EMPTY_OPTION_LIST);\n const [internalError, setInternalError] = useState(false);\n const [optionsLoading, setOptionsLoading] = useState(false);\n const currentRequestRef = useRef<DataProviderRequest>();\n\n // TODO loading/inProgress реализовать в отдельном компоненте\n // const loadingTimeoutRef = useRef<number>(0);\n // const inProgressTimeoutRef = useRef<number>(0);\n // const [searchInProgress, setSearchInProgress] = useState(false);\n\n const updateOptionsFromProvider = useCallback(\n (text: string) => {\n if (!dataProvider) {\n return;\n }\n setInternalError(false);\n currentRequestRef.current?.cancel();\n const request = dataProvider(text);\n currentRequestRef.current = request;\n request\n .then((result) => {\n currentRequestRef.current = undefined;\n const newOptions: SelectOption<DataType>[] = [];\n result.forEach((section) => {\n if (section.type === 'delimiter') {\n newOptions.push({\n data: { text: section.text, value: section.text } as DataType,\n type: 'delimiter',\n });\n }\n if (section.type === 'cells') {\n section.items.forEach((item) => {\n newOptions.push({\n data: item.data ? item.data : ({ text: item.value, value: item.value } as DataType),\n disabled: item.disabled,\n });\n });\n }\n });\n\n const hasRealOptions = newOptions.some((item) => item.type !== 'delimiter');\n setOptionList(hasRealOptions ? newOptions : EMPTY_OPTION_LIST);\n })\n .catch((error) => {\n // включаем error state если это НЕ ошибка\n // вызванная `minCharsCount` или отменненым запросом\n if (!(error instanceof DataProviderError)) {\n setInternalError(true);\n setOptionList(EMPTY_OPTION_LIST);\n }\n })\n .finally(() => {\n setOptionsLoading(false);\n });\n },\n [dataProvider]\n );\n\n // уведомляем клиента об изменении списка опций вне фазы рендера (только при реальной смене ссылки)\n const notifiedListRef = useRef(optionList);\n useEffect(() => {\n if (notifiedListRef.current === optionList) {\n return;\n }\n notifiedListRef.current = optionList;\n onOptionsChangeExternal?.(optionList);\n }, [optionList, onOptionsChangeExternal]);\n\n // обрабатываем обновление провайдера из клиента\n useEffect(() => {\n updateOptionsFromProvider(searchValue);\n // eslint-disable-next-line disable-autofix/react-hooks/exhaustive-deps\n }, [dataProvider]);\n\n // TODO убрать в тригер/пикер\n // сбрасываем select при закрытии компонента\n /* useEffect(() => {\n if (!showOptions) {\n setSearchValue('');\n updateOptionsFromProvider('');\n }\n // eslint-disable-next-line disable-autofix/react-hooks/exhaustive-deps\n }, [showOptions]);\n\n // обрабатываем поиск\n\n useEffect(() => {\n updateOptionsFromProvider(searchValue);\n // eslint-disable-next-line disable-autofix/react-hooks/exhaustive-deps\n }, [searchValue]);*/\n\n // после анмаунта надо отменить все запросы\n useEffect(\n () => () => {\n currentRequestRef.current?.cancel();\n },\n []\n );\n\n return useMemo(\n () => ({\n internalError,\n internalLoading: optionsLoading && showOptions,\n optionList,\n searchValue,\n setSearchValue,\n }),\n [internalError, optionList, optionsLoading, searchValue, setSearchValue, showOptions]\n );\n};\n"],"names":[],"mappings":"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"}