feat(demo-free-layout): context-menu-plugin (#329)

This commit is contained in:
xiamidaxia 2025-06-05 19:21:34 +08:00 committed by GitHub
parent 0b4b85da55
commit b87c3e918c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 93 additions and 4 deletions

View File

@ -83,7 +83,7 @@ export const NodeMenu: FC<NodeMenuProps> = ({ node, deleteNode, updateTitleEdit
}, [updateTitleEdit]);
if (!visible) {
return;
return <></>;
}
return (

View File

@ -6,7 +6,7 @@ import { createMinimapPlugin } from '@flowgram.ai/minimap-plugin';
import { createFreeSnapPlugin } from '@flowgram.ai/free-snap-plugin';
import { createFreeNodePanelPlugin } from '@flowgram.ai/free-node-panel-plugin';
import { createFreeLinesPlugin } from '@flowgram.ai/free-lines-plugin';
import { FreeLayoutProps } from '@flowgram.ai/free-layout-editor';
import { FreeLayoutProps, WorkflowNodeLinesData } from '@flowgram.ai/free-layout-editor';
import { createFreeGroupPlugin } from '@flowgram.ai/free-group-plugin';
import { createContainerNodePlugin } from '@flowgram.ai/free-container-plugin';
@ -14,7 +14,7 @@ import { onDragLineEnd } from '../utils';
import { FlowNodeRegistry, FlowDocumentJSON } from '../typings';
import { shortcuts } from '../shortcuts';
import { CustomService, RunningService } from '../services';
import { createSyncVariablePlugin } from '../plugins';
import { createSyncVariablePlugin, createContextMenuPlugin } from '../plugins';
import { defaultFormMeta } from '../nodes/default-form-meta';
import { WorkflowNodeType } from '../nodes';
import { SelectorBoxPopover } from '../components/selector-box-popover';
@ -92,7 +92,11 @@ export function useEditorProps(
if (fromPort.node === toPort.node) {
return false;
}
return true;
/**
* 线
* Line loop detection, which is not allowed to connect to the node in front of it
*/
return !fromPort.node.getData(WorkflowNodeLinesData).allInputNodes.includes(toPort.node);
},
/**
* Check whether the line can be deleted, this triggers on the default shortcut `Bakspace` or `Delete`
@ -157,6 +161,7 @@ export function useEditorProps(
* Running line
*/
isFlowingLine: (ctx, line) => ctx.get(RunningService).isFlowingLine(line),
/**
* Shortcuts
*/
@ -249,9 +254,16 @@ export function useEditorProps(
* loop
*/
createContainerNodePlugin({}),
/**
* Group plugin
*/
createFreeGroupPlugin({
groupNodeRender: GroupNodeRender,
}),
/**
* ContextMenu plugin
*/
createContextMenuPlugin({}),
],
}),
[]

View File

@ -0,0 +1,52 @@
import { NodePanelResult, WorkflowNodePanelService } from '@flowgram.ai/free-node-panel-plugin';
import {
Layer,
injectable,
inject,
FreeLayoutPluginContext,
WorkflowHoverService,
WorkflowNodeEntity,
WorkflowNodeJSON,
} from '@flowgram.ai/free-layout-editor';
@injectable()
export class ContextMenuLayer extends Layer {
@inject(FreeLayoutPluginContext) ctx: FreeLayoutPluginContext;
@inject(WorkflowNodePanelService) nodePanelService: WorkflowNodePanelService;
@inject(WorkflowHoverService) hoverService: WorkflowHoverService;
onReady() {
this.listenPlaygroundEvent('contextmenu', (e) => {
this.openNodePanel(e);
e.preventDefault();
e.stopPropagation();
});
}
openNodePanel(e: MouseEvent) {
const pos = this.getPosFromMouseEvent(e);
this.nodePanelService.callNodePanel({
position: pos,
panelProps: {},
// handle node selection from panel - 处理从面板中选择节点
onSelect: async (panelParams?: NodePanelResult) => {
if (!panelParams) {
return;
}
const { nodeType, nodeJSON } = panelParams;
// create new workflow node based on selected type - 根据选择的类型创建新的工作流节点
const node: WorkflowNodeEntity = this.ctx.document.createWorkflowNodeByType(
nodeType,
pos,
nodeJSON ?? ({} as WorkflowNodeJSON)
);
// select the newly created node - 选择新创建的节点
this.ctx.selection.selection = [node];
},
// handle panel close - 处理面板关闭
onClose: () => {},
});
}
}

View File

@ -0,0 +1,23 @@
import {
definePluginCreator,
PluginCreator,
FreeLayoutPluginContext,
} from '@flowgram.ai/free-layout-editor';
import { ContextMenuLayer } from './context-menu-layer';
export interface ContextMenuPluginOptions {}
/**
* Creates a plugin of contextmenu
* @param ctx - The plugin context, containing the document and other relevant information.
* @param options - Plugin options, currently an empty object.
*/
export const createContextMenuPlugin: PluginCreator<ContextMenuPluginOptions> = definePluginCreator<
ContextMenuPluginOptions,
FreeLayoutPluginContext
>({
onInit(ctx, options) {
ctx.playground.registerLayer(ContextMenuLayer);
},
});

View File

@ -0,0 +1 @@
export { createContextMenuPlugin } from './context-menu-plugin';

View File

@ -1 +1,2 @@
export { createSyncVariablePlugin } from './sync-variable-plugin/sync-variable-plugin';
export { createContextMenuPlugin } from './context-menu-plugin';