Skip to content

Commit 3e5d55e

Browse files
authored
enhance: not reopen when closed (#411)
1 parent 60583ce commit 3e5d55e

File tree

3 files changed

+71
-19
lines changed

3 files changed

+71
-19
lines changed

docs/examples/body-overflow.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,26 @@
11
/* eslint no-console:0 */
22
import Trigger from 'rc-trigger';
33
import React from 'react';
4+
import { createPortal } from 'react-dom';
45
import '../../assets/index.less';
56

7+
const PortalDemo = () => {
8+
return createPortal(
9+
<div
10+
style={{
11+
position: 'fixed',
12+
top: 0,
13+
right: 0,
14+
background: 'red',
15+
zIndex: 999,
16+
}}
17+
>
18+
PortalNode
19+
</div>,
20+
document.body,
21+
);
22+
};
23+
624
export default () => {
725
const [open, setOpen] = React.useState(false);
826
const [open1, setOpen1] = React.useState(false);
@@ -47,6 +65,8 @@ export default () => {
4765
>
4866
Close
4967
</button>
68+
69+
<PortalDemo />
5070
</div>
5171
}
5272
// popupVisible

src/index.tsx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -337,11 +337,14 @@ export function generateTrigger(
337337
// ========================== Motion ============================
338338
const [inMotion, setInMotion] = React.useState(false);
339339

340-
useLayoutEffect((firstMount) => {
341-
if (!firstMount || mergedOpen) {
342-
setInMotion(true);
343-
}
344-
}, [mergedOpen]);
340+
useLayoutEffect(
341+
(firstMount) => {
342+
if (!firstMount || mergedOpen) {
343+
setInMotion(true);
344+
}
345+
},
346+
[mergedOpen],
347+
);
345348

346349
const [motionPrepareResolve, setMotionPrepareResolve] =
347350
React.useState<VoidFunction>(null);
@@ -522,7 +525,10 @@ export function generateTrigger(
522525
setMousePosByEvent(event);
523526
});
524527
onPopupMouseEnter = () => {
525-
triggerOpen(true, mouseEnterDelay);
528+
// Only trigger re-open when popup is visible
529+
if (mergedOpen || inMotion) {
530+
triggerOpen(true, mouseEnterDelay);
531+
}
526532
};
527533

528534
// Align Point
@@ -613,9 +619,9 @@ export function generateTrigger(
613619

614620
const innerArrow: ArrowTypeOuter = arrow
615621
? {
616-
// true and Object likely
617-
...(arrow !== true ? arrow : {}),
618-
}
622+
// true and Object likely
623+
...(arrow !== true ? arrow : {}),
624+
}
619625
: null;
620626

621627
// Render

tests/basic.test.jsx

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ describe('Trigger.Basic', () => {
3636
.className.includes('-hidden');
3737
}
3838
function isPopupClassHidden(name) {
39-
return document
40-
.querySelector(name).className.includes('-hidden')
39+
return document.querySelector(name).className.includes('-hidden');
4140
}
4241
function isPopupAllHidden() {
43-
const popupArr = document
44-
.querySelectorAll('.rc-trigger-popup')
45-
46-
return Array.from(popupArr).every(item => item.className.includes('-hidden'))
42+
const popupArr = document.querySelectorAll('.rc-trigger-popup');
43+
44+
return Array.from(popupArr).every((item) =>
45+
item.className.includes('-hidden'),
46+
);
4747
}
4848
describe('getPopupContainer', () => {
4949
it('defaults to document.body', () => {
@@ -176,7 +176,7 @@ describe('Trigger.Basic', () => {
176176
<>
177177
<Trigger
178178
ref={triggerRef1}
179-
popupClassName='trigger-popup1'
179+
popupClassName="trigger-popup1"
180180
action={['contextMenu']}
181181
popupAlign={placementAlignMap.left}
182182
popup={<strong>trigger1</strong>}
@@ -186,15 +186,15 @@ describe('Trigger.Basic', () => {
186186
<Trigger
187187
ref={triggerRef2}
188188
action={['contextMenu']}
189-
popupClassName='trigger-popup2'
189+
popupClassName="trigger-popup2"
190190
popupAlign={placementAlignMap.right}
191191
popup={<strong>trigger2</strong>}
192192
>
193193
<div className="target2">contextMenu 2</div>
194194
</Trigger>
195195
</>,
196196
);
197-
197+
198198
trigger(container, '.target1', 'contextMenu');
199199
trigger(container, '.target2', 'contextMenu');
200200
expect(isPopupClassHidden('.trigger-popup1')).toBeTruthy();
@@ -882,7 +882,7 @@ describe('Trigger.Basic', () => {
882882
});
883883

884884
it('find real dom node if children not support `forwardRef`', () => {
885-
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => { });
885+
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
886886
const Node = () => <p />;
887887

888888
render(
@@ -1066,4 +1066,30 @@ describe('Trigger.Basic', () => {
10661066
expect(document.querySelector('.rc-trigger-popup-hidden')).toBeFalsy();
10671067
});
10681068
});
1069+
1070+
it('not trigger open when hover hidden popup node', () => {
1071+
const onPopupVisibleChange = jest.fn();
1072+
1073+
const { container } = render(
1074+
<Trigger
1075+
onPopupVisibleChange={onPopupVisibleChange}
1076+
action="hover"
1077+
popup={<strong className="popup">trigger</strong>}
1078+
getPopupContainer={() => container}
1079+
>
1080+
<div className="target" />
1081+
</Trigger>,
1082+
);
1083+
1084+
trigger(container, '.target', 'mouseEnter');
1085+
expect(onPopupVisibleChange).toHaveBeenCalledWith(true);
1086+
onPopupVisibleChange.mockReset();
1087+
1088+
trigger(container, '.target', 'mouseLeave');
1089+
expect(onPopupVisibleChange).toHaveBeenCalledWith(false);
1090+
onPopupVisibleChange.mockReset();
1091+
1092+
trigger(container, '.popup', 'mouseEnter');
1093+
expect(onPopupVisibleChange).not.toHaveBeenCalled();
1094+
});
10691095
});

0 commit comments

Comments
 (0)