Skip to content

Commit

Permalink
fix: fix issue about contextmenu (#5913)
Browse files Browse the repository at this point in the history
* fix: fix issue about contextmenu

* test: update test case
  • Loading branch information
Aarebecca authored Jun 21, 2024
1 parent ee335ed commit 8956d98
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 22 deletions.
3 changes: 3 additions & 0 deletions packages/g6/__tests__/demos/plugin-contextmenu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ export const pluginContextmenu: TestCase = async (context) => {
autoResize: true,
data,
layout: { type: 'd3-force' },
behaviors: ['drag-canvas'],
plugins: [
{
key: 'contextmenu',
type: 'contextmenu',
trigger: 'contextmenu',
className: 'custom-class-name',
getItems: () => {
return [
{ name: '展开一度关系', value: 'spread' },
Expand Down
45 changes: 39 additions & 6 deletions packages/g6/__tests__/unit/plugins/contextmenu.spec.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,53 @@
import { pluginContextmenu } from '@/__tests__/demos';
import { createDemoGraph } from '@@/utils';
import type { Contextmenu } from '@/src';
import { NodeEvent } from '@/src';
import { createDemoGraph, sleep } from '@@/utils';

describe('plugin contextmenu', () => {
it('contextmenu', async () => {
const graph = await createDemoGraph(pluginContextmenu);
const onClick = jest.fn();
graph.updatePlugin({ key: 'contextmenu', onClick });

const container = graph.getCanvas().getContainer()!;

const el = container.querySelector('.g6-contextmenu') as HTMLDivElement;

expect(graph.getPlugins().length).toBe(1);
// @ts-expect-error ignore
expect(graph.getPlugins()[0].trigger).toBe('contextmenu');
const $dom = container.querySelector('.g6-contextmenu');
expect($dom).toBeTruthy();
expect($dom?.classList.contains('custom-class-name')).toBeTruthy();

expect(el.querySelector('.g6-contextmenu-li')).toBeFalsy();

await graph.destroy();
expect(container.querySelector('.g6-contextmenu')).toBeFalsy();
const emit = () => {
graph.emit(NodeEvent.CONTEXT_MENU, {
target: { id: '1' },
targetType: 'node',
client: {
x: 100,
y: 100,
},
});
};

emit();

await sleep(100);
expect(el.querySelector('.g6-contextmenu-ul')).toBeTruthy();
expect(el.querySelectorAll('.g6-contextmenu-li').length).toBe(2);

const instance = graph.getPluginInstance<Contextmenu>('contextmenu');

// @ts-expect-error private method
instance.onMenuItemClick({ target: el.querySelector('.g6-contextmenu-li') });
expect(onClick).toHaveBeenCalledTimes(1);
expect(container.querySelector<HTMLDivElement>('.g6-contextmenu')!.style.display).toBe('none');

emit();

await sleep(100);
expect(container.querySelector<HTMLDivElement>('.g6-contextmenu')!.style.display).toBe('block');
document.body.click();
expect(container.querySelector<HTMLDivElement>('.g6-contextmenu')!.style.display).toBe('none');
});
});
32 changes: 16 additions & 16 deletions packages/g6/src/plugins/contextmenu/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import { CONTEXTMENU_CSS, getContentFromItems } from './util';
*/
export interface ContextmenuOptions extends BasePluginOptions {
/**
* <zh/> 给菜单的 DOM 追加的 classname,便于自定义样式。默认是包含 `g6-contextmenu`
* <zh/> 给菜单的 DOM 追加的类名
*
* <en/> The classname appended to the menu DOM for custom styles. The default is `g6-contextmenu`
* <en/> The class name appended to the menu DOM for custom styles
* @defaultValue 'g6-contextmenu'
*/
className?: string;
Expand All @@ -42,7 +42,7 @@ export interface ContextmenuOptions extends BasePluginOptions {
*
* <en/> The callback method triggered when the menu is clicked
*/
onClick?: (v: string, target: HTMLElement) => void;
onClick?: (value: string, target: HTMLElement) => void;
/**
* <zh/> 返回菜单的项目列表,支持 `Promise` 类型的返回值。是 `getContent` 的快捷配置
*
Expand Down Expand Up @@ -88,18 +88,24 @@ export class Contextmenu extends BasePlugin<ContextmenuOptions> {
enable: () => true,
};

private $element: HTMLElement = createPluginContainer('contextmenu', false);
private $element!: HTMLElement;

constructor(context: RuntimeContext, options: ContextmenuOptions) {
super(context, Object.assign({}, Contextmenu.defaultOptions, options));

this.initElement();
this.update(options);
}

private initElement() {
this.$element = createPluginContainer('contextmenu', false);
const { className } = this.options;
if (className) this.$element.classList.add(className);

const $container = this.context.canvas.getContainer();
$container!.appendChild(this.$element);

// 设置样式
insertDOM('g6-contextmenu-css', 'style', {}, CONTEXTMENU_CSS, document.head);

this.update(options);
}

/**
Expand Down Expand Up @@ -210,16 +216,10 @@ export class Contextmenu extends BasePlugin<ContextmenuOptions> {
const { onClick } = this.options;
if (event.target instanceof HTMLElement) {
if (event.target.className.includes('g6-contextmenu-li')) {
const v = event.target.getAttribute('value') as string;
onClick && onClick(v, event.target);

this.hide();
}

// 点击其他地方,隐藏菜单
if (!this.context.graph.getCanvas().getContainer()!.contains(event.target)) {
this.hide();
const value = event.target.getAttribute('value') as string;
onClick?.(value, event.target);
}
}
this.hide();
};
}

0 comments on commit 8956d98

Please sign in to comment.