Skip to content

Commit 3780838

Browse files
authored
fix: blur should not trigger close when next activeElement still is input ref (#1175)
* fix: blur to close logic * test: fix test case * chore: clean up
1 parent 6b3a9fa commit 3780838

File tree

5 files changed

+19
-7
lines changed

5 files changed

+19
-7
lines changed

src/BaseSelect/index.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -570,9 +570,6 @@ const BaseSelect = React.forwardRef<BaseSelectRef, BaseSelectProps>((props, ref)
570570
}
571571

572572
if (!disabled) {
573-
triggerOpen(false, {
574-
lazy: true,
575-
});
576573
onBlur?.(event);
577574
}
578575
};

src/SelectInput/index.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { clsx } from 'clsx';
1111
import type { ComponentsConfig } from '../hooks/useComponents';
1212
import { getDOM } from '@rc-component/util/lib/Dom/findDOMNode';
1313
import { composeRef } from '@rc-component/util/lib/ref';
14+
import { macroTask } from '../hooks/useOpen';
1415

1516
export interface SelectInputRef {
1617
focus: (options?: FocusOptions) => void;
@@ -197,7 +198,16 @@ export default React.forwardRef<SelectInputRef, SelectInputProps>(function Selec
197198
});
198199

199200
const onInternalBlur: SelectInputProps['onBlur'] = (event) => {
200-
toggleOpen(false);
201+
macroTask(() => {
202+
const inputNode = getDOM(inputRef.current);
203+
if (
204+
!inputNode ||
205+
(inputNode !== document.activeElement && !inputNode.contains(document.activeElement))
206+
) {
207+
toggleOpen(false);
208+
}
209+
});
210+
201211
onBlur?.(event);
202212
};
203213

src/hooks/useOpen.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const internalMacroTask = (fn: VoidFunction) => {
77
channel.port2.postMessage(null);
88
};
99

10-
const macroTask = (fn: VoidFunction, times = 1) => {
10+
export const macroTask = (fn: VoidFunction, times = 1) => {
1111
if (times <= 0) {
1212
fn();
1313
return;
@@ -68,15 +68,15 @@ export default function useOpen(
6868
});
6969

7070
const toggleOpen = useEvent<TriggerOpenType>((nextOpen, config = {}) => {
71-
const { ignoreNext = false, lazy = false } = config;
71+
const { ignoreNext = false } = config;
7272

7373
taskIdRef.current += 1;
7474
const id = taskIdRef.current;
7575

7676
const nextOpenVal = typeof nextOpen === 'boolean' ? nextOpen : !mergedOpen;
7777

7878
// Since `mergedOpen` is post-processed, we need to check if the value really changed
79-
if (nextOpenVal || !lazy) {
79+
if (nextOpenVal) {
8080
if (!taskLockRef.current) {
8181
triggerEvent(nextOpenVal);
8282

tests/Combobox.test.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,8 @@ describe('Select.Combobox', () => {
503503
}
504504

505505
fireEvent.blur(container.querySelector('input')!);
506+
container.querySelector('input').blur();
507+
506508
await delay(100);
507509

508510
expectOpen(container, false);
@@ -591,6 +593,7 @@ describe('Select.Combobox', () => {
591593

592594
fireEvent.blur(container.querySelector('input'));
593595
act(() => {
596+
container.querySelector('input').blur();
594597
jest.runAllTimers();
595598
});
596599

tests/Select.test.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,8 @@ describe('Select.Basic', () => {
807807
toggleOpen(container);
808808
fireEvent.blur(container.querySelector('input'));
809809
act(() => {
810+
// Force trigger blur to active to document.body
811+
container.querySelector('input').blur();
810812
jest.runAllTimers();
811813
});
812814
expectOpen(container, false);

0 commit comments

Comments
 (0)