Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: disable context menu (fix #1432) #1515

Merged
merged 6 commits into from
Nov 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions packages/toast-ui.grid/cypress/integration/contextMenu.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,18 @@ describe('context menu', () => {
cy.getByCls('cell-dummy').first().rightclick();
cy.getByCls('context-menu').should('be.not.visible');
});

it('should disable the context menu by passing opions to null', () => {
const data = [
{ name: 'Lee', age: 20 },
{ name: 'Han', age: 28 },
{ name: 'Ryu', age: 22 },
];
const columns = [{ name: 'name' }, { name: 'age' }];

cy.createGrid({ data, columns, contextMenu: null });

showContextMenu(0, 'name');
cy.getByCls('context-menu').should('be.not.visible');
});
});
5 changes: 4 additions & 1 deletion packages/toast-ui.grid/docs/ko/contextMenu.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
TOAST UI Grid는 `v4.18.0` 버전부터 컨텍스트 메뉴 기능을 제공한다. 셀에서 마우스 우측 버튼을 누르면 컨텍스트 메뉴가 나오며, `contextMenu` 옵션으로 원하는 컨텍스트 메뉴를 설정할 수 있다.

### 옵션
`contextMenu` 옵션은 반드시 함수가 되어야 하며, 함수의 반환값은 아래와 같은 2차원 배열이어야 한다.
`contextMenu` 옵션은 함수나 `null`이 되어야 하며, 함수의 반환값은 아래와 같은 2차원 배열이어야 한다.

```js
const grid = Grid({
Expand Down Expand Up @@ -51,6 +51,9 @@ const grid = Grid({

![image](https://user-images.githubusercontent.com/37766175/123938532-2a3e0800-d9d2-11eb-9ded-ec4562cb026e.png)

`contextMenu` 옵션이 `null`이면 컨텍스트 메뉴는 비활성화 되며 브라우저의 기본 컨텍스트 메뉴가 활성화 된다.

![image](https://user-images.githubusercontent.com/41339744/142086149-bb853f02-08e0-41cf-9a46-5dc48c85db20.gif)

#### 동적 컨텍스트 메뉴
`contextMenu` 옵션으로 설정한 함수는 `rowKey`, `columnName`로 구성된 객체를 인자로 받는다. 이 객체는 컨텍스트 메뉴를 띄운 셀의 `rowKey`, `columnName`을 의미하며, 아래처럼 동적으로 메뉴 구성을 변경하고 싶은 경우 사용한다.
Expand Down
7 changes: 7 additions & 0 deletions packages/toast-ui.grid/src/helper/mouse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export function emitMouseup(el: HTMLElement) {
const mouseupEvent = new MouseEvent('mouseup', {
bubbles: true,
cancelable: true,
});
el.dispatchEvent(mouseupEvent);
}
9 changes: 6 additions & 3 deletions packages/toast-ui.grid/src/store/contextMenu.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ContextMenu, MenuItem, CreateMenuGroups } from '@t/store/contextMenu';
import { isNull } from '../helper/common';
import { observable } from '../helper/observable';
import i18n from '../i18n';

Expand Down Expand Up @@ -47,17 +48,19 @@ interface ContextMenuOptions {
export function create({ createMenuGroups }: ContextMenuOptions) {
return observable<ContextMenu>({
posInfo: null,
createMenuGroups: createMenuGroups || createDefaultContextMenu,
createMenuGroups: isNull(createMenuGroups)
? null
: createMenuGroups || createDefaultContextMenu,

get flattenTopMenuItems() {
if (!this.posInfo) {
return [];
}

const { rowKey, columnName } = this.posInfo;
const menuGroups = this.createMenuGroups({ rowKey, columnName });
const menuGroups = this.createMenuGroups?.({ rowKey, columnName });

return menuGroups.reduce((acc: MenuItem[], group: MenuItem[], groupIndex: number) => {
return menuGroups?.reduce((acc: MenuItem[], group: MenuItem[], groupIndex: number) => {
const menuItems: MenuItem[] = [];
group.forEach((menuItem, itemIndex) => {
menuItems.push(menuItem);
Expand Down
7 changes: 6 additions & 1 deletion packages/toast-ui.grid/src/view/container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import GridEvent from '../event/gridEvent';
import { isMobile } from '../helper/browser';
import { isNull } from '../helper/common';
import { keyNameMap, KeyNameMap } from '../helper/keyboard';
import { emitMouseup } from '../helper/mouse';

interface OwnProps {
rootElement: HTMLElement;
Expand Down Expand Up @@ -336,7 +337,11 @@ export class ContainerComp extends Component<Props> {
}

handleContextMenu = (ev: MouseEvent) => {
if (isParentExistWithClassNames(ev.target as HTMLElement, ['cell-header', 'cell-dummy'])) {
if (
isParentExistWithClassNames(ev.target as HTMLElement, ['cell-header', 'cell-dummy']) ||
!this.context.store.contextMenu.createMenuGroups
) {
emitMouseup(this.el!);
return;
}

Expand Down
8 changes: 4 additions & 4 deletions packages/toast-ui.grid/src/view/contextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { MenuItem, MenuPos } from '@t/store/contextMenu';
import { ContextMenuItem } from './contextMenuItem';

interface StoreProps {
menuItems: MenuItem[];
menuItems: MenuItem[] | null;
pos: MenuPos | null;
}

Expand All @@ -21,7 +21,7 @@ export class ContextMenuComp extends Component<Props> {
if (pos) {
return (
<ul class={cls('context-menu')} style={pos}>
{menuItems.map((menuItem) => (
{menuItems!.map((menuItem) => (
<ContextMenuItem key={menuItem.name} menuItem={menuItem} />
))}
</ul>
Expand All @@ -32,6 +32,6 @@ export class ContextMenuComp extends Component<Props> {
}

export const ContextMenu = connect<StoreProps, OwnProps>(({ contextMenu }, { menuItems, pos }) => ({
pos: pos || (contextMenu.posInfo?.pos ?? null),
menuItems: menuItems || contextMenu.flattenTopMenuItems,
pos: pos || (contextMenu?.posInfo?.pos ?? null),
menuItems: menuItems || contextMenu?.flattenTopMenuItems,
}))(ContextMenuComp);
6 changes: 4 additions & 2 deletions packages/toast-ui.grid/types/store/contextMenu.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ export interface MenuPosInfo {
columnName: string;
}

export type CreateMenuGroups = (params: { rowKey: RowKey; columnName: string }) => MenuItem[][];
export type CreateMenuGroups =
| ((params: { rowKey: RowKey; columnName: string }) => MenuItem[][])
| null;

export interface ContextMenu {
posInfo: MenuPosInfo | null;
createMenuGroups: CreateMenuGroups;
flattenTopMenuItems: MenuItem[];
flattenTopMenuItems: MenuItem[] | null;
}