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(context-menu): update context-menu docs, details, styles #2831

Merged
merged 1 commit into from
Jan 11, 2024
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
62 changes: 62 additions & 0 deletions docs/docs/api/commonUI.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,70 @@ CommonUI API 是一个专为低代码引擎设计的组件 UI 库,使用它开
| condition | 显示条件函数<br/>Function to determine display condition | (nodes: IPublicModelNode[]) => boolean (optional) | |
| disabled | 禁用条件函数,可选<br/>Function to determine disabled condition, optional | (nodes: IPublicModelNode[]) => boolean (optional) | |

**ContextMenu 示例**

```typescript
const App = () => {
const menuItems: IPublicTypeContextMenuAction[] = [
{
name: 'a',
title: '选项 1',
action: () => console.log('选项 1 被点击'),
},
{
name: 'b',
title: '选项 2',
action: () => console.log('选项 2 被点击'),
},
];

const ContextMenu = ctx.commonUI.ContextMenu;

return (
<div>
<ContextMenu menus={menuItems}>
<div>右键点击这里</div>
</ContextMenu>
</div>
);
};

export default App;
```

**ContextMenu.create 示例**

```typescript
const App = () => {
const menuItems: IPublicTypeContextMenuAction[] = [
{
name: 'a',
title: '选项 1',
action: () => console.log('选项 1 被点击'),
},
{
name: 'b',
title: '选项 2',
action: () => console.log('选项 2 被点击'),
},
];

const ContextMenu = ctx.commonUI.ContextMenu;

return (
<div>
<div onClick={(e) => {
ContextMenu.create(menuItems, e);
}}>点击这里</div>
</div>
);
};

export default App;
```

### Balloon

详细文档: [Balloon Documentation](https://fusion.design/pc/component/balloon)

### Breadcrumb
Expand Down
46 changes: 46 additions & 0 deletions docs/docs/api/material.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,33 @@ material.modifyBuiltinComponentAction('remove', (action) => {
addContextMenuOption(action: IPublicTypeContextMenuAction): void;
```

示例

```typescript
import { IPublicEnumContextMenuType } from '@alilc/lowcode-types';

material.addContextMenuOption({
name: 'parentItem',
title: 'Parent Item',
condition: (nodes) => true,
items: [
{
name: 'childItem1',
title: 'Child Item 1',
action: (nodes) => console.log('Child Item 1 clicked', nodes),
condition: (nodes) => true
},
// 分割线
{
type: IPublicEnumContextMenuType.SEPARATOR
name: 'separator.1'
}
// 更多子菜单项...
]
});

```

#### removeContextMenuOption

删除特定右键菜单项
Expand All @@ -274,7 +301,26 @@ removeContextMenuOption(name: string): void;
adjustContextMenuLayout(fn: (actions: IPublicTypeContextMenuItem[]) => IPublicTypeContextMenuItem[]): void;
```

**示例**

通过 adjustContextMenuLayout 补充分割线

```typescript
material.adjustContextMenuLayout((actions: IPublicTypeContextMenuAction) => {
const names = ['a', 'b'];
const newActions = [];
actions.forEach(d => {
newActions.push(d);
if (names.include(d.name)) {
newActions.push({ type: 'separator' })
}
});
return newActions
})
```

### 物料元数据

#### getComponentMeta
获取指定名称的物料元数据

Expand Down
11 changes: 9 additions & 2 deletions packages/designer/src/context-menu-actions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IPublicTypeContextMenuAction, IPublicEnumContextMenuType, IPublicTypeContextMenuItem, IPublicApiMaterial } from '@alilc/lowcode-types';
import { IPublicTypeContextMenuAction, IPublicEnumContextMenuType, IPublicTypeContextMenuItem, IPublicApiMaterial, IPublicModelPluginContext } from '@alilc/lowcode-types';
import { IDesigner, INode } from './designer';
import { createContextMenu, parseContextMenuAsReactNode, parseContextMenuProperties, uniqueId } from '@alilc/lowcode-utils';
import { Menu } from '@alifd/next';
Expand Down Expand Up @@ -48,6 +48,7 @@ export class GlobalContextMenuActions {
event.preventDefault();

const actions: IPublicTypeContextMenuAction[] = [];
let contextMenu: ContextMenuActions = this.contextMenuActionsMap.values().next().value;
this.contextMenuActionsMap.forEach((contextMenu) => {
actions.push(...contextMenu.actions);
});
Expand All @@ -57,11 +58,13 @@ export class GlobalContextMenuActions {
const destroy = () => {
destroyFn?.();
};
const pluginContext: IPublicModelPluginContext = contextMenu.designer.editor.get('pluginContext') as IPublicModelPluginContext;

const menus: IPublicTypeContextMenuItem[] = parseContextMenuProperties(actions, {
nodes: [],
destroy,
event,
pluginContext,
});

if (!menus.length) {
Expand All @@ -73,6 +76,7 @@ export class GlobalContextMenuActions {
const menuNode = parseContextMenuAsReactNode(layoutMenu, {
destroy,
nodes: [],
pluginContext,
});

const target = event.target;
Expand Down Expand Up @@ -160,10 +164,13 @@ export class ContextMenuActions implements IContextMenuActions {
destroyFn?.();
};

const pluginContext: IPublicModelPluginContext = this.designer.editor.get('pluginContext') as IPublicModelPluginContext;

const menus: IPublicTypeContextMenuItem[] = parseContextMenuProperties(actions, {
nodes: nodes.map(d => designer.shellModelFactory.createNode(d)!),
destroy,
event,
pluginContext,
});

if (!menus.length) {
Expand All @@ -175,7 +182,7 @@ export class ContextMenuActions implements IContextMenuActions {
const menuNode = parseContextMenuAsReactNode(layoutMenu, {
destroy,
nodes: nodes.map(d => designer.shellModelFactory.createNode(d)!),
designer,
pluginContext,
});

destroyFn = createContextMenu(menuNode, {
Expand Down
4 changes: 2 additions & 2 deletions packages/engine/src/engine-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,11 @@ const innerSetters = new InnerSetters();
const setters = new Setters(innerSetters);

const material = new Material(editor);
const commonUI = new CommonUI();
const commonUI = new CommonUI(editor);
editor.set('project', project);
editor.set('setters' as any, setters);
editor.set('material', material);
editor.set('innerHotkey', innerHotkey);
editor.set('commonUI' as any, commonUI);
const config = new Config(engineConfig);
const event = new Event(commonEvent, { prefix: 'common' });
const logger = new Logger({ level: 'warn', bizName: 'common' });
Expand All @@ -147,6 +146,7 @@ const pluginContextApiAssembler: ILowCodePluginContextApiAssembler = {
context.commonUI = commonUI;
context.registerLevel = IPublicEnumPluginRegisterLevel.Default;
context.isPluginRegisteredInWorkspace = false;
editor.set('pluginContext', context);
},
};

Expand Down
21 changes: 6 additions & 15 deletions packages/engine/src/inner-plugins/default-context-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,18 @@ import {
IPublicModelNode,
IPublicModelPluginContext,
IPublicTypeDragNodeDataObject,
IPublicTypeI18nData,
IPublicTypeNodeSchema,
} from '@alilc/lowcode-types';
import { isI18nData, isProjectSchema } from '@alilc/lowcode-utils';
import { isProjectSchema } from '@alilc/lowcode-utils';
import { Notification } from '@alifd/next';
import { intl, getLocale } from '../locale';
import { intl } from '../locale';

function getNodesSchema(nodes: IPublicModelNode[]) {
const componentsTree = nodes.map((node) => node?.exportSchema(IPublicEnumTransformStage.Clone));
const data = { type: 'nodeSchema', componentsMap: {}, componentsTree };
return data;
}

function getIntlStr(data: string | IPublicTypeI18nData) {
if (!isI18nData(data)) {
return data;
}

const locale = getLocale();
return data[locale] || data['zh-CN'] || data['zh_CN'] || data['en-US'] || data['en_US'] || '';
}

async function getClipboardText(): Promise<IPublicTypeNodeSchema[]> {
return new Promise((resolve, reject) => {
// 使用 Clipboard API 读取剪贴板内容
Expand Down Expand Up @@ -61,8 +51,9 @@ async function getClipboardText(): Promise<IPublicTypeNodeSchema[]> {
}

export const defaultContextMenu = (ctx: IPublicModelPluginContext) => {
const { material, canvas } = ctx;
const { material, canvas, common } = ctx;
const { clipboard } = canvas;
const { intl: utilsIntl } = common.utils;

return {
init() {
Expand Down Expand Up @@ -150,7 +141,7 @@ export const defaultContextMenu = (ctx: IPublicModelPluginContext) => {
});
if (canAddNodes.length === 0) {
Notification.open({
content: `${nodeSchema.map(d => getIntlStr(d.title || d.componentName)).join(',')}等组件无法放置到${getIntlStr(parent.title || parent.componentName as any)}内`,
content: `${nodeSchema.map(d => utilsIntl(d.title || d.componentName)).join(',')}等组件无法放置到${utilsIntl(parent.title || parent.componentName as any)}内`,
type: 'error',
});
return;
Expand Down Expand Up @@ -198,7 +189,7 @@ export const defaultContextMenu = (ctx: IPublicModelPluginContext) => {
});
if (canAddNodes.length === 0) {
Notification.open({
content: `${nodeSchema.map(d => getIntlStr(d.title || d.componentName)).join(',')}等组件无法放置到${getIntlStr(node.title || node.componentName as any)}内`,
content: `${nodeSchema.map(d => utilsIntl(d.title || d.componentName)).join(',')}等组件无法放置到${utilsIntl(node.title || node.componentName as any)}内`,
type: 'error',
});
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { IPublicApiCommonUI } from '@alilc/lowcode-types';
import { IPublicApiCommonUI, IPublicModelPluginContext, IPublicTypeContextMenuAction } from '@alilc/lowcode-types';
import {
IEditor,
Tip as InnerTip,
Title as InnerTitle,
} from '@alilc/lowcode-editor-core';
import { Balloon, Breadcrumb, Button, Card, Checkbox, DatePicker, Dialog, Dropdown, Form, Icon, Input, Loading, Message, Overlay, Pagination, Radio, Search, Select, SplitButton, Step, Switch, Tab, Table, Tree, TreeSelect, Upload, Divider } from '@alifd/next';
import { ContextMenu } from '../components/context-menu';
import { editorSymbol } from '../symbols';

export class CommonUI implements IPublicApiCommonUI {
[editorSymbol]: IEditor;

Balloon = Balloon;
Breadcrumb = Breadcrumb;
Button = Button;
Expand Down Expand Up @@ -35,13 +39,29 @@ export class CommonUI implements IPublicApiCommonUI {
Upload = Upload;
Divider = Divider;

constructor(editor: IEditor) {
this[editorSymbol] = editor;
}

get Tip() {
return InnerTip;
}
get Title() {
return InnerTitle;
}

get ContextMenu() {
return ContextMenu;
const editor = this[editorSymbol];
const innerContextMenu = (props: any) => {
const pluginContext: IPublicModelPluginContext = editor.get('pluginContext') as IPublicModelPluginContext;
return <ContextMenu {...props} pluginContext={pluginContext} />;
};

innerContextMenu.create = (menus: IPublicTypeContextMenuAction[], event: MouseEvent) => {
const pluginContext: IPublicModelPluginContext = editor.get('pluginContext') as IPublicModelPluginContext;
return ContextMenu.create(pluginContext, menus, event);
};

return innerContextMenu;
}
}
28 changes: 24 additions & 4 deletions packages/shell/src/components/context-menu.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { createContextMenu, parseContextMenuAsReactNode, parseContextMenuProperties } from '@alilc/lowcode-utils';
import { engineConfig } from '@alilc/lowcode-editor-core';
import { IPublicTypeContextMenuAction } from '@alilc/lowcode-types';
import { IPublicModelPluginContext, IPublicTypeContextMenuAction } from '@alilc/lowcode-types';
import React from 'react';

export function ContextMenu({ children, menus }: {
export function ContextMenu({ children, menus, pluginContext }: {
menus: IPublicTypeContextMenuAction[];
children: React.ReactElement[] | React.ReactElement;
pluginContext: IPublicModelPluginContext;
}): React.ReactElement<any, string | React.JSXElementConstructor<any>> {
if (!engineConfig.get('enableContextMenu')) {
return (
Expand All @@ -23,7 +24,10 @@ export function ContextMenu({ children, menus }: {
};
const children: React.ReactNode[] = parseContextMenuAsReactNode(parseContextMenuProperties(menus, {
destroy,
}));
pluginContext,
}), {
pluginContext,
});

if (!children?.length) {
return;
Expand All @@ -44,4 +48,20 @@ export function ContextMenu({ children, menus }: {
return (
<>{childrenWithContextMenu}</>
);
}
}

ContextMenu.create = (pluginContext: IPublicModelPluginContext, menus: IPublicTypeContextMenuAction[], event: MouseEvent) => {
const children: React.ReactNode[] = parseContextMenuAsReactNode(parseContextMenuProperties(menus, {
pluginContext,
}), {
pluginContext,
});

if (!children?.length) {
return;
}

return createContextMenu(children, {
event,
});
};
Loading
Loading