@flowgram.ai/document 0.1.0-alpha.3 → 0.1.0-alpha.30

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/index.js CHANGED
@@ -27,8 +27,8 @@ var __decorateClass = (decorators, target, key, kind) => {
27
27
  var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
28
28
 
29
29
  // src/index.ts
30
- var src_exports = {};
31
- __export(src_exports, {
30
+ var index_exports = {};
31
+ __export(index_exports, {
32
32
  ConstantKeys: () => ConstantKeys,
33
33
  DEFAULT_FLOW_NODE_META: () => DEFAULT_FLOW_NODE_META,
34
34
  DEFAULT_SIZE: () => DEFAULT_SIZE,
@@ -71,7 +71,7 @@ __export(src_exports, {
71
71
  drawLineToNext: () => drawLineToNext,
72
72
  getDefaultSpacing: () => getDefaultSpacing
73
73
  });
74
- module.exports = __toCommonJS(src_exports);
74
+ module.exports = __toCommonJS(index_exports);
75
75
 
76
76
  // src/typings/flow.ts
77
77
  var FlowNodeBaseType = /* @__PURE__ */ ((FlowNodeBaseType2) => {
@@ -85,11 +85,19 @@ var FlowNodeBaseType = /* @__PURE__ */ ((FlowNodeBaseType2) => {
85
85
  FlowNodeBaseType2["BLOCK_ORDER_ICON"] = "blockOrderIcon";
86
86
  FlowNodeBaseType2["GROUP"] = "group";
87
87
  FlowNodeBaseType2["END"] = "end";
88
+ FlowNodeBaseType2["BREAK"] = "break";
88
89
  FlowNodeBaseType2["CONDITION"] = "condition";
89
90
  FlowNodeBaseType2["SUB_CANVAS"] = "subCanvas";
91
+ FlowNodeBaseType2["MULTI_INPUTS"] = "multiInputs";
92
+ FlowNodeBaseType2["MULTI_OUTPUTS"] = "multiOutputs";
93
+ FlowNodeBaseType2["INPUT"] = "input";
94
+ FlowNodeBaseType2["OUTPUT"] = "output";
95
+ FlowNodeBaseType2["SLOT"] = "slot";
96
+ FlowNodeBaseType2["SLOT_BLOCK"] = "slotBlock";
90
97
  return FlowNodeBaseType2;
91
98
  })(FlowNodeBaseType || {});
92
99
  var FlowNodeSplitType = /* @__PURE__ */ ((FlowNodeSplitType2) => {
100
+ FlowNodeSplitType2["SIMPLE_SPLIT"] = "simpleSplit";
93
101
  FlowNodeSplitType2["DYNAMIC_SPLIT"] = "dynamicSplit";
94
102
  FlowNodeSplitType2["STATIC_SPLIT"] = "staticSplit";
95
103
  return FlowNodeSplitType2;
@@ -145,6 +153,14 @@ var DefaultSpacingKey = {
145
153
  * 普通节点间距。垂直 / 水平
146
154
  */
147
155
  NODE_SPACING: "SPACING",
156
+ /**
157
+ * 分支节点间距
158
+ */
159
+ BRANCH_SPACING: "BRANCH_SPACING",
160
+ /**
161
+ * 圆弧线条拐角 radius
162
+ */
163
+ ROUNDED_LINE_RADIUS: "ROUNDED_LINE_RADIUS",
148
164
  /**
149
165
  * 圆弧线条 x radius
150
166
  */
@@ -171,13 +187,19 @@ var DEFAULT_SPACING = {
171
187
  NULL: 0,
172
188
  [DefaultSpacingKey.NODE_SPACING]: 32,
173
189
  // 普通节点间距。垂直 / 水平
190
+ [DefaultSpacingKey.BRANCH_SPACING]: 20,
191
+ // 分支节点间距
192
+ /**
193
+ * @deprecated use 'BRANCH_SPACING' instead
194
+ */
174
195
  MARGIN_RIGHT: 20,
175
- // 普通节点右边间距
196
+ // 分支节点右边间距
176
197
  INLINE_BLOCK_PADDING_BOTTOM: 16,
177
198
  // block 底部留白
178
199
  INLINE_BLOCKS_PADDING_TOP: 30,
179
200
  // block list 上部留白间距
180
- [DefaultSpacingKey.INLINE_BLOCKS_PADDING_BOTTOM]: 40,
201
+ // JS 浮点数有误差,1046.6 -1006.6 = 39.9999999,会导致 间距/20 < 2 导致布局计算问题,因此需要额外增加 0.1 像素
202
+ [DefaultSpacingKey.INLINE_BLOCKS_PADDING_BOTTOM]: 40.1,
181
203
  // block lit 下部留白间距,因为有两个拐弯,所以翻一倍
182
204
  MIN_INLINE_BLOCK_SPACING: 200,
183
205
  // 分支间最小边距 (垂直布局)
@@ -185,6 +207,8 @@ var DEFAULT_SPACING = {
185
207
  // 分支间最小边距 (水平布局)
186
208
  [DefaultSpacingKey.COLLAPSED_SPACING]: 12,
187
209
  // 复合节点距离上个节点的距离
210
+ [DefaultSpacingKey.ROUNDED_LINE_RADIUS]: 16,
211
+ // 圆弧线条拐角 radius
188
212
  [DefaultSpacingKey.ROUNDED_LINE_X_RADIUS]: 16,
189
213
  // 圆弧线条 x radius
190
214
  [DefaultSpacingKey.ROUNDED_LINE_Y_RADIUS]: 20,
@@ -212,8 +236,6 @@ var DEFAULT_FLOW_NODE_META = (nodeType, document) => {
212
236
  isStart: nodeType === "start",
213
237
  hidden,
214
238
  defaultExpanded: document.options.allNodesDefaultExpanded,
215
- expandedSize: { width: 520, height: 300 },
216
- // 展开后的大小
217
239
  size: DEFAULT_SIZE,
218
240
  origin: document.layout.getDefaultNodeOrigin(),
219
241
  isInlineBlocks: nodeType === "inlineBlocks" /* INLINE_BLOCKS */,
@@ -233,13 +255,37 @@ var DEFAULT_FLOW_NODE_META = (nodeType, document) => {
233
255
  };
234
256
  var FlowNodeRegistry;
235
257
  ((FlowNodeRegistry4) => {
258
+ function mergeChildRegistries(r1 = [], r2 = []) {
259
+ if (r1.length === 0 || r2.length === 0) {
260
+ return [...r1, ...r2];
261
+ }
262
+ const r1Filter = r1.map((r1Current) => {
263
+ const r2Current = r2.find((n) => n.type === r1Current.type);
264
+ if (r2Current) {
265
+ return merge(r1Current, r2Current, r1Current.type);
266
+ }
267
+ return r1Current;
268
+ });
269
+ const r2Filter = r2.filter((n) => !r1.some((r) => r.type === n.type));
270
+ return [...r1Filter, ...r2Filter];
271
+ }
272
+ FlowNodeRegistry4.mergeChildRegistries = mergeChildRegistries;
236
273
  function merge(registry1, registry2, finalType) {
274
+ const extendKeys = registry1.__extends__ ? registry1.__extends__.slice() : [];
275
+ if (registry1.type !== registry2.type) {
276
+ extendKeys.unshift(registry1.type);
277
+ }
237
278
  return {
238
279
  ...registry1,
239
280
  ...registry2,
281
+ extendChildRegistries: mergeChildRegistries(
282
+ registry1.extendChildRegistries,
283
+ registry2.extendChildRegistries
284
+ ),
240
285
  meta: { ...registry1.meta, ...registry2.meta },
241
286
  extend: void 0,
242
- type: finalType
287
+ type: finalType,
288
+ __extends__: extendKeys
243
289
  };
244
290
  }
245
291
  FlowNodeRegistry4.merge = merge;
@@ -263,7 +309,6 @@ var OperationType = /* @__PURE__ */ ((OperationType2) => {
263
309
  OperationType2["moveChildNodes"] = "moveChildNodes";
264
310
  OperationType2["addNodes"] = "addNodes";
265
311
  OperationType2["deleteNodes"] = "deleteNodes";
266
- OperationType2["changeNode"] = "changeNode";
267
312
  OperationType2["addChildNode"] = "addChildNode";
268
313
  OperationType2["deleteChildNode"] = "deleteChildNode";
269
314
  OperationType2["addNode"] = "addNode";
@@ -304,16 +349,18 @@ var _FlowNodeRenderData = class _FlowNodeRenderData extends import_core.EntityDa
304
349
  expanded: defaultExpanded || false,
305
350
  activated: false,
306
351
  hovered: false,
307
- dragging: false
352
+ dragging: false,
353
+ stackIndex: 0
308
354
  };
309
355
  }
310
- updateExtInfo(info) {
311
- if (import_utils.Compare.isChanged(this.data.extInfo, info)) {
312
- const oldInfo = this.data.extInfo;
356
+ updateExtInfo(info, fullUpdate) {
357
+ const oldInfo = this.data.extInfo;
358
+ const newInfo = fullUpdate ? info : { ...oldInfo, ...info };
359
+ if (import_utils.Compare.isChanged(oldInfo, newInfo)) {
313
360
  this.update({
314
- extInfo: info
361
+ extInfo: newInfo
315
362
  });
316
- this.onExtInfoChangeEmitter.fire({ oldInfo, newInfo: info });
363
+ this.onExtInfoChangeEmitter.fire({ oldInfo, newInfo });
317
364
  }
318
365
  }
319
366
  getExtInfo() {
@@ -410,6 +457,12 @@ var _FlowNodeRenderData = class _FlowNodeRenderData extends import_core.EntityDa
410
457
  }
411
458
  return this.data.activated;
412
459
  }
460
+ get stackIndex() {
461
+ return this.data.stackIndex;
462
+ }
463
+ set stackIndex(index) {
464
+ this.data.stackIndex = index;
465
+ }
413
466
  get lineActivated() {
414
467
  const { activated } = this;
415
468
  if (!activated) return false;
@@ -459,10 +512,9 @@ var _FlowNodeTransformData = class _FlowNodeTransformData extends import_core2.E
459
512
  return this.entity.id;
460
513
  }
461
514
  getDefaultData() {
462
- const { size, defaultExpanded, expandedSize, hidden } = this.entity.getNodeMeta();
463
- const defaultSize = defaultExpanded ? expandedSize : size;
515
+ const { size, hidden } = this.entity.getNodeMeta();
464
516
  return {
465
- size: !hidden ? { ...defaultSize } : { width: 0, height: 0 }
517
+ size: !hidden ? { ...size } : { width: 0, height: 0 }
466
518
  };
467
519
  }
468
520
  /**
@@ -493,6 +545,11 @@ var _FlowNodeTransformData = class _FlowNodeTransformData extends import_core2.E
493
545
  y: position.y
494
546
  };
495
547
  }
548
+ set position(position) {
549
+ this.transform.update({
550
+ position
551
+ });
552
+ }
496
553
  set size(size) {
497
554
  const { width, height } = this.data.size;
498
555
  if (this.isContainer) return;
@@ -701,8 +758,9 @@ var drawLineToNext = (transition) => {
701
758
  var drawLineToBottom = (transition) => {
702
759
  const { transform } = transition;
703
760
  const currentOutput = transform.outputPoint;
761
+ const isParentRoot = transform.parent?.entity.flowNodeType === "root" /* ROOT */;
704
762
  const parentOutput = transform.parent?.outputPoint;
705
- if (!transform.next && parentOutput && !new import_utils3.Point().copyFrom(currentOutput).equals(parentOutput) && !transition.isNodeEnd) {
763
+ if (!isParentRoot && !transform.next && parentOutput && !new import_utils3.Point().copyFrom(currentOutput).equals(parentOutput) && !transition.isNodeEnd) {
706
764
  return [
707
765
  {
708
766
  type: 0 /* STRAIGHT_LINE */,
@@ -1040,37 +1098,7 @@ var FlowNodeEntity = class extends import_core4.Entity {
1040
1098
  * @param newId
1041
1099
  */
1042
1100
  toJSON() {
1043
- if (this.document.options.toNodeJSON) {
1044
- return this.document.options.toNodeJSON(this);
1045
- }
1046
- const nodesMap = {};
1047
- let startNodeJSON;
1048
- this.document.traverse((node) => {
1049
- const isSystemNode = node.id.startsWith("$");
1050
- if (isSystemNode) return;
1051
- const nodeJSONData = this.getJSONData();
1052
- const nodeJSON = {
1053
- id: node.id,
1054
- type: node.flowNodeType
1055
- };
1056
- if (nodeJSONData !== void 0) {
1057
- nodeJSON.data = nodeJSONData;
1058
- }
1059
- if (!startNodeJSON) startNodeJSON = nodeJSON;
1060
- let { parent } = node;
1061
- if (parent && parent.id.startsWith("$")) {
1062
- parent = parent.originParent;
1063
- }
1064
- const parentJSON = parent ? nodesMap[parent.id] : void 0;
1065
- if (parentJSON) {
1066
- if (!parentJSON.blocks) {
1067
- parentJSON.blocks = [];
1068
- }
1069
- parentJSON.blocks.push(nodeJSON);
1070
- }
1071
- nodesMap[node.id] = nodeJSON;
1072
- }, this);
1073
- return startNodeJSON;
1101
+ return this.document.toNodeJSON(this);
1074
1102
  }
1075
1103
  get isVertical() {
1076
1104
  return this.document.layout.name === "vertical-fixed-layout" /* VERTICAL_FIXED_LAYOUT */;
@@ -1079,8 +1107,8 @@ var FlowNodeEntity = class extends import_core4.Entity {
1079
1107
  * 修改节点扩展信息
1080
1108
  * @param info
1081
1109
  */
1082
- updateExtInfo(extInfo) {
1083
- this.getData(FlowNodeRenderData).updateExtInfo(extInfo);
1110
+ updateExtInfo(extInfo, fullUpdate) {
1111
+ this.getData(FlowNodeRenderData).updateExtInfo(extInfo, fullUpdate);
1084
1112
  }
1085
1113
  /**
1086
1114
  * 获取节点扩展信息
@@ -1109,6 +1137,19 @@ var FlowNodeEntity = class extends import_core4.Entity {
1109
1137
  get bounds() {
1110
1138
  return this.transform.bounds;
1111
1139
  }
1140
+ /**
1141
+ * Check node extend type
1142
+ */
1143
+ isExtend(parentType) {
1144
+ return this.document.isExtend(this.flowNodeType, parentType);
1145
+ }
1146
+ /**
1147
+ * Check node type
1148
+ * @param parentType
1149
+ */
1150
+ isTypeOrExtendType(parentType) {
1151
+ return this.document.isTypeOrExtendType(this.flowNodeType, parentType);
1152
+ }
1112
1153
  };
1113
1154
  FlowNodeEntity.type = "FlowNodeEntity";
1114
1155
  ((FlowNodeEntity2) => {
@@ -1202,7 +1243,7 @@ var FlowDocumentTransformerEntity = class extends import_core5.ConfigEntity {
1202
1243
  FlowDocumentTransformerEntity.type = "FlowDocumentTransformerEntity";
1203
1244
 
1204
1245
  // src/entities/flow-renderer-state-entity.ts
1205
- var import_lodash = require("lodash");
1246
+ var import_lodash_es = require("lodash-es");
1206
1247
  var import_core6 = require("@flowgram.ai/core");
1207
1248
  var FlowRendererStateEntity = class extends import_core6.ConfigEntity {
1208
1249
  getDefaultConfig() {
@@ -1219,6 +1260,22 @@ var FlowRendererStateEntity = class extends import_core6.ConfigEntity {
1219
1260
  nodeHoveredId: node?.id
1220
1261
  });
1221
1262
  }
1263
+ get dragging() {
1264
+ return this.config.dragging;
1265
+ }
1266
+ setDragging(dragging) {
1267
+ this.updateConfig({
1268
+ dragging
1269
+ });
1270
+ }
1271
+ get isBranch() {
1272
+ return this.config.isBranch;
1273
+ }
1274
+ setIsBranch(isBranch) {
1275
+ this.updateConfig({
1276
+ isBranch
1277
+ });
1278
+ }
1222
1279
  getDragLabelSide() {
1223
1280
  return this.config.dragLabelSide;
1224
1281
  }
@@ -1257,13 +1314,13 @@ var FlowRendererStateEntity = class extends import_core6.ConfigEntity {
1257
1314
  });
1258
1315
  }
1259
1316
  onNodeHoveredChange(fn, debounceTime = 100) {
1260
- return this.onConfigChanged((0, import_lodash.debounce)(() => fn(this.getNodeHovered()), debounceTime));
1317
+ return this.onConfigChanged((0, import_lodash_es.debounce)(() => fn(this.getNodeHovered()), debounceTime));
1261
1318
  }
1262
1319
  };
1263
1320
  FlowRendererStateEntity.type = "FlowRendererStateEntity";
1264
1321
 
1265
1322
  // src/flow-document.ts
1266
- var import_lodash2 = require("lodash");
1323
+ var import_lodash_es2 = require("lodash-es");
1267
1324
  var import_inversify2 = require("inversify");
1268
1325
  var import_utils7 = require("@flowgram.ai/utils");
1269
1326
  var import_core7 = require("@flowgram.ai/core");
@@ -1441,13 +1498,15 @@ var FlowVirtualTree = class _FlowVirtualTree {
1441
1498
  get size() {
1442
1499
  return this.map.size;
1443
1500
  }
1444
- toString() {
1501
+ toString(showType) {
1445
1502
  const ret = [];
1446
1503
  this.traverse((node, depth) => {
1447
1504
  if (depth === 0) {
1448
1505
  ret.push(node.id);
1449
1506
  } else {
1450
- ret.push(`|${new Array(depth).fill("--").join("")} ${node.id}`);
1507
+ ret.push(
1508
+ `|${new Array(depth).fill("--").join("")} ${showType ? `${node.flowNodeType}(${node.id})` : node.id}`
1509
+ );
1451
1510
  }
1452
1511
  });
1453
1512
  return `${ret.join("\n")}`;
@@ -1653,7 +1712,12 @@ var ConstantKeys = {
1653
1712
  /***
1654
1713
  * 线条、label 激活后的颜色
1655
1714
  */
1656
- BASE_ACTIVATED_COLOR: "BASE_ACTIVATED_COLOR"
1715
+ BASE_ACTIVATED_COLOR: "BASE_ACTIVATED_COLOR",
1716
+ /**
1717
+ * Branch bottom margin
1718
+ * 分支下边距
1719
+ */
1720
+ INLINE_BLOCKS_PADDING_TOP: "INLINE_BLOCKS_PADDING_TOP"
1657
1721
  };
1658
1722
 
1659
1723
  // src/flow-document-contribution.ts
@@ -1708,6 +1772,13 @@ var FlowDocument = class {
1708
1772
  this.onNodeCreate = this.onNodeCreateEmitter.event;
1709
1773
  this.onNodeDispose = this.onNodeDisposeEmitter.event;
1710
1774
  this.onLayoutChange = this.onLayoutChangeEmitter.event;
1775
+ this._disposed = false;
1776
+ }
1777
+ /**
1778
+ *
1779
+ */
1780
+ get disposed() {
1781
+ return this._disposed;
1711
1782
  }
1712
1783
  init() {
1713
1784
  if (!this.options) this.options = FlowDocumentOptionsDefault;
@@ -1733,6 +1804,7 @@ var FlowDocument = class {
1733
1804
  * @param fireRender 是否要触发渲染,默认 true
1734
1805
  */
1735
1806
  fromJSON(json, fireRender = true) {
1807
+ if (this._disposed) return;
1736
1808
  this.originTree.clear();
1737
1809
  this.renderTree.clear();
1738
1810
  this.entityManager.changeEntityLocked = true;
@@ -1801,7 +1873,7 @@ var FlowDocument = class {
1801
1873
  * @param data
1802
1874
  * @param addedNodes
1803
1875
  */
1804
- addNode(data, addedNodes, ignoreCreateEvent) {
1876
+ addNode(data, addedNodes) {
1805
1877
  const { id, type = "block", originParent, parent, meta, hidden, index } = data;
1806
1878
  let node = this.getNode(id);
1807
1879
  let isNew = false;
@@ -1819,13 +1891,14 @@ var FlowDocument = class {
1819
1891
  originParent,
1820
1892
  meta
1821
1893
  });
1894
+ this.options.preNodeCreate?.(node);
1822
1895
  const datas = dataRegistries ? this.nodeDataRegistries.concat(...dataRegistries) : this.nodeDataRegistries;
1823
1896
  node.addInitializeData(datas);
1824
1897
  node.onDispose(() => this.onNodeDisposeEmitter.fire({ node }));
1825
- if (this.options.fromNodeJSON) {
1826
- this.options.fromNodeJSON(node, data);
1827
- }
1898
+ this.options.fromNodeJSON?.(node, data, true);
1828
1899
  isNew = true;
1900
+ } else {
1901
+ this.options.fromNodeJSON?.(node, data, false);
1829
1902
  }
1830
1903
  node.initData({
1831
1904
  originParent,
@@ -1837,7 +1910,6 @@ var FlowDocument = class {
1837
1910
  if (node.isStart) {
1838
1911
  this.root.addChild(node);
1839
1912
  }
1840
- this.onNodeUpdateEmitter.fire({ node, data });
1841
1913
  addedNodes?.push(node);
1842
1914
  if (register.onCreate) {
1843
1915
  const extendNodes = register.onCreate(node, data);
@@ -1851,11 +1923,14 @@ var FlowDocument = class {
1851
1923
  this.addBlocksAsChildren(node, data.blocks, addedNodes);
1852
1924
  }
1853
1925
  }
1854
- if (isNew && !ignoreCreateEvent) {
1926
+ if (isNew) {
1855
1927
  this.onNodeCreateEmitter.fire({
1856
1928
  node,
1857
- data
1929
+ data,
1930
+ json: data
1858
1931
  });
1932
+ } else {
1933
+ this.onNodeUpdateEmitter.fire({ node, data, json: data });
1859
1934
  }
1860
1935
  return node;
1861
1936
  }
@@ -1891,18 +1966,16 @@ var FlowDocument = class {
1891
1966
  parent: node
1892
1967
  });
1893
1968
  addedNodes.push(blockIconNode);
1894
- if (blocks.length > 0) {
1895
- const inlineBlocksNode = this.addNode({
1896
- id: `$inlineBlocks$${node.id}`,
1897
- type: "inlineBlocks" /* INLINE_BLOCKS */,
1898
- originParent: node,
1899
- parent: node
1900
- });
1901
- addedNodes.push(inlineBlocksNode);
1902
- blocks.forEach((blockData) => {
1903
- this.addBlock(node, blockData, addedNodes);
1904
- });
1905
- }
1969
+ const inlineBlocksNode = this.addNode({
1970
+ id: `$inlineBlocks$${node.id}`,
1971
+ type: "inlineBlocks" /* INLINE_BLOCKS */,
1972
+ originParent: node,
1973
+ parent: node
1974
+ });
1975
+ addedNodes.push(inlineBlocksNode);
1976
+ blocks.forEach((blockData) => {
1977
+ this.addBlock(node, blockData, addedNodes);
1978
+ });
1906
1979
  return addedNodes;
1907
1980
  }
1908
1981
  /**
@@ -1920,7 +1993,7 @@ var FlowDocument = class {
1920
1993
  }
1921
1994
  parent = parent || this.getNode(`$inlineBlocks$${node.id}`);
1922
1995
  const block = this.addNode({
1923
- ...(0, import_lodash2.omit)(blockData, "blocks"),
1996
+ ...(0, import_lodash_es2.omit)(blockData, "blocks"),
1924
1997
  type: blockData.type || "block" /* BLOCK */,
1925
1998
  originParent: node,
1926
1999
  parent,
@@ -1967,14 +2040,39 @@ var FlowDocument = class {
1967
2040
  meta: {
1968
2041
  ...preRegistry?.meta,
1969
2042
  ...newRegistry?.meta
1970
- }
2043
+ },
2044
+ extendChildRegistries: FlowNodeRegistry.mergeChildRegistries(
2045
+ preRegistry?.extendChildRegistries,
2046
+ newRegistry?.extendChildRegistries
2047
+ )
1971
2048
  });
1972
2049
  });
1973
2050
  }
2051
+ /**
2052
+ * Check node extend
2053
+ * @param currentType
2054
+ * @param extendType
2055
+ */
2056
+ isExtend(currentType, extendType) {
2057
+ return (this.getNodeRegistry(currentType).__extends__ || []).includes(extendType);
2058
+ }
2059
+ /**
2060
+ * Check node type
2061
+ * @param currentType
2062
+ * @param extendType
2063
+ */
2064
+ isTypeOrExtendType(currentType, extendType) {
2065
+ return currentType === extendType || this.isExtend(currentType, extendType);
2066
+ }
1974
2067
  /**
1975
2068
  * 导出数据,可以重载
1976
2069
  */
1977
2070
  toJSON() {
2071
+ if (this.disposed) {
2072
+ throw new Error(
2073
+ "The FlowDocument has been disposed and it is no longer possible to call toJSON."
2074
+ );
2075
+ }
1978
2076
  return {
1979
2077
  nodes: this.root.toJSON().blocks
1980
2078
  };
@@ -1994,6 +2092,7 @@ var FlowDocument = class {
1994
2092
  const customDefaultRegistry = this.options.getNodeDefaultRegistry?.(type);
1995
2093
  let register = this.registers.get(type) || { type };
1996
2094
  const extendRegisters = [];
2095
+ const extendKey = register.extend;
1997
2096
  if (register.extend && this.registers.has(register.extend)) {
1998
2097
  register = FlowNodeRegistry.merge(
1999
2098
  this.getNodeRegistry(register.extend),
@@ -2024,6 +2123,9 @@ var FlowDocument = class {
2024
2123
  ...register.meta
2025
2124
  }
2026
2125
  };
2126
+ if (extendKey) {
2127
+ res.extend = extendKey;
2128
+ }
2027
2129
  this.nodeRegistryCache.set(typeKey, res);
2028
2130
  return res;
2029
2131
  }
@@ -2074,8 +2176,8 @@ var FlowDocument = class {
2074
2176
  getAllNodes() {
2075
2177
  return this.entityManager.getEntities(FlowNodeEntity);
2076
2178
  }
2077
- toString() {
2078
- return this.originTree.toString();
2179
+ toString(showType) {
2180
+ return this.originTree.toString(showType);
2079
2181
  }
2080
2182
  /**
2081
2183
  * 返回需要渲染的数据
@@ -2088,6 +2190,39 @@ var FlowDocument = class {
2088
2190
  });
2089
2191
  return result;
2090
2192
  }
2193
+ toNodeJSON(node) {
2194
+ if (this.options.toNodeJSON) {
2195
+ return this.options.toNodeJSON(node);
2196
+ }
2197
+ const nodesMap = {};
2198
+ let startNodeJSON;
2199
+ this.traverse((node2) => {
2200
+ const isSystemNode = node2.id.startsWith("$");
2201
+ if (isSystemNode) return;
2202
+ const nodeJSONData = node2.getJSONData();
2203
+ const nodeJSON = {
2204
+ id: node2.id,
2205
+ type: node2.flowNodeType
2206
+ };
2207
+ if (nodeJSONData !== void 0) {
2208
+ nodeJSON.data = nodeJSONData;
2209
+ }
2210
+ if (!startNodeJSON) startNodeJSON = nodeJSON;
2211
+ let { parent } = node2;
2212
+ if (parent && parent.id.startsWith("$")) {
2213
+ parent = parent.originParent;
2214
+ }
2215
+ const parentJSON = parent ? nodesMap[parent.id] : void 0;
2216
+ if (parentJSON) {
2217
+ if (!parentJSON.blocks) {
2218
+ parentJSON.blocks = [];
2219
+ }
2220
+ parentJSON.blocks.push(nodeJSON);
2221
+ }
2222
+ nodesMap[node2.id] = nodeJSON;
2223
+ }, node);
2224
+ return startNodeJSON;
2225
+ }
2091
2226
  /**
2092
2227
  * 移动节点
2093
2228
  * @param param0
@@ -2170,6 +2305,7 @@ var FlowDocument = class {
2170
2305
  );
2171
2306
  }
2172
2307
  dispose() {
2308
+ if (this._disposed) return;
2173
2309
  this.registers.clear();
2174
2310
  this.nodeRegistryCache.clear();
2175
2311
  this.originTree.dispose();
@@ -2178,6 +2314,7 @@ var FlowDocument = class {
2178
2314
  this.onNodeCreateEmitter.dispose();
2179
2315
  this.onNodeDisposeEmitter.dispose();
2180
2316
  this.onLayoutChangeEmitter.dispose();
2317
+ this._disposed = true;
2181
2318
  }
2182
2319
  };
2183
2320
  __decorateClass([
@@ -2205,113 +2342,427 @@ FlowDocument = __decorateClass([
2205
2342
  var import_inversify8 = require("inversify");
2206
2343
 
2207
2344
  // src/services/flow-drag-service.ts
2208
- var import_inversify5 = require("inversify");
2209
- var import_core10 = require("@flowgram.ai/core");
2210
- var import_utils9 = require("@flowgram.ai/utils");
2211
-
2212
- // src/services/flow-operation-base-service.ts
2213
2345
  var import_inversify3 = require("inversify");
2214
2346
  var import_utils8 = require("@flowgram.ai/utils");
2215
2347
  var import_core8 = require("@flowgram.ai/core");
2216
- var FlowOperationBaseServiceImpl = class {
2217
- constructor() {
2218
- this.onNodeAddEmitter = new import_utils8.Emitter();
2219
- this.onNodeAdd = this.onNodeAddEmitter.event;
2220
- this.toDispose = new import_utils8.DisposableCollection();
2348
+
2349
+ // src/services/flow-group-service/flow-group-controller.ts
2350
+ var FlowGroupController = class _FlowGroupController {
2351
+ constructor(groupNode) {
2352
+ this.groupNode = groupNode;
2221
2353
  }
2222
- init() {
2223
- this.toDispose.push(this.onNodeAddEmitter);
2354
+ get nodes() {
2355
+ return this.groupNode.collapsedChildren || [];
2224
2356
  }
2225
- addNode(nodeJSON, config = {}) {
2226
- const { parent, index, hidden } = config;
2227
- let parentEntity;
2228
- if (parent) {
2229
- parentEntity = this.toNodeEntity(parent);
2357
+ get collapsed() {
2358
+ const groupTransformData = this.groupNode.getData(FlowNodeTransformData);
2359
+ return groupTransformData.collapsed;
2360
+ }
2361
+ collapse() {
2362
+ this.collapsed = true;
2363
+ }
2364
+ expand() {
2365
+ this.collapsed = false;
2366
+ }
2367
+ /** 获取分组外围的最大边框 */
2368
+ get bounds() {
2369
+ const groupNodeBounds = this.groupNode.getData(FlowNodeTransformData).bounds;
2370
+ return groupNodeBounds;
2371
+ }
2372
+ /** 是否是开始节点 */
2373
+ isStartNode(node) {
2374
+ if (!node) {
2375
+ return false;
2230
2376
  }
2231
- let register;
2232
- if (parentEntity) {
2233
- register = parentEntity.getNodeRegistry();
2377
+ const nodes = this.nodes;
2378
+ if (!nodes[0]) {
2379
+ return false;
2234
2380
  }
2235
- const addJSON = {
2236
- ...nodeJSON,
2237
- type: nodeJSON.type || "block" /* BLOCK */
2238
- };
2239
- const addNodeData = {
2240
- ...addJSON,
2241
- parent: parentEntity,
2242
- index,
2243
- hidden
2244
- };
2245
- let added;
2246
- if (parentEntity && register?.addChild) {
2247
- added = register.addChild(parentEntity, addJSON, {
2248
- index,
2249
- hidden
2250
- });
2251
- } else {
2252
- added = this.document.addNode(addNodeData);
2381
+ return node.id === nodes[0].id;
2382
+ }
2383
+ /** 是否是结束节点 */
2384
+ isEndNode(node) {
2385
+ if (!node) {
2386
+ return false;
2253
2387
  }
2254
- this.onNodeAddEmitter.fire({
2255
- node: added,
2256
- data: addNodeData
2257
- });
2258
- return added;
2388
+ const nodes = this.nodes;
2389
+ if (!nodes[nodes.length - 1]) {
2390
+ return false;
2391
+ }
2392
+ return node.id === nodes[nodes.length - 1].id;
2259
2393
  }
2260
- addFromNode(fromNode, nodeJSON) {
2261
- return this.document.addFromNode(fromNode, nodeJSON);
2394
+ set note(note) {
2395
+ this.groupNode.getNodeMeta().note = note;
2262
2396
  }
2263
- deleteNode(node) {
2264
- this.document.removeNode(node);
2397
+ get note() {
2398
+ return this.groupNode.getNodeMeta().note || "";
2265
2399
  }
2266
- deleteNodes(nodes) {
2267
- (nodes || []).forEach((node) => {
2268
- this.deleteNode(node);
2269
- });
2400
+ set noteHeight(height) {
2401
+ this.groupNode.getNodeMeta().noteHeight = height;
2270
2402
  }
2271
- addBlock(target, blockJSON, config = {}) {
2272
- const { parent, index } = config;
2273
- return this.document.addBlock(target, blockJSON, void 0, parent, index);
2403
+ get noteHeight() {
2404
+ return this.groupNode.getNodeMeta().noteHeight || 0;
2274
2405
  }
2275
- moveNode(node, config = {}) {
2276
- const { parent: newParent, index } = config;
2277
- const entity = this.toNodeEntity(node);
2278
- const parent = entity?.parent;
2279
- if (!parent) {
2280
- return;
2406
+ get positionConfig() {
2407
+ return this.groupNode.getNodeMeta().positionConfig;
2408
+ }
2409
+ set collapsed(collapsed) {
2410
+ const groupTransformData = this.groupNode.getData(FlowNodeTransformData);
2411
+ groupTransformData.collapsed = collapsed;
2412
+ groupTransformData.localDirty = true;
2413
+ if (groupTransformData.parent) groupTransformData.parent.localDirty = true;
2414
+ if (groupTransformData.parent?.firstChild)
2415
+ groupTransformData.parent.firstChild.localDirty = true;
2416
+ }
2417
+ set hovered(hovered) {
2418
+ const groupRenderData = this.groupNode.getData(FlowNodeRenderData);
2419
+ if (hovered) {
2420
+ groupRenderData.toggleMouseEnter();
2421
+ } else {
2422
+ groupRenderData.toggleMouseLeave();
2281
2423
  }
2282
- const newParentEntity = newParent ? this.toNodeEntity(newParent) : parent;
2283
- if (!newParentEntity) {
2284
- console.warn("no new parent found", newParent);
2424
+ if (groupRenderData.hovered === hovered) {
2285
2425
  return;
2286
2426
  }
2287
- let toIndex = typeof index === "undefined" ? parent.children.length : index;
2288
- return this.doMoveNode(entity, newParentEntity, toIndex);
2427
+ groupRenderData.hovered = hovered;
2289
2428
  }
2290
- /**
2291
- * 拖拽节点
2292
- * @param param0
2293
- * @returns
2294
- */
2295
- dragNodes({ dropNode, nodes }) {
2296
- if (nodes.length === 0) {
2429
+ get hovered() {
2430
+ const groupRenderData = this.groupNode.getData(FlowNodeRenderData);
2431
+ return groupRenderData.hovered;
2432
+ }
2433
+ static create(groupNode) {
2434
+ if (!groupNode) {
2297
2435
  return;
2298
2436
  }
2299
- const startNode = nodes[0];
2300
- const fromParent = startNode.parent;
2301
- const toParent = dropNode.parent;
2302
- if (!fromParent || !toParent) {
2437
+ if (!FlowGroupUtils.isGroupNode(groupNode)) {
2303
2438
  return;
2304
2439
  }
2305
- const fromIndex = fromParent.children.findIndex((child) => child === startNode);
2306
- const dropIndex = toParent.children.findIndex((child) => child === dropNode);
2307
- let toIndex = dropIndex + 1;
2308
- if (fromParent === toParent && fromIndex < dropIndex) {
2309
- toIndex = toIndex - nodes.length;
2310
- }
2311
- const value = {
2312
- nodeIds: nodes.map((node) => node.id),
2313
- fromParentId: fromParent.id,
2314
- toParentId: toParent.id,
2440
+ return new _FlowGroupController(groupNode);
2441
+ }
2442
+ };
2443
+
2444
+ // src/services/flow-group-service/flow-group-utils.ts
2445
+ var FlowGroupUtils;
2446
+ ((FlowGroupUtils2) => {
2447
+ const findNodeParents = (node) => {
2448
+ const parents = [];
2449
+ let parent = node.parent;
2450
+ while (parent) {
2451
+ parents.push(parent);
2452
+ parent = parent.parent;
2453
+ }
2454
+ return parents;
2455
+ };
2456
+ const isNodeInGroup = (node) => {
2457
+ if (node?.parent?.flowNodeType === "group" /* GROUP */) {
2458
+ return true;
2459
+ }
2460
+ return false;
2461
+ };
2462
+ FlowGroupUtils2.validate = (nodes) => {
2463
+ if (!nodes || !Array.isArray(nodes) || nodes.length === 0) {
2464
+ return false;
2465
+ }
2466
+ const isGroupRelatedNode = nodes.some((node) => (0, FlowGroupUtils2.isGroupNode)(node));
2467
+ if (isGroupRelatedNode) return false;
2468
+ const hasGroup = nodes.some((node) => node && isNodeInGroup(node));
2469
+ if (hasGroup) return false;
2470
+ const parent = nodes[0].parent;
2471
+ const isSameParent = nodes.every((node) => node.parent === parent);
2472
+ if (!isSameParent) return false;
2473
+ const indexes = nodes.map((node) => node.index).sort((a, b) => a - b);
2474
+ const isIndexContinuous = indexes.every((index, i, arr) => {
2475
+ if (i === 0) {
2476
+ return true;
2477
+ }
2478
+ return index === arr[i - 1] + 1;
2479
+ });
2480
+ if (!isIndexContinuous) return false;
2481
+ const parents = findNodeParents(nodes[0]);
2482
+ const parentsInGroup = parents.some((parent2) => isNodeInGroup(parent2));
2483
+ if (parentsInGroup) return false;
2484
+ return true;
2485
+ };
2486
+ FlowGroupUtils2.getNodeGroupController = (node) => {
2487
+ if (!node) {
2488
+ return;
2489
+ }
2490
+ if (!isNodeInGroup(node)) {
2491
+ return;
2492
+ }
2493
+ const groupNode = node?.parent;
2494
+ return FlowGroupController.create(groupNode);
2495
+ };
2496
+ FlowGroupUtils2.getNodeRecursionGroupController = (node) => {
2497
+ if (!node) {
2498
+ return;
2499
+ }
2500
+ const group = (0, FlowGroupUtils2.getNodeGroupController)(node);
2501
+ if (group) {
2502
+ return group;
2503
+ }
2504
+ if (node.parent) {
2505
+ return (0, FlowGroupUtils2.getNodeRecursionGroupController)(node.parent);
2506
+ }
2507
+ return;
2508
+ };
2509
+ FlowGroupUtils2.isGroupNode = (group) => group.flowNodeType === "group" /* GROUP */;
2510
+ })(FlowGroupUtils || (FlowGroupUtils = {}));
2511
+
2512
+ // src/services/flow-drag-service.ts
2513
+ var FlowDragService = class {
2514
+ constructor() {
2515
+ this.onDropEmitter = new import_utils8.Emitter();
2516
+ this.onDrop = this.onDropEmitter.event;
2517
+ }
2518
+ get renderState() {
2519
+ return this.document.renderState;
2520
+ }
2521
+ // 拖拽所有节点中的首个节点
2522
+ get dragStartNode() {
2523
+ return this.renderState.getDragStartEntity();
2524
+ }
2525
+ // 拖拽的所有节点
2526
+ get dragNodes() {
2527
+ return this.renderState.getDragEntities();
2528
+ }
2529
+ // 放置的区域
2530
+ get dropNodeId() {
2531
+ return this.renderState.getNodeDroppingId();
2532
+ }
2533
+ // 是否在拖拽分支
2534
+ get isDragBranch() {
2535
+ return this.renderState.isBranch || this.dragStartNode?.isInlineBlock;
2536
+ }
2537
+ // 拖拽的所有节点及其自节点
2538
+ get nodeDragIdsWithChildren() {
2539
+ return this.renderState.config.nodeDragIdsWithChildren || [];
2540
+ }
2541
+ get dragging() {
2542
+ return !!this.renderState.dragging;
2543
+ }
2544
+ get labelSide() {
2545
+ return this.renderState.config.dragLabelSide;
2546
+ }
2547
+ /**
2548
+ * 放置到目标分支
2549
+ */
2550
+ dropBranch() {
2551
+ this.dropNode();
2552
+ }
2553
+ /**
2554
+ * 移动并且创建节点
2555
+ * Move and create node
2556
+ */
2557
+ async dropCreateNode(json, onCreateNode) {
2558
+ const dropEntity = this.document.getNode(this.dropNodeId);
2559
+ if (!dropEntity) {
2560
+ return;
2561
+ }
2562
+ if (json) {
2563
+ const dragNodes = await onCreateNode?.(json, dropEntity);
2564
+ this.onDropEmitter.fire({
2565
+ dropNode: dropEntity,
2566
+ dragNodes: dragNodes ? [dragNodes] : [],
2567
+ dragJSON: json
2568
+ });
2569
+ }
2570
+ }
2571
+ /**
2572
+ * 移动到目标节点
2573
+ */
2574
+ dropNode() {
2575
+ const dropEntity = this.document.getNode(this.dropNodeId);
2576
+ if (!dropEntity) {
2577
+ return;
2578
+ }
2579
+ const sortNodes = [];
2580
+ let curr = this.dragStartNode;
2581
+ while (curr && this.dragNodes.includes(curr)) {
2582
+ sortNodes.push(curr);
2583
+ curr = curr.next;
2584
+ }
2585
+ this.operationService.dragNodes({
2586
+ dropNode: dropEntity,
2587
+ nodes: sortNodes
2588
+ });
2589
+ if (sortNodes.length > 0) {
2590
+ this.onDropEmitter.fire({
2591
+ dropNode: dropEntity,
2592
+ dragNodes: sortNodes
2593
+ });
2594
+ }
2595
+ }
2596
+ /**
2597
+ * 拖拽是否可以释放在该节点后面
2598
+ */
2599
+ isDroppableNode(node) {
2600
+ if (!this.dragging || this.isDragBranch) {
2601
+ return false;
2602
+ }
2603
+ if (this.nodeDragIdsWithChildren.includes(node.id) || node.next && this.nodeDragIdsWithChildren.includes(node.next.id)) {
2604
+ return false;
2605
+ }
2606
+ if (node.isInlineBlocks || node.isInlineBlock) {
2607
+ return false;
2608
+ }
2609
+ const hasGroupNode = this.dragNodes.some(
2610
+ (node2) => node2.flowNodeType === "group" /* GROUP */
2611
+ );
2612
+ if (hasGroupNode) {
2613
+ const group = FlowGroupUtils.getNodeRecursionGroupController(node);
2614
+ if (group) {
2615
+ return false;
2616
+ }
2617
+ }
2618
+ return true;
2619
+ }
2620
+ /**
2621
+ * 拖拽分支是否可以释放在该分支
2622
+ * @param node 拖拽的分支节点
2623
+ * @param side 分支的前面还是后面
2624
+ */
2625
+ isDroppableBranch(node, side = "normal_branch" /* NORMAL_BRANCH */) {
2626
+ if (this.renderState.isBranch) {
2627
+ return true;
2628
+ }
2629
+ if (this.isDragBranch) {
2630
+ if (
2631
+ // 拖拽到分支
2632
+ !node.isInlineBlock || // 只能在同一分支条件下
2633
+ node.parent !== this.dragStartNode.parent || // 自己不能拖拽给自己
2634
+ node === this.dragStartNode
2635
+ ) {
2636
+ return false;
2637
+ }
2638
+ if (side === "normal_branch" /* NORMAL_BRANCH */ && node.next !== this.dragStartNode) {
2639
+ return true;
2640
+ }
2641
+ if (side === "pre_branch" /* PRE_BRANCH */ && node.pre !== this.dragStartNode) {
2642
+ return true;
2643
+ }
2644
+ }
2645
+ return false;
2646
+ }
2647
+ };
2648
+ __decorateClass([
2649
+ (0, import_inversify3.inject)(FlowDocument)
2650
+ ], FlowDragService.prototype, "document", 2);
2651
+ __decorateClass([
2652
+ (0, import_inversify3.inject)(FlowOperationBaseService)
2653
+ ], FlowDragService.prototype, "operationService", 2);
2654
+ __decorateClass([
2655
+ (0, import_inversify3.inject)(import_core8.EntityManager)
2656
+ ], FlowDragService.prototype, "entityManager", 2);
2657
+ FlowDragService = __decorateClass([
2658
+ (0, import_inversify3.injectable)()
2659
+ ], FlowDragService);
2660
+
2661
+ // src/services/flow-operation-base-service.ts
2662
+ var import_inversify4 = require("inversify");
2663
+ var import_utils9 = require("@flowgram.ai/utils");
2664
+ var import_core9 = require("@flowgram.ai/core");
2665
+ var FlowOperationBaseServiceImpl = class {
2666
+ constructor() {
2667
+ this.onNodeAddEmitter = new import_utils9.Emitter();
2668
+ this.onNodeAdd = this.onNodeAddEmitter.event;
2669
+ this.toDispose = new import_utils9.DisposableCollection();
2670
+ this.onNodeMoveEmitter = new import_utils9.Emitter();
2671
+ this.onNodeMove = this.onNodeMoveEmitter.event;
2672
+ }
2673
+ init() {
2674
+ this.toDispose.pushAll([this.onNodeAddEmitter, this.onNodeMoveEmitter]);
2675
+ }
2676
+ addNode(nodeJSON, config = {}) {
2677
+ const { parent, index, hidden } = config;
2678
+ let parentEntity;
2679
+ if (parent) {
2680
+ parentEntity = this.toNodeEntity(parent);
2681
+ }
2682
+ let register;
2683
+ if (parentEntity) {
2684
+ register = parentEntity.getNodeRegistry();
2685
+ }
2686
+ const addJSON = {
2687
+ ...nodeJSON,
2688
+ type: nodeJSON.type || "block" /* BLOCK */
2689
+ };
2690
+ const addNodeData = {
2691
+ ...addJSON,
2692
+ parent: parentEntity,
2693
+ index,
2694
+ hidden
2695
+ };
2696
+ let added;
2697
+ if (parentEntity && register?.addChild) {
2698
+ added = register.addChild(parentEntity, addJSON, {
2699
+ index,
2700
+ hidden
2701
+ });
2702
+ } else {
2703
+ added = this.document.addNode(addNodeData);
2704
+ }
2705
+ this.onNodeAddEmitter.fire({
2706
+ node: added,
2707
+ data: addNodeData
2708
+ });
2709
+ return added;
2710
+ }
2711
+ addFromNode(fromNode, nodeJSON) {
2712
+ return this.document.addFromNode(fromNode, nodeJSON);
2713
+ }
2714
+ deleteNode(node) {
2715
+ this.document.removeNode(node);
2716
+ }
2717
+ deleteNodes(nodes) {
2718
+ (nodes || []).forEach((node) => {
2719
+ this.deleteNode(node);
2720
+ });
2721
+ }
2722
+ addBlock(target, blockJSON, config = {}) {
2723
+ const { parent, index } = config;
2724
+ return this.document.addBlock(target, blockJSON, void 0, parent, index);
2725
+ }
2726
+ moveNode(node, config = {}) {
2727
+ const { parent: newParent, index } = config;
2728
+ const entity = this.toNodeEntity(node);
2729
+ const parent = entity?.parent;
2730
+ if (!parent) {
2731
+ return;
2732
+ }
2733
+ const newParentEntity = newParent ? this.toNodeEntity(newParent) : parent;
2734
+ if (!newParentEntity) {
2735
+ console.warn("no new parent found", newParent);
2736
+ return;
2737
+ }
2738
+ let toIndex = typeof index === "undefined" ? newParentEntity.collapsedChildren.length : index;
2739
+ return this.doMoveNode(entity, newParentEntity, toIndex);
2740
+ }
2741
+ /**
2742
+ * 拖拽节点
2743
+ * @param param0
2744
+ * @returns
2745
+ */
2746
+ dragNodes({ dropNode, nodes }) {
2747
+ if (nodes.length === 0) {
2748
+ return;
2749
+ }
2750
+ const startNode = nodes[0];
2751
+ const fromParent = startNode.parent;
2752
+ const toParent = dropNode.parent;
2753
+ if (!fromParent || !toParent) {
2754
+ return;
2755
+ }
2756
+ const fromIndex = fromParent.children.findIndex((child) => child === startNode);
2757
+ const dropIndex = toParent.children.findIndex((child) => child === dropNode);
2758
+ let toIndex = dropIndex + 1;
2759
+ if (fromParent === toParent && fromIndex < dropIndex) {
2760
+ toIndex = toIndex - nodes.length;
2761
+ }
2762
+ const value = {
2763
+ nodeIds: nodes.map((node) => node.id),
2764
+ fromParentId: fromParent.id,
2765
+ toParentId: toParent.id,
2315
2766
  fromIndex,
2316
2767
  toIndex
2317
2768
  };
@@ -2426,420 +2877,140 @@ var FlowOperationBaseServiceImpl = class {
2426
2877
  return typeof node === "string" ? node : node.id;
2427
2878
  }
2428
2879
  toNodeEntity(node) {
2429
- return typeof node === "string" ? this.document.getNode(node) : node;
2430
- }
2431
- getNodeIndex(node) {
2432
- const entity = this.toNodeEntity(node);
2433
- const parent = entity?.parent;
2434
- if (!parent) {
2435
- return -1;
2436
- }
2437
- return parent.children.findIndex((child) => child === entity);
2438
- }
2439
- doMoveNode(node, newParent, index) {
2440
- return this.document.moveChildNodes({
2441
- nodeIds: [this.toId(node)],
2442
- toParentId: this.toId(newParent),
2443
- toIndex: index
2444
- });
2445
- }
2446
- };
2447
- __decorateClass([
2448
- (0, import_inversify3.inject)(import_core8.EntityManager)
2449
- ], FlowOperationBaseServiceImpl.prototype, "entityManager", 2);
2450
- __decorateClass([
2451
- (0, import_inversify3.inject)(FlowDocument)
2452
- ], FlowOperationBaseServiceImpl.prototype, "document", 2);
2453
- __decorateClass([
2454
- (0, import_inversify3.postConstruct)()
2455
- ], FlowOperationBaseServiceImpl.prototype, "init", 1);
2456
- FlowOperationBaseServiceImpl = __decorateClass([
2457
- (0, import_inversify3.injectable)()
2458
- ], FlowOperationBaseServiceImpl);
2459
-
2460
- // src/services/flow-group-service.ts
2461
- var import_nanoid = require("nanoid");
2462
- var import_inversify4 = require("inversify");
2463
- var import_core9 = require("@flowgram.ai/core");
2464
- var FlowGroupService = class {
2465
- /** 创建分组节点 */
2466
- createGroup(nodes) {
2467
- if (!nodes || !Array.isArray(nodes) || nodes.length === 0) {
2468
- return;
2469
- }
2470
- if (!FlowGroupController.validate(nodes)) {
2471
- return;
2472
- }
2473
- const sortedNodes = nodes.sort((a, b) => a.index - b.index);
2474
- const fromNode = sortedNodes[0];
2475
- const groupId = `group_${(0, import_nanoid.nanoid)(5)}`;
2476
- this.operationService.apply({
2477
- type: "createGroup" /* createGroup */,
2478
- value: {
2479
- targetId: fromNode.id,
2480
- groupId,
2481
- nodeIds: nodes.map((node) => node.id)
2482
- }
2483
- });
2484
- const groupNode = this.entityManager.getEntityById(groupId);
2485
- if (!groupNode) {
2486
- return;
2487
- }
2488
- const group = this.groupController(groupNode);
2489
- if (!group) {
2490
- return;
2491
- }
2492
- group.expand();
2493
- return groupNode;
2494
- }
2495
- /** 删除分组 */
2496
- deleteGroup(groupNode) {
2497
- const json = groupNode.toJSON();
2498
- if (!groupNode.pre || !json) {
2499
- return;
2500
- }
2501
- this.operationService.apply({
2502
- type: "deleteNodes" /* deleteNodes */,
2503
- value: {
2504
- fromId: groupNode.pre.id,
2505
- nodes: [json]
2506
- }
2507
- });
2508
- }
2509
- /** 取消分组 */
2510
- ungroup(groupNode) {
2511
- const group = this.groupController(groupNode);
2512
- if (!group) {
2513
- return;
2514
- }
2515
- const nodes = group.nodes;
2516
- if (!groupNode.pre) {
2517
- return;
2518
- }
2519
- group.collapse();
2520
- this.operationService.apply({
2521
- type: "ungroup" /* ungroup */,
2522
- value: {
2523
- groupId: groupNode.id,
2524
- targetId: groupNode.pre.id,
2525
- nodeIds: nodes.map((node) => node.id)
2526
- }
2527
- });
2528
- }
2529
- /** 返回所有分组节点 */
2530
- getAllGroups() {
2531
- const allNodes = this.entityManager.getEntities(FlowNodeEntity);
2532
- const groupNodes = allNodes.filter((node) => node.flowNodeType === "group" /* GROUP */);
2533
- return groupNodes.map((node) => this.groupController(node)).filter(Boolean);
2534
- }
2535
- /** 获取分组控制器*/
2536
- groupController(group) {
2537
- return FlowGroupController.create(group);
2538
- }
2539
- static validate(nodes) {
2540
- return FlowGroupController.validate(nodes);
2541
- }
2542
- };
2543
- __decorateClass([
2544
- (0, import_inversify4.inject)(import_core9.EntityManager)
2545
- ], FlowGroupService.prototype, "entityManager", 2);
2546
- __decorateClass([
2547
- (0, import_inversify4.inject)(FlowOperationBaseService)
2548
- ], FlowGroupService.prototype, "operationService", 2);
2549
- FlowGroupService = __decorateClass([
2550
- (0, import_inversify4.injectable)()
2551
- ], FlowGroupService);
2552
- var FlowGroupController = class _FlowGroupController {
2553
- constructor(groupNode) {
2554
- this.groupNode = groupNode;
2555
- }
2556
- get nodes() {
2557
- return this.groupNode.collapsedChildren || [];
2558
- }
2559
- get collapsed() {
2560
- const groupTransformData = this.groupNode.getData(FlowNodeTransformData);
2561
- return groupTransformData.collapsed;
2562
- }
2563
- collapse() {
2564
- this.collapsed = true;
2565
- }
2566
- expand() {
2567
- this.collapsed = false;
2568
- }
2569
- /** 获取分组外围的最大边框 */
2570
- get bounds() {
2571
- const groupNodeBounds = this.groupNode.getData(FlowNodeTransformData).bounds;
2572
- return groupNodeBounds;
2573
- }
2574
- /** 是否是开始节点 */
2575
- isStartNode(node) {
2576
- if (!node) {
2577
- return false;
2578
- }
2579
- const nodes = this.nodes;
2580
- if (!nodes[0]) {
2581
- return false;
2582
- }
2583
- return node.id === nodes[0].id;
2584
- }
2585
- /** 是否是结束节点 */
2586
- isEndNode(node) {
2587
- if (!node) {
2588
- return false;
2589
- }
2590
- const nodes = this.nodes;
2591
- if (!nodes[nodes.length - 1]) {
2592
- return false;
2593
- }
2594
- return node.id === nodes[nodes.length - 1].id;
2595
- }
2596
- set note(note) {
2597
- this.groupNode.getNodeMeta().note = note;
2598
- }
2599
- get note() {
2600
- return this.groupNode.getNodeMeta().note || "";
2601
- }
2602
- set noteHeight(height) {
2603
- this.groupNode.getNodeMeta().noteHeight = height;
2604
- }
2605
- get noteHeight() {
2606
- return this.groupNode.getNodeMeta().noteHeight || 0;
2607
- }
2608
- get positionConfig() {
2609
- return this.groupNode.getNodeMeta().positionConfig;
2610
- }
2611
- set collapsed(collapsed) {
2612
- const groupTransformData = this.groupNode.getData(FlowNodeTransformData);
2613
- groupTransformData.collapsed = collapsed;
2614
- groupTransformData.localDirty = true;
2615
- if (groupTransformData.parent) groupTransformData.parent.localDirty = true;
2616
- if (groupTransformData.parent?.firstChild)
2617
- groupTransformData.parent.firstChild.localDirty = true;
2880
+ return typeof node === "string" ? this.document.getNode(node) : node;
2618
2881
  }
2619
- set hovered(hovered) {
2620
- const groupRenderData = this.groupNode.getData(FlowNodeRenderData);
2621
- if (hovered) {
2622
- groupRenderData.toggleMouseEnter();
2623
- } else {
2624
- groupRenderData.toggleMouseLeave();
2625
- }
2626
- if (groupRenderData.hovered === hovered) {
2627
- return;
2882
+ getNodeIndex(node) {
2883
+ const entity = this.toNodeEntity(node);
2884
+ const parent = entity?.parent;
2885
+ if (!parent) {
2886
+ return -1;
2628
2887
  }
2629
- groupRenderData.hovered = hovered;
2888
+ return parent.children.findIndex((child) => child === entity);
2630
2889
  }
2631
- get hovered() {
2632
- const groupRenderData = this.groupNode.getData(FlowNodeRenderData);
2633
- return groupRenderData.hovered;
2890
+ doMoveNode(node, newParent, index) {
2891
+ if (!node.parent) {
2892
+ throw new Error("root node cannot move");
2893
+ }
2894
+ const event = {
2895
+ node,
2896
+ fromParent: node.parent,
2897
+ toParent: newParent,
2898
+ fromIndex: this.getNodeIndex(node),
2899
+ toIndex: index
2900
+ };
2901
+ this.document.moveChildNodes({
2902
+ nodeIds: [this.toId(node)],
2903
+ toParentId: this.toId(newParent),
2904
+ toIndex: index
2905
+ });
2906
+ this.onNodeMoveEmitter.fire(event);
2634
2907
  }
2635
- static create(groupNode) {
2636
- if (!groupNode) {
2908
+ };
2909
+ __decorateClass([
2910
+ (0, import_inversify4.inject)(import_core9.EntityManager)
2911
+ ], FlowOperationBaseServiceImpl.prototype, "entityManager", 2);
2912
+ __decorateClass([
2913
+ (0, import_inversify4.inject)(FlowDocument)
2914
+ ], FlowOperationBaseServiceImpl.prototype, "document", 2);
2915
+ __decorateClass([
2916
+ (0, import_inversify4.postConstruct)()
2917
+ ], FlowOperationBaseServiceImpl.prototype, "init", 1);
2918
+ FlowOperationBaseServiceImpl = __decorateClass([
2919
+ (0, import_inversify4.injectable)()
2920
+ ], FlowOperationBaseServiceImpl);
2921
+
2922
+ // src/services/flow-group-service/flow-group-service.ts
2923
+ var import_nanoid = require("nanoid");
2924
+ var import_inversify5 = require("inversify");
2925
+ var import_core10 = require("@flowgram.ai/core");
2926
+ var FlowGroupService = class {
2927
+ /** 创建分组节点 */
2928
+ createGroup(nodes) {
2929
+ if (!nodes || !Array.isArray(nodes) || nodes.length === 0) {
2637
2930
  return;
2638
2931
  }
2639
- if (!_FlowGroupController.isGroupNode(groupNode)) {
2932
+ if (!FlowGroupUtils.validate(nodes)) {
2640
2933
  return;
2641
2934
  }
2642
- return new _FlowGroupController(groupNode);
2643
- }
2644
- /** 判断节点能否组成分组 */
2645
- static validate(nodes) {
2646
- if (!nodes || !Array.isArray(nodes) || nodes.length === 0) {
2647
- return false;
2648
- }
2649
- const isGroupRelatedNode = nodes.some((node) => _FlowGroupController.isGroupNode(node));
2650
- if (isGroupRelatedNode) return false;
2651
- const hasGroup = nodes.some((node) => node && this.isNodeInGroup(node));
2652
- if (hasGroup) return false;
2653
- const parent = nodes[0].parent;
2654
- const isSameParent = nodes.every((node) => node.parent === parent);
2655
- if (!isSameParent) return false;
2656
- const indexes = nodes.map((node) => node.index).sort((a, b) => a - b);
2657
- const isIndexContinuous = indexes.every((index, i, arr) => {
2658
- if (i === 0) {
2659
- return true;
2935
+ const sortedNodes = nodes.sort((a, b) => a.index - b.index);
2936
+ const fromNode = sortedNodes[0];
2937
+ const groupId = `group_${(0, import_nanoid.nanoid)(5)}`;
2938
+ this.operationService.apply({
2939
+ type: "createGroup" /* createGroup */,
2940
+ value: {
2941
+ targetId: fromNode.id,
2942
+ groupId,
2943
+ nodeIds: nodes.map((node) => node.id)
2660
2944
  }
2661
- return index === arr[i - 1] + 1;
2662
2945
  });
2663
- if (!isIndexContinuous) return false;
2664
- const parents = this.findNodeParents(nodes[0]);
2665
- const parentsInGroup = parents.some((parent2) => this.isNodeInGroup(parent2));
2666
- if (parentsInGroup) return false;
2667
- return true;
2668
- }
2669
- /** 获取节点分组控制 */
2670
- static getNodeGroupController(node) {
2671
- if (!node) {
2946
+ const groupNode = this.entityManager.getEntityById(groupId);
2947
+ if (!groupNode) {
2672
2948
  return;
2673
2949
  }
2674
- if (!this.isNodeInGroup(node)) {
2950
+ const group = this.groupController(groupNode);
2951
+ if (!group) {
2675
2952
  return;
2676
2953
  }
2677
- const groupNode = node?.parent;
2678
- return _FlowGroupController.create(groupNode);
2954
+ group.expand();
2955
+ return groupNode;
2679
2956
  }
2680
- /** 向上递归查找分组递归控制 */
2681
- static getNodeRecursionGroupController(node) {
2682
- if (!node) {
2957
+ /** 删除分组 */
2958
+ deleteGroup(groupNode) {
2959
+ const json = groupNode.toJSON();
2960
+ if (!groupNode.pre || !json) {
2683
2961
  return;
2684
2962
  }
2685
- const group = this.getNodeGroupController(node);
2686
- if (group) {
2687
- return group;
2688
- }
2689
- if (node.parent) {
2690
- return this.getNodeRecursionGroupController(node.parent);
2691
- }
2692
- return;
2693
- }
2694
- /** 是否分组节点 */
2695
- static isGroupNode(group) {
2696
- return group.flowNodeType === "group" /* GROUP */;
2697
- }
2698
- /** 找到节点所有上级 */
2699
- static findNodeParents(node) {
2700
- const parents = [];
2701
- let parent = node.parent;
2702
- while (parent) {
2703
- parents.push(parent);
2704
- parent = parent.parent;
2705
- }
2706
- return parents;
2707
- }
2708
- /** 节点是否处于分组中 */
2709
- static isNodeInGroup(node) {
2710
- if (node?.parent?.flowNodeType === "group" /* GROUP */) {
2711
- return true;
2712
- }
2713
- return false;
2714
- }
2715
- };
2716
-
2717
- // src/services/flow-drag-service.ts
2718
- var FlowDragService = class {
2719
- constructor() {
2720
- this.onDropEmitter = new import_utils9.Emitter();
2721
- this.onDrop = this.onDropEmitter.event;
2722
- }
2723
- get renderState() {
2724
- return this.document.renderState;
2725
- }
2726
- // 拖拽所有节点中的首个节点
2727
- get dragStartNode() {
2728
- return this.renderState.getDragStartEntity();
2729
- }
2730
- // 拖拽的所有节点
2731
- get dragNodes() {
2732
- return this.renderState.getDragEntities();
2733
- }
2734
- // 放置的区域
2735
- get dropNodeId() {
2736
- return this.renderState.getNodeDroppingId();
2737
- }
2738
- // 是否在拖拽分支
2739
- get isDragBranch() {
2740
- return this.dragStartNode?.isInlineBlock;
2741
- }
2742
- // 拖拽的所有节点及其自节点
2743
- get nodeDragIdsWithChildren() {
2744
- return this.renderState.config.nodeDragIdsWithChildren || [];
2745
- }
2746
- get dragging() {
2747
- const renderData = this.dragStartNode?.getData(FlowNodeRenderData);
2748
- return !!renderData?.dragging;
2749
- }
2750
- get labelSide() {
2751
- return this.renderState.config.dragLabelSide;
2752
- }
2753
- /**
2754
- * 放置到目标分支
2755
- */
2756
- dropBranch() {
2757
- this.dropNode();
2963
+ this.operationService.apply({
2964
+ type: "deleteNodes" /* deleteNodes */,
2965
+ value: {
2966
+ fromId: groupNode.pre.id,
2967
+ nodes: [json]
2968
+ }
2969
+ });
2758
2970
  }
2759
- /**
2760
- * 移动到目标节点
2761
- */
2762
- dropNode() {
2763
- const dropEntity = this.document.getNode(this.dropNodeId);
2764
- if (!dropEntity) {
2971
+ /** 取消分组 */
2972
+ ungroup(groupNode) {
2973
+ const group = this.groupController(groupNode);
2974
+ if (!group) {
2765
2975
  return;
2766
2976
  }
2767
- const sortNodes = [];
2768
- let curr = this.dragStartNode;
2769
- while (curr && this.dragNodes.includes(curr)) {
2770
- sortNodes.push(curr);
2771
- curr = curr.next;
2977
+ const nodes = group.nodes;
2978
+ if (!groupNode.pre) {
2979
+ return;
2772
2980
  }
2773
- this.operationService.dragNodes({
2774
- dropNode: dropEntity,
2775
- nodes: sortNodes
2981
+ group.collapse();
2982
+ this.operationService.apply({
2983
+ type: "ungroup" /* ungroup */,
2984
+ value: {
2985
+ groupId: groupNode.id,
2986
+ targetId: groupNode.pre.id,
2987
+ nodeIds: nodes.map((node) => node.id)
2988
+ }
2776
2989
  });
2777
- if (sortNodes.length > 0) {
2778
- this.onDropEmitter.fire({
2779
- dropNode: dropEntity,
2780
- dragNodes: sortNodes
2781
- });
2782
- }
2783
2990
  }
2784
- /**
2785
- * 拖拽是否可以释放在该节点后面
2786
- */
2787
- isDroppableNode(node) {
2788
- if (!this.dragging || this.isDragBranch) {
2789
- return false;
2790
- }
2791
- if (this.nodeDragIdsWithChildren.includes(node.id) || node.next && this.nodeDragIdsWithChildren.includes(node.next.id)) {
2792
- return false;
2793
- }
2794
- if (node.isInlineBlocks || node.isInlineBlock) {
2795
- return false;
2796
- }
2797
- const hasGroupNode = this.dragNodes.some((node2) => node2.flowNodeType === "group" /* GROUP */);
2798
- if (hasGroupNode) {
2799
- const group = FlowGroupController.getNodeRecursionGroupController(node);
2800
- if (group) {
2801
- return false;
2802
- }
2803
- }
2804
- return true;
2991
+ /** 返回所有分组节点 */
2992
+ getAllGroups() {
2993
+ const allNodes = this.entityManager.getEntities(FlowNodeEntity);
2994
+ const groupNodes = allNodes.filter((node) => node.flowNodeType === "group" /* GROUP */);
2995
+ return groupNodes.map((node) => this.groupController(node)).filter(Boolean);
2805
2996
  }
2806
- /**
2807
- * 拖拽分支是否可以释放在该分支
2808
- * @param node 拖拽的分支节点
2809
- * @param side 分支的前面还是后面
2810
- */
2811
- isDroppableBranch(node, side = "normal_branch" /* NORMAL_BRANCH */) {
2812
- if (this.isDragBranch) {
2813
- if (
2814
- // 拖拽到分支
2815
- !node.isInlineBlock || // 只能在同一分支条件下
2816
- node.parent !== this.dragStartNode.parent || // 自己不能拖拽给自己
2817
- node === this.dragStartNode
2818
- ) {
2819
- return false;
2820
- }
2821
- if (side === "normal_branch" /* NORMAL_BRANCH */ && node.next !== this.dragStartNode) {
2822
- return true;
2823
- }
2824
- if (side === "pre_branch" /* PRE_BRANCH */ && node.pre !== this.dragStartNode) {
2825
- return true;
2826
- }
2827
- }
2828
- return false;
2997
+ /** 获取分组控制器*/
2998
+ groupController(group) {
2999
+ return FlowGroupController.create(group);
3000
+ }
3001
+ static validate(nodes) {
3002
+ return FlowGroupUtils.validate(nodes);
2829
3003
  }
2830
3004
  };
2831
3005
  __decorateClass([
2832
- (0, import_inversify5.inject)(FlowDocument)
2833
- ], FlowDragService.prototype, "document", 2);
3006
+ (0, import_inversify5.inject)(import_core10.EntityManager)
3007
+ ], FlowGroupService.prototype, "entityManager", 2);
2834
3008
  __decorateClass([
2835
3009
  (0, import_inversify5.inject)(FlowOperationBaseService)
2836
- ], FlowDragService.prototype, "operationService", 2);
2837
- __decorateClass([
2838
- (0, import_inversify5.inject)(import_core10.EntityManager)
2839
- ], FlowDragService.prototype, "entityManager", 2);
2840
- FlowDragService = __decorateClass([
3010
+ ], FlowGroupService.prototype, "operationService", 2);
3011
+ FlowGroupService = __decorateClass([
2841
3012
  (0, import_inversify5.injectable)()
2842
- ], FlowDragService);
3013
+ ], FlowGroupService);
2843
3014
 
2844
3015
  // src/layout/vertical-fixed-layout.ts
2845
3016
  var import_inversify6 = require("inversify");