@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/esm/index.js CHANGED
@@ -22,11 +22,19 @@ var FlowNodeBaseType = /* @__PURE__ */ ((FlowNodeBaseType2) => {
22
22
  FlowNodeBaseType2["BLOCK_ORDER_ICON"] = "blockOrderIcon";
23
23
  FlowNodeBaseType2["GROUP"] = "group";
24
24
  FlowNodeBaseType2["END"] = "end";
25
+ FlowNodeBaseType2["BREAK"] = "break";
25
26
  FlowNodeBaseType2["CONDITION"] = "condition";
26
27
  FlowNodeBaseType2["SUB_CANVAS"] = "subCanvas";
28
+ FlowNodeBaseType2["MULTI_INPUTS"] = "multiInputs";
29
+ FlowNodeBaseType2["MULTI_OUTPUTS"] = "multiOutputs";
30
+ FlowNodeBaseType2["INPUT"] = "input";
31
+ FlowNodeBaseType2["OUTPUT"] = "output";
32
+ FlowNodeBaseType2["SLOT"] = "slot";
33
+ FlowNodeBaseType2["SLOT_BLOCK"] = "slotBlock";
27
34
  return FlowNodeBaseType2;
28
35
  })(FlowNodeBaseType || {});
29
36
  var FlowNodeSplitType = /* @__PURE__ */ ((FlowNodeSplitType2) => {
37
+ FlowNodeSplitType2["SIMPLE_SPLIT"] = "simpleSplit";
30
38
  FlowNodeSplitType2["DYNAMIC_SPLIT"] = "dynamicSplit";
31
39
  FlowNodeSplitType2["STATIC_SPLIT"] = "staticSplit";
32
40
  return FlowNodeSplitType2;
@@ -82,6 +90,14 @@ var DefaultSpacingKey = {
82
90
  * 普通节点间距。垂直 / 水平
83
91
  */
84
92
  NODE_SPACING: "SPACING",
93
+ /**
94
+ * 分支节点间距
95
+ */
96
+ BRANCH_SPACING: "BRANCH_SPACING",
97
+ /**
98
+ * 圆弧线条拐角 radius
99
+ */
100
+ ROUNDED_LINE_RADIUS: "ROUNDED_LINE_RADIUS",
85
101
  /**
86
102
  * 圆弧线条 x radius
87
103
  */
@@ -108,13 +124,19 @@ var DEFAULT_SPACING = {
108
124
  NULL: 0,
109
125
  [DefaultSpacingKey.NODE_SPACING]: 32,
110
126
  // 普通节点间距。垂直 / 水平
127
+ [DefaultSpacingKey.BRANCH_SPACING]: 20,
128
+ // 分支节点间距
129
+ /**
130
+ * @deprecated use 'BRANCH_SPACING' instead
131
+ */
111
132
  MARGIN_RIGHT: 20,
112
- // 普通节点右边间距
133
+ // 分支节点右边间距
113
134
  INLINE_BLOCK_PADDING_BOTTOM: 16,
114
135
  // block 底部留白
115
136
  INLINE_BLOCKS_PADDING_TOP: 30,
116
137
  // block list 上部留白间距
117
- [DefaultSpacingKey.INLINE_BLOCKS_PADDING_BOTTOM]: 40,
138
+ // JS 浮点数有误差,1046.6 -1006.6 = 39.9999999,会导致 间距/20 < 2 导致布局计算问题,因此需要额外增加 0.1 像素
139
+ [DefaultSpacingKey.INLINE_BLOCKS_PADDING_BOTTOM]: 40.1,
118
140
  // block lit 下部留白间距,因为有两个拐弯,所以翻一倍
119
141
  MIN_INLINE_BLOCK_SPACING: 200,
120
142
  // 分支间最小边距 (垂直布局)
@@ -122,6 +144,8 @@ var DEFAULT_SPACING = {
122
144
  // 分支间最小边距 (水平布局)
123
145
  [DefaultSpacingKey.COLLAPSED_SPACING]: 12,
124
146
  // 复合节点距离上个节点的距离
147
+ [DefaultSpacingKey.ROUNDED_LINE_RADIUS]: 16,
148
+ // 圆弧线条拐角 radius
125
149
  [DefaultSpacingKey.ROUNDED_LINE_X_RADIUS]: 16,
126
150
  // 圆弧线条 x radius
127
151
  [DefaultSpacingKey.ROUNDED_LINE_Y_RADIUS]: 20,
@@ -149,8 +173,6 @@ var DEFAULT_FLOW_NODE_META = (nodeType, document) => {
149
173
  isStart: nodeType === "start",
150
174
  hidden,
151
175
  defaultExpanded: document.options.allNodesDefaultExpanded,
152
- expandedSize: { width: 520, height: 300 },
153
- // 展开后的大小
154
176
  size: DEFAULT_SIZE,
155
177
  origin: document.layout.getDefaultNodeOrigin(),
156
178
  isInlineBlocks: nodeType === "inlineBlocks" /* INLINE_BLOCKS */,
@@ -170,13 +192,37 @@ var DEFAULT_FLOW_NODE_META = (nodeType, document) => {
170
192
  };
171
193
  var FlowNodeRegistry;
172
194
  ((FlowNodeRegistry4) => {
195
+ function mergeChildRegistries(r1 = [], r2 = []) {
196
+ if (r1.length === 0 || r2.length === 0) {
197
+ return [...r1, ...r2];
198
+ }
199
+ const r1Filter = r1.map((r1Current) => {
200
+ const r2Current = r2.find((n) => n.type === r1Current.type);
201
+ if (r2Current) {
202
+ return merge(r1Current, r2Current, r1Current.type);
203
+ }
204
+ return r1Current;
205
+ });
206
+ const r2Filter = r2.filter((n) => !r1.some((r) => r.type === n.type));
207
+ return [...r1Filter, ...r2Filter];
208
+ }
209
+ FlowNodeRegistry4.mergeChildRegistries = mergeChildRegistries;
173
210
  function merge(registry1, registry2, finalType) {
211
+ const extendKeys = registry1.__extends__ ? registry1.__extends__.slice() : [];
212
+ if (registry1.type !== registry2.type) {
213
+ extendKeys.unshift(registry1.type);
214
+ }
174
215
  return {
175
216
  ...registry1,
176
217
  ...registry2,
218
+ extendChildRegistries: mergeChildRegistries(
219
+ registry1.extendChildRegistries,
220
+ registry2.extendChildRegistries
221
+ ),
177
222
  meta: { ...registry1.meta, ...registry2.meta },
178
223
  extend: void 0,
179
- type: finalType
224
+ type: finalType,
225
+ __extends__: extendKeys
180
226
  };
181
227
  }
182
228
  FlowNodeRegistry4.merge = merge;
@@ -200,7 +246,6 @@ var OperationType = /* @__PURE__ */ ((OperationType2) => {
200
246
  OperationType2["moveChildNodes"] = "moveChildNodes";
201
247
  OperationType2["addNodes"] = "addNodes";
202
248
  OperationType2["deleteNodes"] = "deleteNodes";
203
- OperationType2["changeNode"] = "changeNode";
204
249
  OperationType2["addChildNode"] = "addChildNode";
205
250
  OperationType2["deleteChildNode"] = "deleteChildNode";
206
251
  OperationType2["addNode"] = "addNode";
@@ -245,16 +290,18 @@ var _FlowNodeRenderData = class _FlowNodeRenderData extends EntityData {
245
290
  expanded: defaultExpanded || false,
246
291
  activated: false,
247
292
  hovered: false,
248
- dragging: false
293
+ dragging: false,
294
+ stackIndex: 0
249
295
  };
250
296
  }
251
- updateExtInfo(info) {
252
- if (Compare.isChanged(this.data.extInfo, info)) {
253
- const oldInfo = this.data.extInfo;
297
+ updateExtInfo(info, fullUpdate) {
298
+ const oldInfo = this.data.extInfo;
299
+ const newInfo = fullUpdate ? info : { ...oldInfo, ...info };
300
+ if (Compare.isChanged(oldInfo, newInfo)) {
254
301
  this.update({
255
- extInfo: info
302
+ extInfo: newInfo
256
303
  });
257
- this.onExtInfoChangeEmitter.fire({ oldInfo, newInfo: info });
304
+ this.onExtInfoChangeEmitter.fire({ oldInfo, newInfo });
258
305
  }
259
306
  }
260
307
  getExtInfo() {
@@ -351,6 +398,12 @@ var _FlowNodeRenderData = class _FlowNodeRenderData extends EntityData {
351
398
  }
352
399
  return this.data.activated;
353
400
  }
401
+ get stackIndex() {
402
+ return this.data.stackIndex;
403
+ }
404
+ set stackIndex(index) {
405
+ this.data.stackIndex = index;
406
+ }
354
407
  get lineActivated() {
355
408
  const { activated } = this;
356
409
  if (!activated) return false;
@@ -400,10 +453,9 @@ var _FlowNodeTransformData = class _FlowNodeTransformData extends EntityData2 {
400
453
  return this.entity.id;
401
454
  }
402
455
  getDefaultData() {
403
- const { size, defaultExpanded, expandedSize, hidden } = this.entity.getNodeMeta();
404
- const defaultSize = defaultExpanded ? expandedSize : size;
456
+ const { size, hidden } = this.entity.getNodeMeta();
405
457
  return {
406
- size: !hidden ? { ...defaultSize } : { width: 0, height: 0 }
458
+ size: !hidden ? { ...size } : { width: 0, height: 0 }
407
459
  };
408
460
  }
409
461
  /**
@@ -434,6 +486,11 @@ var _FlowNodeTransformData = class _FlowNodeTransformData extends EntityData2 {
434
486
  y: position.y
435
487
  };
436
488
  }
489
+ set position(position) {
490
+ this.transform.update({
491
+ position
492
+ });
493
+ }
437
494
  set size(size) {
438
495
  const { width, height } = this.data.size;
439
496
  if (this.isContainer) return;
@@ -981,37 +1038,7 @@ var FlowNodeEntity = class extends Entity {
981
1038
  * @param newId
982
1039
  */
983
1040
  toJSON() {
984
- if (this.document.options.toNodeJSON) {
985
- return this.document.options.toNodeJSON(this);
986
- }
987
- const nodesMap = {};
988
- let startNodeJSON;
989
- this.document.traverse((node) => {
990
- const isSystemNode = node.id.startsWith("$");
991
- if (isSystemNode) return;
992
- const nodeJSONData = this.getJSONData();
993
- const nodeJSON = {
994
- id: node.id,
995
- type: node.flowNodeType
996
- };
997
- if (nodeJSONData !== void 0) {
998
- nodeJSON.data = nodeJSONData;
999
- }
1000
- if (!startNodeJSON) startNodeJSON = nodeJSON;
1001
- let { parent } = node;
1002
- if (parent && parent.id.startsWith("$")) {
1003
- parent = parent.originParent;
1004
- }
1005
- const parentJSON = parent ? nodesMap[parent.id] : void 0;
1006
- if (parentJSON) {
1007
- if (!parentJSON.blocks) {
1008
- parentJSON.blocks = [];
1009
- }
1010
- parentJSON.blocks.push(nodeJSON);
1011
- }
1012
- nodesMap[node.id] = nodeJSON;
1013
- }, this);
1014
- return startNodeJSON;
1041
+ return this.document.toNodeJSON(this);
1015
1042
  }
1016
1043
  get isVertical() {
1017
1044
  return this.document.layout.name === "vertical-fixed-layout" /* VERTICAL_FIXED_LAYOUT */;
@@ -1020,8 +1047,8 @@ var FlowNodeEntity = class extends Entity {
1020
1047
  * 修改节点扩展信息
1021
1048
  * @param info
1022
1049
  */
1023
- updateExtInfo(extInfo) {
1024
- this.getData(FlowNodeRenderData).updateExtInfo(extInfo);
1050
+ updateExtInfo(extInfo, fullUpdate) {
1051
+ this.getData(FlowNodeRenderData).updateExtInfo(extInfo, fullUpdate);
1025
1052
  }
1026
1053
  /**
1027
1054
  * 获取节点扩展信息
@@ -1050,6 +1077,19 @@ var FlowNodeEntity = class extends Entity {
1050
1077
  get bounds() {
1051
1078
  return this.transform.bounds;
1052
1079
  }
1080
+ /**
1081
+ * Check node extend type
1082
+ */
1083
+ isExtend(parentType) {
1084
+ return this.document.isExtend(this.flowNodeType, parentType);
1085
+ }
1086
+ /**
1087
+ * Check node type
1088
+ * @param parentType
1089
+ */
1090
+ isTypeOrExtendType(parentType) {
1091
+ return this.document.isTypeOrExtendType(this.flowNodeType, parentType);
1092
+ }
1053
1093
  };
1054
1094
  FlowNodeEntity.type = "FlowNodeEntity";
1055
1095
  ((FlowNodeEntity2) => {
@@ -1143,7 +1183,7 @@ var FlowDocumentTransformerEntity = class extends ConfigEntity {
1143
1183
  FlowDocumentTransformerEntity.type = "FlowDocumentTransformerEntity";
1144
1184
 
1145
1185
  // src/entities/flow-renderer-state-entity.ts
1146
- import { debounce } from "lodash";
1186
+ import { debounce } from "lodash-es";
1147
1187
  import { ConfigEntity as ConfigEntity2 } from "@flowgram.ai/core";
1148
1188
  var FlowRendererStateEntity = class extends ConfigEntity2 {
1149
1189
  getDefaultConfig() {
@@ -1160,6 +1200,22 @@ var FlowRendererStateEntity = class extends ConfigEntity2 {
1160
1200
  nodeHoveredId: node?.id
1161
1201
  });
1162
1202
  }
1203
+ get dragging() {
1204
+ return this.config.dragging;
1205
+ }
1206
+ setDragging(dragging) {
1207
+ this.updateConfig({
1208
+ dragging
1209
+ });
1210
+ }
1211
+ get isBranch() {
1212
+ return this.config.isBranch;
1213
+ }
1214
+ setIsBranch(isBranch) {
1215
+ this.updateConfig({
1216
+ isBranch
1217
+ });
1218
+ }
1163
1219
  getDragLabelSide() {
1164
1220
  return this.config.dragLabelSide;
1165
1221
  }
@@ -1204,7 +1260,7 @@ var FlowRendererStateEntity = class extends ConfigEntity2 {
1204
1260
  FlowRendererStateEntity.type = "FlowRendererStateEntity";
1205
1261
 
1206
1262
  // src/flow-document.ts
1207
- import { omit } from "lodash";
1263
+ import { omit } from "lodash-es";
1208
1264
  import { inject as inject2, injectable as injectable2, multiInject, optional as optional2, postConstruct } from "inversify";
1209
1265
  import { Emitter as Emitter5 } from "@flowgram.ai/utils";
1210
1266
  import { EntityManager } from "@flowgram.ai/core";
@@ -1382,13 +1438,15 @@ var FlowVirtualTree = class _FlowVirtualTree {
1382
1438
  get size() {
1383
1439
  return this.map.size;
1384
1440
  }
1385
- toString() {
1441
+ toString(showType) {
1386
1442
  const ret = [];
1387
1443
  this.traverse((node, depth) => {
1388
1444
  if (depth === 0) {
1389
1445
  ret.push(node.id);
1390
1446
  } else {
1391
- ret.push(`|${new Array(depth).fill("--").join("")} ${node.id}`);
1447
+ ret.push(
1448
+ `|${new Array(depth).fill("--").join("")} ${showType ? `${node.flowNodeType}(${node.id})` : node.id}`
1449
+ );
1392
1450
  }
1393
1451
  });
1394
1452
  return `${ret.join("\n")}`;
@@ -1594,7 +1652,12 @@ var ConstantKeys = {
1594
1652
  /***
1595
1653
  * 线条、label 激活后的颜色
1596
1654
  */
1597
- BASE_ACTIVATED_COLOR: "BASE_ACTIVATED_COLOR"
1655
+ BASE_ACTIVATED_COLOR: "BASE_ACTIVATED_COLOR",
1656
+ /**
1657
+ * Branch bottom margin
1658
+ * 分支下边距
1659
+ */
1660
+ INLINE_BLOCKS_PADDING_TOP: "INLINE_BLOCKS_PADDING_TOP"
1598
1661
  };
1599
1662
 
1600
1663
  // src/flow-document-contribution.ts
@@ -1649,6 +1712,13 @@ var FlowDocument = class {
1649
1712
  this.onNodeCreate = this.onNodeCreateEmitter.event;
1650
1713
  this.onNodeDispose = this.onNodeDisposeEmitter.event;
1651
1714
  this.onLayoutChange = this.onLayoutChangeEmitter.event;
1715
+ this._disposed = false;
1716
+ }
1717
+ /**
1718
+ *
1719
+ */
1720
+ get disposed() {
1721
+ return this._disposed;
1652
1722
  }
1653
1723
  init() {
1654
1724
  if (!this.options) this.options = FlowDocumentOptionsDefault;
@@ -1674,6 +1744,7 @@ var FlowDocument = class {
1674
1744
  * @param fireRender 是否要触发渲染,默认 true
1675
1745
  */
1676
1746
  fromJSON(json, fireRender = true) {
1747
+ if (this._disposed) return;
1677
1748
  this.originTree.clear();
1678
1749
  this.renderTree.clear();
1679
1750
  this.entityManager.changeEntityLocked = true;
@@ -1742,7 +1813,7 @@ var FlowDocument = class {
1742
1813
  * @param data
1743
1814
  * @param addedNodes
1744
1815
  */
1745
- addNode(data, addedNodes, ignoreCreateEvent) {
1816
+ addNode(data, addedNodes) {
1746
1817
  const { id, type = "block", originParent, parent, meta, hidden, index } = data;
1747
1818
  let node = this.getNode(id);
1748
1819
  let isNew = false;
@@ -1760,13 +1831,14 @@ var FlowDocument = class {
1760
1831
  originParent,
1761
1832
  meta
1762
1833
  });
1834
+ this.options.preNodeCreate?.(node);
1763
1835
  const datas = dataRegistries ? this.nodeDataRegistries.concat(...dataRegistries) : this.nodeDataRegistries;
1764
1836
  node.addInitializeData(datas);
1765
1837
  node.onDispose(() => this.onNodeDisposeEmitter.fire({ node }));
1766
- if (this.options.fromNodeJSON) {
1767
- this.options.fromNodeJSON(node, data);
1768
- }
1838
+ this.options.fromNodeJSON?.(node, data, true);
1769
1839
  isNew = true;
1840
+ } else {
1841
+ this.options.fromNodeJSON?.(node, data, false);
1770
1842
  }
1771
1843
  node.initData({
1772
1844
  originParent,
@@ -1778,7 +1850,6 @@ var FlowDocument = class {
1778
1850
  if (node.isStart) {
1779
1851
  this.root.addChild(node);
1780
1852
  }
1781
- this.onNodeUpdateEmitter.fire({ node, data });
1782
1853
  addedNodes?.push(node);
1783
1854
  if (register.onCreate) {
1784
1855
  const extendNodes = register.onCreate(node, data);
@@ -1792,11 +1863,14 @@ var FlowDocument = class {
1792
1863
  this.addBlocksAsChildren(node, data.blocks, addedNodes);
1793
1864
  }
1794
1865
  }
1795
- if (isNew && !ignoreCreateEvent) {
1866
+ if (isNew) {
1796
1867
  this.onNodeCreateEmitter.fire({
1797
1868
  node,
1798
- data
1869
+ data,
1870
+ json: data
1799
1871
  });
1872
+ } else {
1873
+ this.onNodeUpdateEmitter.fire({ node, data, json: data });
1800
1874
  }
1801
1875
  return node;
1802
1876
  }
@@ -1832,18 +1906,16 @@ var FlowDocument = class {
1832
1906
  parent: node
1833
1907
  });
1834
1908
  addedNodes.push(blockIconNode);
1835
- if (blocks.length > 0) {
1836
- const inlineBlocksNode = this.addNode({
1837
- id: `$inlineBlocks$${node.id}`,
1838
- type: "inlineBlocks" /* INLINE_BLOCKS */,
1839
- originParent: node,
1840
- parent: node
1841
- });
1842
- addedNodes.push(inlineBlocksNode);
1843
- blocks.forEach((blockData) => {
1844
- this.addBlock(node, blockData, addedNodes);
1845
- });
1846
- }
1909
+ const inlineBlocksNode = this.addNode({
1910
+ id: `$inlineBlocks$${node.id}`,
1911
+ type: "inlineBlocks" /* INLINE_BLOCKS */,
1912
+ originParent: node,
1913
+ parent: node
1914
+ });
1915
+ addedNodes.push(inlineBlocksNode);
1916
+ blocks.forEach((blockData) => {
1917
+ this.addBlock(node, blockData, addedNodes);
1918
+ });
1847
1919
  return addedNodes;
1848
1920
  }
1849
1921
  /**
@@ -1908,14 +1980,39 @@ var FlowDocument = class {
1908
1980
  meta: {
1909
1981
  ...preRegistry?.meta,
1910
1982
  ...newRegistry?.meta
1911
- }
1983
+ },
1984
+ extendChildRegistries: FlowNodeRegistry.mergeChildRegistries(
1985
+ preRegistry?.extendChildRegistries,
1986
+ newRegistry?.extendChildRegistries
1987
+ )
1912
1988
  });
1913
1989
  });
1914
1990
  }
1991
+ /**
1992
+ * Check node extend
1993
+ * @param currentType
1994
+ * @param extendType
1995
+ */
1996
+ isExtend(currentType, extendType) {
1997
+ return (this.getNodeRegistry(currentType).__extends__ || []).includes(extendType);
1998
+ }
1999
+ /**
2000
+ * Check node type
2001
+ * @param currentType
2002
+ * @param extendType
2003
+ */
2004
+ isTypeOrExtendType(currentType, extendType) {
2005
+ return currentType === extendType || this.isExtend(currentType, extendType);
2006
+ }
1915
2007
  /**
1916
2008
  * 导出数据,可以重载
1917
2009
  */
1918
2010
  toJSON() {
2011
+ if (this.disposed) {
2012
+ throw new Error(
2013
+ "The FlowDocument has been disposed and it is no longer possible to call toJSON."
2014
+ );
2015
+ }
1919
2016
  return {
1920
2017
  nodes: this.root.toJSON().blocks
1921
2018
  };
@@ -1935,6 +2032,7 @@ var FlowDocument = class {
1935
2032
  const customDefaultRegistry = this.options.getNodeDefaultRegistry?.(type);
1936
2033
  let register = this.registers.get(type) || { type };
1937
2034
  const extendRegisters = [];
2035
+ const extendKey = register.extend;
1938
2036
  if (register.extend && this.registers.has(register.extend)) {
1939
2037
  register = FlowNodeRegistry.merge(
1940
2038
  this.getNodeRegistry(register.extend),
@@ -1965,6 +2063,9 @@ var FlowDocument = class {
1965
2063
  ...register.meta
1966
2064
  }
1967
2065
  };
2066
+ if (extendKey) {
2067
+ res.extend = extendKey;
2068
+ }
1968
2069
  this.nodeRegistryCache.set(typeKey, res);
1969
2070
  return res;
1970
2071
  }
@@ -2015,8 +2116,8 @@ var FlowDocument = class {
2015
2116
  getAllNodes() {
2016
2117
  return this.entityManager.getEntities(FlowNodeEntity);
2017
2118
  }
2018
- toString() {
2019
- return this.originTree.toString();
2119
+ toString(showType) {
2120
+ return this.originTree.toString(showType);
2020
2121
  }
2021
2122
  /**
2022
2123
  * 返回需要渲染的数据
@@ -2029,6 +2130,39 @@ var FlowDocument = class {
2029
2130
  });
2030
2131
  return result;
2031
2132
  }
2133
+ toNodeJSON(node) {
2134
+ if (this.options.toNodeJSON) {
2135
+ return this.options.toNodeJSON(node);
2136
+ }
2137
+ const nodesMap = {};
2138
+ let startNodeJSON;
2139
+ this.traverse((node2) => {
2140
+ const isSystemNode = node2.id.startsWith("$");
2141
+ if (isSystemNode) return;
2142
+ const nodeJSONData = node2.getJSONData();
2143
+ const nodeJSON = {
2144
+ id: node2.id,
2145
+ type: node2.flowNodeType
2146
+ };
2147
+ if (nodeJSONData !== void 0) {
2148
+ nodeJSON.data = nodeJSONData;
2149
+ }
2150
+ if (!startNodeJSON) startNodeJSON = nodeJSON;
2151
+ let { parent } = node2;
2152
+ if (parent && parent.id.startsWith("$")) {
2153
+ parent = parent.originParent;
2154
+ }
2155
+ const parentJSON = parent ? nodesMap[parent.id] : void 0;
2156
+ if (parentJSON) {
2157
+ if (!parentJSON.blocks) {
2158
+ parentJSON.blocks = [];
2159
+ }
2160
+ parentJSON.blocks.push(nodeJSON);
2161
+ }
2162
+ nodesMap[node2.id] = nodeJSON;
2163
+ }, node);
2164
+ return startNodeJSON;
2165
+ }
2032
2166
  /**
2033
2167
  * 移动节点
2034
2168
  * @param param0
@@ -2111,6 +2245,7 @@ var FlowDocument = class {
2111
2245
  );
2112
2246
  }
2113
2247
  dispose() {
2248
+ if (this._disposed) return;
2114
2249
  this.registers.clear();
2115
2250
  this.nodeRegistryCache.clear();
2116
2251
  this.originTree.dispose();
@@ -2119,6 +2254,7 @@ var FlowDocument = class {
2119
2254
  this.onNodeCreateEmitter.dispose();
2120
2255
  this.onNodeDisposeEmitter.dispose();
2121
2256
  this.onLayoutChangeEmitter.dispose();
2257
+ this._disposed = true;
2122
2258
  }
2123
2259
  };
2124
2260
  __decorateClass([
@@ -2146,113 +2282,427 @@ FlowDocument = __decorateClass([
2146
2282
  import { ContainerModule } from "inversify";
2147
2283
 
2148
2284
  // src/services/flow-drag-service.ts
2149
- import { inject as inject5, injectable as injectable5 } from "inversify";
2150
- import { EntityManager as EntityManager4 } from "@flowgram.ai/core";
2151
- import { Emitter as Emitter7 } from "@flowgram.ai/utils";
2152
-
2153
- // src/services/flow-operation-base-service.ts
2154
- import { inject as inject3, injectable as injectable3, postConstruct as postConstruct2 } from "inversify";
2155
- import { DisposableCollection, Emitter as Emitter6 } from "@flowgram.ai/utils";
2285
+ import { inject as inject3, injectable as injectable3 } from "inversify";
2286
+ import { Emitter as Emitter6 } from "@flowgram.ai/utils";
2156
2287
  import { EntityManager as EntityManager2 } from "@flowgram.ai/core";
2157
- var FlowOperationBaseServiceImpl = class {
2158
- constructor() {
2159
- this.onNodeAddEmitter = new Emitter6();
2160
- this.onNodeAdd = this.onNodeAddEmitter.event;
2161
- this.toDispose = new DisposableCollection();
2288
+
2289
+ // src/services/flow-group-service/flow-group-controller.ts
2290
+ var FlowGroupController = class _FlowGroupController {
2291
+ constructor(groupNode) {
2292
+ this.groupNode = groupNode;
2162
2293
  }
2163
- init() {
2164
- this.toDispose.push(this.onNodeAddEmitter);
2294
+ get nodes() {
2295
+ return this.groupNode.collapsedChildren || [];
2165
2296
  }
2166
- addNode(nodeJSON, config = {}) {
2167
- const { parent, index, hidden } = config;
2168
- let parentEntity;
2169
- if (parent) {
2170
- parentEntity = this.toNodeEntity(parent);
2297
+ get collapsed() {
2298
+ const groupTransformData = this.groupNode.getData(FlowNodeTransformData);
2299
+ return groupTransformData.collapsed;
2300
+ }
2301
+ collapse() {
2302
+ this.collapsed = true;
2303
+ }
2304
+ expand() {
2305
+ this.collapsed = false;
2306
+ }
2307
+ /** 获取分组外围的最大边框 */
2308
+ get bounds() {
2309
+ const groupNodeBounds = this.groupNode.getData(FlowNodeTransformData).bounds;
2310
+ return groupNodeBounds;
2311
+ }
2312
+ /** 是否是开始节点 */
2313
+ isStartNode(node) {
2314
+ if (!node) {
2315
+ return false;
2171
2316
  }
2172
- let register;
2173
- if (parentEntity) {
2174
- register = parentEntity.getNodeRegistry();
2317
+ const nodes = this.nodes;
2318
+ if (!nodes[0]) {
2319
+ return false;
2175
2320
  }
2176
- const addJSON = {
2177
- ...nodeJSON,
2178
- type: nodeJSON.type || "block" /* BLOCK */
2179
- };
2180
- const addNodeData = {
2181
- ...addJSON,
2182
- parent: parentEntity,
2183
- index,
2184
- hidden
2185
- };
2186
- let added;
2187
- if (parentEntity && register?.addChild) {
2188
- added = register.addChild(parentEntity, addJSON, {
2189
- index,
2190
- hidden
2191
- });
2192
- } else {
2193
- added = this.document.addNode(addNodeData);
2321
+ return node.id === nodes[0].id;
2322
+ }
2323
+ /** 是否是结束节点 */
2324
+ isEndNode(node) {
2325
+ if (!node) {
2326
+ return false;
2194
2327
  }
2195
- this.onNodeAddEmitter.fire({
2196
- node: added,
2197
- data: addNodeData
2198
- });
2199
- return added;
2328
+ const nodes = this.nodes;
2329
+ if (!nodes[nodes.length - 1]) {
2330
+ return false;
2331
+ }
2332
+ return node.id === nodes[nodes.length - 1].id;
2200
2333
  }
2201
- addFromNode(fromNode, nodeJSON) {
2202
- return this.document.addFromNode(fromNode, nodeJSON);
2334
+ set note(note) {
2335
+ this.groupNode.getNodeMeta().note = note;
2203
2336
  }
2204
- deleteNode(node) {
2205
- this.document.removeNode(node);
2337
+ get note() {
2338
+ return this.groupNode.getNodeMeta().note || "";
2206
2339
  }
2207
- deleteNodes(nodes) {
2208
- (nodes || []).forEach((node) => {
2209
- this.deleteNode(node);
2210
- });
2340
+ set noteHeight(height) {
2341
+ this.groupNode.getNodeMeta().noteHeight = height;
2211
2342
  }
2212
- addBlock(target, blockJSON, config = {}) {
2213
- const { parent, index } = config;
2214
- return this.document.addBlock(target, blockJSON, void 0, parent, index);
2343
+ get noteHeight() {
2344
+ return this.groupNode.getNodeMeta().noteHeight || 0;
2215
2345
  }
2216
- moveNode(node, config = {}) {
2217
- const { parent: newParent, index } = config;
2218
- const entity = this.toNodeEntity(node);
2219
- const parent = entity?.parent;
2220
- if (!parent) {
2221
- return;
2346
+ get positionConfig() {
2347
+ return this.groupNode.getNodeMeta().positionConfig;
2348
+ }
2349
+ set collapsed(collapsed) {
2350
+ const groupTransformData = this.groupNode.getData(FlowNodeTransformData);
2351
+ groupTransformData.collapsed = collapsed;
2352
+ groupTransformData.localDirty = true;
2353
+ if (groupTransformData.parent) groupTransformData.parent.localDirty = true;
2354
+ if (groupTransformData.parent?.firstChild)
2355
+ groupTransformData.parent.firstChild.localDirty = true;
2356
+ }
2357
+ set hovered(hovered) {
2358
+ const groupRenderData = this.groupNode.getData(FlowNodeRenderData);
2359
+ if (hovered) {
2360
+ groupRenderData.toggleMouseEnter();
2361
+ } else {
2362
+ groupRenderData.toggleMouseLeave();
2222
2363
  }
2223
- const newParentEntity = newParent ? this.toNodeEntity(newParent) : parent;
2224
- if (!newParentEntity) {
2225
- console.warn("no new parent found", newParent);
2364
+ if (groupRenderData.hovered === hovered) {
2226
2365
  return;
2227
2366
  }
2228
- let toIndex = typeof index === "undefined" ? parent.children.length : index;
2229
- return this.doMoveNode(entity, newParentEntity, toIndex);
2367
+ groupRenderData.hovered = hovered;
2230
2368
  }
2231
- /**
2232
- * 拖拽节点
2233
- * @param param0
2234
- * @returns
2235
- */
2236
- dragNodes({ dropNode, nodes }) {
2237
- if (nodes.length === 0) {
2369
+ get hovered() {
2370
+ const groupRenderData = this.groupNode.getData(FlowNodeRenderData);
2371
+ return groupRenderData.hovered;
2372
+ }
2373
+ static create(groupNode) {
2374
+ if (!groupNode) {
2238
2375
  return;
2239
2376
  }
2240
- const startNode = nodes[0];
2241
- const fromParent = startNode.parent;
2242
- const toParent = dropNode.parent;
2243
- if (!fromParent || !toParent) {
2377
+ if (!FlowGroupUtils.isGroupNode(groupNode)) {
2244
2378
  return;
2245
2379
  }
2246
- const fromIndex = fromParent.children.findIndex((child) => child === startNode);
2247
- const dropIndex = toParent.children.findIndex((child) => child === dropNode);
2248
- let toIndex = dropIndex + 1;
2249
- if (fromParent === toParent && fromIndex < dropIndex) {
2250
- toIndex = toIndex - nodes.length;
2251
- }
2252
- const value = {
2253
- nodeIds: nodes.map((node) => node.id),
2254
- fromParentId: fromParent.id,
2255
- toParentId: toParent.id,
2380
+ return new _FlowGroupController(groupNode);
2381
+ }
2382
+ };
2383
+
2384
+ // src/services/flow-group-service/flow-group-utils.ts
2385
+ var FlowGroupUtils;
2386
+ ((FlowGroupUtils2) => {
2387
+ const findNodeParents = (node) => {
2388
+ const parents = [];
2389
+ let parent = node.parent;
2390
+ while (parent) {
2391
+ parents.push(parent);
2392
+ parent = parent.parent;
2393
+ }
2394
+ return parents;
2395
+ };
2396
+ const isNodeInGroup = (node) => {
2397
+ if (node?.parent?.flowNodeType === "group" /* GROUP */) {
2398
+ return true;
2399
+ }
2400
+ return false;
2401
+ };
2402
+ FlowGroupUtils2.validate = (nodes) => {
2403
+ if (!nodes || !Array.isArray(nodes) || nodes.length === 0) {
2404
+ return false;
2405
+ }
2406
+ const isGroupRelatedNode = nodes.some((node) => (0, FlowGroupUtils2.isGroupNode)(node));
2407
+ if (isGroupRelatedNode) return false;
2408
+ const hasGroup = nodes.some((node) => node && isNodeInGroup(node));
2409
+ if (hasGroup) return false;
2410
+ const parent = nodes[0].parent;
2411
+ const isSameParent = nodes.every((node) => node.parent === parent);
2412
+ if (!isSameParent) return false;
2413
+ const indexes = nodes.map((node) => node.index).sort((a, b) => a - b);
2414
+ const isIndexContinuous = indexes.every((index, i, arr) => {
2415
+ if (i === 0) {
2416
+ return true;
2417
+ }
2418
+ return index === arr[i - 1] + 1;
2419
+ });
2420
+ if (!isIndexContinuous) return false;
2421
+ const parents = findNodeParents(nodes[0]);
2422
+ const parentsInGroup = parents.some((parent2) => isNodeInGroup(parent2));
2423
+ if (parentsInGroup) return false;
2424
+ return true;
2425
+ };
2426
+ FlowGroupUtils2.getNodeGroupController = (node) => {
2427
+ if (!node) {
2428
+ return;
2429
+ }
2430
+ if (!isNodeInGroup(node)) {
2431
+ return;
2432
+ }
2433
+ const groupNode = node?.parent;
2434
+ return FlowGroupController.create(groupNode);
2435
+ };
2436
+ FlowGroupUtils2.getNodeRecursionGroupController = (node) => {
2437
+ if (!node) {
2438
+ return;
2439
+ }
2440
+ const group = (0, FlowGroupUtils2.getNodeGroupController)(node);
2441
+ if (group) {
2442
+ return group;
2443
+ }
2444
+ if (node.parent) {
2445
+ return (0, FlowGroupUtils2.getNodeRecursionGroupController)(node.parent);
2446
+ }
2447
+ return;
2448
+ };
2449
+ FlowGroupUtils2.isGroupNode = (group) => group.flowNodeType === "group" /* GROUP */;
2450
+ })(FlowGroupUtils || (FlowGroupUtils = {}));
2451
+
2452
+ // src/services/flow-drag-service.ts
2453
+ var FlowDragService = class {
2454
+ constructor() {
2455
+ this.onDropEmitter = new Emitter6();
2456
+ this.onDrop = this.onDropEmitter.event;
2457
+ }
2458
+ get renderState() {
2459
+ return this.document.renderState;
2460
+ }
2461
+ // 拖拽所有节点中的首个节点
2462
+ get dragStartNode() {
2463
+ return this.renderState.getDragStartEntity();
2464
+ }
2465
+ // 拖拽的所有节点
2466
+ get dragNodes() {
2467
+ return this.renderState.getDragEntities();
2468
+ }
2469
+ // 放置的区域
2470
+ get dropNodeId() {
2471
+ return this.renderState.getNodeDroppingId();
2472
+ }
2473
+ // 是否在拖拽分支
2474
+ get isDragBranch() {
2475
+ return this.renderState.isBranch || this.dragStartNode?.isInlineBlock;
2476
+ }
2477
+ // 拖拽的所有节点及其自节点
2478
+ get nodeDragIdsWithChildren() {
2479
+ return this.renderState.config.nodeDragIdsWithChildren || [];
2480
+ }
2481
+ get dragging() {
2482
+ return !!this.renderState.dragging;
2483
+ }
2484
+ get labelSide() {
2485
+ return this.renderState.config.dragLabelSide;
2486
+ }
2487
+ /**
2488
+ * 放置到目标分支
2489
+ */
2490
+ dropBranch() {
2491
+ this.dropNode();
2492
+ }
2493
+ /**
2494
+ * 移动并且创建节点
2495
+ * Move and create node
2496
+ */
2497
+ async dropCreateNode(json, onCreateNode) {
2498
+ const dropEntity = this.document.getNode(this.dropNodeId);
2499
+ if (!dropEntity) {
2500
+ return;
2501
+ }
2502
+ if (json) {
2503
+ const dragNodes = await onCreateNode?.(json, dropEntity);
2504
+ this.onDropEmitter.fire({
2505
+ dropNode: dropEntity,
2506
+ dragNodes: dragNodes ? [dragNodes] : [],
2507
+ dragJSON: json
2508
+ });
2509
+ }
2510
+ }
2511
+ /**
2512
+ * 移动到目标节点
2513
+ */
2514
+ dropNode() {
2515
+ const dropEntity = this.document.getNode(this.dropNodeId);
2516
+ if (!dropEntity) {
2517
+ return;
2518
+ }
2519
+ const sortNodes = [];
2520
+ let curr = this.dragStartNode;
2521
+ while (curr && this.dragNodes.includes(curr)) {
2522
+ sortNodes.push(curr);
2523
+ curr = curr.next;
2524
+ }
2525
+ this.operationService.dragNodes({
2526
+ dropNode: dropEntity,
2527
+ nodes: sortNodes
2528
+ });
2529
+ if (sortNodes.length > 0) {
2530
+ this.onDropEmitter.fire({
2531
+ dropNode: dropEntity,
2532
+ dragNodes: sortNodes
2533
+ });
2534
+ }
2535
+ }
2536
+ /**
2537
+ * 拖拽是否可以释放在该节点后面
2538
+ */
2539
+ isDroppableNode(node) {
2540
+ if (!this.dragging || this.isDragBranch) {
2541
+ return false;
2542
+ }
2543
+ if (this.nodeDragIdsWithChildren.includes(node.id) || node.next && this.nodeDragIdsWithChildren.includes(node.next.id)) {
2544
+ return false;
2545
+ }
2546
+ if (node.isInlineBlocks || node.isInlineBlock) {
2547
+ return false;
2548
+ }
2549
+ const hasGroupNode = this.dragNodes.some(
2550
+ (node2) => node2.flowNodeType === "group" /* GROUP */
2551
+ );
2552
+ if (hasGroupNode) {
2553
+ const group = FlowGroupUtils.getNodeRecursionGroupController(node);
2554
+ if (group) {
2555
+ return false;
2556
+ }
2557
+ }
2558
+ return true;
2559
+ }
2560
+ /**
2561
+ * 拖拽分支是否可以释放在该分支
2562
+ * @param node 拖拽的分支节点
2563
+ * @param side 分支的前面还是后面
2564
+ */
2565
+ isDroppableBranch(node, side = "normal_branch" /* NORMAL_BRANCH */) {
2566
+ if (this.renderState.isBranch) {
2567
+ return true;
2568
+ }
2569
+ if (this.isDragBranch) {
2570
+ if (
2571
+ // 拖拽到分支
2572
+ !node.isInlineBlock || // 只能在同一分支条件下
2573
+ node.parent !== this.dragStartNode.parent || // 自己不能拖拽给自己
2574
+ node === this.dragStartNode
2575
+ ) {
2576
+ return false;
2577
+ }
2578
+ if (side === "normal_branch" /* NORMAL_BRANCH */ && node.next !== this.dragStartNode) {
2579
+ return true;
2580
+ }
2581
+ if (side === "pre_branch" /* PRE_BRANCH */ && node.pre !== this.dragStartNode) {
2582
+ return true;
2583
+ }
2584
+ }
2585
+ return false;
2586
+ }
2587
+ };
2588
+ __decorateClass([
2589
+ inject3(FlowDocument)
2590
+ ], FlowDragService.prototype, "document", 2);
2591
+ __decorateClass([
2592
+ inject3(FlowOperationBaseService)
2593
+ ], FlowDragService.prototype, "operationService", 2);
2594
+ __decorateClass([
2595
+ inject3(EntityManager2)
2596
+ ], FlowDragService.prototype, "entityManager", 2);
2597
+ FlowDragService = __decorateClass([
2598
+ injectable3()
2599
+ ], FlowDragService);
2600
+
2601
+ // src/services/flow-operation-base-service.ts
2602
+ import { inject as inject4, injectable as injectable4, postConstruct as postConstruct2 } from "inversify";
2603
+ import { DisposableCollection, Emitter as Emitter7 } from "@flowgram.ai/utils";
2604
+ import { EntityManager as EntityManager3 } from "@flowgram.ai/core";
2605
+ var FlowOperationBaseServiceImpl = class {
2606
+ constructor() {
2607
+ this.onNodeAddEmitter = new Emitter7();
2608
+ this.onNodeAdd = this.onNodeAddEmitter.event;
2609
+ this.toDispose = new DisposableCollection();
2610
+ this.onNodeMoveEmitter = new Emitter7();
2611
+ this.onNodeMove = this.onNodeMoveEmitter.event;
2612
+ }
2613
+ init() {
2614
+ this.toDispose.pushAll([this.onNodeAddEmitter, this.onNodeMoveEmitter]);
2615
+ }
2616
+ addNode(nodeJSON, config = {}) {
2617
+ const { parent, index, hidden } = config;
2618
+ let parentEntity;
2619
+ if (parent) {
2620
+ parentEntity = this.toNodeEntity(parent);
2621
+ }
2622
+ let register;
2623
+ if (parentEntity) {
2624
+ register = parentEntity.getNodeRegistry();
2625
+ }
2626
+ const addJSON = {
2627
+ ...nodeJSON,
2628
+ type: nodeJSON.type || "block" /* BLOCK */
2629
+ };
2630
+ const addNodeData = {
2631
+ ...addJSON,
2632
+ parent: parentEntity,
2633
+ index,
2634
+ hidden
2635
+ };
2636
+ let added;
2637
+ if (parentEntity && register?.addChild) {
2638
+ added = register.addChild(parentEntity, addJSON, {
2639
+ index,
2640
+ hidden
2641
+ });
2642
+ } else {
2643
+ added = this.document.addNode(addNodeData);
2644
+ }
2645
+ this.onNodeAddEmitter.fire({
2646
+ node: added,
2647
+ data: addNodeData
2648
+ });
2649
+ return added;
2650
+ }
2651
+ addFromNode(fromNode, nodeJSON) {
2652
+ return this.document.addFromNode(fromNode, nodeJSON);
2653
+ }
2654
+ deleteNode(node) {
2655
+ this.document.removeNode(node);
2656
+ }
2657
+ deleteNodes(nodes) {
2658
+ (nodes || []).forEach((node) => {
2659
+ this.deleteNode(node);
2660
+ });
2661
+ }
2662
+ addBlock(target, blockJSON, config = {}) {
2663
+ const { parent, index } = config;
2664
+ return this.document.addBlock(target, blockJSON, void 0, parent, index);
2665
+ }
2666
+ moveNode(node, config = {}) {
2667
+ const { parent: newParent, index } = config;
2668
+ const entity = this.toNodeEntity(node);
2669
+ const parent = entity?.parent;
2670
+ if (!parent) {
2671
+ return;
2672
+ }
2673
+ const newParentEntity = newParent ? this.toNodeEntity(newParent) : parent;
2674
+ if (!newParentEntity) {
2675
+ console.warn("no new parent found", newParent);
2676
+ return;
2677
+ }
2678
+ let toIndex = typeof index === "undefined" ? newParentEntity.collapsedChildren.length : index;
2679
+ return this.doMoveNode(entity, newParentEntity, toIndex);
2680
+ }
2681
+ /**
2682
+ * 拖拽节点
2683
+ * @param param0
2684
+ * @returns
2685
+ */
2686
+ dragNodes({ dropNode, nodes }) {
2687
+ if (nodes.length === 0) {
2688
+ return;
2689
+ }
2690
+ const startNode = nodes[0];
2691
+ const fromParent = startNode.parent;
2692
+ const toParent = dropNode.parent;
2693
+ if (!fromParent || !toParent) {
2694
+ return;
2695
+ }
2696
+ const fromIndex = fromParent.children.findIndex((child) => child === startNode);
2697
+ const dropIndex = toParent.children.findIndex((child) => child === dropNode);
2698
+ let toIndex = dropIndex + 1;
2699
+ if (fromParent === toParent && fromIndex < dropIndex) {
2700
+ toIndex = toIndex - nodes.length;
2701
+ }
2702
+ const value = {
2703
+ nodeIds: nodes.map((node) => node.id),
2704
+ fromParentId: fromParent.id,
2705
+ toParentId: toParent.id,
2256
2706
  fromIndex,
2257
2707
  toIndex
2258
2708
  };
@@ -2369,418 +2819,138 @@ var FlowOperationBaseServiceImpl = class {
2369
2819
  toNodeEntity(node) {
2370
2820
  return typeof node === "string" ? this.document.getNode(node) : node;
2371
2821
  }
2372
- getNodeIndex(node) {
2373
- const entity = this.toNodeEntity(node);
2374
- const parent = entity?.parent;
2375
- if (!parent) {
2376
- return -1;
2377
- }
2378
- return parent.children.findIndex((child) => child === entity);
2379
- }
2380
- doMoveNode(node, newParent, index) {
2381
- return this.document.moveChildNodes({
2382
- nodeIds: [this.toId(node)],
2383
- toParentId: this.toId(newParent),
2384
- toIndex: index
2385
- });
2386
- }
2387
- };
2388
- __decorateClass([
2389
- inject3(EntityManager2)
2390
- ], FlowOperationBaseServiceImpl.prototype, "entityManager", 2);
2391
- __decorateClass([
2392
- inject3(FlowDocument)
2393
- ], FlowOperationBaseServiceImpl.prototype, "document", 2);
2394
- __decorateClass([
2395
- postConstruct2()
2396
- ], FlowOperationBaseServiceImpl.prototype, "init", 1);
2397
- FlowOperationBaseServiceImpl = __decorateClass([
2398
- injectable3()
2399
- ], FlowOperationBaseServiceImpl);
2400
-
2401
- // src/services/flow-group-service.ts
2402
- import { nanoid } from "nanoid";
2403
- import { inject as inject4, injectable as injectable4 } from "inversify";
2404
- import { EntityManager as EntityManager3 } from "@flowgram.ai/core";
2405
- var FlowGroupService = class {
2406
- /** 创建分组节点 */
2407
- createGroup(nodes) {
2408
- if (!nodes || !Array.isArray(nodes) || nodes.length === 0) {
2409
- return;
2410
- }
2411
- if (!FlowGroupController.validate(nodes)) {
2412
- return;
2413
- }
2414
- const sortedNodes = nodes.sort((a, b) => a.index - b.index);
2415
- const fromNode = sortedNodes[0];
2416
- const groupId = `group_${nanoid(5)}`;
2417
- this.operationService.apply({
2418
- type: "createGroup" /* createGroup */,
2419
- value: {
2420
- targetId: fromNode.id,
2421
- groupId,
2422
- nodeIds: nodes.map((node) => node.id)
2423
- }
2424
- });
2425
- const groupNode = this.entityManager.getEntityById(groupId);
2426
- if (!groupNode) {
2427
- return;
2428
- }
2429
- const group = this.groupController(groupNode);
2430
- if (!group) {
2431
- return;
2432
- }
2433
- group.expand();
2434
- return groupNode;
2435
- }
2436
- /** 删除分组 */
2437
- deleteGroup(groupNode) {
2438
- const json = groupNode.toJSON();
2439
- if (!groupNode.pre || !json) {
2440
- return;
2441
- }
2442
- this.operationService.apply({
2443
- type: "deleteNodes" /* deleteNodes */,
2444
- value: {
2445
- fromId: groupNode.pre.id,
2446
- nodes: [json]
2447
- }
2448
- });
2449
- }
2450
- /** 取消分组 */
2451
- ungroup(groupNode) {
2452
- const group = this.groupController(groupNode);
2453
- if (!group) {
2454
- return;
2455
- }
2456
- const nodes = group.nodes;
2457
- if (!groupNode.pre) {
2458
- return;
2459
- }
2460
- group.collapse();
2461
- this.operationService.apply({
2462
- type: "ungroup" /* ungroup */,
2463
- value: {
2464
- groupId: groupNode.id,
2465
- targetId: groupNode.pre.id,
2466
- nodeIds: nodes.map((node) => node.id)
2467
- }
2468
- });
2469
- }
2470
- /** 返回所有分组节点 */
2471
- getAllGroups() {
2472
- const allNodes = this.entityManager.getEntities(FlowNodeEntity);
2473
- const groupNodes = allNodes.filter((node) => node.flowNodeType === "group" /* GROUP */);
2474
- return groupNodes.map((node) => this.groupController(node)).filter(Boolean);
2475
- }
2476
- /** 获取分组控制器*/
2477
- groupController(group) {
2478
- return FlowGroupController.create(group);
2479
- }
2480
- static validate(nodes) {
2481
- return FlowGroupController.validate(nodes);
2482
- }
2483
- };
2484
- __decorateClass([
2485
- inject4(EntityManager3)
2486
- ], FlowGroupService.prototype, "entityManager", 2);
2487
- __decorateClass([
2488
- inject4(FlowOperationBaseService)
2489
- ], FlowGroupService.prototype, "operationService", 2);
2490
- FlowGroupService = __decorateClass([
2491
- injectable4()
2492
- ], FlowGroupService);
2493
- var FlowGroupController = class _FlowGroupController {
2494
- constructor(groupNode) {
2495
- this.groupNode = groupNode;
2496
- }
2497
- get nodes() {
2498
- return this.groupNode.collapsedChildren || [];
2499
- }
2500
- get collapsed() {
2501
- const groupTransformData = this.groupNode.getData(FlowNodeTransformData);
2502
- return groupTransformData.collapsed;
2503
- }
2504
- collapse() {
2505
- this.collapsed = true;
2506
- }
2507
- expand() {
2508
- this.collapsed = false;
2509
- }
2510
- /** 获取分组外围的最大边框 */
2511
- get bounds() {
2512
- const groupNodeBounds = this.groupNode.getData(FlowNodeTransformData).bounds;
2513
- return groupNodeBounds;
2514
- }
2515
- /** 是否是开始节点 */
2516
- isStartNode(node) {
2517
- if (!node) {
2518
- return false;
2519
- }
2520
- const nodes = this.nodes;
2521
- if (!nodes[0]) {
2522
- return false;
2523
- }
2524
- return node.id === nodes[0].id;
2525
- }
2526
- /** 是否是结束节点 */
2527
- isEndNode(node) {
2528
- if (!node) {
2529
- return false;
2530
- }
2531
- const nodes = this.nodes;
2532
- if (!nodes[nodes.length - 1]) {
2533
- return false;
2534
- }
2535
- return node.id === nodes[nodes.length - 1].id;
2536
- }
2537
- set note(note) {
2538
- this.groupNode.getNodeMeta().note = note;
2539
- }
2540
- get note() {
2541
- return this.groupNode.getNodeMeta().note || "";
2542
- }
2543
- set noteHeight(height) {
2544
- this.groupNode.getNodeMeta().noteHeight = height;
2545
- }
2546
- get noteHeight() {
2547
- return this.groupNode.getNodeMeta().noteHeight || 0;
2548
- }
2549
- get positionConfig() {
2550
- return this.groupNode.getNodeMeta().positionConfig;
2551
- }
2552
- set collapsed(collapsed) {
2553
- const groupTransformData = this.groupNode.getData(FlowNodeTransformData);
2554
- groupTransformData.collapsed = collapsed;
2555
- groupTransformData.localDirty = true;
2556
- if (groupTransformData.parent) groupTransformData.parent.localDirty = true;
2557
- if (groupTransformData.parent?.firstChild)
2558
- groupTransformData.parent.firstChild.localDirty = true;
2559
- }
2560
- set hovered(hovered) {
2561
- const groupRenderData = this.groupNode.getData(FlowNodeRenderData);
2562
- if (hovered) {
2563
- groupRenderData.toggleMouseEnter();
2564
- } else {
2565
- groupRenderData.toggleMouseLeave();
2566
- }
2567
- if (groupRenderData.hovered === hovered) {
2568
- return;
2822
+ getNodeIndex(node) {
2823
+ const entity = this.toNodeEntity(node);
2824
+ const parent = entity?.parent;
2825
+ if (!parent) {
2826
+ return -1;
2569
2827
  }
2570
- groupRenderData.hovered = hovered;
2828
+ return parent.children.findIndex((child) => child === entity);
2571
2829
  }
2572
- get hovered() {
2573
- const groupRenderData = this.groupNode.getData(FlowNodeRenderData);
2574
- return groupRenderData.hovered;
2830
+ doMoveNode(node, newParent, index) {
2831
+ if (!node.parent) {
2832
+ throw new Error("root node cannot move");
2833
+ }
2834
+ const event = {
2835
+ node,
2836
+ fromParent: node.parent,
2837
+ toParent: newParent,
2838
+ fromIndex: this.getNodeIndex(node),
2839
+ toIndex: index
2840
+ };
2841
+ this.document.moveChildNodes({
2842
+ nodeIds: [this.toId(node)],
2843
+ toParentId: this.toId(newParent),
2844
+ toIndex: index
2845
+ });
2846
+ this.onNodeMoveEmitter.fire(event);
2575
2847
  }
2576
- static create(groupNode) {
2577
- if (!groupNode) {
2848
+ };
2849
+ __decorateClass([
2850
+ inject4(EntityManager3)
2851
+ ], FlowOperationBaseServiceImpl.prototype, "entityManager", 2);
2852
+ __decorateClass([
2853
+ inject4(FlowDocument)
2854
+ ], FlowOperationBaseServiceImpl.prototype, "document", 2);
2855
+ __decorateClass([
2856
+ postConstruct2()
2857
+ ], FlowOperationBaseServiceImpl.prototype, "init", 1);
2858
+ FlowOperationBaseServiceImpl = __decorateClass([
2859
+ injectable4()
2860
+ ], FlowOperationBaseServiceImpl);
2861
+
2862
+ // src/services/flow-group-service/flow-group-service.ts
2863
+ import { nanoid } from "nanoid";
2864
+ import { inject as inject5, injectable as injectable5 } from "inversify";
2865
+ import { EntityManager as EntityManager4 } from "@flowgram.ai/core";
2866
+ var FlowGroupService = class {
2867
+ /** 创建分组节点 */
2868
+ createGroup(nodes) {
2869
+ if (!nodes || !Array.isArray(nodes) || nodes.length === 0) {
2578
2870
  return;
2579
2871
  }
2580
- if (!_FlowGroupController.isGroupNode(groupNode)) {
2872
+ if (!FlowGroupUtils.validate(nodes)) {
2581
2873
  return;
2582
2874
  }
2583
- return new _FlowGroupController(groupNode);
2584
- }
2585
- /** 判断节点能否组成分组 */
2586
- static validate(nodes) {
2587
- if (!nodes || !Array.isArray(nodes) || nodes.length === 0) {
2588
- return false;
2589
- }
2590
- const isGroupRelatedNode = nodes.some((node) => _FlowGroupController.isGroupNode(node));
2591
- if (isGroupRelatedNode) return false;
2592
- const hasGroup = nodes.some((node) => node && this.isNodeInGroup(node));
2593
- if (hasGroup) return false;
2594
- const parent = nodes[0].parent;
2595
- const isSameParent = nodes.every((node) => node.parent === parent);
2596
- if (!isSameParent) return false;
2597
- const indexes = nodes.map((node) => node.index).sort((a, b) => a - b);
2598
- const isIndexContinuous = indexes.every((index, i, arr) => {
2599
- if (i === 0) {
2600
- return true;
2875
+ const sortedNodes = nodes.sort((a, b) => a.index - b.index);
2876
+ const fromNode = sortedNodes[0];
2877
+ const groupId = `group_${nanoid(5)}`;
2878
+ this.operationService.apply({
2879
+ type: "createGroup" /* createGroup */,
2880
+ value: {
2881
+ targetId: fromNode.id,
2882
+ groupId,
2883
+ nodeIds: nodes.map((node) => node.id)
2601
2884
  }
2602
- return index === arr[i - 1] + 1;
2603
2885
  });
2604
- if (!isIndexContinuous) return false;
2605
- const parents = this.findNodeParents(nodes[0]);
2606
- const parentsInGroup = parents.some((parent2) => this.isNodeInGroup(parent2));
2607
- if (parentsInGroup) return false;
2608
- return true;
2609
- }
2610
- /** 获取节点分组控制 */
2611
- static getNodeGroupController(node) {
2612
- if (!node) {
2886
+ const groupNode = this.entityManager.getEntityById(groupId);
2887
+ if (!groupNode) {
2613
2888
  return;
2614
2889
  }
2615
- if (!this.isNodeInGroup(node)) {
2890
+ const group = this.groupController(groupNode);
2891
+ if (!group) {
2616
2892
  return;
2617
2893
  }
2618
- const groupNode = node?.parent;
2619
- return _FlowGroupController.create(groupNode);
2894
+ group.expand();
2895
+ return groupNode;
2620
2896
  }
2621
- /** 向上递归查找分组递归控制 */
2622
- static getNodeRecursionGroupController(node) {
2623
- if (!node) {
2897
+ /** 删除分组 */
2898
+ deleteGroup(groupNode) {
2899
+ const json = groupNode.toJSON();
2900
+ if (!groupNode.pre || !json) {
2624
2901
  return;
2625
2902
  }
2626
- const group = this.getNodeGroupController(node);
2627
- if (group) {
2628
- return group;
2629
- }
2630
- if (node.parent) {
2631
- return this.getNodeRecursionGroupController(node.parent);
2632
- }
2633
- return;
2634
- }
2635
- /** 是否分组节点 */
2636
- static isGroupNode(group) {
2637
- return group.flowNodeType === "group" /* GROUP */;
2638
- }
2639
- /** 找到节点所有上级 */
2640
- static findNodeParents(node) {
2641
- const parents = [];
2642
- let parent = node.parent;
2643
- while (parent) {
2644
- parents.push(parent);
2645
- parent = parent.parent;
2646
- }
2647
- return parents;
2648
- }
2649
- /** 节点是否处于分组中 */
2650
- static isNodeInGroup(node) {
2651
- if (node?.parent?.flowNodeType === "group" /* GROUP */) {
2652
- return true;
2653
- }
2654
- return false;
2655
- }
2656
- };
2657
-
2658
- // src/services/flow-drag-service.ts
2659
- var FlowDragService = class {
2660
- constructor() {
2661
- this.onDropEmitter = new Emitter7();
2662
- this.onDrop = this.onDropEmitter.event;
2663
- }
2664
- get renderState() {
2665
- return this.document.renderState;
2666
- }
2667
- // 拖拽所有节点中的首个节点
2668
- get dragStartNode() {
2669
- return this.renderState.getDragStartEntity();
2670
- }
2671
- // 拖拽的所有节点
2672
- get dragNodes() {
2673
- return this.renderState.getDragEntities();
2674
- }
2675
- // 放置的区域
2676
- get dropNodeId() {
2677
- return this.renderState.getNodeDroppingId();
2678
- }
2679
- // 是否在拖拽分支
2680
- get isDragBranch() {
2681
- return this.dragStartNode?.isInlineBlock;
2682
- }
2683
- // 拖拽的所有节点及其自节点
2684
- get nodeDragIdsWithChildren() {
2685
- return this.renderState.config.nodeDragIdsWithChildren || [];
2686
- }
2687
- get dragging() {
2688
- const renderData = this.dragStartNode?.getData(FlowNodeRenderData);
2689
- return !!renderData?.dragging;
2690
- }
2691
- get labelSide() {
2692
- return this.renderState.config.dragLabelSide;
2693
- }
2694
- /**
2695
- * 放置到目标分支
2696
- */
2697
- dropBranch() {
2698
- this.dropNode();
2903
+ this.operationService.apply({
2904
+ type: "deleteNodes" /* deleteNodes */,
2905
+ value: {
2906
+ fromId: groupNode.pre.id,
2907
+ nodes: [json]
2908
+ }
2909
+ });
2699
2910
  }
2700
- /**
2701
- * 移动到目标节点
2702
- */
2703
- dropNode() {
2704
- const dropEntity = this.document.getNode(this.dropNodeId);
2705
- if (!dropEntity) {
2911
+ /** 取消分组 */
2912
+ ungroup(groupNode) {
2913
+ const group = this.groupController(groupNode);
2914
+ if (!group) {
2706
2915
  return;
2707
2916
  }
2708
- const sortNodes = [];
2709
- let curr = this.dragStartNode;
2710
- while (curr && this.dragNodes.includes(curr)) {
2711
- sortNodes.push(curr);
2712
- curr = curr.next;
2917
+ const nodes = group.nodes;
2918
+ if (!groupNode.pre) {
2919
+ return;
2713
2920
  }
2714
- this.operationService.dragNodes({
2715
- dropNode: dropEntity,
2716
- nodes: sortNodes
2921
+ group.collapse();
2922
+ this.operationService.apply({
2923
+ type: "ungroup" /* ungroup */,
2924
+ value: {
2925
+ groupId: groupNode.id,
2926
+ targetId: groupNode.pre.id,
2927
+ nodeIds: nodes.map((node) => node.id)
2928
+ }
2717
2929
  });
2718
- if (sortNodes.length > 0) {
2719
- this.onDropEmitter.fire({
2720
- dropNode: dropEntity,
2721
- dragNodes: sortNodes
2722
- });
2723
- }
2724
2930
  }
2725
- /**
2726
- * 拖拽是否可以释放在该节点后面
2727
- */
2728
- isDroppableNode(node) {
2729
- if (!this.dragging || this.isDragBranch) {
2730
- return false;
2731
- }
2732
- if (this.nodeDragIdsWithChildren.includes(node.id) || node.next && this.nodeDragIdsWithChildren.includes(node.next.id)) {
2733
- return false;
2734
- }
2735
- if (node.isInlineBlocks || node.isInlineBlock) {
2736
- return false;
2737
- }
2738
- const hasGroupNode = this.dragNodes.some((node2) => node2.flowNodeType === "group" /* GROUP */);
2739
- if (hasGroupNode) {
2740
- const group = FlowGroupController.getNodeRecursionGroupController(node);
2741
- if (group) {
2742
- return false;
2743
- }
2744
- }
2745
- return true;
2931
+ /** 返回所有分组节点 */
2932
+ getAllGroups() {
2933
+ const allNodes = this.entityManager.getEntities(FlowNodeEntity);
2934
+ const groupNodes = allNodes.filter((node) => node.flowNodeType === "group" /* GROUP */);
2935
+ return groupNodes.map((node) => this.groupController(node)).filter(Boolean);
2746
2936
  }
2747
- /**
2748
- * 拖拽分支是否可以释放在该分支
2749
- * @param node 拖拽的分支节点
2750
- * @param side 分支的前面还是后面
2751
- */
2752
- isDroppableBranch(node, side = "normal_branch" /* NORMAL_BRANCH */) {
2753
- if (this.isDragBranch) {
2754
- if (
2755
- // 拖拽到分支
2756
- !node.isInlineBlock || // 只能在同一分支条件下
2757
- node.parent !== this.dragStartNode.parent || // 自己不能拖拽给自己
2758
- node === this.dragStartNode
2759
- ) {
2760
- return false;
2761
- }
2762
- if (side === "normal_branch" /* NORMAL_BRANCH */ && node.next !== this.dragStartNode) {
2763
- return true;
2764
- }
2765
- if (side === "pre_branch" /* PRE_BRANCH */ && node.pre !== this.dragStartNode) {
2766
- return true;
2767
- }
2768
- }
2769
- return false;
2937
+ /** 获取分组控制器*/
2938
+ groupController(group) {
2939
+ return FlowGroupController.create(group);
2940
+ }
2941
+ static validate(nodes) {
2942
+ return FlowGroupUtils.validate(nodes);
2770
2943
  }
2771
2944
  };
2772
2945
  __decorateClass([
2773
- inject5(FlowDocument)
2774
- ], FlowDragService.prototype, "document", 2);
2946
+ inject5(EntityManager4)
2947
+ ], FlowGroupService.prototype, "entityManager", 2);
2775
2948
  __decorateClass([
2776
2949
  inject5(FlowOperationBaseService)
2777
- ], FlowDragService.prototype, "operationService", 2);
2778
- __decorateClass([
2779
- inject5(EntityManager4)
2780
- ], FlowDragService.prototype, "entityManager", 2);
2781
- FlowDragService = __decorateClass([
2950
+ ], FlowGroupService.prototype, "operationService", 2);
2951
+ FlowGroupService = __decorateClass([
2782
2952
  injectable5()
2783
- ], FlowDragService);
2953
+ ], FlowGroupService);
2784
2954
 
2785
2955
  // src/layout/vertical-fixed-layout.ts
2786
2956
  import { injectable as injectable6, inject as inject6, multiInject as multiInject2, optional as optional3 } from "inversify";