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

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