Skip to content

Commit e3ca501

Browse files
committed
Revert "chore: adjust order of call (#1183)"
This reverts commit f5509e2.
1 parent c8f7469 commit e3ca501

File tree

5 files changed

+46
-45
lines changed

5 files changed

+46
-45
lines changed

src/BaseSelect/index.tsx

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import type { RefTriggerProps } from '../SelectTrigger';
2121
import SelectTrigger from '../SelectTrigger';
2222
import { getSeparatedContent, isValidCount } from '../utils/valueUtil';
2323
import Polite from './Polite';
24-
import useOpen from '../hooks/useOpen';
24+
import useOpen, { macroTask } from '../hooks/useOpen';
2525
import { useEvent } from '@rc-component/util';
2626
import type { SelectInputRef } from '../SelectInput';
2727
import SelectInput from '../SelectInput';
@@ -564,12 +564,11 @@ const BaseSelect = React.forwardRef<BaseSelectRef, BaseSelectProps>((props, ref)
564564
};
565565

566566
const onRootBlur = () => {
567-
// Delay close should check the activeElement
568-
if (mergedOpen) {
569-
triggerOpen(false, {
570-
cancelFun: () => isInside(getSelectElements(), document.activeElement as HTMLElement),
571-
});
572-
}
567+
macroTask(() => {
568+
if (!isInside(getSelectElements(), document.activeElement as HTMLElement)) {
569+
triggerOpen(false);
570+
}
571+
});
573572
};
574573

575574
const onInternalBlur: React.FocusEventHandler<HTMLElement> = (event) => {
@@ -594,14 +593,16 @@ const BaseSelect = React.forwardRef<BaseSelectRef, BaseSelectProps>((props, ref)
594593
}
595594
};
596595

597-
const onRootMouseDown: React.MouseEventHandler<HTMLDivElement> = (event, ...restArgs) => {
596+
const onInternalMouseDown: React.MouseEventHandler<HTMLDivElement> = (event, ...restArgs) => {
598597
const { target } = event;
599598
const popupElement: HTMLDivElement = triggerRef.current?.getPopupElement();
600599

601600
// We should give focus back to selector if clicked item is not focusable
602601
if (popupElement?.contains(target as HTMLElement) && triggerOpen) {
603602
// Tell `open` not to close since it's safe in the popup
604-
triggerOpen(true);
603+
triggerOpen(true, {
604+
ignoreNext: true,
605+
});
605606
}
606607

607608
onMouseDown?.(event, ...restArgs);
@@ -746,7 +747,7 @@ const BaseSelect = React.forwardRef<BaseSelectRef, BaseSelectProps>((props, ref)
746747
// Token handling
747748
tokenWithEnter={tokenWithEnter}
748749
// Open
749-
onMouseDown={onRootMouseDown}
750+
onMouseDown={onInternalMouseDown}
750751
// Components
751752
components={mergedComponents}
752753
/>
@@ -773,7 +774,7 @@ const BaseSelect = React.forwardRef<BaseSelectRef, BaseSelectProps>((props, ref)
773774
empty={emptyOptions}
774775
onPopupVisibleChange={onTriggerVisibleChange}
775776
onPopupMouseEnter={onPopupMouseEnter}
776-
onPopupMouseDown={onRootMouseDown}
777+
onPopupMouseDown={onInternalMouseDown}
777778
onPopupBlur={onRootBlur}
778779
>
779780
{renderNode}

src/SelectInput/index.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,13 @@ export default React.forwardRef<SelectInputRef, SelectInputProps>(function Selec
170170
// ====================== Open ======================
171171
const onInternalMouseDown: SelectInputProps['onMouseDown'] = useEvent((event) => {
172172
if (!disabled) {
173-
const inputDOM = getDOM(inputRef.current);
174-
175173
// https://github.com/ant-design/ant-design/issues/56002
176174
// Tell `useSelectTriggerControl` to ignore this event
177175
// When icon is dynamic render, the parentNode will miss
178176
// so we need to mark the event directly
179-
(event.nativeEvent as any)._ori_target = inputDOM;
177+
(event.nativeEvent as any)._ignore_global_close = true;
180178

179+
const inputDOM = getDOM(inputRef.current);
181180
if (inputDOM && event.target !== inputDOM && !inputDOM.contains(event.target as Node)) {
182181
event.preventDefault();
183182
}

src/hooks/useOpen.ts

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@ export const macroTask = (fn: VoidFunction, times = 1) => {
2020

2121
/**
2222
* Trigger by latest open call, if nextOpen is undefined, means toggle.
23-
* `weak` means this call can be ignored if previous call exists.
23+
* ignoreNext will skip next call in the macro task queue.
2424
*/
2525
export type TriggerOpenType = (
2626
nextOpen?: boolean,
2727
config?: {
28-
cancelFun?: () => boolean;
28+
ignoreNext?: boolean;
29+
lazy?: boolean;
2930
},
3031
) => void;
3132

@@ -57,6 +58,7 @@ export default function useOpen(
5758
const mergedOpen = postOpen(ssrSafeOpen);
5859

5960
const taskIdRef = useRef(0);
61+
const taskLockRef = useRef(false);
6062

6163
const triggerEvent = useEvent((nextOpen: boolean) => {
6264
if (onOpen && mergedOpen !== nextOpen) {
@@ -66,32 +68,35 @@ export default function useOpen(
6668
});
6769

6870
const toggleOpen = useEvent<TriggerOpenType>((nextOpen, config = {}) => {
69-
const { cancelFun } = config;
71+
const { ignoreNext = false } = config;
7072

7173
taskIdRef.current += 1;
7274
const id = taskIdRef.current;
7375

7476
const nextOpenVal = typeof nextOpen === 'boolean' ? nextOpen : !mergedOpen;
7577

76-
function triggerUpdate() {
77-
if (
78-
// Always check if id is match
79-
id === taskIdRef.current &&
80-
// Check if need to cancel
81-
!cancelFun?.()
82-
) {
78+
// Since `mergedOpen` is post-processed, we need to check if the value really changed
79+
if (nextOpenVal) {
80+
if (!taskLockRef.current) {
8381
triggerEvent(nextOpenVal);
82+
83+
// Lock if needed
84+
if (ignoreNext) {
85+
taskLockRef.current = ignoreNext;
86+
87+
macroTask(() => {
88+
taskLockRef.current = false;
89+
}, 3);
90+
}
8491
}
92+
return;
8593
}
8694

87-
// Weak update can be ignored
88-
if (nextOpenVal) {
89-
triggerUpdate();
90-
} else {
91-
macroTask(() => {
92-
triggerUpdate();
93-
});
94-
}
95+
macroTask(() => {
96+
if (id === taskIdRef.current && !taskLockRef.current) {
97+
triggerEvent(nextOpenVal);
98+
}
99+
});
95100
});
96101

97102
return [mergedOpen, toggleOpen] as const;

src/hooks/useSelectTriggerControl.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import * as React from 'react';
22
import { useEvent } from '@rc-component/util';
3-
import type { TriggerOpenType } from './useOpen';
43

54
export function isInside(elements: (HTMLElement | SVGElement | undefined)[], target: HTMLElement) {
65
return elements
@@ -11,7 +10,7 @@ export function isInside(elements: (HTMLElement | SVGElement | undefined)[], tar
1110
export default function useSelectTriggerControl(
1211
elements: () => (HTMLElement | SVGElement | undefined)[],
1312
open: boolean,
14-
triggerOpen: TriggerOpenType,
13+
triggerOpen: (open: boolean) => void,
1514
customizedTrigger: boolean,
1615
) {
1716
const onGlobalMouseDown = useEvent((event: MouseEvent) => {
@@ -26,13 +25,10 @@ export default function useSelectTriggerControl(
2625
target = (event.composedPath()[0] || target) as HTMLElement;
2726
}
2827

29-
if ((event as any)._ori_target) {
30-
target = (event as any)._ori_target;
31-
}
32-
3328
if (
3429
open &&
3530
// Marked by SelectInput mouseDown event
31+
!(event as any)._ignore_global_close &&
3632
!isInside(elements(), target)
3733
) {
3834
// Should trigger close

tests/Select.test.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ describe('Select.Basic', () => {
561561
</Select>,
562562
);
563563

564-
keyDown(container.querySelector('input'), KeyCode.DOWN);
564+
keyDown(container.querySelector('input'), 40);
565565
expectOpen(container);
566566
});
567567

@@ -2524,9 +2524,9 @@ describe('Select.Basic', () => {
25242524
await waitFakeTimer();
25252525
expectOpen(container, true);
25262526

2527-
keyDown(inputElem!, KeyCode.DOWN);
2528-
keyUp(inputElem!, KeyCode.DOWN);
2529-
keyDown(inputElem!, KeyCode.ENTER);
2527+
keyDown(inputElem!, 40);
2528+
keyUp(inputElem!, 40);
2529+
keyDown(inputElem!, 13);
25302530

25312531
await waitFakeTimer();
25322532
expect(onBlur).toHaveBeenCalledTimes(1);
@@ -2537,9 +2537,9 @@ describe('Select.Basic', () => {
25372537
await waitFakeTimer();
25382538
expectOpen(container, true);
25392539

2540-
keyDown(inputElem!, KeyCode.DOWN);
2541-
keyUp(inputElem!, KeyCode.DOWN);
2542-
keyDown(inputElem!, KeyCode.ENTER);
2540+
keyDown(inputElem!, 40);
2541+
keyUp(inputElem!, 40);
2542+
keyDown(inputElem!, 13);
25432543

25442544
await waitFakeTimer();
25452545
expect(onBlur).toHaveBeenCalledTimes(2);

0 commit comments

Comments
 (0)