@logicflow/extension 2.2.3 → 2.2.4-alpha.1

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 (51) hide show
  1. package/dist/index.min.js +1 -1
  2. package/dist/index.min.js.map +1 -1
  3. package/es/constant/events.d.ts +9 -0
  4. package/es/constant/events.js +11 -0
  5. package/es/dynamic-group/index.d.ts +52 -3
  6. package/es/dynamic-group/index.js +294 -117
  7. package/es/dynamic-group/model.d.ts +56 -3
  8. package/es/dynamic-group/model.js +148 -25
  9. package/es/dynamic-group/node.d.ts +1 -0
  10. package/es/dynamic-group/node.js +52 -19
  11. package/es/dynamic-group/titleText.d.ts +8 -0
  12. package/es/dynamic-group/titleText.js +84 -0
  13. package/es/dynamic-group/utils.d.ts +69 -0
  14. package/es/dynamic-group/utils.js +162 -0
  15. package/es/index.css +321 -1
  16. package/es/index.d.ts +1 -0
  17. package/es/index.js +1 -0
  18. package/es/index.less +1 -0
  19. package/es/materials/group/GroupNode.js +5 -2
  20. package/es/materials/group/index.js +7 -6
  21. package/es/pool/LaneModel.d.ts +1 -1
  22. package/es/pool/PoolModel.d.ts +1 -1
  23. package/es/pool/index.d.ts +3 -2
  24. package/es/pool/index.js +44 -60
  25. package/es/style/index.css +321 -1
  26. package/es/style/index.less +381 -0
  27. package/lib/constant/events.d.ts +9 -0
  28. package/lib/constant/events.js +14 -0
  29. package/lib/dynamic-group/index.d.ts +52 -3
  30. package/lib/dynamic-group/index.js +293 -116
  31. package/lib/dynamic-group/model.d.ts +56 -3
  32. package/lib/dynamic-group/model.js +148 -25
  33. package/lib/dynamic-group/node.d.ts +1 -0
  34. package/lib/dynamic-group/node.js +53 -20
  35. package/lib/dynamic-group/titleText.d.ts +8 -0
  36. package/lib/dynamic-group/titleText.js +90 -0
  37. package/lib/dynamic-group/utils.d.ts +69 -0
  38. package/lib/dynamic-group/utils.js +172 -1
  39. package/lib/index.css +321 -1
  40. package/lib/index.d.ts +1 -0
  41. package/lib/index.js +1 -0
  42. package/lib/index.less +1 -0
  43. package/lib/materials/group/GroupNode.js +5 -2
  44. package/lib/materials/group/index.js +7 -6
  45. package/lib/pool/LaneModel.d.ts +1 -1
  46. package/lib/pool/PoolModel.d.ts +1 -1
  47. package/lib/pool/index.d.ts +3 -2
  48. package/lib/pool/index.js +44 -60
  49. package/lib/style/index.css +321 -1
  50. package/lib/style/index.less +381 -0
  51. package/package.json +8 -8
@@ -24,6 +24,17 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
24
24
  var __exportStar = (this && this.__exportStar) || function(m, exports) {
25
25
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
26
26
  };
27
+ var __values = (this && this.__values) || function(o) {
28
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
29
+ if (m) return m.call(o);
30
+ if (o && typeof o.length === "number") return {
31
+ next: function () {
32
+ if (o && i >= o.length) o = void 0;
33
+ return { value: o && o[i++], done: !o };
34
+ }
35
+ };
36
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
37
+ };
27
38
  var __read = (this && this.__read) || function (o, n) {
28
39
  var m = typeof Symbol === "function" && o[Symbol.iterator];
29
40
  if (!m) return o;
@@ -55,6 +66,7 @@ var core_1 = require("@logicflow/core");
55
66
  var lodash_es_1 = require("lodash-es");
56
67
  var node_1 = require("./node");
57
68
  var model_1 = require("./model");
69
+ var events_1 = require("../constant/events");
58
70
  var utils_1 = require("./utils");
59
71
  __exportStar(require("./node"), exports);
60
72
  __exportStar(require("./model"), exports);
@@ -69,85 +81,209 @@ var DynamicGroup = /** @class */ (function () {
69
81
  function DynamicGroup(_a) {
70
82
  var lf = _a.lf, options = _a.options;
71
83
  var _this = this;
84
+ /**
85
+ * 为 true 时禁止手动将边连到/从 dynamic-group 节点本身。
86
+ * 默认 false,与历史行为一致;折叠虚拟边不受影响。
87
+ */
88
+ this.disallowEdgeConnectToGroup = false;
89
+ /**
90
+ * 删除 dynamic-group 时是否级联删除其成员。
91
+ * 默认 true,与 v1.1 以来行为一致;为 false 时仅删除分组,成员保留并解除归属。
92
+ */
93
+ this.cascadeDeleteChildren = true;
94
+ this.sensorOutline = {};
72
95
  this.topGroupZIndex = DEFAULT_BOTTOM_Z_INDEX;
73
96
  // 存储节点与 group 的映射关系
74
97
  this.nodeGroupMap = new Map();
98
+ /** 折叠态虚拟边 id → 所属分组与真实边 id */
99
+ this.collapsedVirtualEdges = new Map();
100
+ /** 折叠隐藏的真实边 id → 分组 id */
101
+ this.collapsedRealEdgeToGroup = new Map();
102
+ /**
103
+ * 折叠态删边:删虚拟边时连带删对应真实边,防止展开后「边复活」(#2395)。
104
+ * Gateway 双分支等场景下,每条虚拟边只映射一条真实边。
105
+ */
106
+ this.onEdgeDelete = function (_a) {
107
+ var e_1, _b;
108
+ var edge = _a.data;
109
+ var virtualMapping = _this.collapsedVirtualEdges.get(edge.id);
110
+ if (virtualMapping) {
111
+ _this.collapsedVirtualEdges.delete(edge.id);
112
+ _this.collapsedRealEdgeToGroup.delete(virtualMapping.realEdgeId);
113
+ // 仅删除本条映射的真实边,不影响同组其它分支
114
+ if (_this.lf.getEdgeModelById(virtualMapping.realEdgeId)) {
115
+ _this.lf.deleteEdge(virtualMapping.realEdgeId);
116
+ }
117
+ return;
118
+ }
119
+ // 真实边被其它路径删除时,同步清理登记与分组内快照
120
+ var groupId = _this.collapsedRealEdgeToGroup.get(edge.id);
121
+ if (groupId) {
122
+ _this.collapsedRealEdgeToGroup.delete(edge.id);
123
+ }
124
+ try {
125
+ for (var _c = __values(_this.collapsedVirtualEdges.entries()), _d = _c.next(); !_d.done; _d = _c.next()) {
126
+ var _e = __read(_d.value, 2), virtualId = _e[0], info = _e[1];
127
+ if (info.realEdgeId === edge.id) {
128
+ _this.collapsedVirtualEdges.delete(virtualId);
129
+ }
130
+ }
131
+ }
132
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
133
+ finally {
134
+ try {
135
+ if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
136
+ }
137
+ finally { if (e_1) throw e_1.error; }
138
+ }
139
+ };
75
140
  this.onSelectionDrop = function () {
141
+ _this.clearDragTargetHighlight();
76
142
  var selectedNodes = _this.lf.graphModel.getSelectElements().nodes;
77
143
  selectedNodes.forEach(function (node) {
78
144
  _this.addNodeToGroup(node);
79
145
  });
80
146
  };
81
- this.onNodeAddOrDrop = function (_a) {
147
+ this.onNodeAdd = function (_a) {
148
+ var node = _a.data;
149
+ _this.syncGroupChildren(node);
150
+ };
151
+ this.onNodeDndAdd = function (_a) {
152
+ var node = _a.data;
153
+ _this.syncGroupChildren(node);
154
+ _this.addNodeToGroup(node);
155
+ _this.clearDragTargetHighlight();
156
+ };
157
+ this.onNodeDrop = function (_a) {
82
158
  var node = _a.data;
159
+ _this.clearDragTargetHighlight();
83
160
  _this.addNodeToGroup(node);
84
161
  };
162
+ this.onNodeMouseUp = function () {
163
+ _this.clearDragTargetHighlight();
164
+ };
165
+ this.detachNodeFromGroup = function (groupId, nodeId) {
166
+ var group = _this.lf.getNodeModelById(groupId);
167
+ if (!group)
168
+ return;
169
+ group.removeChild(nodeId);
170
+ _this.nodeGroupMap.delete(nodeId);
171
+ group.setAllowAppendChild(false);
172
+ };
173
+ this.releaseGroupMembers = function (groupModel) {
174
+ if (groupModel.isCollapsed) {
175
+ // 复用展开路径恢复真实边与成员可见性,避免删虚拟边时误删真实边
176
+ groupModel.toggleCollapse(false);
177
+ }
178
+ (0, lodash_es_1.forEach)(Array.from(groupModel.children), function (childId) {
179
+ _this.detachNodeFromGroup(groupModel.id, childId);
180
+ });
181
+ };
182
+ this.removeChildFromOtherGroups = function (childId, ownerGroupId) {
183
+ var preGroupId = _this.nodeGroupMap.get(childId);
184
+ if (preGroupId && preGroupId !== ownerGroupId) {
185
+ var preGroup = _this.lf.getNodeModelById(preGroupId);
186
+ preGroup === null || preGroup === void 0 ? void 0 : preGroup.removeChild(childId);
187
+ }
188
+ (0, lodash_es_1.forEach)(_this.lf.graphModel.nodes, function (node) {
189
+ var _a;
190
+ if (!node.isGroup || node.id === ownerGroupId)
191
+ return;
192
+ var group = node;
193
+ if ((_a = group.children) === null || _a === void 0 ? void 0 : _a.has(childId)) {
194
+ group.removeChild(childId);
195
+ }
196
+ });
197
+ };
198
+ this.setNodeGroup = function (groupId, childId) {
199
+ _this.removeChildFromOtherGroups(childId, groupId);
200
+ _this.nodeGroupMap.set(childId, groupId);
201
+ };
202
+ this.syncGroupChildren = function (node) {
203
+ var nodeModel = _this.lf.getNodeModelById(node.id);
204
+ if (!(nodeModel === null || nodeModel === void 0 ? void 0 : nodeModel.isGroup))
205
+ return;
206
+ var group = nodeModel;
207
+ (0, lodash_es_1.forEach)(Array.from(group.children), function (childId) {
208
+ _this.setNodeGroup(node.id, childId);
209
+ });
210
+ // 新增 group 时进行 this.topGroupZIndex 的校准更新
211
+ _this.calibrateTopGroupZIndex([node]);
212
+ _this.onNodeSelect({
213
+ data: node,
214
+ isSelected: false,
215
+ isMultiple: false,
216
+ });
217
+ };
85
218
  this.addNodeToGroup = function (node) {
219
+ var nodeModel = _this.lf.getNodeModelById(node.id);
220
+ var bounds = nodeModel === null || nodeModel === void 0 ? void 0 : nodeModel.getBounds();
221
+ if (!nodeModel || !bounds)
222
+ return;
86
223
  // 1. 如果该节点之前已经在 group 中了,则将其从之前的 group 移除
87
224
  var preGroupId = _this.nodeGroupMap.get(node.id);
88
- if (preGroupId) {
89
- var group = _this.lf.getNodeModelById(preGroupId);
90
- group.removeChild(node.id);
91
- _this.nodeGroupMap.delete(node.id);
92
- group.setAllowAppendChild(false);
93
- }
94
225
  // 2. 然后再判断这个节点是否在某个 group 范围内,如果是,则将其添加到对应的 group 中
95
- var nodeModel = _this.lf.getNodeModelById(node.id);
96
- var bounds = nodeModel === null || nodeModel === void 0 ? void 0 : nodeModel.getBounds();
97
- if (nodeModel && bounds) {
98
- // TODO: 确认下面的注释内容
99
- // https://github.com/didi/LogicFlow/issues/1261
100
- // 当使用 SelectionSelect 框选后触发 lf.addNode(Group)
101
- // 会触发 appendNodeToGroup() 的执行
102
- // 由于 this.getGroup() 会判断 node.id !== nodeData.id
103
- // 因此当 addNode 是 Group 类型时,this.getGroup() 会一直返回空
104
- // 导致了下面这段代码无法执行,也就是无法将当前添加的 Group 添加到 this.nodeGroupMap 中
105
- // 这导致了折叠分组时触发的 foldEdge() 无法正确通过 getNodeGroup() 拿到正确的 groupId
106
- // 从而导致折叠分组时一直都会创建一个虚拟边
107
- // 而初始化分组时由于正确设置了nodeGroupMap的数据,因此不会产生虚拟边的错误情况
108
- if (nodeModel.isGroup) {
109
- var group_1 = nodeModel;
110
- (0, lodash_es_1.forEach)(Array.from(group_1.children), function (childId) {
111
- _this.nodeGroupMap.set(childId, node.id);
112
- });
113
- // 新增 node 时进行 this.topGroupZIndex 的校准更新
114
- _this.calibrateTopGroupZIndex([node]);
115
- _this.onNodeSelect({
116
- data: node,
117
- isSelected: false,
118
- isMultiple: false,
226
+ // TODO: 找到这个范围内的 groupModel, 并加 node 添加到该 group
227
+ var targetGroup = _this.getGroupByBounds(bounds, node);
228
+ // 同组内移动,成员关系不变(#2412)
229
+ if (preGroupId && (targetGroup === null || targetGroup === void 0 ? void 0 : targetGroup.id) === preGroupId) {
230
+ return;
231
+ }
232
+ if (!targetGroup) {
233
+ if (preGroupId) {
234
+ _this.detachNodeFromGroup(preGroupId, node.id);
235
+ }
236
+ return;
237
+ }
238
+ if (!preGroupId) {
239
+ if (targetGroup.isAllowAppendIn(node)) {
240
+ targetGroup.addChild(node.id);
241
+ // 建立节点与 group 的映射关系放在了 group.addChild 触发的事件中,与直接调用 addChild 的行为保持一致
242
+ }
243
+ else {
244
+ // 抛出不允许插入的事件
245
+ _this.lf.emit(events_1.ExtensionEventType.GROUP_NOT_ALLOWED, {
246
+ group: targetGroup.getData(),
247
+ node: node,
119
248
  });
120
249
  }
121
- // TODO: 找到这个范围内的 groupModel, 并加 node 添加到该 group
122
- var group = _this.getGroupByBounds(bounds, node);
123
- if (group) {
124
- var isAllowAppendIn = group.isAllowAppendIn(node);
125
- if (isAllowAppendIn) {
126
- group.addChild(node.id);
127
- // 建立节点与 group 的映射关系放在了 group.addChild 触发的事件中,与直接调用 addChild 的行为保持一致
128
- group.setAllowAppendChild(false);
129
- }
130
- else {
131
- // 抛出不允许插入的事件
132
- _this.lf.emit('group:not-allowed', {
133
- group: group.getData(),
134
- node: node,
135
- });
136
- }
250
+ return;
251
+ }
252
+ if (targetGroup.isAllowAppendIn(node)) {
253
+ _this.detachNodeFromGroup(preGroupId, node.id);
254
+ targetGroup.addChild(node.id);
255
+ // 建立节点与 group 的映射关系放在了 group.addChild 触发的事件中,与直接调用 addChild 的行为保持一致
256
+ }
257
+ else {
258
+ var preGroup = _this.lf.getNodeModelById(preGroupId);
259
+ if (preGroup && (0, utils_1.isBoundsInGroup)(bounds, preGroup)) {
260
+ return;
137
261
  }
262
+ _this.detachNodeFromGroup(preGroupId, node.id);
263
+ // 抛出不允许插入的事件
264
+ _this.lf.emit(events_1.ExtensionEventType.GROUP_NOT_ALLOWED, {
265
+ group: targetGroup.getData(),
266
+ node: node,
267
+ });
138
268
  }
139
269
  };
140
270
  this.onGroupAddNode = function (_a) {
141
271
  var groupData = _a.data, childId = _a.childId;
142
- _this.nodeGroupMap.set(childId, groupData.id);
272
+ _this.setNodeGroup(groupData.id, childId);
143
273
  };
144
274
  this.removeNodeFromGroup = function (_a) {
145
275
  var node = _a.data, model = _a.model;
146
276
  if (model.isGroup && node.children) {
147
- (0, lodash_es_1.forEach)(Array.from(node.children), function (childId) {
148
- _this.nodeGroupMap.delete(childId);
149
- _this.lf.deleteNode(childId);
150
- });
277
+ var groupModel = model;
278
+ if (_this.cascadeDeleteChildren) {
279
+ (0, lodash_es_1.forEach)(Array.from(groupModel.children), function (childId) {
280
+ _this.nodeGroupMap.delete(childId);
281
+ _this.lf.deleteNode(childId);
282
+ });
283
+ }
284
+ else {
285
+ _this.releaseGroupMembers(groupModel);
286
+ }
151
287
  }
152
288
  var groupId = _this.nodeGroupMap.get(node.id);
153
289
  if (groupId) {
@@ -233,12 +369,8 @@ var DynamicGroup = /** @class */ (function () {
233
369
  }
234
370
  };
235
371
  this.onNodeMove = function (_a) {
236
- var deltaX = _a.deltaX, deltaY = _a.deltaY, data = _a.data;
237
- var id = data.id, x = data.x, y = data.y, properties = data.properties;
238
- if (!properties) {
239
- return;
240
- }
241
- var width = properties.width, height = properties.height;
372
+ var data = _a.data;
373
+ var id = data.id;
242
374
  var groupId = _this.nodeGroupMap.get(id);
243
375
  if (!groupId) {
244
376
  return;
@@ -249,13 +381,13 @@ var DynamicGroup = /** @class */ (function () {
249
381
  }
250
382
  // 当父节点isRestrict=true & autoResize=true
251
383
  // 子节点在父节点中移动时,父节点会自动调整大小
252
- // step1: 计算出当前child的bounds
253
- var newX = x + deltaX / 2;
254
- var newY = y + deltaY / 2;
255
- var minX = newX - width / 2;
256
- var minY = newY - height / 2;
257
- var maxX = newX + width / 2;
258
- var maxY = newY + height / 2;
384
+ var childModel = _this.lf.getNodeModelById(id);
385
+ if (!childModel) {
386
+ return;
387
+ }
388
+ // node:mousemove data onDragging 之前采集,坐标滞后;
389
+ // 此时子节点 model 已更新,直接读取 getBounds()。
390
+ var _b = childModel.getBounds(), minX = _b.minX, minY = _b.minY, maxX = _b.maxX, maxY = _b.maxY;
259
391
  // step2:比较当前child.bounds与parent.bounds的差异,比如child.minX<parent.minX,那么parent.minX=child.minX
260
392
  var hasChange = false;
261
393
  var groupBounds = groupModel.getBounds();
@@ -287,9 +419,24 @@ var DynamicGroup = /** @class */ (function () {
287
419
  groupModel.moveTo(newGroupX, newGroupY);
288
420
  groupModel.width = newGroupWidth;
289
421
  groupModel.height = newGroupHeight;
422
+ groupModel.updateExpandedSize(newGroupWidth, newGroupHeight);
423
+ groupModel.setTextPosition();
424
+ };
425
+ this.onNodeResize = function (_a) {
426
+ var model = _a.model;
427
+ if ((model === null || model === void 0 ? void 0 : model.isGroup) && !model.isCollapsed) {
428
+ ;
429
+ model.setTextPosition();
430
+ }
290
431
  };
291
432
  this.onGraphRendered = function (_a) {
292
433
  var data = _a.data;
434
+ // lf.render / graphDataToModel 不会逐节点触发 node:delete,需在整图重建时重置插件侧状态
435
+ _this.nodeGroupMap.clear();
436
+ _this.collapsedVirtualEdges.clear();
437
+ _this.collapsedRealEdgeToGroup.clear();
438
+ _this.activeGroup = undefined;
439
+ _this.topGroupZIndex = DEFAULT_BOTTOM_Z_INDEX;
293
440
  (0, lodash_es_1.forEach)(data.nodes, function (node) {
294
441
  if (node.children) {
295
442
  (0, lodash_es_1.forEach)(node.children, function (childId) {
@@ -317,6 +464,20 @@ var DynamicGroup = /** @class */ (function () {
317
464
  return this.lf.getNodeModelById(groupId);
318
465
  }
319
466
  };
467
+ DynamicGroup.prototype.registerCollapsedVirtualEdge = function (virtualId, groupId, realEdgeId) {
468
+ // 双向索引:删虚拟边时能找到真实边;删真实边时能清理虚拟边登记
469
+ this.collapsedVirtualEdges.set(virtualId, { groupId: groupId, realEdgeId: realEdgeId });
470
+ this.collapsedRealEdgeToGroup.set(realEdgeId, groupId);
471
+ };
472
+ DynamicGroup.prototype.unregisterCollapsedVirtualEdge = function (virtualId) {
473
+ var info = this.collapsedVirtualEdges.get(virtualId);
474
+ if (info) {
475
+ this.collapsedVirtualEdges.delete(virtualId);
476
+ if (this.collapsedRealEdgeToGroup.get(info.realEdgeId) === info.groupId) {
477
+ this.collapsedRealEdgeToGroup.delete(info.realEdgeId);
478
+ }
479
+ }
480
+ };
320
481
  /**
321
482
  * 获取自定位置及其所属分组
322
483
  * 当分组重合时,优先返回最上层的分组
@@ -425,6 +586,12 @@ var DynamicGroup = /** @class */ (function () {
425
586
  });
426
587
  this.topGroupZIndex = max;
427
588
  };
589
+ DynamicGroup.prototype.clearDragTargetHighlight = function () {
590
+ if (this.activeGroup) {
591
+ this.activeGroup.setAllowAppendChild(false);
592
+ this.activeGroup = undefined;
593
+ }
594
+ };
428
595
  DynamicGroup.prototype.removeChildrenInGroupNodeData = function (nodeData) {
429
596
  var _a;
430
597
  var newNodeData = (0, lodash_es_1.cloneDeep)(nodeData);
@@ -507,35 +674,22 @@ var DynamicGroup = /** @class */ (function () {
507
674
  * @param newHeight
508
675
  */
509
676
  DynamicGroup.prototype.checkGroupBoundsWithChildren = function (groupModel, deltaX, deltaY, newWidth, newHeight) {
510
- if (groupModel.children) {
511
- var children = groupModel.children, x = groupModel.x, y = groupModel.y;
512
- // 根据deltaX和deltaY计算出当前model的bounds
513
- var newX = x + deltaX / 2;
514
- var newY = y + deltaY / 2;
515
- var groupMinX = newX - newWidth / 2;
516
- var groupMinY = newY - newHeight / 2;
517
- var groupMaxX = newX + newWidth / 2;
518
- var groupMaxY = newY + newHeight / 2;
519
- var childrenArray = Array.from(children);
520
- for (var i = 0; i < childrenArray.length; i++) {
521
- var childId = childrenArray[i];
522
- var child = this.lf.getNodeModelById(childId);
523
- if (!child) {
524
- continue;
525
- }
526
- var childBounds = child.getBounds();
527
- var minX = childBounds.minX, minY = childBounds.minY, maxX = childBounds.maxX, maxY = childBounds.maxY;
528
- // parent:resize后的bounds不能小于child:bounds,否则阻止其resize
529
- var canResize = groupMinX <= minX &&
530
- groupMinY <= minY &&
531
- groupMaxX >= maxX &&
532
- groupMaxY >= maxY;
533
- if (!canResize) {
534
- return false;
535
- }
536
- }
677
+ var _this = this;
678
+ var childrenBounds = (0, utils_1.getChildrenBounds)(groupModel, function (id) {
679
+ return _this.lf.getNodeModelById(id);
680
+ });
681
+ if (!childrenBounds) {
682
+ return true;
537
683
  }
538
- return true;
684
+ var newX = groupModel.x + deltaX / 2;
685
+ var newY = groupModel.y + deltaY / 2;
686
+ var groupBounds = {
687
+ minX: newX - newWidth / 2,
688
+ minY: newY - newHeight / 2,
689
+ maxX: newX + newWidth / 2,
690
+ maxY: newY + newHeight / 2,
691
+ };
692
+ return (0, utils_1.isGroupBoundsContainsChildren)(groupBounds, childrenBounds);
539
693
  };
540
694
  /**
541
695
  * Group 插件的初始化方法
@@ -582,27 +736,42 @@ var DynamicGroup = /** @class */ (function () {
582
736
  }
583
737
  return true;
584
738
  });
585
- // https://github.com/didi/LogicFlow/issues/1442
586
- // https://github.com/didi/LogicFlow/issues/937
587
739
  // 添加分组节点resize规则
588
- // isRestrict限制模式下,当前model resize时不能小于children的占地面积
589
- // 并且在isRestrict限制模式下,transformWidthContainer即使设置为true,也无效
740
+ // 所有分组默认不可缩小到直接子节点占地面积以下
590
741
  graphModel.addNodeResizeRules(function (model, deltaX, deltaY, width, height) {
591
- if (model.isGroup && model.isRestrict) {
742
+ if (model.isGroup) {
592
743
  return _this.checkGroupBoundsWithChildren(model, deltaX, deltaY, width, height);
593
744
  }
594
745
  return true;
595
746
  });
596
747
  graphModel.dynamicGroup = this;
597
- lf.on('node:add,node:drop,node:dnd-add', this.onNodeAddOrDrop);
598
- lf.on('selection:drop', this.onSelectionDrop);
599
- lf.on('node:delete', this.removeNodeFromGroup);
600
- lf.on('node:drag,node:dnd-drag', this.onNodeDrag);
601
- lf.on('selection:drag', this.onSelectionDrag);
602
- lf.on('node:click', this.onNodeSelect);
603
- lf.on('node:mousemove', this.onNodeMove);
604
- lf.on('graph:rendered', this.onGraphRendered);
605
- lf.on('group:add-node', this.onGroupAddNode);
748
+ // cascadeDeleteChildren=false 时须在 core 删除「指向分组的边」之前释放成员,
749
+ // 否则折叠虚拟边被删会连带删掉真实边(graphModel.deleteNode 先删边再 emit node:delete)
750
+ this.originDeleteNode = lf.deleteNode.bind(lf);
751
+ lf.deleteNode = function (nodeId) {
752
+ var nodeModel = lf.getNodeModelById(nodeId);
753
+ if (!_this.cascadeDeleteChildren && (nodeModel === null || nodeModel === void 0 ? void 0 : nodeModel.isGroup)) {
754
+ var groupModel = nodeModel;
755
+ if (groupModel.children.size > 0) {
756
+ _this.releaseGroupMembers(groupModel);
757
+ }
758
+ }
759
+ return _this.originDeleteNode(nodeId);
760
+ };
761
+ lf.on(core_1.EventType.NODE_ADD, this.onNodeAdd);
762
+ lf.on(core_1.EventType.NODE_DND_ADD, this.onNodeDndAdd);
763
+ lf.on(core_1.EventType.NODE_DROP, this.onNodeDrop);
764
+ lf.on(core_1.EventType.NODE_MOUSEUP, this.onNodeMouseUp);
765
+ lf.on(core_1.EventType.SELECTION_DROP, this.onSelectionDrop);
766
+ lf.on(core_1.EventType.NODE_DELETE, this.removeNodeFromGroup);
767
+ lf.on(core_1.EventType.EDGE_DELETE, this.onEdgeDelete);
768
+ lf.on(events_1.NODE_DRAG_EVENTS, this.onNodeDrag);
769
+ lf.on(core_1.EventType.SELECTION_DRAG, this.onSelectionDrag);
770
+ lf.on(core_1.EventType.NODE_CLICK, this.onNodeSelect);
771
+ lf.on(core_1.EventType.NODE_MOUSEMOVE, this.onNodeMove);
772
+ lf.on(core_1.EventType.NODE_RESIZE, this.onNodeResize);
773
+ lf.on(core_1.EventType.GRAPH_RENDERED, this.onGraphRendered);
774
+ lf.on(events_1.ExtensionEventType.GROUP_ADD_NODE, this.onGroupAddNode);
606
775
  // https://github.com/didi/LogicFlow/issues/1346
607
776
  // 重写 addElements() 方法,在 addElements() 原有基础上增加对 group 内部所有 nodes 和 edges 的复制功能
608
777
  // 使用场景:addElements api 项目内部目前只在快捷键粘贴时使用(此处解决的也应该是粘贴场景的问题)
@@ -647,16 +816,24 @@ var DynamicGroup = /** @class */ (function () {
647
816
  DynamicGroup.prototype.render = function () { };
648
817
  DynamicGroup.prototype.destroy = function () {
649
818
  // 销毁监听的事件,并移除渲染的 dom 内容
650
- this.lf.off('node:add,node:drop,node:dnd-add', this.onNodeAddOrDrop);
651
- this.lf.off('selection:drop', this.onSelectionDrop);
652
- this.lf.off('node:delete', this.removeNodeFromGroup);
653
- this.lf.off('node:drag,node:dnd-drag', this.onNodeDrag);
654
- this.lf.off('selection:drag', this.onSelectionDrag);
655
- this.lf.off('node:click', this.onNodeSelect);
656
- this.lf.off('node:mousemove', this.onNodeMove);
657
- this.lf.off('graph:rendered', this.onGraphRendered);
658
- this.lf.off('group:add-node', this.onGroupAddNode);
819
+ this.lf.off(core_1.EventType.NODE_ADD, this.onNodeAdd);
820
+ this.lf.off(core_1.EventType.NODE_DND_ADD, this.onNodeDndAdd);
821
+ this.lf.off(core_1.EventType.NODE_DROP, this.onNodeDrop);
822
+ this.lf.off(core_1.EventType.NODE_MOUSEUP, this.onNodeMouseUp);
823
+ this.lf.off(core_1.EventType.SELECTION_DROP, this.onSelectionDrop);
824
+ this.lf.off(core_1.EventType.NODE_DELETE, this.removeNodeFromGroup);
825
+ this.lf.off(core_1.EventType.EDGE_DELETE, this.onEdgeDelete);
826
+ this.lf.off(events_1.NODE_DRAG_EVENTS, this.onNodeDrag);
827
+ this.lf.off(core_1.EventType.SELECTION_DRAG, this.onSelectionDrag);
828
+ this.lf.off(core_1.EventType.NODE_CLICK, this.onNodeSelect);
829
+ this.lf.off(core_1.EventType.NODE_MOUSEMOVE, this.onNodeMove);
830
+ this.lf.off(core_1.EventType.NODE_RESIZE, this.onNodeResize);
831
+ this.lf.off(core_1.EventType.GRAPH_RENDERED, this.onGraphRendered);
832
+ this.lf.off(events_1.ExtensionEventType.GROUP_ADD_NODE, this.onGroupAddNode);
659
833
  // 还原 lf.addElements 方法?
834
+ if (this.originDeleteNode) {
835
+ this.lf.deleteNode = this.originDeleteNode;
836
+ }
660
837
  // 移除 graphModel 上重写的 addNodeMoveRules 方法?
661
838
  // TODO: 讨论一下插件该具体做些什么
662
839
  };
@@ -2,6 +2,12 @@ import LogicFlow, { BaseEdgeModel, GraphModel, IRectNodeProperties, RectNodeMode
2
2
  import NodeData = LogicFlow.NodeData;
3
3
  import NodeConfig = LogicFlow.NodeConfig;
4
4
  import EdgeConfig = LogicFlow.EdgeConfig;
5
+ /** 拖拽感应外框默认样式(可通过 pluginsOptions.dynamicGroup.sensorOutline 覆盖) */
6
+ export declare const DEFAULT_SENSOR_OUTLINE: {
7
+ readonly stroke: "#feb663";
8
+ readonly strokeWidth: 2;
9
+ };
10
+ export type SensorOutlineOptions = Partial<typeof DEFAULT_SENSOR_OUTLINE>;
5
11
  export type IGroupNodeProperties = {
6
12
  /**
7
13
  * 当前分组中的节点 id
@@ -43,6 +49,11 @@ export type IGroupNodeProperties = {
43
49
  * 分组节点是否自动置顶
44
50
  */
45
51
  autoToFront?: boolean;
52
+ /**
53
+ * 是否允许手动将边连到/从本分组节点。
54
+ * 显式设置时优先于插件选项 disallowEdgeConnectToGroup。
55
+ */
56
+ allowEdgeConnect?: boolean;
46
57
  isAllowAppendIn?: (_nodeData: any) => boolean;
47
58
  } & IRectNodeProperties;
48
59
  export declare class DynamicGroupNodeModel extends RectNodeModel<IGroupNodeProperties> {
@@ -63,6 +74,28 @@ export declare class DynamicGroupNodeModel extends RectNodeModel<IGroupNodePrope
63
74
  constructor(data: NodeConfig<IGroupNodeProperties>, graphModel: GraphModel);
64
75
  initNodeData(data: LogicFlow.NodeConfig<IGroupNodeProperties>): void;
65
76
  setAttributes(): void;
77
+ getTextStyle(): Record<string, unknown> & {
78
+ [x: string]: unknown;
79
+ fill?: string | undefined;
80
+ stroke?: string | undefined;
81
+ strokeWidth?: number | undefined;
82
+ radius?: number | undefined;
83
+ rx?: number | undefined;
84
+ ry?: number | undefined;
85
+ width?: number | undefined;
86
+ height?: number | undefined;
87
+ path?: string | undefined;
88
+ overflowMode?: "default" | "autoWrap" | "ellipsis" | undefined;
89
+ textWidth?: number | undefined;
90
+ background?: LogicFlow.CommonTheme | undefined;
91
+ wrapPadding?: string | undefined;
92
+ color?: string | undefined;
93
+ fontSize: number;
94
+ lineHeight?: number | undefined;
95
+ textAnchor?: "middle" | "start" | "end" | undefined;
96
+ dominantBaseline?: "middle" | "central" | "auto" | "text-bottom" | "alphabetic" | "ideographic" | "mathematical" | "hanging" | "text-top" | undefined;
97
+ };
98
+ setProperties(properties: Partial<IGroupNodeProperties>): void;
66
99
  getData(): NodeData;
67
100
  /**
68
101
  * 获取分组内的节点
@@ -82,10 +115,15 @@ export declare class DynamicGroupNodeModel extends RectNodeModel<IGroupNodePrope
82
115
  * @param collapse {boolean} true -> 折叠;false -> 展开
83
116
  */
84
117
  toggleCollapse(collapse?: boolean): void;
118
+ getTitleHtmlRect(): import("./utils").TitleForeignObjectRect;
119
+ /**
120
+ * autoResize 更新分组尺寸后同步展开态快照,避免折叠/展开回退到旧尺寸。
121
+ */
122
+ updateExpandedSize(width: number, height: number): void;
85
123
  setTextPosition(): void;
86
124
  private collapse;
87
125
  private expand;
88
- createVirtualEdge(edgeConfig: EdgeConfig): void;
126
+ createVirtualEdge(edgeConfig: EdgeConfig, realEdgeId: string): BaseEdgeModel<LogicFlow.PropertiesType>;
89
127
  /**
90
128
  * 折叠分组的时候,需要处理分组自身的连线和分组内部子节点上的连线
91
129
  * 边的分类:
@@ -133,13 +171,28 @@ export declare class DynamicGroupNodeModel extends RectNodeModel<IGroupNodePrope
133
171
  /**
134
172
  * 重写 Group 节点的 Resize Outline
135
173
  */
174
+ /**
175
+ * 展开态手动连线是否允许连到/从分组节点本身。
176
+ * 未设置 allowEdgeConnect 时由插件 disallowEdgeConnectToGroup 决定;折叠虚拟边不受影响。
177
+ */
178
+ isManualEdgeConnectAllowed(): boolean;
179
+ getConnectedTargetRules(): import("@logicflow/core").Model.ConnectRule[];
180
+ getConnectedSourceRules(): import("@logicflow/core").Model.ConnectRule[];
181
+ /**
182
+ * 保留锚点供折叠态虚拟边使用;禁止手动连线时关闭 edgeAddable。
183
+ */
184
+ getDefaultAnchor(): {
185
+ x: number;
186
+ y: number;
187
+ id: string;
188
+ }[];
136
189
  getAnchorStyle(): LogicFlow.AnchorTheme;
137
190
  /**
138
191
  * 设置分组节点 drop 区域的样式
139
192
  */
140
193
  getAddableOutlineStyle(): {
141
- stroke: string;
142
- strokeWidth: number;
194
+ stroke: "#feb663";
195
+ strokeWidth: 2;
143
196
  strokeDasharray: string;
144
197
  fill: string;
145
198
  };