From be6503c963d4860c99681d04e4ad0c0fadc5bdcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Wed, 26 Nov 2025 18:06:01 +0800 Subject: [PATCH 1/3] fix: blur to close logic --- src/BaseSelect/index.tsx | 6 +++--- src/SelectInput/index.tsx | 9 ++++++++- src/hooks/useOpen.ts | 6 +++--- tests/Select.test.tsx | 2 ++ 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/BaseSelect/index.tsx b/src/BaseSelect/index.tsx index 96e2e47e..37346f9b 100644 --- a/src/BaseSelect/index.tsx +++ b/src/BaseSelect/index.tsx @@ -570,9 +570,9 @@ const BaseSelect = React.forwardRef((props, ref) } if (!disabled) { - triggerOpen(false, { - lazy: true, - }); + // triggerOpen(false, { + // lazy: true, + // }); onBlur?.(event); } }; diff --git a/src/SelectInput/index.tsx b/src/SelectInput/index.tsx index 6eb93b2e..2b32616a 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,13 @@ export default React.forwardRef(function Selec }); const onInternalBlur: SelectInputProps['onBlur'] = (event) => { - toggleOpen(false); + macroTask(() => { + const inputNode = getDOM(inputRef.current); + if (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/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); From dd860f6c3b99c1c0e2d1e192ef8e164965cd8959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Wed, 26 Nov 2025 18:07:31 +0800 Subject: [PATCH 2/3] test: fix test case --- tests/Combobox.test.tsx | 3 +++ 1 file changed, 3 insertions(+) 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(); }); From 14b6ae36f6453504bc188f29247670614a21954d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Thu, 27 Nov 2025 11:00:57 +0800 Subject: [PATCH 3/3] chore: clean up --- src/BaseSelect/index.tsx | 3 --- src/SelectInput/index.tsx | 5 ++++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/BaseSelect/index.tsx b/src/BaseSelect/index.tsx index 37346f9b..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 2b32616a..db0bc308 100644 --- a/src/SelectInput/index.tsx +++ b/src/SelectInput/index.tsx @@ -200,7 +200,10 @@ export default React.forwardRef(function Selec const onInternalBlur: SelectInputProps['onBlur'] = (event) => { macroTask(() => { const inputNode = getDOM(inputRef.current); - if (inputNode !== document.activeElement && !inputNode.contains(document.activeElement)) { + if ( + !inputNode || + (inputNode !== document.activeElement && !inputNode.contains(document.activeElement)) + ) { toggleOpen(false); } });