Skip to content

Commit 7ad58ab

Browse files
authored
fix: improve global contextMenu in activity bar (#200)
* fix: improve global contextMenu in activity bar * fix: fix ci problem * fix: remove useless code
1 parent 1e8b03c commit 7ad58ab

File tree

5 files changed

+52
-52
lines changed

5 files changed

+52
-52
lines changed

src/common/dom.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
export type HTMLElementType = HTMLElement | null;
22
export type TriggerEvent = 'click' | 'contextmenu' | 'hover';
3-
export type PlacementType = 'top' | 'right' | 'bottom' | 'left';
3+
/**
4+
* specify `rightBottom` means align to the bottom and keep in right
5+
*/
6+
export type PlacementType = 'top' | 'right' | 'bottom' | 'left' | 'rightBottom';
47
export const select = document.querySelector.bind(document);
58
export const selectAll = document.querySelectorAll.bind(document);
69

@@ -122,8 +125,10 @@ export function getPositionByPlacement(
122125
y = domRect.y + domRect.height;
123126
} else if (placement === 'left') {
124127
x = domRect.x - domRect.width;
128+
} else if (placement === 'rightBottom') {
129+
x = domRect.x + domRect.width;
130+
y = domRect.y + domRect.height;
125131
}
126-
console.log('getPositionByPlacement', x, y);
127132
return { x, y };
128133
}
129134

src/components/dropdown/index.tsx

+6-3
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@ export interface IDropDownProps extends React.ComponentProps<'div'> {
1212
overlay: ReactNode;
1313
trigger?: TriggerEvent;
1414
placement?: PlacementType;
15-
ref?: React.RefObject<any>;
1615
}
1716

17+
export type DropDownRef = {
18+
dispose: () => void;
19+
};
20+
1821
const defaultDropDownClassName = prefixClaName('drop-down');
1922

20-
export const DropDown = React.forwardRef(
21-
(props: React.PropsWithChildren<IDropDownProps>, ref) => {
23+
export const DropDown = React.forwardRef<DropDownRef, IDropDownProps>(
24+
(props, ref) => {
2225
const {
2326
className,
2427
overlay,

src/workbench/activityBar/activityBarItem.tsx

+35-43
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import * as React from 'react';
2-
import { useCallback, useEffect, useRef } from 'react';
2+
import { useRef } from 'react';
33
import { classNames } from 'mo/common/className';
44
import { IActivityBarItem } from 'mo/model/workbench/activityBar';
5-
import { useContextMenu } from 'mo/components/contextMenu';
65
import { IMenuItemProps, Menu } from 'mo/components/menu';
76
import { IActivityBarController } from 'mo/controller/activityBar';
87

@@ -13,6 +12,8 @@ import {
1312
itemCheckedClassName,
1413
itemDisabledClassName,
1514
} from './base';
15+
import { DropDown } from 'mo/components';
16+
import { DropDownRef } from 'mo/components/dropdown';
1617

1718
export function ActivityBarItem(
1819
props: IActivityBarItem & IActivityBarController
@@ -30,53 +31,38 @@ export function ActivityBarItem(
3031
className,
3132
onContextMenuClick,
3233
} = props;
33-
let content: React.ReactNode = '';
34-
if (render) {
35-
content = render();
36-
}
3734

38-
let contextViewMenu;
39-
const currentElem = useRef<HTMLLIElement>(null);
35+
const contextMenuRef = useRef<DropDownRef>(null);
4036

41-
const onClickMenuItem = useCallback(
42-
(e: React.MouseEvent, item: IMenuItemProps | undefined) => {
43-
onContextMenuClick?.(e, item);
44-
contextViewMenu?.dispose();
45-
},
46-
[contextMenu]
47-
);
48-
const renderContextMenu = () => (
49-
<Menu onClick={onClickMenuItem} data={contextMenu} />
50-
);
51-
52-
useEffect(() => {
53-
if (contextMenu.length > 0) {
54-
contextViewMenu = useContextMenu({
55-
anchor: currentElem.current,
56-
render: renderContextMenu,
57-
});
58-
}
59-
return function cleanup() {
60-
contextViewMenu?.dispose();
61-
};
62-
});
37+
const onClickMenuItem = (
38+
e: React.MouseEvent,
39+
item: IMenuItemProps | undefined
40+
) => {
41+
onContextMenuClick?.(e, item);
42+
contextMenuRef.current?.dispose();
43+
};
6344

6445
const onClickItem = function (event) {
6546
if (onClick) {
6647
onClick(props.id, props);
6748
}
68-
if (contextMenu.length > 0 && contextViewMenu) {
69-
contextViewMenu.show({
70-
x: event.clientX,
71-
y: event.clientY,
72-
});
73-
}
7449
};
7550

51+
const content = (
52+
<a
53+
title={title}
54+
className={classNames(labelClassName, 'codicon', iconName)}
55+
>
56+
{render?.() || null}
57+
</a>
58+
);
59+
const overlay = <Menu onClick={onClickMenuItem} data={contextMenu} />;
60+
61+
const hasContextMenu = contextMenu.length > 0;
62+
7663
return (
7764
<li
7865
id={id}
79-
ref={currentElem}
8066
onClick={onClickItem}
8167
className={classNames(
8268
className,
@@ -86,12 +72,18 @@ export function ActivityBarItem(
8672
)}
8773
data-id={data.id}
8874
>
89-
<a
90-
title={title}
91-
className={classNames(labelClassName, 'codicon', iconName)}
92-
>
93-
{content}
94-
</a>
75+
{hasContextMenu ? (
76+
<DropDown
77+
ref={contextMenuRef}
78+
trigger="click"
79+
placement="rightBottom"
80+
overlay={overlay}
81+
>
82+
{content}
83+
</DropDown>
84+
) : (
85+
content
86+
)}
9587
{checked ? <div className={indicatorClassName}></div> : null}
9688
</li>
9789
);

src/workbench/editor/action.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as React from 'react';
22
import { memo, useCallback } from 'react';
33
import { Icon } from 'mo/components/icon';
44
import { Menu } from 'mo/components/menu';
5-
import { DropDown } from 'mo/components/dropdown';
5+
import { DropDown, DropDownRef } from 'mo/components/dropdown';
66
import { IEditorAction } from 'mo/model';
77
import { groupActionsClassName, groupActionsItemClassName } from './base';
88
import { IEditorController } from 'mo/controller/editor';
@@ -19,7 +19,7 @@ function EditorAction(props: IEditorActionProps & IEditorController) {
1919
onSplitEditorRight,
2020
} = props;
2121

22-
const childRef = React.useRef();
22+
const childRef = React.useRef<DropDownRef>(null);
2323

2424
const handleOnMenuClick = (e: React.MouseEvent, item) => {
2525
onClickContextMenu?.(e, item);

src/workbench/menuBar/menuBar.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ import { IMenuBar } from 'mo/model/workbench/menuBar';
44
import { IMenuBarController } from 'mo/controller/menuBar';
55

66
import { Menu } from 'mo/components/menu';
7-
import { DropDown } from 'mo/components/dropdown';
7+
import { DropDown, DropDownRef } from 'mo/components/dropdown';
88
import { Icon } from 'mo/components/icon';
99

1010
const defaultClassName = prefixClaName('menuBar');
1111
const actionClassName = getBEMElement(defaultClassName, 'action');
1212

1313
export function MenuBar(props: IMenuBar & IMenuBarController) {
1414
const { data, onClick } = props;
15-
const childRef = React.useRef();
15+
const childRef = React.useRef<DropDownRef>(null);
1616
const handleClick = (e: React.MouseEvent, item) => {
1717
onClick?.(e, item);
1818
(childRef.current as any)!.dispose();

0 commit comments

Comments
 (0)