Skip to content

Commit

Permalink
fix: Use pointerDown to check if click with portal (#493)
Browse files Browse the repository at this point in the history
* fix: use pointer to handle mouseDown

* test: add test case
  • Loading branch information
zombieJ authored Nov 8, 2024
1 parent d8bfea2 commit a412327
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 14 deletions.
6 changes: 3 additions & 3 deletions src/Popup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export interface PopupProps {
onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;
onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;
onPointerEnter?: React.MouseEventHandler<HTMLDivElement>;
onMouseDownCapture?: React.MouseEventHandler<HTMLDivElement>;
onPointerDownCapture?: React.MouseEventHandler<HTMLDivElement>;
zIndex?: number;

mask?: boolean;
Expand Down Expand Up @@ -106,7 +106,7 @@ const Popup = React.forwardRef<HTMLDivElement, PopupProps>((props, ref) => {
onMouseEnter,
onMouseLeave,
onPointerEnter,
onMouseDownCapture,
onPointerDownCapture,

ready,
offsetX,
Expand Down Expand Up @@ -257,7 +257,7 @@ const Popup = React.forwardRef<HTMLDivElement, PopupProps>((props, ref) => {
onMouseLeave={onMouseLeave}
onPointerEnter={onPointerEnter}
onClick={onClick}
onMouseDownCapture={onMouseDownCapture}
onPointerDownCapture={onPointerDownCapture}
>
{arrow && (
<Arrow
Expand Down
17 changes: 16 additions & 1 deletion src/hooks/useWinClick.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,28 @@ export default function useWinClick(
const openRef = React.useRef(open);
openRef.current = open;

const popupPointerDownRef = React.useRef(false);

// Click to hide is special action since click popup element should not hide
React.useEffect(() => {
if (clickToHide && popupEle && (!mask || maskClosable)) {
const onPointerDown = () => {
popupPointerDownRef.current = false;
};

const onTriggerClose = (e: MouseEvent) => {
if (
openRef.current &&
!inPopupOrChild(e.composedPath?.()?.[0] || e.target)
!inPopupOrChild(e.composedPath?.()?.[0] || e.target) &&
!popupPointerDownRef.current
) {
triggerOpen(false);
}
};

const win = getWin(popupEle);

win.addEventListener('pointerdown', onPointerDown, true);
win.addEventListener('mousedown', onTriggerClose, true);
win.addEventListener('contextmenu', onTriggerClose, true);

Expand All @@ -52,6 +60,7 @@ export default function useWinClick(
}

return () => {
win.removeEventListener('pointerdown', onPointerDown, true);
win.removeEventListener('mousedown', onTriggerClose, true);
win.removeEventListener('contextmenu', onTriggerClose, true);

Expand All @@ -70,4 +79,10 @@ export default function useWinClick(
};
}
}, [clickToHide, targetEle, popupEle, mask, maskClosable]);

function onPopupPointerDown() {
popupPointerDownRef.current = true;
}

return onPopupPointerDown;
}
11 changes: 2 additions & 9 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ export function generateTrigger(
}

// Click to hide is special action since click popup element should not hide
useWinClick(
const onPopupPointerDown = useWinClick(
mergedOpen,
clickToHide,
targetEle,
Expand Down Expand Up @@ -722,14 +722,7 @@ export function generateTrigger(
fresh={fresh}
// Click
onClick={onPopupClick}
onMouseDownCapture={() => {
// Additional check for click to hide
// Since `createPortal` will not included in the popup element
// So we use capture to handle this
if (clickToHide) {
triggerOpen(true);
}
}}
onPointerDownCapture={onPopupPointerDown}
// Mask
mask={mask}
// Motion
Expand Down
4 changes: 3 additions & 1 deletion tests/basic.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -1220,11 +1220,13 @@ describe('Trigger.Basic', () => {
expect(isPopupHidden()).toBeFalsy();

// Click portal should not close
fireEvent.click(document.querySelector('.portal'));
fireEvent.pointerDown(document.querySelector('.portal'));
fireEvent.mouseDown(document.querySelector('.portal'));
await awaitFakeTimer();
expect(isPopupHidden()).toBeFalsy();

// Click outside to close
fireEvent.pointerDown(document.querySelector('.outer'));
fireEvent.mouseDown(container.querySelector('.outer'));
await awaitFakeTimer();
expect(isPopupHidden()).toBeTruthy();
Expand Down

0 comments on commit a412327

Please sign in to comment.