@flowgram.ai/document 0.1.0-alpha.2 → 0.1.0-alpha.21

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;
@@ -1040,37 +1097,7 @@ var FlowNodeEntity = class extends import_core4.Entity {
1040
1097
  * @param newId
1041
1098
  */
1042
1099
  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;
1100
+ return this.document.toNodeJSON(this);
1074
1101
  }
1075
1102
  get isVertical() {
1076
1103
  return this.document.layout.name === "vertical-fixed-layout" /* VERTICAL_FIXED_LAYOUT */;
@@ -1079,8 +1106,8 @@ var FlowNodeEntity = class extends import_core4.Entity {
1079
1106
  * 修改节点扩展信息
1080
1107
  * @param info
1081
1108
  */
1082
- updateExtInfo(extInfo) {
1083
- this.getData(FlowNodeRenderData).updateExtInfo(extInfo);
1109
+ updateExtInfo(extInfo, fullUpdate) {
1110
+ this.getData(FlowNodeRenderData).updateExtInfo(extInfo, fullUpdate);
1084
1111
  }
1085
1112
  /**
1086
1113
  * 获取节点扩展信息
@@ -1109,6 +1136,19 @@ var FlowNodeEntity = class extends import_core4.Entity {
1109
1136
  get bounds() {
1110
1137
  return this.transform.bounds;
1111
1138
  }
1139
+ /**
1140
+ * Check node extend type
1141
+ */
1142
+ isExtend(parentType) {
1143
+ return this.document.isExtend(this.flowNodeType, parentType);
1144
+ }
1145
+ /**
1146
+ * Check node type
1147
+ * @param parentType
1148
+ */
1149
+ isTypeOrExtendType(parentType) {
1150
+ return this.document.isTypeOrExtendType(this.flowNodeType, parentType);
1151
+ }
1112
1152
  };
1113
1153
  FlowNodeEntity.type = "FlowNodeEntity";
1114
1154
  ((FlowNodeEntity2) => {
@@ -1202,7 +1242,7 @@ var FlowDocumentTransformerEntity = class extends import_core5.ConfigEntity {
1202
1242
  FlowDocumentTransformerEntity.type = "FlowDocumentTransformerEntity";
1203
1243
 
1204
1244
  // src/entities/flow-renderer-state-entity.ts
1205
- var import_lodash = require("lodash");
1245
+ var import_lodash_es = require("lodash-es");
1206
1246
  var import_core6 = require("@flowgram.ai/core");
1207
1247
  var FlowRendererStateEntity = class extends import_core6.ConfigEntity {
1208
1248
  getDefaultConfig() {
@@ -1219,6 +1259,22 @@ var FlowRendererStateEntity = class extends import_core6.ConfigEntity {
1219
1259
  nodeHoveredId: node?.id
1220
1260
  });
1221
1261
  }
1262
+ get dragging() {
1263
+ return this.config.dragging;
1264
+ }
1265
+ setDragging(dragging) {
1266
+ this.updateConfig({
1267
+ dragging
1268
+ });
1269
+ }
1270
+ get isBranch() {
1271
+ return this.config.isBranch;
1272
+ }
1273
+ setIsBranch(isBranch) {
1274
+ this.updateConfig({
1275
+ isBranch
1276
+ });
1277
+ }
1222
1278
  getDragLabelSide() {
1223
1279
  return this.config.dragLabelSide;
1224
1280
  }
@@ -1257,13 +1313,13 @@ var FlowRendererStateEntity = class extends import_core6.ConfigEntity {
1257
1313
  });
1258
1314
  }
1259
1315
  onNodeHoveredChange(fn, debounceTime = 100) {
1260
- return this.onConfigChanged((0, import_lodash.debounce)(() => fn(this.getNodeHovered()), debounceTime));
1316
+ return this.onConfigChanged((0, import_lodash_es.debounce)(() => fn(this.getNodeHovered()), debounceTime));
1261
1317
  }
1262
1318
  };
1263
1319
  FlowRendererStateEntity.type = "FlowRendererStateEntity";
1264
1320
 
1265
1321
  // src/flow-document.ts
1266
- var import_lodash2 = require("lodash");
1322
+ var import_lodash_es2 = require("lodash-es");
1267
1323
  var import_inversify2 = require("inversify");
1268
1324
  var import_utils7 = require("@flowgram.ai/utils");
1269
1325
  var import_core7 = require("@flowgram.ai/core");
@@ -1441,13 +1497,15 @@ var FlowVirtualTree = class _FlowVirtualTree {
1441
1497
  get size() {
1442
1498
  return this.map.size;
1443
1499
  }
1444
- toString() {
1500
+ toString(showType) {
1445
1501
  const ret = [];
1446
1502
  this.traverse((node, depth) => {
1447
1503
  if (depth === 0) {
1448
1504
  ret.push(node.id);
1449
1505
  } else {
1450
- ret.push(`|${new Array(depth).fill("--").join("")} ${node.id}`);
1506
+ ret.push(
1507
+ `|${new Array(depth).fill("--").join("")} ${showType ? `${node.flowNodeType}(${node.id})` : node.id}`
1508
+ );
1451
1509
  }
1452
1510
  });
1453
1511
  return `${ret.join("\n")}`;
@@ -1653,7 +1711,12 @@ var ConstantKeys = {
1653
1711
  /***
1654
1712
  * 线条、label 激活后的颜色
1655
1713
  */
1656
- BASE_ACTIVATED_COLOR: "BASE_ACTIVATED_COLOR"
1714
+ BASE_ACTIVATED_COLOR: "BASE_ACTIVATED_COLOR",
1715
+ /**
1716
+ * Branch bottom margin
1717
+ * 分支下边距
1718
+ */
1719
+ INLINE_BLOCKS_PADDING_TOP: "INLINE_BLOCKS_PADDING_TOP"
1657
1720
  };
1658
1721
 
1659
1722
  // src/flow-document-contribution.ts
@@ -1708,6 +1771,13 @@ var FlowDocument = class {
1708
1771
  this.onNodeCreate = this.onNodeCreateEmitter.event;
1709
1772
  this.onNodeDispose = this.onNodeDisposeEmitter.event;
1710
1773
  this.onLayoutChange = this.onLayoutChangeEmitter.event;
1774
+ this._disposed = false;
1775
+ }
1776
+ /**
1777
+ *
1778
+ */
1779
+ get disposed() {
1780
+ return this._disposed;
1711
1781
  }
1712
1782
  init() {
1713
1783
  if (!this.options) this.options = FlowDocumentOptionsDefault;
@@ -1733,6 +1803,7 @@ var FlowDocument = class {
1733
1803
  * @param fireRender 是否要触发渲染,默认 true
1734
1804
  */
1735
1805
  fromJSON(json, fireRender = true) {
1806
+ if (this._disposed) return;
1736
1807
  this.originTree.clear();
1737
1808
  this.renderTree.clear();
1738
1809
  this.entityManager.changeEntityLocked = true;
@@ -1801,7 +1872,7 @@ var FlowDocument = class {
1801
1872
  * @param data
1802
1873
  * @param addedNodes
1803
1874
  */
1804
- addNode(data, addedNodes, ignoreCreateEvent) {
1875
+ addNode(data, addedNodes) {
1805
1876
  const { id, type = "block", originParent, parent, meta, hidden, index } = data;
1806
1877
  let node = this.getNode(id);
1807
1878
  let isNew = false;
@@ -1819,13 +1890,14 @@ var FlowDocument = class {
1819
1890
  originParent,
1820
1891
  meta
1821
1892
  });
1893
+ this.options.preNodeCreate?.(node);
1822
1894
  const datas = dataRegistries ? this.nodeDataRegistries.concat(...dataRegistries) : this.nodeDataRegistries;
1823
1895
  node.addInitializeData(datas);
1824
1896
  node.onDispose(() => this.onNodeDisposeEmitter.fire({ node }));
1825
- if (this.options.fromNodeJSON) {
1826
- this.options.fromNodeJSON(node, data);
1827
- }
1897
+ this.options.fromNodeJSON?.(node, data, true);
1828
1898
  isNew = true;
1899
+ } else {
1900
+ this.options.fromNodeJSON?.(node, data, false);
1829
1901
  }
1830
1902
  node.initData({
1831
1903
  originParent,
@@ -1837,7 +1909,6 @@ var FlowDocument = class {
1837
1909
  if (node.isStart) {
1838
1910
  this.root.addChild(node);
1839
1911
  }
1840
- this.onNodeUpdateEmitter.fire({ node, data });
1841
1912
  addedNodes?.push(node);
1842
1913
  if (register.onCreate) {
1843
1914
  const extendNodes = register.onCreate(node, data);
@@ -1851,11 +1922,14 @@ var FlowDocument = class {
1851
1922
  this.addBlocksAsChildren(node, data.blocks, addedNodes);
1852
1923
  }
1853
1924
  }
1854
- if (isNew && !ignoreCreateEvent) {
1925
+ if (isNew) {
1855
1926
  this.onNodeCreateEmitter.fire({
1856
1927
  node,
1857
- data
1928
+ data,
1929
+ json: data
1858
1930
  });
1931
+ } else {
1932
+ this.onNodeUpdateEmitter.fire({ node, data, json: data });
1859
1933
  }
1860
1934
  return node;
1861
1935
  }
@@ -1891,18 +1965,16 @@ var FlowDocument = class {
1891
1965
  parent: node
1892
1966
  });
1893
1967
  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
- }
1968
+ const inlineBlocksNode = this.addNode({
1969
+ id: `$inlineBlocks$${node.id}`,
1970
+ type: "inlineBlocks" /* INLINE_BLOCKS */,
1971
+ originParent: node,
1972
+ parent: node
1973
+ });
1974
+ addedNodes.push(inlineBlocksNode);
1975
+ blocks.forEach((blockData) => {
1976
+ this.addBlock(node, blockData, addedNodes);
1977
+ });
1906
1978
  return addedNodes;
1907
1979
  }
1908
1980
  /**
@@ -1920,7 +1992,7 @@ var FlowDocument = class {
1920
1992
  }
1921
1993
  parent = parent || this.getNode(`$inlineBlocks$${node.id}`);
1922
1994
  const block = this.addNode({
1923
- ...(0, import_lodash2.omit)(blockData, "blocks"),
1995
+ ...(0, import_lodash_es2.omit)(blockData, "blocks"),
1924
1996
  type: blockData.type || "block" /* BLOCK */,
1925
1997
  originParent: node,
1926
1998
  parent,
@@ -1967,14 +2039,39 @@ var FlowDocument = class {
1967
2039
  meta: {
1968
2040
  ...preRegistry?.meta,
1969
2041
  ...newRegistry?.meta
1970
- }
2042
+ },
2043
+ extendChildRegistries: FlowNodeRegistry.mergeChildRegistries(
2044
+ preRegistry?.extendChildRegistries,
2045
+ newRegistry?.extendChildRegistries
2046
+ )
1971
2047
  });
1972
2048
  });
1973
2049
  }
2050
+ /**
2051
+ * Check node extend
2052
+ * @param currentType
2053
+ * @param extendType
2054
+ */
2055
+ isExtend(currentType, extendType) {
2056
+ return (this.getNodeRegistry(currentType).__extends__ || []).includes(extendType);
2057
+ }
2058
+ /**
2059
+ * Check node type
2060
+ * @param currentType
2061
+ * @param extendType
2062
+ */
2063
+ isTypeOrExtendType(currentType, extendType) {
2064
+ return currentType === extendType || this.isExtend(currentType, extendType);
2065
+ }
1974
2066
  /**
1975
2067
  * 导出数据,可以重载
1976
2068
  */
1977
2069
  toJSON() {
2070
+ if (this.disposed) {
2071
+ throw new Error(
2072
+ "The FlowDocument has been disposed and it is no longer possible to call toJSON."
2073
+ );
2074
+ }
1978
2075
  return {
1979
2076
  nodes: this.root.toJSON().blocks
1980
2077
  };
@@ -1994,6 +2091,7 @@ var FlowDocument = class {
1994
2091
  const customDefaultRegistry = this.options.getNodeDefaultRegistry?.(type);
1995
2092
  let register = this.registers.get(type) || { type };
1996
2093
  const extendRegisters = [];
2094
+ const extendKey = register.extend;
1997
2095
  if (register.extend && this.registers.has(register.extend)) {
1998
2096
  register = FlowNodeRegistry.merge(
1999
2097
  this.getNodeRegistry(register.extend),
@@ -2024,6 +2122,9 @@ var FlowDocument = class {
2024
2122
  ...register.meta
2025
2123
  }
2026
2124
  };
2125
+ if (extendKey) {
2126
+ res.extend = extendKey;
2127
+ }
2027
2128
  this.nodeRegistryCache.set(typeKey, res);
2028
2129
  return res;
2029
2130
  }
@@ -2074,8 +2175,8 @@ var FlowDocument = class {
2074
2175
  getAllNodes() {
2075
2176
  return this.entityManager.getEntities(FlowNodeEntity);
2076
2177
  }
2077
- toString() {
2078
- return this.originTree.toString();
2178
+ toString(showType) {
2179
+ return this.originTree.toString(showType);
2079
2180
  }
2080
2181
  /**
2081
2182
  * 返回需要渲染的数据
@@ -2088,6 +2189,39 @@ var FlowDocument = class {
2088
2189
  });
2089
2190
  return result;
2090
2191
  }
2192
+ toNodeJSON(node) {
2193
+ if (this.options.toNodeJSON) {
2194
+ return this.options.toNodeJSON(node);
2195
+ }
2196
+ const nodesMap = {};
2197
+ let startNodeJSON;
2198
+ this.traverse((node2) => {
2199
+ const isSystemNode = node2.id.startsWith("$");
2200
+ if (isSystemNode) return;
2201
+ const nodeJSONData = node2.getJSONData();
2202
+ const nodeJSON = {
2203
+ id: node2.id,
2204
+ type: node2.flowNodeType
2205
+ };
2206
+ if (nodeJSONData !== void 0) {
2207
+ nodeJSON.data = nodeJSONData;
2208
+ }
2209
+ if (!startNodeJSON) startNodeJSON = nodeJSON;
2210
+ let { parent } = node2;
2211
+ if (parent && parent.id.startsWith("$")) {
2212
+ parent = parent.originParent;
2213
+ }
2214
+ const parentJSON = parent ? nodesMap[parent.id] : void 0;
2215
+ if (parentJSON) {
2216
+ if (!parentJSON.blocks) {
2217
+ parentJSON.blocks = [];
2218
+ }
2219
+ parentJSON.blocks.push(nodeJSON);
2220
+ }
2221
+ nodesMap[node2.id] = nodeJSON;
2222
+ }, node);
2223
+ return startNodeJSON;
2224
+ }
2091
2225
  /**
2092
2226
  * 移动节点
2093
2227
  * @param param0
@@ -2170,6 +2304,7 @@ var FlowDocument = class {
2170
2304
  );
2171
2305
  }
2172
2306
  dispose() {
2307
+ if (this._disposed) return;
2173
2308
  this.registers.clear();
2174
2309
  this.nodeRegistryCache.clear();
2175
2310
  this.originTree.dispose();
@@ -2178,6 +2313,7 @@ var FlowDocument = class {
2178
2313
  this.onNodeCreateEmitter.dispose();
2179
2314
  this.onNodeDisposeEmitter.dispose();
2180
2315
  this.onLayoutChangeEmitter.dispose();
2316
+ this._disposed = true;
2181
2317
  }
2182
2318
  };
2183
2319
  __decorateClass([
@@ -2205,113 +2341,427 @@ FlowDocument = __decorateClass([
2205
2341
  var import_inversify8 = require("inversify");
2206
2342
 
2207
2343
  // 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
2344
  var import_inversify3 = require("inversify");
2214
2345
  var import_utils8 = require("@flowgram.ai/utils");
2215
2346
  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();
2347
+
2348
+ // src/services/flow-group-service/flow-group-controller.ts
2349
+ var FlowGroupController = class _FlowGroupController {
2350
+ constructor(groupNode) {
2351
+ this.groupNode = groupNode;
2221
2352
  }
2222
- init() {
2223
- this.toDispose.push(this.onNodeAddEmitter);
2353
+ get nodes() {
2354
+ return this.groupNode.collapsedChildren || [];
2224
2355
  }
2225
- addNode(nodeJSON, config = {}) {
2226
- const { parent, index, hidden } = config;
2227
- let parentEntity;
2228
- if (parent) {
2229
- parentEntity = this.toNodeEntity(parent);
2356
+ get collapsed() {
2357
+ const groupTransformData = this.groupNode.getData(FlowNodeTransformData);
2358
+ return groupTransformData.collapsed;
2359
+ }
2360
+ collapse() {
2361
+ this.collapsed = true;
2362
+ }
2363
+ expand() {
2364
+ this.collapsed = false;
2365
+ }
2366
+ /** 获取分组外围的最大边框 */
2367
+ get bounds() {
2368
+ const groupNodeBounds = this.groupNode.getData(FlowNodeTransformData).bounds;
2369
+ return groupNodeBounds;
2370
+ }
2371
+ /** 是否是开始节点 */
2372
+ isStartNode(node) {
2373
+ if (!node) {
2374
+ return false;
2230
2375
  }
2231
- let register;
2232
- if (parentEntity) {
2233
- register = parentEntity.getNodeRegistry();
2376
+ const nodes = this.nodes;
2377
+ if (!nodes[0]) {
2378
+ return false;
2234
2379
  }
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);
2380
+ return node.id === nodes[0].id;
2381
+ }
2382
+ /** 是否是结束节点 */
2383
+ isEndNode(node) {
2384
+ if (!node) {
2385
+ return false;
2253
2386
  }
2254
- this.onNodeAddEmitter.fire({
2255
- node: added,
2256
- data: addNodeData
2257
- });
2258
- return added;
2387
+ const nodes = this.nodes;
2388
+ if (!nodes[nodes.length - 1]) {
2389
+ return false;
2390
+ }
2391
+ return node.id === nodes[nodes.length - 1].id;
2259
2392
  }
2260
- addFromNode(fromNode, nodeJSON) {
2261
- return this.document.addFromNode(fromNode, nodeJSON);
2393
+ set note(note) {
2394
+ this.groupNode.getNodeMeta().note = note;
2262
2395
  }
2263
- deleteNode(node) {
2264
- this.document.removeNode(node);
2396
+ get note() {
2397
+ return this.groupNode.getNodeMeta().note || "";
2265
2398
  }
2266
- deleteNodes(nodes) {
2267
- (nodes || []).forEach((node) => {
2268
- this.deleteNode(node);
2269
- });
2399
+ set noteHeight(height) {
2400
+ this.groupNode.getNodeMeta().noteHeight = height;
2270
2401
  }
2271
- addBlock(target, blockJSON, config = {}) {
2272
- const { parent, index } = config;
2273
- return this.document.addBlock(target, blockJSON, void 0, parent, index);
2402
+ get noteHeight() {
2403
+ return this.groupNode.getNodeMeta().noteHeight || 0;
2274
2404
  }
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;
2405
+ get positionConfig() {
2406
+ return this.groupNode.getNodeMeta().positionConfig;
2407
+ }
2408
+ set collapsed(collapsed) {
2409
+ const groupTransformData = this.groupNode.getData(FlowNodeTransformData);
2410
+ groupTransformData.collapsed = collapsed;
2411
+ groupTransformData.localDirty = true;
2412
+ if (groupTransformData.parent) groupTransformData.parent.localDirty = true;
2413
+ if (groupTransformData.parent?.firstChild)
2414
+ groupTransformData.parent.firstChild.localDirty = true;
2415
+ }
2416
+ set hovered(hovered) {
2417
+ const groupRenderData = this.groupNode.getData(FlowNodeRenderData);
2418
+ if (hovered) {
2419
+ groupRenderData.toggleMouseEnter();
2420
+ } else {
2421
+ groupRenderData.toggleMouseLeave();
2281
2422
  }
2282
- const newParentEntity = newParent ? this.toNodeEntity(newParent) : parent;
2283
- if (!newParentEntity) {
2284
- console.warn("no new parent found", newParent);
2423
+ if (groupRenderData.hovered === hovered) {
2285
2424
  return;
2286
2425
  }
2287
- let toIndex = typeof index === "undefined" ? parent.children.length : index;
2288
- return this.doMoveNode(entity, newParentEntity, toIndex);
2426
+ groupRenderData.hovered = hovered;
2289
2427
  }
2290
- /**
2291
- * 拖拽节点
2292
- * @param param0
2293
- * @returns
2294
- */
2295
- dragNodes({ dropNode, nodes }) {
2296
- if (nodes.length === 0) {
2428
+ get hovered() {
2429
+ const groupRenderData = this.groupNode.getData(FlowNodeRenderData);
2430
+ return groupRenderData.hovered;
2431
+ }
2432
+ static create(groupNode) {
2433
+ if (!groupNode) {
2297
2434
  return;
2298
2435
  }
2299
- const startNode = nodes[0];
2300
- const fromParent = startNode.parent;
2301
- const toParent = dropNode.parent;
2302
- if (!fromParent || !toParent) {
2436
+ if (!FlowGroupUtils.isGroupNode(groupNode)) {
2303
2437
  return;
2304
2438
  }
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,
2439
+ return new _FlowGroupController(groupNode);
2440
+ }
2441
+ };
2442
+
2443
+ // src/services/flow-group-service/flow-group-utils.ts
2444
+ var FlowGroupUtils;
2445
+ ((FlowGroupUtils2) => {
2446
+ const findNodeParents = (node) => {
2447
+ const parents = [];
2448
+ let parent = node.parent;
2449
+ while (parent) {
2450
+ parents.push(parent);
2451
+ parent = parent.parent;
2452
+ }
2453
+ return parents;
2454
+ };
2455
+ const isNodeInGroup = (node) => {
2456
+ if (node?.parent?.flowNodeType === "group" /* GROUP */) {
2457
+ return true;
2458
+ }
2459
+ return false;
2460
+ };
2461
+ FlowGroupUtils2.validate = (nodes) => {
2462
+ if (!nodes || !Array.isArray(nodes) || nodes.length === 0) {
2463
+ return false;
2464
+ }
2465
+ const isGroupRelatedNode = nodes.some((node) => (0, FlowGroupUtils2.isGroupNode)(node));
2466
+ if (isGroupRelatedNode) return false;
2467
+ const hasGroup = nodes.some((node) => node && isNodeInGroup(node));
2468
+ if (hasGroup) return false;
2469
+ const parent = nodes[0].parent;
2470
+ const isSameParent = nodes.every((node) => node.parent === parent);
2471
+ if (!isSameParent) return false;
2472
+ const indexes = nodes.map((node) => node.index).sort((a, b) => a - b);
2473
+ const isIndexContinuous = indexes.every((index, i, arr) => {
2474
+ if (i === 0) {
2475
+ return true;
2476
+ }
2477
+ return index === arr[i - 1] + 1;
2478
+ });
2479
+ if (!isIndexContinuous) return false;
2480
+ const parents = findNodeParents(nodes[0]);
2481
+ const parentsInGroup = parents.some((parent2) => isNodeInGroup(parent2));
2482
+ if (parentsInGroup) return false;
2483
+ return true;
2484
+ };
2485
+ FlowGroupUtils2.getNodeGroupController = (node) => {
2486
+ if (!node) {
2487
+ return;
2488
+ }
2489
+ if (!isNodeInGroup(node)) {
2490
+ return;
2491
+ }
2492
+ const groupNode = node?.parent;
2493
+ return FlowGroupController.create(groupNode);
2494
+ };
2495
+ FlowGroupUtils2.getNodeRecursionGroupController = (node) => {
2496
+ if (!node) {
2497
+ return;
2498
+ }
2499
+ const group = (0, FlowGroupUtils2.getNodeGroupController)(node);
2500
+ if (group) {
2501
+ return group;
2502
+ }
2503
+ if (node.parent) {
2504
+ return (0, FlowGroupUtils2.getNodeRecursionGroupController)(node.parent);
2505
+ }
2506
+ return;
2507
+ };
2508
+ FlowGroupUtils2.isGroupNode = (group) => group.flowNodeType === "group" /* GROUP */;
2509
+ })(FlowGroupUtils || (FlowGroupUtils = {}));
2510
+
2511
+ // src/services/flow-drag-service.ts
2512
+ var FlowDragService = class {
2513
+ constructor() {
2514
+ this.onDropEmitter = new import_utils8.Emitter();
2515
+ this.onDrop = this.onDropEmitter.event;
2516
+ }
2517
+ get renderState() {
2518
+ return this.document.renderState;
2519
+ }
2520
+ // 拖拽所有节点中的首个节点
2521
+ get dragStartNode() {
2522
+ return this.renderState.getDragStartEntity();
2523
+ }
2524
+ // 拖拽的所有节点
2525
+ get dragNodes() {
2526
+ return this.renderState.getDragEntities();
2527
+ }
2528
+ // 放置的区域
2529
+ get dropNodeId() {
2530
+ return this.renderState.getNodeDroppingId();
2531
+ }
2532
+ // 是否在拖拽分支
2533
+ get isDragBranch() {
2534
+ return this.renderState.isBranch || this.dragStartNode?.isInlineBlock;
2535
+ }
2536
+ // 拖拽的所有节点及其自节点
2537
+ get nodeDragIdsWithChildren() {
2538
+ return this.renderState.config.nodeDragIdsWithChildren || [];
2539
+ }
2540
+ get dragging() {
2541
+ return !!this.renderState.dragging;
2542
+ }
2543
+ get labelSide() {
2544
+ return this.renderState.config.dragLabelSide;
2545
+ }
2546
+ /**
2547
+ * 放置到目标分支
2548
+ */
2549
+ dropBranch() {
2550
+ this.dropNode();
2551
+ }
2552
+ /**
2553
+ * 移动并且创建节点
2554
+ * Move and create node
2555
+ */
2556
+ async dropCreateNode(json, onCreateNode) {
2557
+ const dropEntity = this.document.getNode(this.dropNodeId);
2558
+ if (!dropEntity) {
2559
+ return;
2560
+ }
2561
+ if (json) {
2562
+ const dragNodes = await onCreateNode?.(json, dropEntity);
2563
+ this.onDropEmitter.fire({
2564
+ dropNode: dropEntity,
2565
+ dragNodes: dragNodes ? [dragNodes] : [],
2566
+ dragJSON: json
2567
+ });
2568
+ }
2569
+ }
2570
+ /**
2571
+ * 移动到目标节点
2572
+ */
2573
+ dropNode() {
2574
+ const dropEntity = this.document.getNode(this.dropNodeId);
2575
+ if (!dropEntity) {
2576
+ return;
2577
+ }
2578
+ const sortNodes = [];
2579
+ let curr = this.dragStartNode;
2580
+ while (curr && this.dragNodes.includes(curr)) {
2581
+ sortNodes.push(curr);
2582
+ curr = curr.next;
2583
+ }
2584
+ this.operationService.dragNodes({
2585
+ dropNode: dropEntity,
2586
+ nodes: sortNodes
2587
+ });
2588
+ if (sortNodes.length > 0) {
2589
+ this.onDropEmitter.fire({
2590
+ dropNode: dropEntity,
2591
+ dragNodes: sortNodes
2592
+ });
2593
+ }
2594
+ }
2595
+ /**
2596
+ * 拖拽是否可以释放在该节点后面
2597
+ */
2598
+ isDroppableNode(node) {
2599
+ if (!this.dragging || this.isDragBranch) {
2600
+ return false;
2601
+ }
2602
+ if (this.nodeDragIdsWithChildren.includes(node.id) || node.next && this.nodeDragIdsWithChildren.includes(node.next.id)) {
2603
+ return false;
2604
+ }
2605
+ if (node.isInlineBlocks || node.isInlineBlock) {
2606
+ return false;
2607
+ }
2608
+ const hasGroupNode = this.dragNodes.some(
2609
+ (node2) => node2.flowNodeType === "group" /* GROUP */
2610
+ );
2611
+ if (hasGroupNode) {
2612
+ const group = FlowGroupUtils.getNodeRecursionGroupController(node);
2613
+ if (group) {
2614
+ return false;
2615
+ }
2616
+ }
2617
+ return true;
2618
+ }
2619
+ /**
2620
+ * 拖拽分支是否可以释放在该分支
2621
+ * @param node 拖拽的分支节点
2622
+ * @param side 分支的前面还是后面
2623
+ */
2624
+ isDroppableBranch(node, side = "normal_branch" /* NORMAL_BRANCH */) {
2625
+ if (this.renderState.isBranch) {
2626
+ return true;
2627
+ }
2628
+ if (this.isDragBranch) {
2629
+ if (
2630
+ // 拖拽到分支
2631
+ !node.isInlineBlock || // 只能在同一分支条件下
2632
+ node.parent !== this.dragStartNode.parent || // 自己不能拖拽给自己
2633
+ node === this.dragStartNode
2634
+ ) {
2635
+ return false;
2636
+ }
2637
+ if (side === "normal_branch" /* NORMAL_BRANCH */ && node.next !== this.dragStartNode) {
2638
+ return true;
2639
+ }
2640
+ if (side === "pre_branch" /* PRE_BRANCH */ && node.pre !== this.dragStartNode) {
2641
+ return true;
2642
+ }
2643
+ }
2644
+ return false;
2645
+ }
2646
+ };
2647
+ __decorateClass([
2648
+ (0, import_inversify3.inject)(FlowDocument)
2649
+ ], FlowDragService.prototype, "document", 2);
2650
+ __decorateClass([
2651
+ (0, import_inversify3.inject)(FlowOperationBaseService)
2652
+ ], FlowDragService.prototype, "operationService", 2);
2653
+ __decorateClass([
2654
+ (0, import_inversify3.inject)(import_core8.EntityManager)
2655
+ ], FlowDragService.prototype, "entityManager", 2);
2656
+ FlowDragService = __decorateClass([
2657
+ (0, import_inversify3.injectable)()
2658
+ ], FlowDragService);
2659
+
2660
+ // src/services/flow-operation-base-service.ts
2661
+ var import_inversify4 = require("inversify");
2662
+ var import_utils9 = require("@flowgram.ai/utils");
2663
+ var import_core9 = require("@flowgram.ai/core");
2664
+ var FlowOperationBaseServiceImpl = class {
2665
+ constructor() {
2666
+ this.onNodeAddEmitter = new import_utils9.Emitter();
2667
+ this.onNodeAdd = this.onNodeAddEmitter.event;
2668
+ this.toDispose = new import_utils9.DisposableCollection();
2669
+ this.onNodeMoveEmitter = new import_utils9.Emitter();
2670
+ this.onNodeMove = this.onNodeMoveEmitter.event;
2671
+ }
2672
+ init() {
2673
+ this.toDispose.pushAll([this.onNodeAddEmitter, this.onNodeMoveEmitter]);
2674
+ }
2675
+ addNode(nodeJSON, config = {}) {
2676
+ const { parent, index, hidden } = config;
2677
+ let parentEntity;
2678
+ if (parent) {
2679
+ parentEntity = this.toNodeEntity(parent);
2680
+ }
2681
+ let register;
2682
+ if (parentEntity) {
2683
+ register = parentEntity.getNodeRegistry();
2684
+ }
2685
+ const addJSON = {
2686
+ ...nodeJSON,
2687
+ type: nodeJSON.type || "block" /* BLOCK */
2688
+ };
2689
+ const addNodeData = {
2690
+ ...addJSON,
2691
+ parent: parentEntity,
2692
+ index,
2693
+ hidden
2694
+ };
2695
+ let added;
2696
+ if (parentEntity && register?.addChild) {
2697
+ added = register.addChild(parentEntity, addJSON, {
2698
+ index,
2699
+ hidden
2700
+ });
2701
+ } else {
2702
+ added = this.document.addNode(addNodeData);
2703
+ }
2704
+ this.onNodeAddEmitter.fire({
2705
+ node: added,
2706
+ data: addNodeData
2707
+ });
2708
+ return added;
2709
+ }
2710
+ addFromNode(fromNode, nodeJSON) {
2711
+ return this.document.addFromNode(fromNode, nodeJSON);
2712
+ }
2713
+ deleteNode(node) {
2714
+ this.document.removeNode(node);
2715
+ }
2716
+ deleteNodes(nodes) {
2717
+ (nodes || []).forEach((node) => {
2718
+ this.deleteNode(node);
2719
+ });
2720
+ }
2721
+ addBlock(target, blockJSON, config = {}) {
2722
+ const { parent, index } = config;
2723
+ return this.document.addBlock(target, blockJSON, void 0, parent, index);
2724
+ }
2725
+ moveNode(node, config = {}) {
2726
+ const { parent: newParent, index } = config;
2727
+ const entity = this.toNodeEntity(node);
2728
+ const parent = entity?.parent;
2729
+ if (!parent) {
2730
+ return;
2731
+ }
2732
+ const newParentEntity = newParent ? this.toNodeEntity(newParent) : parent;
2733
+ if (!newParentEntity) {
2734
+ console.warn("no new parent found", newParent);
2735
+ return;
2736
+ }
2737
+ let toIndex = typeof index === "undefined" ? newParentEntity.collapsedChildren.length : index;
2738
+ return this.doMoveNode(entity, newParentEntity, toIndex);
2739
+ }
2740
+ /**
2741
+ * 拖拽节点
2742
+ * @param param0
2743
+ * @returns
2744
+ */
2745
+ dragNodes({ dropNode, nodes }) {
2746
+ if (nodes.length === 0) {
2747
+ return;
2748
+ }
2749
+ const startNode = nodes[0];
2750
+ const fromParent = startNode.parent;
2751
+ const toParent = dropNode.parent;
2752
+ if (!fromParent || !toParent) {
2753
+ return;
2754
+ }
2755
+ const fromIndex = fromParent.children.findIndex((child) => child === startNode);
2756
+ const dropIndex = toParent.children.findIndex((child) => child === dropNode);
2757
+ let toIndex = dropIndex + 1;
2758
+ if (fromParent === toParent && fromIndex < dropIndex) {
2759
+ toIndex = toIndex - nodes.length;
2760
+ }
2761
+ const value = {
2762
+ nodeIds: nodes.map((node) => node.id),
2763
+ fromParentId: fromParent.id,
2764
+ toParentId: toParent.id,
2315
2765
  fromIndex,
2316
2766
  toIndex
2317
2767
  };
@@ -2426,420 +2876,140 @@ var FlowOperationBaseServiceImpl = class {
2426
2876
  return typeof node === "string" ? node : node.id;
2427
2877
  }
2428
2878
  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;
2879
+ return typeof node === "string" ? this.document.getNode(node) : node;
2618
2880
  }
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;
2881
+ getNodeIndex(node) {
2882
+ const entity = this.toNodeEntity(node);
2883
+ const parent = entity?.parent;
2884
+ if (!parent) {
2885
+ return -1;
2628
2886
  }
2629
- groupRenderData.hovered = hovered;
2887
+ return parent.children.findIndex((child) => child === entity);
2630
2888
  }
2631
- get hovered() {
2632
- const groupRenderData = this.groupNode.getData(FlowNodeRenderData);
2633
- return groupRenderData.hovered;
2889
+ doMoveNode(node, newParent, index) {
2890
+ if (!node.parent) {
2891
+ throw new Error("root node cannot move");
2892
+ }
2893
+ const event = {
2894
+ node,
2895
+ fromParent: node.parent,
2896
+ toParent: newParent,
2897
+ fromIndex: this.getNodeIndex(node),
2898
+ toIndex: index
2899
+ };
2900
+ this.document.moveChildNodes({
2901
+ nodeIds: [this.toId(node)],
2902
+ toParentId: this.toId(newParent),
2903
+ toIndex: index
2904
+ });
2905
+ this.onNodeMoveEmitter.fire(event);
2634
2906
  }
2635
- static create(groupNode) {
2636
- if (!groupNode) {
2907
+ };
2908
+ __decorateClass([
2909
+ (0, import_inversify4.inject)(import_core9.EntityManager)
2910
+ ], FlowOperationBaseServiceImpl.prototype, "entityManager", 2);
2911
+ __decorateClass([
2912
+ (0, import_inversify4.inject)(FlowDocument)
2913
+ ], FlowOperationBaseServiceImpl.prototype, "document", 2);
2914
+ __decorateClass([
2915
+ (0, import_inversify4.postConstruct)()
2916
+ ], FlowOperationBaseServiceImpl.prototype, "init", 1);
2917
+ FlowOperationBaseServiceImpl = __decorateClass([
2918
+ (0, import_inversify4.injectable)()
2919
+ ], FlowOperationBaseServiceImpl);
2920
+
2921
+ // src/services/flow-group-service/flow-group-service.ts
2922
+ var import_nanoid = require("nanoid");
2923
+ var import_inversify5 = require("inversify");
2924
+ var import_core10 = require("@flowgram.ai/core");
2925
+ var FlowGroupService = class {
2926
+ /** 创建分组节点 */
2927
+ createGroup(nodes) {
2928
+ if (!nodes || !Array.isArray(nodes) || nodes.length === 0) {
2637
2929
  return;
2638
2930
  }
2639
- if (!_FlowGroupController.isGroupNode(groupNode)) {
2931
+ if (!FlowGroupUtils.validate(nodes)) {
2640
2932
  return;
2641
2933
  }
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;
2934
+ const sortedNodes = nodes.sort((a, b) => a.index - b.index);
2935
+ const fromNode = sortedNodes[0];
2936
+ const groupId = `group_${(0, import_nanoid.nanoid)(5)}`;
2937
+ this.operationService.apply({
2938
+ type: "createGroup" /* createGroup */,
2939
+ value: {
2940
+ targetId: fromNode.id,
2941
+ groupId,
2942
+ nodeIds: nodes.map((node) => node.id)
2660
2943
  }
2661
- return index === arr[i - 1] + 1;
2662
2944
  });
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) {
2945
+ const groupNode = this.entityManager.getEntityById(groupId);
2946
+ if (!groupNode) {
2672
2947
  return;
2673
2948
  }
2674
- if (!this.isNodeInGroup(node)) {
2949
+ const group = this.groupController(groupNode);
2950
+ if (!group) {
2675
2951
  return;
2676
2952
  }
2677
- const groupNode = node?.parent;
2678
- return _FlowGroupController.create(groupNode);
2953
+ group.expand();
2954
+ return groupNode;
2679
2955
  }
2680
- /** 向上递归查找分组递归控制 */
2681
- static getNodeRecursionGroupController(node) {
2682
- if (!node) {
2956
+ /** 删除分组 */
2957
+ deleteGroup(groupNode) {
2958
+ const json = groupNode.toJSON();
2959
+ if (!groupNode.pre || !json) {
2683
2960
  return;
2684
2961
  }
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();
2962
+ this.operationService.apply({
2963
+ type: "deleteNodes" /* deleteNodes */,
2964
+ value: {
2965
+ fromId: groupNode.pre.id,
2966
+ nodes: [json]
2967
+ }
2968
+ });
2758
2969
  }
2759
- /**
2760
- * 移动到目标节点
2761
- */
2762
- dropNode() {
2763
- const dropEntity = this.document.getNode(this.dropNodeId);
2764
- if (!dropEntity) {
2970
+ /** 取消分组 */
2971
+ ungroup(groupNode) {
2972
+ const group = this.groupController(groupNode);
2973
+ if (!group) {
2765
2974
  return;
2766
2975
  }
2767
- const sortNodes = [];
2768
- let curr = this.dragStartNode;
2769
- while (curr && this.dragNodes.includes(curr)) {
2770
- sortNodes.push(curr);
2771
- curr = curr.next;
2976
+ const nodes = group.nodes;
2977
+ if (!groupNode.pre) {
2978
+ return;
2772
2979
  }
2773
- this.operationService.dragNodes({
2774
- dropNode: dropEntity,
2775
- nodes: sortNodes
2980
+ group.collapse();
2981
+ this.operationService.apply({
2982
+ type: "ungroup" /* ungroup */,
2983
+ value: {
2984
+ groupId: groupNode.id,
2985
+ targetId: groupNode.pre.id,
2986
+ nodeIds: nodes.map((node) => node.id)
2987
+ }
2776
2988
  });
2777
- if (sortNodes.length > 0) {
2778
- this.onDropEmitter.fire({
2779
- dropNode: dropEntity,
2780
- dragNodes: sortNodes
2781
- });
2782
- }
2783
2989
  }
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;
2990
+ /** 返回所有分组节点 */
2991
+ getAllGroups() {
2992
+ const allNodes = this.entityManager.getEntities(FlowNodeEntity);
2993
+ const groupNodes = allNodes.filter((node) => node.flowNodeType === "group" /* GROUP */);
2994
+ return groupNodes.map((node) => this.groupController(node)).filter(Boolean);
2805
2995
  }
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;
2996
+ /** 获取分组控制器*/
2997
+ groupController(group) {
2998
+ return FlowGroupController.create(group);
2999
+ }
3000
+ static validate(nodes) {
3001
+ return FlowGroupUtils.validate(nodes);
2829
3002
  }
2830
3003
  };
2831
3004
  __decorateClass([
2832
- (0, import_inversify5.inject)(FlowDocument)
2833
- ], FlowDragService.prototype, "document", 2);
3005
+ (0, import_inversify5.inject)(import_core10.EntityManager)
3006
+ ], FlowGroupService.prototype, "entityManager", 2);
2834
3007
  __decorateClass([
2835
3008
  (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([
3009
+ ], FlowGroupService.prototype, "operationService", 2);
3010
+ FlowGroupService = __decorateClass([
2841
3011
  (0, import_inversify5.injectable)()
2842
- ], FlowDragService);
3012
+ ], FlowGroupService);
2843
3013
 
2844
3014
  // src/layout/vertical-fixed-layout.ts
2845
3015
  var import_inversify6 = require("inversify");