@logicflow/extension 2.2.2 → 2.2.4-alpha.0

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 (52) hide show
  1. package/es/constant/events.d.ts +9 -0
  2. package/es/constant/events.js +11 -0
  3. package/es/dynamic-group/index.d.ts +41 -3
  4. package/es/dynamic-group/index.js +281 -117
  5. package/es/dynamic-group/model.d.ts +48 -1
  6. package/es/dynamic-group/model.js +138 -23
  7. package/es/dynamic-group/node.d.ts +1 -0
  8. package/es/dynamic-group/node.js +52 -19
  9. package/es/dynamic-group/titleText.d.ts +8 -0
  10. package/es/dynamic-group/titleText.js +84 -0
  11. package/es/dynamic-group/utils.d.ts +69 -0
  12. package/es/dynamic-group/utils.js +162 -0
  13. package/es/index.css +321 -1
  14. package/es/index.d.ts +1 -0
  15. package/es/index.js +1 -0
  16. package/es/index.less +1 -0
  17. package/es/materials/group/GroupNode.js +5 -2
  18. package/es/materials/group/index.js +7 -6
  19. package/es/pool/LaneModel.d.ts +1 -1
  20. package/es/pool/PoolModel.d.ts +1 -1
  21. package/es/pool/index.d.ts +3 -2
  22. package/es/pool/index.js +44 -60
  23. package/es/style/index.css +321 -1
  24. package/es/style/index.less +381 -0
  25. package/lib/constant/events.d.ts +9 -0
  26. package/lib/constant/events.js +14 -0
  27. package/lib/dynamic-group/index.d.ts +41 -3
  28. package/lib/dynamic-group/index.js +280 -116
  29. package/lib/dynamic-group/model.d.ts +48 -1
  30. package/lib/dynamic-group/model.js +137 -22
  31. package/lib/dynamic-group/node.d.ts +1 -0
  32. package/lib/dynamic-group/node.js +53 -20
  33. package/lib/dynamic-group/titleText.d.ts +8 -0
  34. package/lib/dynamic-group/titleText.js +90 -0
  35. package/lib/dynamic-group/utils.d.ts +69 -0
  36. package/lib/dynamic-group/utils.js +172 -1
  37. package/lib/index.css +321 -1
  38. package/lib/index.d.ts +1 -0
  39. package/lib/index.js +1 -0
  40. package/lib/index.less +1 -0
  41. package/lib/materials/group/GroupNode.js +5 -2
  42. package/lib/materials/group/index.js +7 -6
  43. package/lib/pool/LaneModel.d.ts +1 -1
  44. package/lib/pool/PoolModel.d.ts +1 -1
  45. package/lib/pool/index.d.ts +3 -2
  46. package/lib/pool/index.js +44 -60
  47. package/lib/style/index.css +321 -1
  48. package/lib/style/index.less +381 -0
  49. package/package.json +6 -6
  50. package/dist/index.css +0 -1
  51. package/dist/index.min.js +0 -2
  52. package/dist/index.min.js.map +0 -1
@@ -43,6 +43,11 @@ export type IGroupNodeProperties = {
43
43
  * 分组节点是否自动置顶
44
44
  */
45
45
  autoToFront?: boolean;
46
+ /**
47
+ * 是否允许手动将边连到/从本分组节点。
48
+ * 显式设置时优先于插件选项 disallowEdgeConnectToGroup。
49
+ */
50
+ allowEdgeConnect?: boolean;
46
51
  isAllowAppendIn?: (_nodeData: any) => boolean;
47
52
  } & IRectNodeProperties;
48
53
  export declare class DynamicGroupNodeModel extends RectNodeModel<IGroupNodeProperties> {
@@ -63,6 +68,28 @@ export declare class DynamicGroupNodeModel extends RectNodeModel<IGroupNodePrope
63
68
  constructor(data: NodeConfig<IGroupNodeProperties>, graphModel: GraphModel);
64
69
  initNodeData(data: LogicFlow.NodeConfig<IGroupNodeProperties>): void;
65
70
  setAttributes(): void;
71
+ getTextStyle(): Record<string, unknown> & {
72
+ [x: string]: unknown;
73
+ fill?: string | undefined;
74
+ stroke?: string | undefined;
75
+ strokeWidth?: number | undefined;
76
+ radius?: number | undefined;
77
+ rx?: number | undefined;
78
+ ry?: number | undefined;
79
+ width?: number | undefined;
80
+ height?: number | undefined;
81
+ path?: string | undefined;
82
+ overflowMode?: "default" | "autoWrap" | "ellipsis" | undefined;
83
+ textWidth?: number | undefined;
84
+ background?: LogicFlow.CommonTheme | undefined;
85
+ wrapPadding?: string | undefined;
86
+ color?: string | undefined;
87
+ fontSize: number;
88
+ lineHeight?: number | undefined;
89
+ textAnchor?: "middle" | "start" | "end" | undefined;
90
+ dominantBaseline?: "middle" | "central" | "auto" | "text-bottom" | "alphabetic" | "ideographic" | "mathematical" | "hanging" | "text-top" | undefined;
91
+ };
92
+ setProperties(properties: Partial<IGroupNodeProperties>): void;
66
93
  getData(): NodeData;
67
94
  /**
68
95
  * 获取分组内的节点
@@ -82,10 +109,15 @@ export declare class DynamicGroupNodeModel extends RectNodeModel<IGroupNodePrope
82
109
  * @param collapse {boolean} true -> 折叠;false -> 展开
83
110
  */
84
111
  toggleCollapse(collapse?: boolean): void;
112
+ getTitleHtmlRect(): import("./utils").TitleForeignObjectRect;
113
+ /**
114
+ * autoResize 更新分组尺寸后同步展开态快照,避免折叠/展开回退到旧尺寸。
115
+ */
116
+ updateExpandedSize(width: number, height: number): void;
85
117
  setTextPosition(): void;
86
118
  private collapse;
87
119
  private expand;
88
- createVirtualEdge(edgeConfig: EdgeConfig): void;
120
+ createVirtualEdge(edgeConfig: EdgeConfig, realEdgeId: string): BaseEdgeModel<LogicFlow.PropertiesType>;
89
121
  /**
90
122
  * 折叠分组的时候,需要处理分组自身的连线和分组内部子节点上的连线
91
123
  * 边的分类:
@@ -133,6 +165,21 @@ export declare class DynamicGroupNodeModel extends RectNodeModel<IGroupNodePrope
133
165
  /**
134
166
  * 重写 Group 节点的 Resize Outline
135
167
  */
168
+ /**
169
+ * 展开态手动连线是否允许连到/从分组节点本身。
170
+ * 未设置 allowEdgeConnect 时由插件 disallowEdgeConnectToGroup 决定;折叠虚拟边不受影响。
171
+ */
172
+ isManualEdgeConnectAllowed(): boolean;
173
+ getConnectedTargetRules(): import("@logicflow/core").Model.ConnectRule[];
174
+ getConnectedSourceRules(): import("@logicflow/core").Model.ConnectRule[];
175
+ /**
176
+ * 保留锚点供折叠态虚拟边使用;禁止手动连线时关闭 edgeAddable。
177
+ */
178
+ getDefaultAnchor(): {
179
+ x: number;
180
+ y: number;
181
+ id: string;
182
+ }[];
136
183
  getAnchorStyle(): LogicFlow.AnchorTheme;
137
184
  /**
138
185
  * 设置分组节点 drop 区域的样式
@@ -56,7 +56,9 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
56
56
  return to.concat(ar || Array.prototype.slice.call(from));
57
57
  };
58
58
  import { observable, ElementType, RectNodeModel, } from '@logicflow/core';
59
- import { forEach } from 'lodash-es';
59
+ import { cloneDeep, forEach } from 'lodash-es';
60
+ import { ExtensionEventType } from '../constant/events';
61
+ import { DEFAULT_TITLE_TEXT_ALIGN, DEFAULT_TITLE_WRAP_PADDING, formatWrapPaddingCss, getTitleForeignObjectRect, parseWrapPadding, resolveTitleTextPosition, textAlignToAnchor, } from './utils';
60
62
  // 分组节点默认展开时的大小
61
63
  var DEFAULT_GROUP_EXPAND_WIDTH = 400;
62
64
  var DEFAULT_GROUP_EXPAND_HEIGHT = 230;
@@ -112,12 +114,29 @@ var DynamicGroupNodeModel = /** @class */ (function (_super) {
112
114
  this.collapsible = collapsible !== null && collapsible !== void 0 ? collapsible : true;
113
115
  this.autoToFront = autoToFront !== null && autoToFront !== void 0 ? autoToFront : false;
114
116
  this.setTextPosition();
115
- // 禁用掉 Group 节点的文本编辑能力
116
- this.text.editable = false;
117
117
  this.text.draggable = false;
118
118
  };
119
119
  DynamicGroupNodeModel.prototype.setAttributes = function () {
120
120
  _super.prototype.setAttributes.call(this);
121
+ this.setTextPosition();
122
+ };
123
+ DynamicGroupNodeModel.prototype.getTextStyle = function () {
124
+ var _a, _b, _c, _d, _e, _f;
125
+ var style = _super.prototype.getTextStyle.call(this);
126
+ var rawWrapPadding = (_d = (_c = (_b = (_a = this.properties) === null || _a === void 0 ? void 0 : _a.textStyle) === null || _b === void 0 ? void 0 : _b.wrapPadding) !== null && _c !== void 0 ? _c : style.wrapPadding) !== null && _d !== void 0 ? _d : DEFAULT_TITLE_WRAP_PADDING;
127
+ var pad = parseWrapPadding(rawWrapPadding);
128
+ var merged = __assign(__assign({ textAlign: DEFAULT_TITLE_TEXT_ALIGN }, style), { wrapPadding: formatWrapPaddingCss(rawWrapPadding) });
129
+ var overflowMode = (_e = merged.overflowMode) !== null && _e !== void 0 ? _e : 'default';
130
+ var fontSize = Number((_f = merged.fontSize) !== null && _f !== void 0 ? _f : 12);
131
+ if (overflowMode === 'ellipsis') {
132
+ merged.textHeight = pad.top + fontSize + 2 + pad.bottom;
133
+ }
134
+ merged.textAnchor = textAlignToAnchor(merged.textAlign);
135
+ merged.dominantBaseline = 'hanging';
136
+ return cloneDeep(merged);
137
+ };
138
+ DynamicGroupNodeModel.prototype.setProperties = function (properties) {
139
+ _super.prototype.setProperties.call(this, properties);
121
140
  };
122
141
  DynamicGroupNodeModel.prototype.getData = function () {
123
142
  var _this = this;
@@ -249,19 +268,57 @@ var DynamicGroupNodeModel = /** @class */ (function (_super) {
249
268
  // step 3
250
269
  this.collapseEdge(nextCollapseState, allRelatedEdges);
251
270
  };
271
+ DynamicGroupNodeModel.prototype.getTitleHtmlRect = function () {
272
+ var _a, _b, _c, _d, _e;
273
+ var style = this.getTextStyle();
274
+ var pad = parseWrapPadding((_c = (_b = (_a = this.properties) === null || _a === void 0 ? void 0 : _a.textStyle) === null || _b === void 0 ? void 0 : _b.wrapPadding) !== null && _c !== void 0 ? _c : DEFAULT_TITLE_WRAP_PADDING);
275
+ var overflowMode = ((_d = style.overflowMode) !== null && _d !== void 0 ? _d : 'default') === 'ellipsis'
276
+ ? 'ellipsis'
277
+ : 'autoWrap';
278
+ return getTitleForeignObjectRect({
279
+ x: this.x,
280
+ y: this.y,
281
+ width: this.width,
282
+ height: this.height,
283
+ overflowMode: overflowMode,
284
+ fontSize: Number((_e = style.fontSize) !== null && _e !== void 0 ? _e : 12),
285
+ pad: pad,
286
+ });
287
+ };
288
+ /**
289
+ * autoResize 更新分组尺寸后同步展开态快照,避免折叠/展开回退到旧尺寸。
290
+ */
291
+ DynamicGroupNodeModel.prototype.updateExpandedSize = function (width, height) {
292
+ this.expandWidth = width;
293
+ this.expandHeight = height;
294
+ this.setProperties({ width: width, height: height });
295
+ };
252
296
  DynamicGroupNodeModel.prototype.setTextPosition = function () {
253
- var _a = this, x = _a.x, y = _a.y, staticTextPosition = _a.staticTextPosition, text = _a.text, isCollapsed = _a.isCollapsed, width = _a.width, height = _a.height, collapsedWidth = _a.collapsedWidth, collapsedHeight = _a.collapsedHeight;
254
- if (staticTextPosition) {
255
- text.x = x;
256
- text.y = isCollapsed ? y : y - height / 2 + 15;
297
+ var _a, _b, _c, _d;
298
+ var _e = this, x = _e.x, y = _e.y, width = _e.width, height = _e.height, text = _e.text;
299
+ if (!text) {
300
+ return;
301
+ }
302
+ if (this.isCollapsed) {
303
+ if (text.x !== x || text.y !== y) {
304
+ this.text = __assign(__assign({}, text), { x: x, y: y });
305
+ }
257
306
  return;
258
307
  }
259
- text.x = isCollapsed
260
- ? x - width / 2 + collapsedWidth / 2
261
- : x + width / 2 - collapsedWidth / 2;
262
- text.y = isCollapsed
263
- ? y - height / 2 + collapsedHeight / 2
264
- : y + height / 2 - collapsedHeight / 2;
308
+ var style = this.getTextStyle();
309
+ var pad = parseWrapPadding((_c = (_b = (_a = this.properties) === null || _a === void 0 ? void 0 : _a.textStyle) === null || _b === void 0 ? void 0 : _b.wrapPadding) !== null && _c !== void 0 ? _c : DEFAULT_TITLE_WRAP_PADDING);
310
+ var textAlign = (_d = style.textAlign) !== null && _d !== void 0 ? _d : DEFAULT_TITLE_TEXT_ALIGN;
311
+ var _f = resolveTitleTextPosition({
312
+ x: x,
313
+ y: y,
314
+ width: width,
315
+ height: height,
316
+ textAlign: textAlign,
317
+ pad: pad,
318
+ }), nextX = _f.x, nextY = _f.y;
319
+ if (nextX !== text.x || nextY !== text.y) {
320
+ this.text = __assign(__assign({}, text), { x: nextX, y: nextY });
321
+ }
265
322
  };
266
323
  // 折叠操作
267
324
  DynamicGroupNodeModel.prototype.collapse = function () {
@@ -287,14 +344,17 @@ var DynamicGroupNodeModel = /** @class */ (function (_super) {
287
344
  // 设置文本位置
288
345
  this.setTextPosition();
289
346
  };
290
- DynamicGroupNodeModel.prototype.createVirtualEdge = function (edgeConfig) {
347
+ DynamicGroupNodeModel.prototype.createVirtualEdge = function (edgeConfig, realEdgeId) {
348
+ // 虚拟边仅用于折叠态展示,路径由锚点重算;不修改真实边的 pointsList
291
349
  edgeConfig.pointsList = undefined;
292
350
  var virtualEdge = this.graphModel.addEdge(edgeConfig);
293
351
  virtualEdge.virtual = true;
294
- // TODO: 强制不保存 group 连线数据???-> 为什么注释掉?是不是不能强制设置为 null,会导致无法回填
295
- // virtualEdge.getData = () => null
296
352
  virtualEdge.text.editable = false;
297
- virtualEdge.isCollapsedEdge = true; // 这一行干啥的,TODO: 项目中没搜到应用的地方,是否应该移除
353
+ virtualEdge.isCollapsedEdge = true;
354
+ // 登记虚拟边 ↔ 真实边映射,供删除虚拟边时同步删除真实边(#2395)
355
+ var registry = this.graphModel.dynamicGroup;
356
+ registry === null || registry === void 0 ? void 0 : registry.registerCollapsedVirtualEdge(virtualEdge.id, this.id, realEdgeId);
357
+ return virtualEdge;
298
358
  };
299
359
  /**
300
360
  * 折叠分组的时候,需要处理分组自身的连线和分组内部子节点上的连线
@@ -323,7 +383,11 @@ var DynamicGroupNodeModel = /** @class */ (function (_super) {
323
383
  var targetNodeId = edgeData.targetNodeId, sourceNodeId = edgeData.sourceNodeId;
324
384
  var edgeConfig = __assign(__assign({}, edgeData), { id: "".concat(edgeData.id, "__").concat(idx), text: (_a = edgeData.text) === null || _a === void 0 ? void 0 : _a.value });
325
385
  if (edge.virtual) {
386
+ // 先注销映射再删边,避免 deleteEdgeById 触发 edge:delete 时映射残留
387
+ var registry = graphModel.dynamicGroup;
388
+ registry === null || registry === void 0 ? void 0 : registry.unregisterCollapsedVirtualEdge(edge.id);
326
389
  graphModel.deleteEdgeById(edge.id);
390
+ return;
327
391
  }
328
392
  // 考虑目标节点也属于分组的情况
329
393
  var targetNodeGroup = graphModel.dynamicGroup.getGroupByNodeId(targetNodeId);
@@ -343,19 +407,25 @@ var DynamicGroupNodeModel = /** @class */ (function (_super) {
343
407
  if (_this.children.has(sourceNodeId) || _this.id === sourceNodeId) {
344
408
  edgeConfig.startPoint = undefined;
345
409
  edgeConfig.sourceNodeId = _this.id;
410
+ delete edgeConfig.sourceAnchorId;
346
411
  }
347
412
  else {
348
413
  edgeConfig.endPoint = undefined;
349
414
  edgeConfig.targetNodeId = _this.id;
415
+ delete edgeConfig.targetAnchorId;
350
416
  }
351
417
  // 如果边的起点和终点都在分组内部,则不创建新的虚拟边
352
418
  if (targetNodeGroup.id !== _this.id || sourceNodeGroup.id !== _this.id) {
353
- _this.createVirtualEdge(edgeConfig);
419
+ _this.createVirtualEdge(edgeConfig, edge.id);
354
420
  }
355
421
  edge.visible = false;
356
422
  }
357
423
  // 展开时,处理被隐藏的边的逻辑 -> expand
358
424
  if (!collapse && !edge.visible) {
425
+ // 折叠期间用户已删虚拟边并连带删掉真实边时,跳过显示
426
+ if (!graphModel.getEdgeModelById(edge.id)) {
427
+ return;
428
+ }
359
429
  // 展开分组时:判断真实边的起点和中带你是否有任一节点在已折叠分组中,如果不是,则显示真实边
360
430
  // 如果是,则修改这个边的对应目标节点 id 来创建虚拟边
361
431
  if (targetNodeGroup &&
@@ -363,16 +433,19 @@ var DynamicGroupNodeModel = /** @class */ (function (_super) {
363
433
  targetNodeGroup.isCollapsed) {
364
434
  edgeConfig.targetNodeId = targetNodeGroup.id;
365
435
  edgeConfig.endPoint = undefined;
366
- _this.createVirtualEdge(edgeConfig);
436
+ delete edgeConfig.targetAnchorId;
437
+ _this.createVirtualEdge(edgeConfig, edge.id);
367
438
  }
368
439
  else if (sourceNodeGroup &&
369
440
  sourceNodeGroup.isGroup &&
370
441
  sourceNodeGroup.isCollapsed) {
371
442
  edgeConfig.sourceNodeId = sourceNodeGroup.id;
372
443
  edgeConfig.startPoint = undefined;
373
- _this.createVirtualEdge(edgeConfig);
444
+ delete edgeConfig.sourceAnchorId;
445
+ _this.createVirtualEdge(edgeConfig, edge.id);
374
446
  }
375
447
  else {
448
+ // 保留折叠态期间隐藏边已更新的几何,勿用折叠瞬间快照覆盖(折叠态拖分组场景)
376
449
  edge.visible = true;
377
450
  }
378
451
  }
@@ -404,7 +477,7 @@ var DynamicGroupNodeModel = /** @class */ (function (_super) {
404
477
  DynamicGroupNodeModel.prototype.addChild = function (id) {
405
478
  this.children.add(id);
406
479
  var groupData = this.getData();
407
- this.graphModel.eventCenter.emit('group:add-node', {
480
+ this.graphModel.eventCenter.emit(ExtensionEventType.GROUP_ADD_NODE, {
408
481
  data: groupData,
409
482
  childId: id,
410
483
  });
@@ -416,7 +489,9 @@ var DynamicGroupNodeModel = /** @class */ (function (_super) {
416
489
  DynamicGroupNodeModel.prototype.removeChild = function (id) {
417
490
  this.children.delete(id);
418
491
  var groupData = this.getData();
419
- this.graphModel.eventCenter.emit('group:remove-node', { data: groupData });
492
+ this.graphModel.eventCenter.emit(ExtensionEventType.GROUP_REMOVE_NODE, {
493
+ data: groupData,
494
+ });
420
495
  };
421
496
  /**
422
497
  * 当 groupA 被添加到 groupB 中时,将 groupB 及 groupB 所属的 group zIndex 减 1
@@ -432,7 +507,47 @@ var DynamicGroupNodeModel = /** @class */ (function (_super) {
432
507
  // // style.stroke = 'none'
433
508
  // return style
434
509
  // }
435
- // TODO: 是否是设置 group 节点没有锚点,而不是设置成透明???
510
+ /**
511
+ * 展开态手动连线是否允许连到/从分组节点本身。
512
+ * 未设置 allowEdgeConnect 时由插件 disallowEdgeConnectToGroup 决定;折叠虚拟边不受影响。
513
+ */
514
+ DynamicGroupNodeModel.prototype.isManualEdgeConnectAllowed = function () {
515
+ var _a;
516
+ var allowEdgeConnect = ((_a = this.properties) !== null && _a !== void 0 ? _a : {}).allowEdgeConnect;
517
+ if (allowEdgeConnect !== undefined) {
518
+ return allowEdgeConnect;
519
+ }
520
+ var plugin = this.graphModel.dynamicGroup;
521
+ return !(plugin === null || plugin === void 0 ? void 0 : plugin.disallowEdgeConnectToGroup);
522
+ };
523
+ DynamicGroupNodeModel.prototype.getConnectedTargetRules = function () {
524
+ var _this = this;
525
+ var rules = _super.prototype.getConnectedTargetRules.call(this);
526
+ rules.push({
527
+ message: '分组节点不允许作为边的终点',
528
+ validate: function () { return _this.isManualEdgeConnectAllowed(); },
529
+ });
530
+ return rules;
531
+ };
532
+ DynamicGroupNodeModel.prototype.getConnectedSourceRules = function () {
533
+ var _this = this;
534
+ var rules = _super.prototype.getConnectedSourceRules.call(this);
535
+ rules.push({
536
+ message: '分组节点不允许作为边的起点',
537
+ validate: function () { return _this.isManualEdgeConnectAllowed(); },
538
+ });
539
+ return rules;
540
+ };
541
+ /**
542
+ * 保留锚点供折叠态虚拟边使用;禁止手动连线时关闭 edgeAddable。
543
+ */
544
+ DynamicGroupNodeModel.prototype.getDefaultAnchor = function () {
545
+ var anchors = _super.prototype.getDefaultAnchor.call(this);
546
+ if (this.isManualEdgeConnectAllowed()) {
547
+ return anchors;
548
+ }
549
+ return anchors.map(function (anchor) { return (__assign(__assign({}, anchor), { edgeAddable: false })); });
550
+ };
436
551
  DynamicGroupNodeModel.prototype.getAnchorStyle = function () {
437
552
  var style = _super.prototype.getAnchorStyle.call(this);
438
553
  style.stroke = 'transparent';
@@ -24,6 +24,7 @@ export declare class DynamicGroupNode<P extends IDynamicGroupNodeProps = IDynami
24
24
  getCollapseIcon(sx: number, sy: number): string;
25
25
  getExpandIcon(sx: number, sy: number): string;
26
26
  getOperateIcon(): h.JSX.Element | null;
27
+ getText(): h.JSX.Element | null;
27
28
  getShape(): h.JSX.Element | null;
28
29
  }
29
30
  export default DynamicGroupNode;
@@ -49,8 +49,10 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
49
49
  }
50
50
  return to.concat(ar || Array.prototype.slice.call(from));
51
51
  };
52
- import { h, RectNode, handleResize, } from '@logicflow/core';
52
+ import { h, RectNode, handleResize, EventType, ElementState, TextMode, } from '@logicflow/core';
53
53
  import { forEach } from 'lodash-es';
54
+ import { DG_OPERATE_BTN_HEIGHT, DG_OPERATE_BTN_WIDTH, DG_OPERATE_INSET, } from './utils';
55
+ import { DynamicGroupText } from './titleText';
54
56
  import { rotatePointAroundCenter } from '../tools/label/utils';
55
57
  var DynamicGroupNode = /** @class */ (function (_super) {
56
58
  __extends(DynamicGroupNode, _super);
@@ -171,21 +173,21 @@ var DynamicGroupNode = /** @class */ (function (_super) {
171
173
  _super.prototype.componentDidMount.call(this);
172
174
  var eventCenter = this.props.graphModel.eventCenter;
173
175
  // 在 group 旋转时,对组内的所有子节点也进行对应的旋转计算
174
- eventCenter.on('node:rotate', this.onNodeRotate);
176
+ eventCenter.on(EventType.NODE_ROTATE, this.onNodeRotate);
175
177
  // 在 group 缩放时,对组内的所有子节点也进行对应的缩放计算
176
- eventCenter.on('node:resize', this.onNodeResize);
178
+ eventCenter.on(EventType.NODE_RESIZE, this.onNodeResize);
177
179
  // 在 group 移动时,对组内的所有子节点也进行对应的移动计算
178
- eventCenter.on('node:mousemove', this.onNodeMouseMove);
180
+ eventCenter.on(EventType.NODE_MOUSEMOVE, this.onNodeMouseMove);
179
181
  // 全部渲染完成后,判断是否【主动触发一次折叠操作】
180
- eventCenter.on('graph:rendered', this.graphRendered);
182
+ eventCenter.on(EventType.GRAPH_RENDERED, this.graphRendered);
181
183
  };
182
184
  DynamicGroupNode.prototype.componentWillUnmount = function () {
183
185
  _super.prototype.componentWillUnmount.call(this);
184
186
  var eventCenter = this.props.graphModel.eventCenter;
185
- eventCenter.off('node:rotate', this.onNodeRotate);
186
- eventCenter.off('node:resize', this.onNodeResize);
187
- eventCenter.off('node:mousemove', this.onNodeMouseMove);
188
- eventCenter.off('graph:rendered', this.graphRendered);
187
+ eventCenter.off(EventType.NODE_ROTATE, this.onNodeRotate);
188
+ eventCenter.off(EventType.NODE_RESIZE, this.onNodeResize);
189
+ eventCenter.off(EventType.NODE_MOUSEMOVE, this.onNodeMouseMove);
190
+ eventCenter.off(EventType.GRAPH_RENDERED, this.graphRendered);
189
191
  };
190
192
  /**
191
193
  * 获取分组内的节点
@@ -233,8 +235,8 @@ var DynamicGroupNode = /** @class */ (function (_super) {
233
235
  DynamicGroupNode.prototype.getOperateIcon = function () {
234
236
  var model = this.props.model;
235
237
  var x = model.x, y = model.y, width = model.width, height = model.height;
236
- var sx = x - width / 2 + 10;
237
- var sy = y - height / 2 + 10;
238
+ var sx = x - width / 2 + DG_OPERATE_INSET;
239
+ var sy = y - height / 2 + DG_OPERATE_INSET;
238
240
  if (!model.collapsible)
239
241
  return null;
240
242
  var iconPath = (model === null || model === void 0 ? void 0 : model.isCollapsed)
@@ -249,8 +251,8 @@ var DynamicGroupNode = /** @class */ (function (_super) {
249
251
  });
250
252
  return h('g', {}, [
251
253
  h('rect', {
252
- height: 12,
253
- width: 14,
254
+ height: DG_OPERATE_BTN_HEIGHT,
255
+ width: DG_OPERATE_BTN_WIDTH,
254
256
  rx: 2,
255
257
  ry: 2,
256
258
  strokeWidth: 1,
@@ -259,20 +261,51 @@ var DynamicGroupNode = /** @class */ (function (_super) {
259
261
  cursor: 'pointer',
260
262
  x: sx,
261
263
  y: sy,
262
- onClick: function () {
264
+ onPointerDown: function (e) {
265
+ e.stopPropagation();
266
+ },
267
+ onClick: function (e) {
268
+ e.stopPropagation();
263
269
  // DONE: 抛出折叠或展开事件 -> 在 toggleCollapse 方法中抛出
264
270
  model.toggleCollapse(!model.isCollapsed);
265
271
  },
272
+ onDblClick: function (e) {
273
+ e.stopPropagation();
274
+ },
266
275
  }),
267
276
  operateIcon,
268
277
  ]);
269
278
  };
279
+ DynamicGroupNode.prototype.getText = function () {
280
+ var _a;
281
+ var _b = this.props, model = _b.model, graphModel = _b.graphModel;
282
+ var editConfigModel = graphModel.editConfigModel;
283
+ if (editConfigModel.nodeTextMode !== TextMode.TEXT)
284
+ return null;
285
+ if (model.state === ElementState.TEXT_EDIT)
286
+ return null;
287
+ var textShape = null;
288
+ if (model.text) {
289
+ var draggable = false;
290
+ if (editConfigModel.nodeTextDraggable && model.text.draggable) {
291
+ draggable = true;
292
+ }
293
+ textShape = h(DynamicGroupText, {
294
+ editable: editConfigModel.nodeTextEdit && ((_a = model.text.editable) !== null && _a !== void 0 ? _a : true),
295
+ model: model,
296
+ graphModel: graphModel,
297
+ draggable: draggable,
298
+ });
299
+ }
300
+ var operateIcon = this.getOperateIcon();
301
+ if (!textShape && !operateIcon)
302
+ return null;
303
+ // 文本在 getShape 之后渲染;overflow 为 autoWrap/ellipsis 时使用 foreignObject,
304
+ // 会盖住同区域的折叠按钮。将 operateIcon 叠在文本之上以保证可点击(#1099)。
305
+ return h('g', {}, textShape, operateIcon);
306
+ };
270
307
  DynamicGroupNode.prototype.getShape = function () {
271
- return h('g', {}, [
272
- this.getAppendAreaShape(),
273
- _super.prototype.getShape.call(this),
274
- this.getOperateIcon(),
275
- ]);
308
+ return h('g', {}, [this.getAppendAreaShape(), _super.prototype.getShape.call(this)]);
276
309
  };
277
310
  return DynamicGroupNode;
278
311
  }(RectNode));
@@ -0,0 +1,8 @@
1
+ import { createElement as h } from 'preact/compat';
2
+ import { BaseText, IBaseTextProps, IBaseTextState } from '@logicflow/core';
3
+ type DynamicGroupTextProps = IBaseTextProps;
4
+ export declare class DynamicGroupText extends BaseText<DynamicGroupTextProps, IBaseTextState> {
5
+ getShape(): h.JSX.Element | null;
6
+ private renderTitleHtmlText;
7
+ }
8
+ export default DynamicGroupText;
@@ -0,0 +1,84 @@
1
+ var __extends = (this && this.__extends) || (function () {
2
+ var extendStatics = function (d, b) {
3
+ extendStatics = Object.setPrototypeOf ||
4
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
6
+ return extendStatics(d, b);
7
+ };
8
+ return function (d, b) {
9
+ if (typeof b !== "function" && b !== null)
10
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
11
+ extendStatics(d, b);
12
+ function __() { this.constructor = d; }
13
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
14
+ };
15
+ })();
16
+ import { jsx as _jsx } from "preact/jsx-runtime";
17
+ import classNames from 'classnames';
18
+ import { BaseText } from '@logicflow/core';
19
+ import { formatWrapPaddingCss, getTitleForeignObjectRect, isHtmlTextOverflow, parseWrapPadding, } from './utils';
20
+ var DynamicGroupText = /** @class */ (function (_super) {
21
+ __extends(DynamicGroupText, _super);
22
+ function DynamicGroupText() {
23
+ return _super !== null && _super.apply(this, arguments) || this;
24
+ }
25
+ DynamicGroupText.prototype.getShape = function () {
26
+ var _a;
27
+ var model = this.props.model;
28
+ var value = model.text.value;
29
+ var style = model.getTextStyle();
30
+ var overflowMode = (_a = style.overflowMode) !== null && _a !== void 0 ? _a : 'default';
31
+ if (isHtmlTextOverflow(overflowMode)) {
32
+ return this.renderTitleHtmlText(value, style);
33
+ }
34
+ return _super.prototype.getShape.call(this);
35
+ };
36
+ DynamicGroupText.prototype.renderTitleHtmlText = function (value, style) {
37
+ var _a;
38
+ var _b = this.props, model = _b.model, graphModel = _b.graphModel;
39
+ var _c = model.text, editable = _c.editable, draggable = _c.draggable;
40
+ var editConfigModel = graphModel.editConfigModel;
41
+ var overflowMode = style.overflowMode;
42
+ var fontSize = Number((_a = style.fontSize) !== null && _a !== void 0 ? _a : 12);
43
+ var rawWrapPadding = style.wrapPadding;
44
+ var pad = parseWrapPadding(rawWrapPadding);
45
+ var wrapPadding = formatWrapPaddingCss(rawWrapPadding);
46
+ var _d = getTitleForeignObjectRect({
47
+ x: model.x,
48
+ y: model.y,
49
+ width: model.width,
50
+ height: model.height,
51
+ overflowMode: overflowMode,
52
+ fontSize: fontSize,
53
+ pad: pad,
54
+ }), foX = _d.foX, foY = _d.foY, foWidth = _d.foWidth, foHeight = _d.foHeight;
55
+ var isEllipsis = overflowMode === 'ellipsis';
56
+ var rows = String(value).split(/[\r\n]/g);
57
+ var isDraggable = editConfigModel.nodeTextDraggable || draggable;
58
+ return (_jsx("g", { className: classNames({
59
+ 'lf-element-text': editable,
60
+ 'lf-text-draggable': !editable && isDraggable,
61
+ 'lf-text-disabled': !editable && !isDraggable,
62
+ }), children: _jsx("foreignObject", { width: foWidth, height: foHeight, x: foX, y: foY, style: { overflow: 'visible', textAlign: 'left' }, children: _jsx("div", { className: "lf-node-text-auto-wrap lf-dg-title-html", style: {
63
+ boxSizing: 'border-box',
64
+ display: 'flex',
65
+ alignItems: 'flex-start',
66
+ justifyContent: 'stretch',
67
+ width: foWidth,
68
+ height: foHeight,
69
+ padding: wrapPadding,
70
+ }, children: _jsx("div", { className: isEllipsis
71
+ ? 'lf-node-text-ellipsis-content'
72
+ : 'lf-node-text-auto-wrap-content', title: isEllipsis ? rows.join('') : '', style: {
73
+ textAlign: style.textAlign,
74
+ fontSize: fontSize,
75
+ lineHeight: style.lineHeight,
76
+ fontFamily: style.fontFamily,
77
+ color: style.fill,
78
+ width: '100%',
79
+ }, children: rows.map(function (row) { return (_jsx("div", { className: "lf-node-text--auto-wrap-inner", children: row })); }) }) }) }) }));
80
+ };
81
+ return DynamicGroupText;
82
+ }(BaseText));
83
+ export { DynamicGroupText };
84
+ export default DynamicGroupText;
@@ -17,3 +17,72 @@ export declare function isAllowMoveTo(groupBounds: BoxBoundsPoint, node: BaseNod
17
17
  x: boolean;
18
18
  y: boolean;
19
19
  };
20
+ /**
21
+ * 计算直接子节点的 bounds 并集。
22
+ * 无有效子节点时返回 null。
23
+ */
24
+ export declare function getChildrenBounds(groupModel: {
25
+ children?: Set<string>;
26
+ }, getNodeById: (id: string) => BaseNodeModel | undefined): BoxBoundsPoint | null;
27
+ /**
28
+ * 判断 groupBounds 是否完全包含 childrenBounds。
29
+ */
30
+ export declare function isGroupBoundsContainsChildren(groupBounds: BoxBoundsPoint, childrenBounds: BoxBoundsPoint): boolean;
31
+ /** 折叠按钮距节点顶边/左边的默认 inset,与 node.getOperateIcon 一致 */
32
+ export declare const DG_OPERATE_INSET = 10;
33
+ /** @deprecated 使用 DG_OPERATE_INSET */
34
+ export declare const DG_OPERATE_INSET_TOP = 10;
35
+ export declare const DG_OPERATE_BTN_WIDTH = 14;
36
+ export declare const DG_OPERATE_BTN_HEIGHT = 12;
37
+ /** 左对齐时推荐用于避开 operator 的 wrapPadding.left(inset + btn + inset) */
38
+ export declare const DG_TITLE_LEFT_CLEARANCE: number;
39
+ export declare const DEFAULT_TITLE_WRAP_PADDING = "0,0,0,0";
40
+ export declare const DEFAULT_TITLE_TEXT_ALIGN = "center";
41
+ export type TitleBand = {
42
+ bandLeft: number;
43
+ bandTop: number;
44
+ bandWidth: number;
45
+ bandHeight: number;
46
+ };
47
+ export type TitleForeignObjectRect = {
48
+ foX: number;
49
+ foY: number;
50
+ foWidth: number;
51
+ foHeight: number;
52
+ };
53
+ export declare function getTitleBand(options: {
54
+ x: number;
55
+ y: number;
56
+ width: number;
57
+ height: number;
58
+ }): TitleBand;
59
+ export declare function resolveTitleTextPosition(options: {
60
+ x: number;
61
+ y: number;
62
+ width: number;
63
+ height: number;
64
+ textAlign: string;
65
+ pad: ReturnType<typeof parseWrapPadding>;
66
+ }): {
67
+ x: number;
68
+ y: number;
69
+ };
70
+ export declare function getTitleForeignObjectRect(options: {
71
+ x: number;
72
+ y: number;
73
+ width: number;
74
+ height: number;
75
+ overflowMode: 'autoWrap' | 'ellipsis';
76
+ fontSize: number;
77
+ pad: ReturnType<typeof parseWrapPadding>;
78
+ }): TitleForeignObjectRect;
79
+ export declare function parseWrapPadding(padding?: string | number | null): {
80
+ top: number;
81
+ right: number;
82
+ bottom: number;
83
+ left: number;
84
+ };
85
+ export declare function textAlignToAnchor(textAlign?: string): 'start' | 'middle' | 'end';
86
+ export declare function isHtmlTextOverflow(overflowMode?: string): boolean;
87
+ /** LogicFlow 存储格式 `15,8,4,8` → CSS padding `15px 8px 4px 8px` */
88
+ export declare function formatWrapPaddingCss(padding?: string | number | null): string;