From 3e5d55e15a0dfcd22a4bce1f336ee3659f916078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E7=88=B1=E5=90=83=E7=99=BD=E8=90=9D?= =?UTF-8?q?=E5=8D=9C?= Date: Mon, 17 Jul 2023 15:59:16 +0800 Subject: [PATCH] enhance: not reopen when closed (#411) --- docs/examples/body-overflow.tsx | 20 ++++++++++++++ src/index.tsx | 24 ++++++++++------- tests/basic.test.jsx | 46 ++++++++++++++++++++++++++------- 3 files changed, 71 insertions(+), 19 deletions(-) diff --git a/docs/examples/body-overflow.tsx b/docs/examples/body-overflow.tsx index 58997c7f..b6ab5182 100644 --- a/docs/examples/body-overflow.tsx +++ b/docs/examples/body-overflow.tsx @@ -1,8 +1,26 @@ /* eslint no-console:0 */ import Trigger from 'rc-trigger'; import React from 'react'; +import { createPortal } from 'react-dom'; import '../../assets/index.less'; +const PortalDemo = () => { + return createPortal( +
+ PortalNode +
, + document.body, + ); +}; + export default () => { const [open, setOpen] = React.useState(false); const [open1, setOpen1] = React.useState(false); @@ -47,6 +65,8 @@ export default () => { > Close + + } // popupVisible diff --git a/src/index.tsx b/src/index.tsx index 074ad58b..4ee07ed4 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -337,11 +337,14 @@ export function generateTrigger( // ========================== Motion ============================ const [inMotion, setInMotion] = React.useState(false); - useLayoutEffect((firstMount) => { - if (!firstMount || mergedOpen) { - setInMotion(true); - } - }, [mergedOpen]); + useLayoutEffect( + (firstMount) => { + if (!firstMount || mergedOpen) { + setInMotion(true); + } + }, + [mergedOpen], + ); const [motionPrepareResolve, setMotionPrepareResolve] = React.useState(null); @@ -522,7 +525,10 @@ export function generateTrigger( setMousePosByEvent(event); }); onPopupMouseEnter = () => { - triggerOpen(true, mouseEnterDelay); + // Only trigger re-open when popup is visible + if (mergedOpen || inMotion) { + triggerOpen(true, mouseEnterDelay); + } }; // Align Point @@ -613,9 +619,9 @@ export function generateTrigger( const innerArrow: ArrowTypeOuter = arrow ? { - // true and Object likely - ...(arrow !== true ? arrow : {}), - } + // true and Object likely + ...(arrow !== true ? arrow : {}), + } : null; // Render diff --git a/tests/basic.test.jsx b/tests/basic.test.jsx index 254cb58b..19b59850 100644 --- a/tests/basic.test.jsx +++ b/tests/basic.test.jsx @@ -36,14 +36,14 @@ describe('Trigger.Basic', () => { .className.includes('-hidden'); } function isPopupClassHidden(name) { - return document - .querySelector(name).className.includes('-hidden') + return document.querySelector(name).className.includes('-hidden'); } function isPopupAllHidden() { - const popupArr = document - .querySelectorAll('.rc-trigger-popup') - - return Array.from(popupArr).every(item => item.className.includes('-hidden')) + const popupArr = document.querySelectorAll('.rc-trigger-popup'); + + return Array.from(popupArr).every((item) => + item.className.includes('-hidden'), + ); } describe('getPopupContainer', () => { it('defaults to document.body', () => { @@ -176,7 +176,7 @@ describe('Trigger.Basic', () => { <> trigger1} @@ -186,7 +186,7 @@ describe('Trigger.Basic', () => { trigger2} > @@ -194,7 +194,7 @@ describe('Trigger.Basic', () => { , ); - + trigger(container, '.target1', 'contextMenu'); trigger(container, '.target2', 'contextMenu'); expect(isPopupClassHidden('.trigger-popup1')).toBeTruthy(); @@ -882,7 +882,7 @@ describe('Trigger.Basic', () => { }); it('find real dom node if children not support `forwardRef`', () => { - const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => { }); + const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); const Node = () =>

; render( @@ -1066,4 +1066,30 @@ describe('Trigger.Basic', () => { expect(document.querySelector('.rc-trigger-popup-hidden')).toBeFalsy(); }); }); + + it('not trigger open when hover hidden popup node', () => { + const onPopupVisibleChange = jest.fn(); + + const { container } = render( + trigger} + getPopupContainer={() => container} + > +

+ , + ); + + trigger(container, '.target', 'mouseEnter'); + expect(onPopupVisibleChange).toHaveBeenCalledWith(true); + onPopupVisibleChange.mockReset(); + + trigger(container, '.target', 'mouseLeave'); + expect(onPopupVisibleChange).toHaveBeenCalledWith(false); + onPopupVisibleChange.mockReset(); + + trigger(container, '.popup', 'mouseEnter'); + expect(onPopupVisibleChange).not.toHaveBeenCalled(); + }); });