@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.
Files changed (126) hide show
  1. package/dist/docs/api/logicflow-constructor/index.en.md +106 -0
  2. package/dist/docs/api/logicflow-constructor/index.zh.md +106 -0
  3. package/dist/docs/api/logicflow-constructor/use.en.md +61 -0
  4. package/dist/docs/api/logicflow-constructor/use.zh.md +61 -0
  5. package/dist/docs/api/logicflow-instance/canvas.en.md +197 -0
  6. package/dist/docs/api/logicflow-instance/canvas.zh.md +199 -0
  7. package/dist/docs/api/logicflow-instance/edge.en.md +273 -0
  8. package/dist/docs/api/logicflow-instance/edge.zh.md +273 -0
  9. package/dist/docs/api/logicflow-instance/edit-config.en.md +59 -0
  10. package/dist/docs/api/logicflow-instance/edit-config.zh.md +59 -0
  11. package/dist/docs/api/logicflow-instance/element.en.md +375 -0
  12. package/dist/docs/api/logicflow-instance/element.zh.md +379 -0
  13. package/dist/docs/api/logicflow-instance/event.en.md +326 -0
  14. package/dist/docs/api/logicflow-instance/event.zh.md +406 -0
  15. package/dist/docs/api/logicflow-instance/history.en.md +38 -0
  16. package/dist/docs/api/logicflow-instance/history.zh.md +38 -0
  17. package/dist/docs/api/logicflow-instance/index.en.md +41 -0
  18. package/dist/docs/api/logicflow-instance/index.zh.md +41 -0
  19. package/dist/docs/api/logicflow-instance/node.en.md +308 -0
  20. package/dist/docs/api/logicflow-instance/node.zh.md +308 -0
  21. package/dist/docs/api/logicflow-instance/register.en.md +76 -0
  22. package/dist/docs/api/logicflow-instance/register.zh.md +76 -0
  23. package/dist/docs/api/logicflow-instance/render-and-data.en.md +179 -0
  24. package/dist/docs/api/logicflow-instance/render-and-data.zh.md +181 -0
  25. package/dist/docs/api/logicflow-instance/text.en.md +60 -0
  26. package/dist/docs/api/logicflow-instance/text.zh.md +60 -0
  27. package/dist/docs/api/logicflow-instance/theme.en.md +179 -0
  28. package/dist/docs/api/logicflow-instance/theme.zh.md +179 -0
  29. package/dist/docs/api/runtime-model/edgeModel.en.md +29 -0
  30. package/dist/docs/api/runtime-model/edgeModel.zh.md +325 -0
  31. package/dist/docs/api/runtime-model/graphModel.en.md +275 -0
  32. package/dist/docs/api/runtime-model/graphModel.zh.md +1153 -0
  33. package/dist/docs/api/runtime-model/nodeModel.en.md +37 -0
  34. package/dist/docs/api/runtime-model/nodeModel.zh.md +644 -0
  35. package/dist/docs/api/type/MainTypes.en.md +598 -0
  36. package/dist/docs/api/type/MainTypes.zh.md +867 -0
  37. package/dist/docs/api/type/Theme.en.md +187 -0
  38. package/dist/docs/api/type/Theme.zh.md +187 -0
  39. package/dist/docs/api/type/canvas-types.en.md +25 -0
  40. package/dist/docs/api/type/canvas-types.zh.md +25 -0
  41. package/dist/docs/api/type/index.en.md +96 -0
  42. package/dist/docs/api/type/index.zh.md +99 -0
  43. package/dist/docs/api/type/node-types.en.md +21 -0
  44. package/dist/docs/api/type/node-types.zh.md +21 -0
  45. package/dist/docs/api/type/plugin-types.en.md +24 -0
  46. package/dist/docs/api/type/plugin-types.zh.md +24 -0
  47. package/dist/docs/index.md +11 -0
  48. package/dist/docs/tutorial/about.en.md +38 -0
  49. package/dist/docs/tutorial/about.zh.md +65 -0
  50. package/dist/docs/tutorial/advanced/dnd.en.md +62 -0
  51. package/dist/docs/tutorial/advanced/dnd.zh.md +52 -0
  52. package/dist/docs/tutorial/advanced/edge.en.md +64 -0
  53. package/dist/docs/tutorial/advanced/edge.zh.md +66 -0
  54. package/dist/docs/tutorial/advanced/keyboard.en.md +70 -0
  55. package/dist/docs/tutorial/advanced/keyboard.zh.md +67 -0
  56. package/dist/docs/tutorial/advanced/node.en.md +338 -0
  57. package/dist/docs/tutorial/advanced/node.zh.md +338 -0
  58. package/dist/docs/tutorial/advanced/react.en.md +106 -0
  59. package/dist/docs/tutorial/advanced/react.zh.md +114 -0
  60. package/dist/docs/tutorial/advanced/silent-mode.en.md +75 -0
  61. package/dist/docs/tutorial/advanced/silent-mode.zh.md +71 -0
  62. package/dist/docs/tutorial/advanced/snapline.en.md +54 -0
  63. package/dist/docs/tutorial/advanced/vue.en.md +249 -0
  64. package/dist/docs/tutorial/advanced/vue.zh.md +248 -0
  65. package/dist/docs/tutorial/ai.en.md +64 -0
  66. package/dist/docs/tutorial/ai.zh.md +64 -0
  67. package/dist/docs/tutorial/basic/background.en.md +50 -0
  68. package/dist/docs/tutorial/basic/canvas.en.md +164 -0
  69. package/dist/docs/tutorial/basic/canvas.zh.md +183 -0
  70. package/dist/docs/tutorial/basic/class.en.md +106 -0
  71. package/dist/docs/tutorial/basic/class.zh.md +103 -0
  72. package/dist/docs/tutorial/basic/edge.en.md +151 -0
  73. package/dist/docs/tutorial/basic/edge.zh.md +152 -0
  74. package/dist/docs/tutorial/basic/event.en.md +70 -0
  75. package/dist/docs/tutorial/basic/event.zh.md +66 -0
  76. package/dist/docs/tutorial/basic/grid.en.md +77 -0
  77. package/dist/docs/tutorial/basic/node.en.md +358 -0
  78. package/dist/docs/tutorial/basic/node.zh.md +318 -0
  79. package/dist/docs/tutorial/basic/theme.en.md +154 -0
  80. package/dist/docs/tutorial/basic/theme.zh.md +157 -0
  81. package/dist/docs/tutorial/extension/adapter.en.md +446 -0
  82. package/dist/docs/tutorial/extension/adapter.zh.md +429 -0
  83. package/dist/docs/tutorial/extension/bpmn-element.en.md +1427 -0
  84. package/dist/docs/tutorial/extension/bpmn-element.zh.md +1472 -0
  85. package/dist/docs/tutorial/extension/control.en.md +117 -0
  86. package/dist/docs/tutorial/extension/control.zh.md +118 -0
  87. package/dist/docs/tutorial/extension/curved-edge.en.md +46 -0
  88. package/dist/docs/tutorial/extension/curved-edge.zh.md +46 -0
  89. package/dist/docs/tutorial/extension/custom.en.md +142 -0
  90. package/dist/docs/tutorial/extension/custom.zh.md +138 -0
  91. package/dist/docs/tutorial/extension/dnd-panel.en.md +109 -0
  92. package/dist/docs/tutorial/extension/dnd-panel.zh.md +109 -0
  93. package/dist/docs/tutorial/extension/dynamic-group.en.md +606 -0
  94. package/dist/docs/tutorial/extension/dynamic-group.zh.md +606 -0
  95. package/dist/docs/tutorial/extension/group.en.md +217 -0
  96. package/dist/docs/tutorial/extension/group.zh.md +209 -0
  97. package/dist/docs/tutorial/extension/highlight.en.md +50 -0
  98. package/dist/docs/tutorial/extension/highlight.zh.md +50 -0
  99. package/dist/docs/tutorial/extension/insert-node-in-polyline.en.md +52 -0
  100. package/dist/docs/tutorial/extension/insert-node-in-polyline.zh.md +47 -0
  101. package/dist/docs/tutorial/extension/intro.en.md +72 -0
  102. package/dist/docs/tutorial/extension/intro.zh.md +95 -0
  103. package/dist/docs/tutorial/extension/label.en.md +136 -0
  104. package/dist/docs/tutorial/extension/label.zh.md +135 -0
  105. package/dist/docs/tutorial/extension/layout.en.md +156 -0
  106. package/dist/docs/tutorial/extension/layout.zh.md +156 -0
  107. package/dist/docs/tutorial/extension/menu.en.md +319 -0
  108. package/dist/docs/tutorial/extension/menu.zh.md +377 -0
  109. package/dist/docs/tutorial/extension/minimap.en.md +164 -0
  110. package/dist/docs/tutorial/extension/minimap.zh.md +180 -0
  111. package/dist/docs/tutorial/extension/node-resize.en.md +199 -0
  112. package/dist/docs/tutorial/extension/node-resize.zh.md +221 -0
  113. package/dist/docs/tutorial/extension/pool.en.md +227 -0
  114. package/dist/docs/tutorial/extension/pool.zh.md +227 -0
  115. package/dist/docs/tutorial/extension/proximity-connect.en.md +104 -0
  116. package/dist/docs/tutorial/extension/proximity-connect.zh.md +107 -0
  117. package/dist/docs/tutorial/extension/selection.en.md +166 -0
  118. package/dist/docs/tutorial/extension/selection.zh.md +150 -0
  119. package/dist/docs/tutorial/extension/snapshot.en.md +276 -0
  120. package/dist/docs/tutorial/extension/snapshot.zh.md +276 -0
  121. package/dist/docs/tutorial/get-started.en.md +501 -0
  122. package/dist/docs/tutorial/get-started.zh.md +139 -0
  123. package/dist/docs/tutorial/update.en.md +213 -0
  124. package/dist/docs/tutorial/update.zh.md +212 -0
  125. package/package.json +5 -3
  126. package/scripts/postinstall-ai-prompt.js +67 -0
@@ -0,0 +1,606 @@
1
+ ---
2
+ nav: Guide
3
+ group:
4
+ title: Plug-in functionality
5
+ order: 3
6
+ title: Group
7
+ order: 8
8
+ toc: content
9
+ tag: New
10
+ ---
11
+
12
+ LogicFlow supports dynamic grouping. Dynamic grouping is an enhanced version of the built-in Group node (since we’ve added Node Resize functionality and the naming of the Group node wasn’t quite appropriate, we introduced the upgraded DynamicGroup node). We will continue to enhance this plugin, and we welcome contributions from the community.
13
+
14
+ ## Demonstration
15
+
16
+ <code id="react-portal" src="@/src/tutorial/extension/dynamic-group"></code>
17
+
18
+ ## Using the Plugin
19
+
20
+ ```tsx | pure
21
+ import LogicFlow from '@logicflow/core';
22
+ import { DynamicGroup } from '@logicflow/extension';
23
+ import '@logicflow/extension/es/style/index.css';
24
+
25
+ const lf = new LogicFlow({
26
+ // ...
27
+ plugins: [DynamicGroup],
28
+ });
29
+ lf.render({
30
+ nodes: [
31
+ {
32
+ type: 'dynamic-group',
33
+ x: 300,
34
+ y: 300,
35
+ },
36
+ ],
37
+ });
38
+ ```
39
+
40
+ ## Data Format for DynamicGroup Nodes
41
+
42
+ `dynamic-group` is a special type of node in LogicFlow, so its data format is similar to that of nodes but with an additional `children` property to store the IDs of its child nodes.
43
+
44
+ ```tsx | pure
45
+ lf.render({
46
+ nodes: [
47
+ {
48
+ type: "dynamic-group",
49
+ x: 400,
50
+ y: 400,
51
+ children: ["rect_2"],
52
+ },
53
+ {
54
+ id: "rect_2",
55
+ type: "circle",
56
+ x: 400,
57
+ y: 400,
58
+ },
59
+ ],
60
+ });
61
+ ```
62
+
63
+ ## Customizing Group Nodes
64
+
65
+ In practical applications, we recommend that developers customize groups based on their business needs and assign meaningful names to these groups. For example, in BPMN, a subgroup might be named `subProcess`, and then customize the group's appearance accordingly.
66
+
67
+ ```tsx | pure
68
+ import { dynamicGroup } from "@logicflow/extension";
69
+
70
+ class CustomGroup extends dynamicGroup.view {}
71
+
72
+ class CustomGroupModel extends dynamicGroup.model {
73
+ getNodeStyle() {
74
+ const style = super.getNodeStyle();
75
+ style.stroke = "#AEAFAE";
76
+ style.strokeDasharray = "3 3";
77
+ style.strokeWidth = 1;
78
+ return style;
79
+ }
80
+ }
81
+
82
+ lf.register({
83
+ type: "my-custom-group",
84
+ view: CustomGroup,
85
+ model: CustomGroupModel,
86
+ });
87
+ ```
88
+
89
+ ## Properties and Methods of groupModel
90
+
91
+ In addition to the standard node properties, group nodes have special properties related to grouping. You can control these properties to achieve various grouping effects. For node properties and methods, see [nodeModel](../../api/runtime-model/nodeModel.en.md).
92
+
93
+ ### State Properties
94
+ ```ts
95
+ export type IRectNodeProperties = {
96
+ width?: number
97
+ height?: number
98
+ radius?: number
99
+ style?: LogicFlow.CommonTheme
100
+ textStyle?: LogicFlow.CommonTheme
101
+
102
+ [key: string]: unknown
103
+ }
104
+
105
+ export type IGroupNodeProperties = {
106
+ /**
107
+ * IDs of nodes within the group
108
+ */
109
+ children?: string[]
110
+ /**
111
+ * Whether the group node can be collapsed
112
+ */
113
+ collapsible?: boolean
114
+ /**
115
+ * Collapsed state of the group node
116
+ */
117
+ isCollapsed?: boolean
118
+ /**
119
+ * Whether to restrict the movement range of child nodes
120
+ * When enabled, child nodes can only move within the group bounds
121
+ * and cannot be dragged outside the group.
122
+ * Also limits resizing to not exceed children's floor area
123
+ * Defaults to false, allowing nodes to be dragged out of the group
124
+ */
125
+ isRestrict?: boolean
126
+ /**
127
+ * When isRestrict mode is enabled and autoResize is true,
128
+ * the parent node will automatically resize when child nodes move within it
129
+ */
130
+ autoResize?: boolean
131
+
132
+ // Default width and height for the expanded state of the group
133
+ /**
134
+ * Width and height of the group node when expanded
135
+ */
136
+ width?: number
137
+ height?: number
138
+
139
+ /**
140
+ * Width and height of the group node when collapsed
141
+ */
142
+ collapsedWidth?: number
143
+ collapsedHeight?: number
144
+
145
+ /**
146
+ * When scaling or rotating a container,
147
+ * whether to scale or rotate the nodes within the group
148
+ * Default to false. When set to true, scaling or rotating the group
149
+ * will also transform the child nodes accordingly
150
+ */
151
+ transformWithContainer?: boolean
152
+
153
+ /**
154
+ * zIndex of the group element
155
+ */
156
+ zIndex?: number
157
+ /**
158
+ * Whether the group node should automatically bring itself to the front
159
+ * When the group is selected, whether to automatically bring the group
160
+ * and its children to the top layer
161
+ */
162
+ autoToFront?: boolean
163
+
164
+ /**
165
+ * Validation function for whether nodes can be added to the group
166
+ * Allows customizing which nodes can be added to the group
167
+ */
168
+ isAllowAppendIn?: (nodeData: LogicFlow.NodeData) => boolean
169
+ } & IRectNodeProperties
170
+ ```
171
+
172
+ ### Default Configuration
173
+
174
+ Group nodes have the following default configuration:
175
+
176
+ ```ts
177
+ // Default size for expanded group
178
+ const DEFAULT_GROUP_EXPAND_WIDTH = 400
179
+ const DEFAULT_GROUP_EXPAND_HEIGHT = 230
180
+ // Default size for collapsed group
181
+ const DEFAULT_GROUP_COLLAPSE_WIDTH = 80
182
+ const DEFAULT_GROUP_COLLAPSE_HEIGHT = 60
183
+ // Default zIndex
184
+ const DEFAULT_BOTTOM_Z_INDEX = -10000
185
+ ```
186
+
187
+ Group properties can be set similarly to node properties, either in the `groupModel`'s `initNodeData` or `setAttributes` methods. It can also be directly provided in the `properties` during node initialization (recommended).
188
+
189
+ ```ts
190
+ const dynamicGroupNodeConfig = {
191
+ id: 'dynamic-group_1',
192
+ type: 'dynamic-group',
193
+ x: 500,
194
+ y: 140,
195
+ text: 'dynamic-group_1',
196
+ resizable: true,
197
+ rotatable: false,
198
+ properties: {
199
+ children: ["rect_3"],
200
+ collapsible: true, // Enable collapsing
201
+ isCollapsed: false, // Initial state is expanded
202
+ width: 420, // Width when expanded
203
+ height: 250, // Height when expanded
204
+ collapsedWidth: 80, // Width when collapsed
205
+ collapsedHeight: 60, // Height when collapsed
206
+ radius: 5, // Border radius
207
+ isRestrict: false, // Don't restrict child node movement
208
+ autoResize: false, // Don't auto-resize
209
+ transformWithContainer: true, // Transform children with group
210
+ zIndex: -1000, // Layer index
211
+ autoToFront: true, // Auto bring to front when selected
212
+ },
213
+ }
214
+ ```
215
+
216
+ ### Complete Configuration Example
217
+
218
+ Here's a complete example showing various property usage:
219
+
220
+ ```tsx | pure
221
+ import LogicFlow from '@logicflow/core'
222
+ import { DynamicGroup, dynamicGroup } from '@logicflow/extension'
223
+
224
+ // Custom group
225
+ class CustomGroup extends dynamicGroup.view {}
226
+
227
+ class CustomGroupModel extends dynamicGroup.model {
228
+ initNodeData(data) {
229
+ super.initNodeData(data)
230
+
231
+ // Set default properties
232
+ this.properties = {
233
+ ...this.properties,
234
+ collapsible: true,
235
+ autoToFront: true,
236
+ transformWithContainer: false,
237
+ }
238
+ }
239
+
240
+ // Custom group styling
241
+ getNodeStyle() {
242
+ const style = super.getNodeStyle()
243
+ style.stroke = '#1890ff'
244
+ style.strokeWidth = 2
245
+ style.fill = 'rgba(24, 144, 255, 0.1)'
246
+ return style
247
+ }
248
+
249
+ // Custom drag-over highlight style
250
+ getAddableOutlineStyle() {
251
+ const style = super.getAddableOutlineStyle()
252
+ style.stroke = '#52c41a'
253
+ style.strokeDasharray = '4 4'
254
+ style.strokeWidth = 2
255
+ return style
256
+ }
257
+
258
+ // Restrict to only allow specific node types
259
+ isAllowAppendIn(nodeData) {
260
+ return ['rect', 'circle', 'diamond'].includes(nodeData.type)
261
+ }
262
+ }
263
+
264
+ // Register custom group
265
+ lf.register({
266
+ type: 'custom-group',
267
+ view: CustomGroup,
268
+ model: CustomGroupModel,
269
+ })
270
+
271
+ // Render data
272
+ lf.render({
273
+ nodes: [
274
+ {
275
+ id: 'group_1',
276
+ type: 'custom-group',
277
+ x: 300,
278
+ y: 200,
279
+ text: 'My Group',
280
+ properties: {
281
+ children: ['node_1', 'node_2'],
282
+ collapsible: true,
283
+ width: 400,
284
+ height: 300,
285
+ isRestrict: true,
286
+ autoResize: true,
287
+ },
288
+ },
289
+ {
290
+ id: 'node_1',
291
+ type: 'rect',
292
+ x: 250,
293
+ y: 150,
294
+ text: 'Node 1',
295
+ },
296
+ {
297
+ id: 'node_2',
298
+ type: 'circle',
299
+ x: 350,
300
+ y: 250,
301
+ text: 'Node 2',
302
+ },
303
+ ],
304
+ })
305
+ ```
306
+
307
+ ## API
308
+
309
+ ### Basic Methods
310
+
311
+ #### addChild
312
+
313
+ Adds a node as a child of the group. Note that this method only establishes the relationship and does not automatically move the node into the group.
314
+
315
+ ```tsx | pure
316
+ const groupModel = lf.getNodeModelById("group_id");
317
+ const node = lf.addNode({
318
+ type: "rect",
319
+ x: groupModel.x,
320
+ y: groupModel.y,
321
+ });
322
+ groupModel.addChild(node.id);
323
+ ```
324
+
325
+ #### removeChild
326
+
327
+ Removes a child node from the group.
328
+
329
+ ```tsx | pure
330
+ const groupModel = lf.getNodeModelById("group_id");
331
+ groupModel.removeChild("node_id_1");
332
+ ```
333
+
334
+ #### toggleCollapse
335
+
336
+ Collapses or expands the group. Pass `true` to collapse, `false` to expand, or no parameter to toggle current state.
337
+
338
+ ```tsx | pure
339
+ const groupModel = lf.getNodeModelById('group_id');
340
+ // Collapse the group
341
+ groupModel.toggleCollapse(true);
342
+ // Expand the group
343
+ groupModel.toggleCollapse(false);
344
+ // Toggle current state
345
+ groupModel.toggleCollapse();
346
+ ```
347
+
348
+ #### getNodesInGroup
349
+
350
+ Gets all node IDs within the group.
351
+
352
+ ```tsx | pure
353
+ const groupModel = lf.getNodeModelById('group_id') as DynamicGroupNodeModel;
354
+ const nodeIds = groupModel.getNodesInGroup(groupModel);
355
+ console.log('Node IDs in group:', nodeIds);
356
+ ```
357
+
358
+ ### Validation Methods
359
+
360
+ #### isAllowAppendIn(nodeData)
361
+
362
+ Checks whether the specified node can be added to this group. By default, all nodes can be added.
363
+
364
+ ```tsx | pure
365
+ class MyGroupModel extends dynamicGroup.model {
366
+ isAllowAppendIn(nodeData) {
367
+ // Only allow nodes of type "custom-rect" to be added to this group
368
+ return nodeData.type === "custom-rect";
369
+ }
370
+ }
371
+ ```
372
+
373
+ :::info{title=Tip}
374
+ If a node is not allowed to be added to a group, it will still be displayed at the user's drop location, but it will not be part of the group. If you want to delete the node, you can listen for the `group:not-allowed` event and manually remove the node.
375
+ :::
376
+
377
+ ### Styling Methods
378
+
379
+ #### getAddableOutlineStyle
380
+
381
+ Sets the highlight style for the group when dragging a node over it.
382
+
383
+ ```tsx | pure
384
+ class MyGroupModel extends dynamicGroup.model {
385
+ getAddableOutlineStyle() {
386
+ const style = super.getAddableOutlineStyle();
387
+ style.stroke = "#AEAFAE";
388
+ style.strokeDasharray = "3 3";
389
+ return style;
390
+ }
391
+ }
392
+ ```
393
+
394
+ #### getResizeOutlineStyle
395
+
396
+ Sets the border style when resizing the group.
397
+
398
+ ```tsx | pure
399
+ class MyGroupModel extends dynamicGroup.model {
400
+ getResizeOutlineStyle() {
401
+ const style = super.getResizeOutlineStyle();
402
+ style.stroke = "#1890ff";
403
+ style.strokeWidth = 1;
404
+ return style;
405
+ }
406
+ }
407
+ ```
408
+
409
+ #### getAnchorStyle
410
+
411
+ Sets the anchor point style for the group.
412
+
413
+ ```tsx | pure
414
+ class MyGroupModel extends dynamicGroup.model {
415
+ getAnchorStyle() {
416
+ const style = super.getAnchorStyle();
417
+ style.stroke = "#1890ff";
418
+ style.fill = "#ffffff";
419
+ return style;
420
+ }
421
+ }
422
+ ```
423
+
424
+ ### Utility Methods
425
+
426
+ #### setAllowAppendChild
427
+
428
+ Sets whether the group is in a state that allows adding child nodes.
429
+
430
+ ```tsx | pure
431
+ const groupModel = lf.getNodeModelById('group_id') as DynamicGroupNodeModel;
432
+ // Enable adding children
433
+ groupModel.setAllowAppendChild(true);
434
+ // Disable adding children
435
+ groupModel.setAllowAppendChild(false);
436
+ ```
437
+
438
+ #### toBack
439
+
440
+ Sends the group node to the back layer.
441
+
442
+ ```tsx | pure
443
+ const groupModel = lf.getNodeModelById('group_id') as DynamicGroupNodeModel;
444
+ groupModel.toBack();
445
+ ```
446
+
447
+ ## Plugin Class API
448
+
449
+ The DynamicGroup plugin class provides some utility methods that you can access through `lf.graphModel.dynamicGroup`:
450
+
451
+ ### getGroupByNodeId
452
+
453
+ Get the group that a node belongs to by node ID.
454
+
455
+ ```tsx | pure
456
+ const nodeGroup = lf.graphModel.dynamicGroup.getGroupByNodeId('node_1');
457
+ if (nodeGroup) {
458
+ console.log('Node belongs to group:', nodeGroup.getData());
459
+ }
460
+ ```
461
+
462
+ ### getGroupByBounds
463
+
464
+ Get the group at the specified position by bounds. When groups overlap, returns the topmost group.
465
+
466
+ ```tsx | pure
467
+ const bounds = {
468
+ minX: 100,
469
+ minY: 100,
470
+ maxX: 200,
471
+ maxY: 200
472
+ };
473
+ const nodeData = { id: 'test', type: 'rect' };
474
+ const group = lf.graphModel.dynamicGroup.getGroupByBounds(bounds, nodeData);
475
+ if (group) {
476
+ console.log('Area belongs to group:', group.getData());
477
+ }
478
+ ```
479
+
480
+ ### sendNodeToFront
481
+
482
+ Bring an element to the front. If it's a group, also brings its child elements to the front.
483
+
484
+ ```tsx | pure
485
+ const nodeModel = lf.getNodeModelById('group_1');
486
+ lf.graphModel.dynamicGroup.sendNodeToFront(nodeModel);
487
+ ```
488
+
489
+ ## Plugin Events
490
+
491
+ The DynamicGroup plugin triggers the following events. You can listen to these events to implement custom business logic:
492
+
493
+ ### Group-related Events
494
+
495
+ | Event Name | Description | Event Object |
496
+ | :------------------ | :--------------------------------------------------- | :--------------------------------------------------------------- |
497
+ | `group:add-node` | Triggered when a node is added to a group | `{ data: Group data, childId: ID of newly added node }` |
498
+ | `group:remove-node` | Triggered when a node is removed from a group | `{ data: Group data, childId: ID of removed node }` |
499
+ | `group:not-allowed` | Triggered when a node is not allowed to join a group | `{ group: Group data, node: Information of the forbidden node }` |
500
+
501
+ ### Event Listening Examples
502
+
503
+ ```tsx | pure
504
+ // Listen for node addition to group
505
+ lf.on('group:add-node', ({ data, childId }) => {
506
+ console.log(`Node ${childId} has been added to group ${data.id}`)
507
+
508
+ // Execute custom logic here, such as updating UI state
509
+ updateGroupInfo(data.id, childId, 'add')
510
+ })
511
+
512
+ // Listen for node removal from group
513
+ lf.on('group:remove-node', ({ data, childId }) => {
514
+ console.log(`Node ${childId} has been removed from group ${data.id}`)
515
+
516
+ updateGroupInfo(data.id, childId, 'remove')
517
+ })
518
+
519
+ // Listen for node rejection from group
520
+ lf.on('group:not-allowed', ({ group, node }) => {
521
+ console.log(`Node ${node.id} is not allowed to join group ${group.id}`)
522
+
523
+ // Show notification
524
+ showNotification(`Node type ${node.type} cannot join this group`)
525
+
526
+ // Delete the rejected node if needed
527
+ // lf.deleteNode(node.id)
528
+ })
529
+ ```
530
+
531
+ ## Advanced Usage
532
+
533
+ ### Restriction Mode (isRestrict)
534
+
535
+ When restriction mode is enabled, child nodes will be constrained within the group bounds and cannot be dragged outside:
536
+
537
+ ```tsx | pure
538
+ const restrictedGroup = {
539
+ type: 'dynamic-group',
540
+ x: 300,
541
+ y: 200,
542
+ properties: {
543
+ isRestrict: true, // Enable restriction mode
544
+ autoResize: true, // Enable auto-resize
545
+ width: 400,
546
+ height: 300,
547
+ },
548
+ }
549
+
550
+ // In restriction mode, the group will auto-resize to accommodate all child nodes when they move
551
+ ```
552
+
553
+ ### Collapse Feature Details
554
+
555
+ The group's collapse feature automatically handles:
556
+
557
+ 1. **Node Hiding**: Hide all child nodes when collapsed, restore visibility when expanded
558
+ 2. **Edge Handling**: Automatically create virtual edges to represent connections between group interior and exterior
559
+ 3. **Size Changes**: Switch between collapsed and expanded dimensions
560
+
561
+ ```tsx | pure
562
+ // Listen for group state changes
563
+ lf.on('node:properties-change', ({ id, properties, preProperties }) => {
564
+ const node = lf.getNodeModelById(id)
565
+ if (node?.isGroup) {
566
+ const wasCollapsed = preProperties.isCollapsed
567
+ const isCollapsed = properties.isCollapsed
568
+
569
+ if (wasCollapsed !== isCollapsed) {
570
+ console.log(`Group ${id} state changed: ${isCollapsed ? 'collapsed' : 'expanded'}`)
571
+ }
572
+ }
573
+ })
574
+ ```
575
+
576
+ ### Transform with Container
577
+
578
+ When `transformWithContainer` is enabled, scaling or rotating the group will also transform child nodes:
579
+
580
+ ```tsx | pure
581
+ const transformGroup = {
582
+ type: 'dynamic-group',
583
+ x: 300,
584
+ y: 200,
585
+ properties: {
586
+ transformWithContainer: true, // Enable synchronized transformation
587
+ width: 400,
588
+ height: 300,
589
+ },
590
+ }
591
+
592
+ // Now when scaling or rotating the group, child nodes will maintain relative positions and transform accordingly
593
+ ```
594
+
595
+ :::info{title=How-to-Prevent-Nodes-from-Connecting-to-a-Group?}
596
+
597
+ Groups are a special type of node, so it is still possible to use [custom connection rules](../advanced/node.en.md#connection-rules) to prevent nodes from connecting directly to groups. However, do not set the number of anchors on a group to 0, as connections are used to represent the relationship between internal and external nodes when the group is collapsed.
598
+
599
+ :::
600
+
601
+ ## About Swimlanes
602
+ :::info{title=About-Swimlanes}
603
+
604
+ Grouping functionality is not the same as swimlanes; developers need to implement swimlanes based on the grouping functionality. Future LogicFlow support for BPMN will include full BPMN swimlane support. Contributions for implementations are welcome.
605
+
606
+ :::