Skip to content

Commit

Permalink
fix: contextMenu close all (#407)
Browse files Browse the repository at this point in the history
* fix: contextMenu close all

* test: add all closed test cases

* style: delete note

---------

Co-authored-by: jzh <[email protected]>
  • Loading branch information
1587315093 and jzh authored Jun 30, 2023
1 parent 0583fd7 commit 4f90505
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 8 deletions.
152 changes: 151 additions & 1 deletion docs/examples/body-overflow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import '../../assets/index.less';

export default () => {
const [open, setOpen] = React.useState(false);

const [open1, setOpen1] = React.useState(false);
const [open2, setOpen2] = React.useState(false);
const [open3, setOpen3] = React.useState(false);
return (
<React.StrictMode>
<style
Expand Down Expand Up @@ -72,6 +74,154 @@ export default () => {
Target
</span>
</Trigger>

<Trigger
arrow
action="click"
popupVisible={open1}
onPopupVisibleChange={(next) => {
console.log('Visible Change:', next);
setOpen1(next);
}}
popupTransitionName="rc-trigger-popup-zoom"
popup={
<div
style={{
background: 'yellow',
border: '1px solid blue',
width: 200,
height: 60,
opacity: 0.9,
}}
>
<button
onClick={() => {
setOpen1(false);
}}
>
Close
</button>
</div>
}
// popupVisible
popupStyle={{ boxShadow: '0 0 5px red' }}
popupAlign={{
points: ['tc', 'bc'],
overflow: {
shiftX: 50,
adjustY: true,
},
htmlRegion: 'scroll',
}}
>
<span
style={{
background: 'green',
color: '#FFF',
paddingBlock: 30,
paddingInline: 70,
opacity: 0.9,
transform: 'scale(0.6)',
display: 'inline-block',
}}
>
Target Click
</span>
</Trigger>

<Trigger
arrow
action="contextMenu"
popupVisible={open2}
onPopupVisibleChange={(next) => {
console.log('Visible Change:', next);
setOpen2(next);
}}
popupTransitionName="rc-trigger-popup-zoom"
popup={
<div
style={{
background: 'yellow',
border: '1px solid blue',
width: 200,
height: 60,
opacity: 0.9,
}}
>
Target ContextMenu1
</div>
}
popupStyle={{ boxShadow: '0 0 5px red' }}
popupAlign={{
points: ['tc', 'bc'],
overflow: {
shiftX: 50,
adjustY: true,
},
htmlRegion: 'scroll',
}}
>
<span
style={{
background: 'blue',
color: '#FFF',
paddingBlock: 30,
paddingInline: 70,
opacity: 0.9,
transform: 'scale(0.6)',
display: 'inline-block',
}}
>
Target ContextMenu1
</span>
</Trigger>

<Trigger
arrow
action="contextMenu"
popupVisible={open3}
onPopupVisibleChange={(next) => {
console.log('Visible Change:', next);
setOpen3(next);
}}
popupTransitionName="rc-trigger-popup-zoom"
popup={
<div
style={{
background: 'yellow',
border: '1px solid blue',
width: 200,
height: 60,
opacity: 0.9,
}}
>
Target ContextMenu2
</div>
}
popupStyle={{ boxShadow: '0 0 5px red' }}
popupAlign={{
points: ['tc', 'bc'],
overflow: {
shiftX: 50,
adjustY: true,
},
htmlRegion: 'scroll',
}}
>
<span
style={{
background: 'blue',
color: '#FFF',
paddingBlock: 30,
paddingInline: 70,
opacity: 0.9,
transform: 'scale(0.6)',
display: 'inline-block',
}}
>
Target ContextMenu2
</span>
</Trigger>
</React.StrictMode>
);
};
4 changes: 4 additions & 0 deletions src/hooks/useWinClick.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,14 @@ export default function useWinClick(

win.addEventListener('mousedown', onWinMouseDown);
win.addEventListener('click', onWinClick);
win.addEventListener('contextmenu', onWinClick);

// shadow root
const targetShadowRoot = getShadowRoot(targetEle);
if (targetShadowRoot) {
targetShadowRoot.addEventListener('mousedown', onShadowMouseDown);
targetShadowRoot.addEventListener('click', onShadowClick);
targetShadowRoot.addEventListener('contextmenu', onShadowClick);
}

// Warning if target and popup not in same root
Expand All @@ -89,10 +91,12 @@ export default function useWinClick(
return () => {
win.removeEventListener('mousedown', onWinMouseDown);
win.removeEventListener('click', onWinClick);
win.removeEventListener('contextmenu', onWinClick);

if (targetShadowRoot) {
targetShadowRoot.removeEventListener('mousedown', onShadowMouseDown);
targetShadowRoot.removeEventListener('click', onShadowClick);
targetShadowRoot.removeEventListener('contextmenu', onShadowClick);
}
};
}
Expand Down
15 changes: 10 additions & 5 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -553,8 +553,13 @@ export function generateTrigger(
// ==================== Action: ContextMenu =====================
if (showActions.has('contextMenu')) {
cloneProps.onContextMenu = (event: React.MouseEvent, ...args: any[]) => {
setMousePosByEvent(event);
triggerOpen(true);
if (openRef.current && hideActions.has('contextMenu')) {
triggerOpen(false);
} else {
setMousePosByEvent(event);
triggerOpen(true);
}

event.preventDefault();

// Pass to origin
Expand Down Expand Up @@ -608,9 +613,9 @@ export function generateTrigger(

const innerArrow: ArrowTypeOuter = arrow
? {
// true and Object likely
...(arrow !== true ? arrow : {}),
}
// true and Object likely
...(arrow !== true ? arrow : {}),
}
: null;

// Render
Expand Down
50 changes: 48 additions & 2 deletions tests/basic.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,16 @@ describe('Trigger.Basic', () => {
.querySelector('.rc-trigger-popup')
.className.includes('-hidden');
}

function isPopupClassHidden(name) {
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'))
}
describe('getPopupContainer', () => {
it('defaults to document.body', () => {
const { container } = render(
Expand Down Expand Up @@ -160,7 +169,44 @@ describe('Trigger.Basic', () => {

expect(isPopupHidden()).toBeTruthy();
});
it('contextMenu all close ', () => {
const triggerRef1 = createRef();
const triggerRef2 = createRef();
const { container } = render(
<>
<Trigger
ref={triggerRef1}
popupClassName='trigger-popup1'
action={['contextMenu']}
popupAlign={placementAlignMap.left}
popup={<strong>trigger1</strong>}
>
<div className="target1">contextMenu 1</div>
</Trigger>
<Trigger
ref={triggerRef2}
action={['contextMenu']}
popupClassName='trigger-popup2'
popupAlign={placementAlignMap.right}
popup={<strong>trigger2</strong>}
>
<div className="target2">contextMenu 2</div>
</Trigger>
</>,
);

trigger(container, '.target1', 'contextMenu');
trigger(container, '.target2', 'contextMenu');
expect(isPopupClassHidden('.trigger-popup1')).toBeTruthy();
expect(isPopupClassHidden('.trigger-popup2')).toBeFalsy();

trigger(container, '.target1', 'contextMenu');
expect(isPopupClassHidden('.trigger-popup1')).toBeFalsy();
expect(isPopupClassHidden('.trigger-popup2')).toBeTruthy();

fireEvent.click(document.body);
expect(isPopupAllHidden()).toBeTruthy();
});
describe('afterPopupVisibleChange can be triggered', () => {
it('uncontrolled', async () => {
let triggered = 0;
Expand Down Expand Up @@ -836,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 = () => <p />;

render(
Expand Down

0 comments on commit 4f90505

Please sign in to comment.