@logicflow/core 2.2.1 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs/api/logicflow-constructor/index.en.md +106 -0
- package/dist/docs/api/logicflow-constructor/index.zh.md +106 -0
- package/dist/docs/api/logicflow-constructor/use.en.md +61 -0
- package/dist/docs/api/logicflow-constructor/use.zh.md +61 -0
- package/dist/docs/api/logicflow-instance/canvas.en.md +197 -0
- package/dist/docs/api/logicflow-instance/canvas.zh.md +199 -0
- package/dist/docs/api/logicflow-instance/edge.en.md +273 -0
- package/dist/docs/api/logicflow-instance/edge.zh.md +273 -0
- package/dist/docs/api/logicflow-instance/edit-config.en.md +59 -0
- package/dist/docs/api/logicflow-instance/edit-config.zh.md +59 -0
- package/dist/docs/api/logicflow-instance/element.en.md +375 -0
- package/dist/docs/api/logicflow-instance/element.zh.md +379 -0
- package/dist/docs/api/logicflow-instance/event.en.md +326 -0
- package/dist/docs/api/logicflow-instance/event.zh.md +406 -0
- package/dist/docs/api/logicflow-instance/history.en.md +38 -0
- package/dist/docs/api/logicflow-instance/history.zh.md +38 -0
- package/dist/docs/api/logicflow-instance/index.en.md +41 -0
- package/dist/docs/api/logicflow-instance/index.zh.md +41 -0
- package/dist/docs/api/logicflow-instance/node.en.md +308 -0
- package/dist/docs/api/logicflow-instance/node.zh.md +308 -0
- package/dist/docs/api/logicflow-instance/register.en.md +76 -0
- package/dist/docs/api/logicflow-instance/register.zh.md +76 -0
- package/dist/docs/api/logicflow-instance/render-and-data.en.md +179 -0
- package/dist/docs/api/logicflow-instance/render-and-data.zh.md +181 -0
- package/dist/docs/api/logicflow-instance/text.en.md +60 -0
- package/dist/docs/api/logicflow-instance/text.zh.md +60 -0
- package/dist/docs/api/logicflow-instance/theme.en.md +179 -0
- package/dist/docs/api/logicflow-instance/theme.zh.md +179 -0
- package/dist/docs/api/runtime-model/edgeModel.en.md +29 -0
- package/dist/docs/api/runtime-model/edgeModel.zh.md +325 -0
- package/dist/docs/api/runtime-model/graphModel.en.md +275 -0
- package/dist/docs/api/runtime-model/graphModel.zh.md +1153 -0
- package/dist/docs/api/runtime-model/nodeModel.en.md +37 -0
- package/dist/docs/api/runtime-model/nodeModel.zh.md +644 -0
- package/dist/docs/api/type/MainTypes.en.md +598 -0
- package/dist/docs/api/type/MainTypes.zh.md +867 -0
- package/dist/docs/api/type/Theme.en.md +187 -0
- package/dist/docs/api/type/Theme.zh.md +187 -0
- package/dist/docs/api/type/canvas-types.en.md +25 -0
- package/dist/docs/api/type/canvas-types.zh.md +25 -0
- package/dist/docs/api/type/index.en.md +96 -0
- package/dist/docs/api/type/index.zh.md +99 -0
- package/dist/docs/api/type/node-types.en.md +21 -0
- package/dist/docs/api/type/node-types.zh.md +21 -0
- package/dist/docs/api/type/plugin-types.en.md +24 -0
- package/dist/docs/api/type/plugin-types.zh.md +24 -0
- package/dist/docs/index.md +11 -0
- package/dist/docs/tutorial/about.en.md +38 -0
- package/dist/docs/tutorial/about.zh.md +65 -0
- package/dist/docs/tutorial/advanced/dnd.en.md +62 -0
- package/dist/docs/tutorial/advanced/dnd.zh.md +52 -0
- package/dist/docs/tutorial/advanced/edge.en.md +64 -0
- package/dist/docs/tutorial/advanced/edge.zh.md +66 -0
- package/dist/docs/tutorial/advanced/keyboard.en.md +70 -0
- package/dist/docs/tutorial/advanced/keyboard.zh.md +67 -0
- package/dist/docs/tutorial/advanced/node.en.md +338 -0
- package/dist/docs/tutorial/advanced/node.zh.md +338 -0
- package/dist/docs/tutorial/advanced/react.en.md +106 -0
- package/dist/docs/tutorial/advanced/react.zh.md +114 -0
- package/dist/docs/tutorial/advanced/silent-mode.en.md +75 -0
- package/dist/docs/tutorial/advanced/silent-mode.zh.md +71 -0
- package/dist/docs/tutorial/advanced/snapline.en.md +54 -0
- package/dist/docs/tutorial/advanced/vue.en.md +249 -0
- package/dist/docs/tutorial/advanced/vue.zh.md +248 -0
- package/dist/docs/tutorial/ai.en.md +64 -0
- package/dist/docs/tutorial/ai.zh.md +64 -0
- package/dist/docs/tutorial/basic/background.en.md +50 -0
- package/dist/docs/tutorial/basic/canvas.en.md +164 -0
- package/dist/docs/tutorial/basic/canvas.zh.md +183 -0
- package/dist/docs/tutorial/basic/class.en.md +106 -0
- package/dist/docs/tutorial/basic/class.zh.md +103 -0
- package/dist/docs/tutorial/basic/edge.en.md +151 -0
- package/dist/docs/tutorial/basic/edge.zh.md +152 -0
- package/dist/docs/tutorial/basic/event.en.md +70 -0
- package/dist/docs/tutorial/basic/event.zh.md +66 -0
- package/dist/docs/tutorial/basic/grid.en.md +77 -0
- package/dist/docs/tutorial/basic/node.en.md +358 -0
- package/dist/docs/tutorial/basic/node.zh.md +318 -0
- package/dist/docs/tutorial/basic/theme.en.md +154 -0
- package/dist/docs/tutorial/basic/theme.zh.md +157 -0
- package/dist/docs/tutorial/extension/adapter.en.md +446 -0
- package/dist/docs/tutorial/extension/adapter.zh.md +429 -0
- package/dist/docs/tutorial/extension/bpmn-element.en.md +1427 -0
- package/dist/docs/tutorial/extension/bpmn-element.zh.md +1472 -0
- package/dist/docs/tutorial/extension/control.en.md +117 -0
- package/dist/docs/tutorial/extension/control.zh.md +118 -0
- package/dist/docs/tutorial/extension/curved-edge.en.md +46 -0
- package/dist/docs/tutorial/extension/curved-edge.zh.md +46 -0
- package/dist/docs/tutorial/extension/custom.en.md +142 -0
- package/dist/docs/tutorial/extension/custom.zh.md +138 -0
- package/dist/docs/tutorial/extension/dnd-panel.en.md +109 -0
- package/dist/docs/tutorial/extension/dnd-panel.zh.md +109 -0
- package/dist/docs/tutorial/extension/dynamic-group.en.md +606 -0
- package/dist/docs/tutorial/extension/dynamic-group.zh.md +606 -0
- package/dist/docs/tutorial/extension/group.en.md +217 -0
- package/dist/docs/tutorial/extension/group.zh.md +209 -0
- package/dist/docs/tutorial/extension/highlight.en.md +50 -0
- package/dist/docs/tutorial/extension/highlight.zh.md +50 -0
- package/dist/docs/tutorial/extension/insert-node-in-polyline.en.md +52 -0
- package/dist/docs/tutorial/extension/insert-node-in-polyline.zh.md +47 -0
- package/dist/docs/tutorial/extension/intro.en.md +72 -0
- package/dist/docs/tutorial/extension/intro.zh.md +95 -0
- package/dist/docs/tutorial/extension/label.en.md +136 -0
- package/dist/docs/tutorial/extension/label.zh.md +135 -0
- package/dist/docs/tutorial/extension/layout.en.md +156 -0
- package/dist/docs/tutorial/extension/layout.zh.md +156 -0
- package/dist/docs/tutorial/extension/menu.en.md +319 -0
- package/dist/docs/tutorial/extension/menu.zh.md +377 -0
- package/dist/docs/tutorial/extension/minimap.en.md +164 -0
- package/dist/docs/tutorial/extension/minimap.zh.md +180 -0
- package/dist/docs/tutorial/extension/node-resize.en.md +199 -0
- package/dist/docs/tutorial/extension/node-resize.zh.md +221 -0
- package/dist/docs/tutorial/extension/pool.en.md +227 -0
- package/dist/docs/tutorial/extension/pool.zh.md +227 -0
- package/dist/docs/tutorial/extension/proximity-connect.en.md +104 -0
- package/dist/docs/tutorial/extension/proximity-connect.zh.md +107 -0
- package/dist/docs/tutorial/extension/selection.en.md +166 -0
- package/dist/docs/tutorial/extension/selection.zh.md +150 -0
- package/dist/docs/tutorial/extension/snapshot.en.md +276 -0
- package/dist/docs/tutorial/extension/snapshot.zh.md +276 -0
- package/dist/docs/tutorial/get-started.en.md +501 -0
- package/dist/docs/tutorial/get-started.zh.md +139 -0
- package/dist/docs/tutorial/update.en.md +213 -0
- package/dist/docs/tutorial/update.zh.md +212 -0
- package/package.json +5 -3
- package/scripts/postinstall-ai-prompt.js +67 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
---
|
|
2
|
+
nav: Guide
|
|
3
|
+
group:
|
|
4
|
+
title: Plug-in functionality
|
|
5
|
+
order: 3
|
|
6
|
+
title: Menu
|
|
7
|
+
order: 1
|
|
8
|
+
toc: content
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<style>
|
|
12
|
+
table td:first-of-type {
|
|
13
|
+
word-break: normal;
|
|
14
|
+
}
|
|
15
|
+
</style>
|
|
16
|
+
|
|
17
|
+
When using flowchart tools for editing, users' attention is often focused on the canvas area. Compared to frequently moving the mouse to click the top menu bar or using shortcut keys, right-clicking directly on nodes, edges, or blank areas is more efficient and intuitive. To better match users' operating habits, LogicFlow has built-in right-click menus, making common operations readily accessible and improving the overall editing experience.
|
|
18
|
+
|
|
19
|
+
## Enable
|
|
20
|
+
|
|
21
|
+
Import and enable the default menu
|
|
22
|
+
|
|
23
|
+
```tsx | pure
|
|
24
|
+
import LogicFlow from "@logicflow/core";
|
|
25
|
+
import { Menu } from "@logicflow/extension";
|
|
26
|
+
import "@logicflow/extension/lib/style/index.css";
|
|
27
|
+
|
|
28
|
+
LogicFlow.use(Menu); // Global import
|
|
29
|
+
|
|
30
|
+
const lf = new LogicFlow({
|
|
31
|
+
plugins: [Menu], // Local import
|
|
32
|
+
})
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
By default, the menu plugin supports node menus, edge menus, and canvas menus, with the following built-in functions:
|
|
36
|
+
|
|
37
|
+
- Node right-click menu (nodeMenu): Delete, Copy, Edit text
|
|
38
|
+
- Edge right-click menu (edgeMenu): Delete, Edit text
|
|
39
|
+
- Canvas right-click menu (graphMenu): None
|
|
40
|
+
|
|
41
|
+
Of course, supporting only these configuration items is far from enough, so we also support users to customize menu configuration items.
|
|
42
|
+
|
|
43
|
+
## Menu configuration items
|
|
44
|
+
|
|
45
|
+
Each function in the menu can be represented by a configuration entry. The specific fields are as follows:
|
|
46
|
+
|
|
47
|
+
| Fields | Type | Role | Required | Description |
|
|
48
|
+
| --------- | ---------------- | --------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
49
|
+
| text | string | Text content | | Text displayed by the menu item |
|
|
50
|
+
| className | string | Class name | | The default class for each item is lf-menu-item, set this field and class will add className to the original. |
|
|
51
|
+
| icon | boolean / string | Whether to create a span placeholder for icon | | If simple text cannot richly represent the menu, you can add an icon. Set to `true` to create an empty icon container with class `lf-menu-icon`. Set to a string for various icon formats: image file paths (e.g., `./icon.png`), base64 image data (e.g., `data:image/png;base64,...`), CSS class names, or HTML content. Usually used in conjunction with className. |
|
|
52
|
+
| disabled | boolean | Whether to disable menu item | | When set to true, the menu item will be displayed in gray and cannot be clicked. This state can be dynamically modified using the `changeMenuItemDisableStatus` method. |
|
|
53
|
+
| callback | Function | Callback executed after clicking | ✅ | You can get node data/edge data/event information in the three menu callbacks respectively. |
|
|
54
|
+
|
|
55
|
+
Here's an example of writing a node right-click menu delete function:
|
|
56
|
+
|
|
57
|
+
```tsx | pure
|
|
58
|
+
// Define a menu item for node deletion
|
|
59
|
+
const menuItem = {
|
|
60
|
+
className: "lf-menu-delete",
|
|
61
|
+
icon: true,
|
|
62
|
+
callback: (node) => {
|
|
63
|
+
// Delete the node and emit a custom-node:deleted event with the deleted node data.
|
|
64
|
+
lf.graphModel.deleteNode(node.id);
|
|
65
|
+
lf.graphModel.eventCenter.emit("custom-node:deleted", node);
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Adding Menu Options
|
|
71
|
+
|
|
72
|
+
You can use the `lf.extension.menu.addMenuConfig` method to add new options to the existing menu. The specific configuration example is as follows:
|
|
73
|
+
|
|
74
|
+
```tsx | pure
|
|
75
|
+
import LogicFlow from "@logicflow/core";
|
|
76
|
+
import { Menu } from "@logicflow/extension";
|
|
77
|
+
|
|
78
|
+
import NodeData = LogicFlow.NodeData;
|
|
79
|
+
import EdgeData = LogicFlow.EdgeData;
|
|
80
|
+
import Position = LogicFlow.Position;
|
|
81
|
+
|
|
82
|
+
// Instantiate LogicFlow
|
|
83
|
+
const lf = new LogicFlow({
|
|
84
|
+
container: document.getElementById("app"),
|
|
85
|
+
// Register plugins
|
|
86
|
+
plugins: [Menu],
|
|
87
|
+
});
|
|
88
|
+
// Add options to the menu
|
|
89
|
+
// You can also call lf.extension.menu.addMenuConfig to set the menu, both have the same effect
|
|
90
|
+
lf.addMenuConfig({
|
|
91
|
+
nodeMenu: [
|
|
92
|
+
{
|
|
93
|
+
text: 'Share',
|
|
94
|
+
callback() {
|
|
95
|
+
alert('Share Success!')
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
text: 'Properties',
|
|
100
|
+
callback(node: NodeData) {
|
|
101
|
+
alert(`
|
|
102
|
+
Node ID: ${node.id}
|
|
103
|
+
Node Type: ${node.type}
|
|
104
|
+
Node Position: (x: ${node.x}, y: ${node.y})
|
|
105
|
+
`)
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
edgeMenu: [
|
|
110
|
+
{
|
|
111
|
+
text: 'Properties',
|
|
112
|
+
callback(edge: EdgeData) {
|
|
113
|
+
const {
|
|
114
|
+
id,
|
|
115
|
+
type,
|
|
116
|
+
startPoint,
|
|
117
|
+
endPoint,
|
|
118
|
+
sourceNodeId,
|
|
119
|
+
targetNodeId,
|
|
120
|
+
} = edge
|
|
121
|
+
alert(`
|
|
122
|
+
Edge ID: ${id}
|
|
123
|
+
Edge Type: ${type}
|
|
124
|
+
Start Point: (x: ${startPoint.x}, y: ${startPoint.y})
|
|
125
|
+
End Point: (x: ${endPoint.x}, y: ${endPoint.y})
|
|
126
|
+
Source Node ID: ${sourceNodeId}
|
|
127
|
+
Target Node ID: ${targetNodeId}
|
|
128
|
+
`)
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
graphMenu: [
|
|
133
|
+
{
|
|
134
|
+
text: 'Share',
|
|
135
|
+
callback() {
|
|
136
|
+
alert('Share Success!')
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
text: 'Add Node',
|
|
141
|
+
callback(data: Position) {
|
|
142
|
+
lf.addNode({
|
|
143
|
+
type: 'rect',
|
|
144
|
+
x: data.x,
|
|
145
|
+
y: data.y,
|
|
146
|
+
})
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
})
|
|
151
|
+
lf.render();
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Overwriting Menus
|
|
155
|
+
|
|
156
|
+
If there are unwanted options in the default menu, or it doesn't meet the requirements, you can use `lf.setMenuConfig` to override the default menu and achieve a custom menu effect.
|
|
157
|
+
|
|
158
|
+
```tsx | pure
|
|
159
|
+
lf.setMenuConfig({
|
|
160
|
+
nodeMenu: [
|
|
161
|
+
{
|
|
162
|
+
text: "Delete",
|
|
163
|
+
callback(node) {
|
|
164
|
+
lf.deleteNode(node.id);
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
], // Override the default node right-click menu
|
|
168
|
+
edgeMenu: false, // Remove the default edge right-click menu
|
|
169
|
+
graphMenu: [], // Override the default edge right-click menu, same behavior as false
|
|
170
|
+
});
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Configuring Menus for Specified Element Types
|
|
174
|
+
|
|
175
|
+
In addition to overwriting the entire menu above, you can also use `lf.setMenuByType` to set menus for elements of specified types.
|
|
176
|
+
|
|
177
|
+
```tsx | pure
|
|
178
|
+
lf.setMenuByType({
|
|
179
|
+
type: "bpmn:startEvent",
|
|
180
|
+
menu: [
|
|
181
|
+
{
|
|
182
|
+
text: "Share111",
|
|
183
|
+
callback() {
|
|
184
|
+
console.log("Share Success222!");
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Dynamic Enable/Disable Menu Items<Badge>New in 2.1.0</Badge>
|
|
192
|
+
|
|
193
|
+
To provide more flexible interaction, version 2.1.0 adds functionality to dynamically control the disabled state of menu items, allowing you to dynamically disable or enable specific menu items based on business logic.
|
|
194
|
+
|
|
195
|
+
### API
|
|
196
|
+
|
|
197
|
+
```tsx | pure
|
|
198
|
+
lf.changeMenuItemDisableStatus(menuKey, text, disabled)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Parameter description:
|
|
202
|
+
- `menuKey`: Menu type, possible values are `'nodeMenu'` | `'edgeMenu'` | `'graphMenu'` | `'selectionMenu'`
|
|
203
|
+
- `text`: Text of the menu item to operate on
|
|
204
|
+
- `disabled`: Whether to disable, `true` to disable, `false` to enable
|
|
205
|
+
|
|
206
|
+
### Usage Example
|
|
207
|
+
|
|
208
|
+
```tsx | pure
|
|
209
|
+
// Disable the "Delete" option in node menu
|
|
210
|
+
lf.changeMenuItemDisableStatus('nodeMenu', 'Delete', true)
|
|
211
|
+
|
|
212
|
+
// Enable the "Properties" option in edge menu
|
|
213
|
+
lf.changeMenuItemDisableStatus('edgeMenu', 'Properties', false)
|
|
214
|
+
|
|
215
|
+
// Disable the "Share" option in graph menu
|
|
216
|
+
lf.changeMenuItemDisableStatus('graphMenu', 'Share', true)
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Setting Disabled State During Configuration
|
|
220
|
+
|
|
221
|
+
You can also directly set certain menu items to disabled state when configuring the menu:
|
|
222
|
+
|
|
223
|
+
```tsx | pure
|
|
224
|
+
lf.addMenuConfig({
|
|
225
|
+
nodeMenu: [
|
|
226
|
+
{
|
|
227
|
+
text: 'Delete',
|
|
228
|
+
disabled: true, // Initially disabled
|
|
229
|
+
callback(node: NodeData) {
|
|
230
|
+
lf.deleteNode(node.id)
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
text: 'Copy',
|
|
235
|
+
disabled: false, // Initially enabled
|
|
236
|
+
callback(node: NodeData) {
|
|
237
|
+
lf.cloneNode(node.id)
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
],
|
|
241
|
+
})
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Selection Menu
|
|
245
|
+
|
|
246
|
+
After using the selection plugin, the selection component will also display a menu. By default, the selection menu only has a delete operation.
|
|
247
|
+
Like other menu items, you can call the methods provided by the Menu plugin to modify the selection menu configuration.
|
|
248
|
+
|
|
249
|
+
```tsx | pure
|
|
250
|
+
// Example: Set the selection menu to not display
|
|
251
|
+
lf.setMenuByType({
|
|
252
|
+
type: "lf:defaultSelectionMenu",
|
|
253
|
+
menu: [],
|
|
254
|
+
});
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Setting Menus for Custom Nodes
|
|
258
|
+
|
|
259
|
+
In addition to setting menus for general canvas elements above, LogicFlow also supports setting menus for custom nodes:
|
|
260
|
+
|
|
261
|
+
```tsx | pure
|
|
262
|
+
|
|
263
|
+
// index.js
|
|
264
|
+
import { RectNode, CustomeModel } from "./custom.ts";
|
|
265
|
+
// Register custom node
|
|
266
|
+
lf.register({
|
|
267
|
+
type: "custome_node",
|
|
268
|
+
view: RectNode,
|
|
269
|
+
model: CustomeModel,
|
|
270
|
+
});
|
|
271
|
+
// Set custom node menu
|
|
272
|
+
lf.setMenuByType({
|
|
273
|
+
type: "custome_node",
|
|
274
|
+
menu: [
|
|
275
|
+
{
|
|
276
|
+
className: "lf-menu-delete",
|
|
277
|
+
icon: true,
|
|
278
|
+
callback: (node) => {
|
|
279
|
+
lf.graphModel.deleteNode(node.id);
|
|
280
|
+
lf.graphModel.eventCenter.emit("custom:event", node);
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
text: "edit",
|
|
285
|
+
className: "lf-menu-item",
|
|
286
|
+
callback: (node) => {
|
|
287
|
+
lf.graphModel.setElementStateById(node.id, 2);
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
text: "copy",
|
|
292
|
+
className: "lf-menu-item",
|
|
293
|
+
disabled: false, // Can set disabled state
|
|
294
|
+
callback: (node) => {
|
|
295
|
+
lf.graphModel.cloneNode(node.id);
|
|
296
|
+
},
|
|
297
|
+
}
|
|
298
|
+
],
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
lf.on("custom:event", (node) => {
|
|
302
|
+
console.log(node);
|
|
303
|
+
});
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Custom Menu Styles
|
|
307
|
+
|
|
308
|
+
The Menu plugin sets a class for each DOM it displays. Users can override the original style based on the class in the menu structure and set styles that match the host's style.
|
|
309
|
+
|
|
310
|
+
- Menu: lf-menu
|
|
311
|
+
- Menu item: lf-menu-item, user-defined className
|
|
312
|
+
- Menu item text: lf-menu-item-text
|
|
313
|
+
- Menu item icon: lf-menu-item-icon, need to set the menu item configuration icon to true
|
|
314
|
+
- Disabled menu item: lf-menu-item__disabled, this class is automatically added when a menu item is disabled
|
|
315
|
+
|
|
316
|
+
By setting these classes, you can override the default style, beautify font color, set menu item icons, etc.
|
|
317
|
+
|
|
318
|
+
## Effect
|
|
319
|
+
<a href="https://codesandbox.io/embed/dazzling-hypatia-en8s9?fontsize=14&hidenavigation=1&theme=dark&view=preview" target="_blank"> Go to CodeSandbox for examples </a>
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
---
|
|
2
|
+
nav: 指南
|
|
3
|
+
group:
|
|
4
|
+
title: 插件功能
|
|
5
|
+
order: 3
|
|
6
|
+
title: 右键菜单 (Menu)
|
|
7
|
+
order: 1
|
|
8
|
+
toc: content
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
在使用流程图工具进行编辑时,用户的注意力往往集中在画布区域。相比频繁移动鼠标去点击顶部菜单栏或使用快捷键,直接在节点、边或空白区域右键操作会更高效、符合直觉。为了更好地贴合用户的操作习惯,LogicFlow内置了右键菜单,让常用操作触手可及,提升整体编辑体验。
|
|
12
|
+
|
|
13
|
+
## 启用
|
|
14
|
+
|
|
15
|
+
引入并启用默认菜单
|
|
16
|
+
|
|
17
|
+
```tsx | pure
|
|
18
|
+
import LogicFlow from "@logicflow/core";
|
|
19
|
+
import { Menu } from "@logicflow/extension";
|
|
20
|
+
import "@logicflow/extension/lib/style/index.css";
|
|
21
|
+
|
|
22
|
+
LogicFlow.use(Menu); // 全局引入
|
|
23
|
+
|
|
24
|
+
const lf = new LogicFlow({
|
|
25
|
+
plugins: [Menu], // 局部引入
|
|
26
|
+
})
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
默认情况下,菜单插件支持节点菜单、边菜单、画布菜单,并内置了以下功能:
|
|
30
|
+
|
|
31
|
+
- 节点右键菜单(nodeMenu): 删除、复制、编辑文案
|
|
32
|
+
- 边右键菜单(edgeMenu):删除、编辑文案
|
|
33
|
+
- 画布右键菜单(graphMenu):无
|
|
34
|
+
|
|
35
|
+
当然,只支持这些配置项是远远不够的,因此我们还支持用户定制菜单配置项。
|
|
36
|
+
|
|
37
|
+
## 菜单配置项
|
|
38
|
+
|
|
39
|
+
菜单中的每一项功能,可以用一条配置进行表示。具体字段如下:
|
|
40
|
+
|
|
41
|
+
| 字段 | 类型 | 作用 | 是否必须 | 描述 |
|
|
42
|
+
| --------- | ---------------- | -------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
43
|
+
| text | string | 文案 | | 菜单项展示的文案 |
|
|
44
|
+
| className | string | class 名称 | | 每一项默认 class 为 lf-menu-item,设置了此字段,class 会在原来的基础上添加 className。 |
|
|
45
|
+
| icon | boolean / string | 是否创建 icon 的 span 展位 | | 如果简单的文案不能丰富表示菜单,可以加个 icon。设置为 `true` 时会创建一个 class 为 `lf-menu-icon` 的空图标容器。<br/>`2.1.0`版本开始,支持多种图标格式:图片文件路径(如 `./icon.png`)、base64 图片数据(如 `data:image/png;base64,...`)、CSS 类名或 HTML 内容。一般与 className 配合使用。 |
|
|
46
|
+
| disabled | boolean | 是否禁用菜单项 | | 设置为 true 时,菜单项会显示为灰色且无法点击。可以通过 `changeMenuItemDisableStatus` 方法动态修改此状态。 |
|
|
47
|
+
| callback | Function | 点击后执行的回调 | ✅ | 三种菜单回调中分别可以拿到节点数据/边数据/事件信息。 |
|
|
48
|
+
|
|
49
|
+
这里以节点右键菜单删除功能的写法为例:
|
|
50
|
+
|
|
51
|
+
```tsx | pure
|
|
52
|
+
// 定义一个做节点删除动作的菜单项
|
|
53
|
+
const menuItem = {
|
|
54
|
+
className: "lf-menu-delete",
|
|
55
|
+
icon: true,
|
|
56
|
+
callback: (node) => {
|
|
57
|
+
// 删除节点,并触发一个自定义事件 custom-node:deleted,把当前删除的节点信息抛出去
|
|
58
|
+
lf.graphModel.deleteNode(node.id);
|
|
59
|
+
lf.graphModel.eventCenter.emit("custom-node:deleted", node);
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## API
|
|
65
|
+
|
|
66
|
+
### addMenuConfig
|
|
67
|
+
|
|
68
|
+
通过`addMenuConfig`方法可以在原有菜单的基础上追加新的选项,具体配置示例如下:
|
|
69
|
+
|
|
70
|
+
```tsx | pure
|
|
71
|
+
import LogicFlow from '@logicflow/core'
|
|
72
|
+
import { Menu } from '@logicflow/extension'
|
|
73
|
+
|
|
74
|
+
import NodeData = LogicFlow.NodeData
|
|
75
|
+
import EdgeData = LogicFlow.EdgeData
|
|
76
|
+
import Position = LogicFlow.Position
|
|
77
|
+
|
|
78
|
+
// 实例化 LogicFlow
|
|
79
|
+
const lf = new LogicFlow({
|
|
80
|
+
container: document.getElementById('app'),
|
|
81
|
+
// 注册插件
|
|
82
|
+
plugins: [Menu],
|
|
83
|
+
})
|
|
84
|
+
// 为菜单追加选项
|
|
85
|
+
// 也可以通过调用 lf.extension.menu.addMenuConfig 设置菜单,二者效果是相同的
|
|
86
|
+
lf.addMenuConfig({
|
|
87
|
+
nodeMenu: [
|
|
88
|
+
{
|
|
89
|
+
text: '分享',
|
|
90
|
+
callback() {
|
|
91
|
+
alert('分享成功!')
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
text: '属性',
|
|
96
|
+
callback(node: NodeData) {
|
|
97
|
+
alert(`
|
|
98
|
+
节点id:${node.id}
|
|
99
|
+
节点类型:${node.type}
|
|
100
|
+
节点坐标:(x: ${node.x}, y: ${node.y})
|
|
101
|
+
`)
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
edgeMenu: [
|
|
106
|
+
{
|
|
107
|
+
text: '属性',
|
|
108
|
+
callback(edge: EdgeData) {
|
|
109
|
+
const {
|
|
110
|
+
id,
|
|
111
|
+
type,
|
|
112
|
+
startPoint,
|
|
113
|
+
endPoint,
|
|
114
|
+
sourceNodeId,
|
|
115
|
+
targetNodeId,
|
|
116
|
+
} = edge
|
|
117
|
+
alert(`
|
|
118
|
+
边id:${id}
|
|
119
|
+
边类型:${type}
|
|
120
|
+
边起点坐标:(startPoint: [${startPoint.x}, ${startPoint.y}])
|
|
121
|
+
边终点坐标:(endPoint: [${endPoint.x}, ${endPoint.y}])
|
|
122
|
+
源节点id:${sourceNodeId}
|
|
123
|
+
目标节点id:${targetNodeId}
|
|
124
|
+
`)
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
graphMenu: [
|
|
129
|
+
{
|
|
130
|
+
text: '分享',
|
|
131
|
+
callback() {
|
|
132
|
+
alert('分享成功!')
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
text: '添加节点',
|
|
137
|
+
callback(data: Position) {
|
|
138
|
+
lf.addNode({
|
|
139
|
+
type: 'rect',
|
|
140
|
+
x: data.x,
|
|
141
|
+
y: data.y,
|
|
142
|
+
})
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
})
|
|
147
|
+
lf.render()
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### setMenuConfig
|
|
151
|
+
|
|
152
|
+
如果默认菜单中存在不需要的选项,或者无法满足需求,可以通过`lf.setMenuConfig`覆盖默认菜单,实现自定义菜单的效果。
|
|
153
|
+
|
|
154
|
+
```tsx | pure
|
|
155
|
+
lf.setMenuConfig({
|
|
156
|
+
nodeMenu: [
|
|
157
|
+
{
|
|
158
|
+
text: "删除",
|
|
159
|
+
callback(node) {
|
|
160
|
+
lf.deleteNode(node.id);
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
], // 覆盖默认的节点右键菜单
|
|
164
|
+
edgeMenu: false, // 删除默认的边右键菜单
|
|
165
|
+
graphMenu: [], // 覆盖默认的边右键菜单,与false表现一样
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### setMenuByType
|
|
170
|
+
|
|
171
|
+
除了上面的复写整个菜单外,还可以使用`lf.setMenuByType`为指定类型的元素设置菜单。
|
|
172
|
+
|
|
173
|
+
```tsx | pure
|
|
174
|
+
lf.setMenuByType({
|
|
175
|
+
type: "bpmn:startEvent",
|
|
176
|
+
menu: [
|
|
177
|
+
{
|
|
178
|
+
text: "分享111",
|
|
179
|
+
callback() {
|
|
180
|
+
console.log("分享成功222!");
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
],
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### changeMenuItemDisableStatus<Badge>2.1.0新增</Badge>
|
|
188
|
+
|
|
189
|
+
为了提供更灵活的交互,在2.1.0版本新增提供了动态控制菜单项禁用状态的功能,可以根据业务逻辑动态地禁用或启用特定的菜单项。
|
|
190
|
+
|
|
191
|
+
```tsx | pure
|
|
192
|
+
lf.changeMenuItemDisableStatus(menuKey, text, disabled)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
参数说明:
|
|
196
|
+
- `menuKey`: 菜单类型,可选值为 `'nodeMenu'` | `'edgeMenu'` | `'graphMenu'` | `'selectionMenu'`
|
|
197
|
+
- `text`: 要操作的菜单项文本
|
|
198
|
+
- `disabled`: 是否禁用,`true` 为禁用,`false` 为启用
|
|
199
|
+
|
|
200
|
+
#### 使用示例
|
|
201
|
+
|
|
202
|
+
```tsx | pure
|
|
203
|
+
// 禁用节点菜单中的"删除"选项
|
|
204
|
+
lf.changeMenuItemDisableStatus('nodeMenu', '删除', true)
|
|
205
|
+
|
|
206
|
+
// 启用边菜单中的"属性"选项
|
|
207
|
+
lf.changeMenuItemDisableStatus('edgeMenu', '属性', false)
|
|
208
|
+
|
|
209
|
+
// 禁用画布菜单中的"分享"选项
|
|
210
|
+
lf.changeMenuItemDisableStatus('graphMenu', '分享', true)
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
#### 配置时设置禁用状态
|
|
214
|
+
|
|
215
|
+
也可以在配置菜单时直接设置某些菜单项为禁用状态:
|
|
216
|
+
|
|
217
|
+
```tsx | pure
|
|
218
|
+
lf.addMenuConfig({
|
|
219
|
+
nodeMenu: [
|
|
220
|
+
{
|
|
221
|
+
text: '删除',
|
|
222
|
+
disabled: true, // 初始状态为禁用
|
|
223
|
+
callback(node: NodeData) {
|
|
224
|
+
lf.deleteNode(node.id)
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
text: '复制',
|
|
229
|
+
disabled: false, // 初始状态为启用
|
|
230
|
+
callback(node: NodeData) {
|
|
231
|
+
lf.cloneNode(node.id)
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
],
|
|
235
|
+
})
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## 选区菜单
|
|
239
|
+
|
|
240
|
+
在使用了选区插件后,选区插件也会出现菜单,默认情况下选区菜单只有删除操作。
|
|
241
|
+
和其他菜单项一样,可以调用Menu插件提供的方法对选区菜单配置进行修改。
|
|
242
|
+
|
|
243
|
+
```tsx | pure
|
|
244
|
+
// 一个🌰:设置选区菜单不展示
|
|
245
|
+
lf.setMenuByType({
|
|
246
|
+
type: "lf:defaultSelectionMenu",
|
|
247
|
+
menu: [],
|
|
248
|
+
});
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## 为自定义节点设置菜单
|
|
252
|
+
|
|
253
|
+
除了上面的为画布通用元素设置菜单外,LogicFlow还支持为自定义节点设置菜单:
|
|
254
|
+
|
|
255
|
+
```tsx | pure
|
|
256
|
+
|
|
257
|
+
// index.js
|
|
258
|
+
import { RectNode, CustomeModel } from "./custom.ts";
|
|
259
|
+
// 注册自定义节点
|
|
260
|
+
lf.register({
|
|
261
|
+
type: "custome_node",
|
|
262
|
+
view: RectNode,
|
|
263
|
+
model: CustomeModel,
|
|
264
|
+
});
|
|
265
|
+
// 设置自定义节点菜单
|
|
266
|
+
lf.setMenuByType({
|
|
267
|
+
type: "custome_node",
|
|
268
|
+
menu: [
|
|
269
|
+
{
|
|
270
|
+
className: "lf-menu-delete",
|
|
271
|
+
icon: true,
|
|
272
|
+
callback: (node) => {
|
|
273
|
+
lf.graphModel.deleteNode(node.id);
|
|
274
|
+
lf.graphModel.eventCenter.emit("custom:event", node);
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
text: "edit",
|
|
279
|
+
className: "lf-menu-item",
|
|
280
|
+
callback: (node) => {
|
|
281
|
+
this.lf.graphModel.setElementStateById(node.id, 2);
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
text: "copy",
|
|
286
|
+
className: "lf-menu-item",
|
|
287
|
+
disabled: false, // 可以设置禁用状态
|
|
288
|
+
callback: (node) => {
|
|
289
|
+
this.lf.graphModel.cloneNode(node.id);
|
|
290
|
+
},
|
|
291
|
+
}
|
|
292
|
+
],
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
lf.on("custom:event", (node) => {
|
|
296
|
+
console.log(node);
|
|
297
|
+
});
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## 自定义菜单样式
|
|
301
|
+
|
|
302
|
+
Menu插件为其展示的每个DOM都设置了 class ,用户可以根据菜单结构中的 class 覆盖原有样式,设置符合宿主风格的样式。
|
|
303
|
+
|
|
304
|
+
- 菜单:lf-menu
|
|
305
|
+
- 菜单项:lf-menu-item、用户自定义的 className
|
|
306
|
+
- 菜单项-文案:lf-menu-item-text
|
|
307
|
+
- 菜单项-图标:lf-menu-item-icon,需要将菜单项配置 icon 设置为 true
|
|
308
|
+
- 禁用菜单项:lf-menu-item__disabled,菜单项被禁用时会自动添加此 class
|
|
309
|
+
|
|
310
|
+
通过设置这些 class,可以覆盖默认样式,美化字体颜色,设置菜单项 icon 等。
|
|
311
|
+
|
|
312
|
+
## 自定义菜单Icon<Badge>2.1.0新增</Badge>
|
|
313
|
+
菜单组件现在支持多种图标配置方式,可以通过 `MenuItem` 的 `icon` 字段来设置图标,目前支持以下几种Icon设置方式:
|
|
314
|
+
|
|
315
|
+
#### 1. 布尔值(兼容老逻辑)
|
|
316
|
+
```typescript
|
|
317
|
+
{
|
|
318
|
+
text: '删除',
|
|
319
|
+
icon: true, // 创建空的图标容器
|
|
320
|
+
callback: (node) => { /* ... */ }
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
#### 2. CSS类名(单个类名)
|
|
325
|
+
```typescript
|
|
326
|
+
{
|
|
327
|
+
text: '删除',
|
|
328
|
+
icon: 'fa-trash', // 添加多个类名
|
|
329
|
+
callback: (node) => { /* ... */ }
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// 或者使用点开头
|
|
333
|
+
{
|
|
334
|
+
text: '删除',
|
|
335
|
+
icon: '.fa .fa-trash', // 添加多个类名
|
|
336
|
+
callback: (node) => { /* ... */ }
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
#### 3. 图片文件路径
|
|
341
|
+
|
|
342
|
+
:::warning{title=Tip}
|
|
343
|
+
目前只支持 `png` `jpg` `jpeg` `gif` `svg` `webp` `ico` `bmp` 格式的图片
|
|
344
|
+
:::
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
{
|
|
348
|
+
text: '删除',
|
|
349
|
+
icon: './assets/icons/delete.png', // 本地图片文件
|
|
350
|
+
callback: (node) => { /* ... */ }
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
{
|
|
354
|
+
text: '复制',
|
|
355
|
+
icon: 'https://example.com/icons/copy.png', // 远程图片
|
|
356
|
+
callback: (node) => { /* ... */ }
|
|
357
|
+
}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
#### 5. HTML内容
|
|
361
|
+
```typescript
|
|
362
|
+
{
|
|
363
|
+
text: '删除',
|
|
364
|
+
icon: '<i class="fa fa-trash"></i>', // 直接插入HTML
|
|
365
|
+
callback: (node) => { /* ... */ }
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// SVG图标
|
|
369
|
+
{
|
|
370
|
+
text: '编辑',
|
|
371
|
+
icon: '<svg width="16" height="16"><path d="..."/></svg>',
|
|
372
|
+
callback: (node) => { /* ... */ }
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## 功能演示
|
|
377
|
+
<code id="react-portal" src="@/src/tutorial/extension/menu"></code>
|