diff --git a/src/BaseSelect/index.tsx b/src/BaseSelect/index.tsx index 96e2e47e..1cd445cd 100644 --- a/src/BaseSelect/index.tsx +++ b/src/BaseSelect/index.tsx @@ -570,9 +570,6 @@ const BaseSelect = React.forwardRef((props, ref) } if (!disabled) { - triggerOpen(false, { - lazy: true, - }); onBlur?.(event); } }; diff --git a/src/SelectInput/index.tsx b/src/SelectInput/index.tsx index 6eb93b2e..db0bc308 100644 --- a/src/SelectInput/index.tsx +++ b/src/SelectInput/index.tsx @@ -11,6 +11,7 @@ import { clsx } from 'clsx'; import type { ComponentsConfig } from '../hooks/useComponents'; import { getDOM } from '@rc-component/util/lib/Dom/findDOMNode'; import { composeRef } from '@rc-component/util/lib/ref'; +import { macroTask } from '../hooks/useOpen'; export interface SelectInputRef { focus: (options?: FocusOptions) => void; @@ -197,7 +198,16 @@ export default React.forwardRef(function Selec }); const onInternalBlur: SelectInputProps['onBlur'] = (event) => { - toggleOpen(false); + macroTask(() => { + const inputNode = getDOM(inputRef.current); + if ( + !inputNode || + (inputNode !== document.activeElement && !inputNode.contains(document.activeElement)) + ) { + toggleOpen(false); + } + }); + onBlur?.(event); }; diff --git a/src/hooks/useOpen.ts b/src/hooks/useOpen.ts index 2347675f..bf08663f 100644 --- a/src/hooks/useOpen.ts +++ b/src/hooks/useOpen.ts @@ -7,7 +7,7 @@ const internalMacroTask = (fn: VoidFunction) => { channel.port2.postMessage(null); }; -const macroTask = (fn: VoidFunction, times = 1) => { +export const macroTask = (fn: VoidFunction, times = 1) => { if (times <= 0) { fn(); return; @@ -68,7 +68,7 @@ export default function useOpen( }); const toggleOpen = useEvent((nextOpen, config = {}) => { - const { ignoreNext = false, lazy = false } = config; + const { ignoreNext = false } = config; taskIdRef.current += 1; const id = taskIdRef.current; @@ -76,7 +76,7 @@ export default function useOpen( const nextOpenVal = typeof nextOpen === 'boolean' ? nextOpen : !mergedOpen; // Since `mergedOpen` is post-processed, we need to check if the value really changed - if (nextOpenVal || !lazy) { + if (nextOpenVal) { if (!taskLockRef.current) { triggerEvent(nextOpenVal); diff --git a/tests/Combobox.test.tsx b/tests/Combobox.test.tsx index 623837ab..8f23e6f7 100644 --- a/tests/Combobox.test.tsx +++ b/tests/Combobox.test.tsx @@ -503,6 +503,8 @@ describe('Select.Combobox', () => { } fireEvent.blur(container.querySelector('input')!); + container.querySelector('input').blur(); + await delay(100); expectOpen(container, false); @@ -591,6 +593,7 @@ describe('Select.Combobox', () => { fireEvent.blur(container.querySelector('input')); act(() => { + container.querySelector('input').blur(); jest.runAllTimers(); }); diff --git a/tests/Select.test.tsx b/tests/Select.test.tsx index 89b4289c..53f59d40 100644 --- a/tests/Select.test.tsx +++ b/tests/Select.test.tsx @@ -807,6 +807,8 @@ describe('Select.Basic', () => { toggleOpen(container); fireEvent.blur(container.querySelector('input')); act(() => { + // Force trigger blur to active to document.body + container.querySelector('input').blur(); jest.runAllTimers(); }); expectOpen(container, false);