@flowgram.ai/free-layout-core 0.1.13 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/esm/{chunk-DE4324TR.js → chunk-IYUZVBAO.js} +1 -1
  2. package/dist/esm/chunk-IYUZVBAO.js.map +1 -0
  3. package/dist/esm/chunk-LJH3TSLZ.js +7 -0
  4. package/dist/esm/chunk-LJH3TSLZ.js.map +1 -0
  5. package/dist/esm/chunk-TQLT57GW.js +1 -0
  6. package/dist/esm/chunk-TQLT57GW.js.map +1 -0
  7. package/dist/esm/index.js +156 -60
  8. package/dist/esm/index.js.map +1 -1
  9. package/dist/esm/typings/index.js +10 -5
  10. package/dist/esm/typings/workflow-drag.js +2 -0
  11. package/dist/esm/typings/workflow-drag.js.map +1 -0
  12. package/dist/esm/typings/workflow-operation.js +8 -0
  13. package/dist/esm/typings/workflow-operation.js.map +1 -0
  14. package/dist/index.d.mts +121 -7
  15. package/dist/index.d.ts +121 -7
  16. package/dist/index.js +202 -105
  17. package/dist/index.js.map +1 -1
  18. package/dist/typings/index.d.mts +2 -1
  19. package/dist/typings/index.d.ts +2 -1
  20. package/dist/typings/index.js +7 -2
  21. package/dist/typings/index.js.map +1 -1
  22. package/dist/typings/workflow-drag.d.mts +8 -0
  23. package/dist/typings/workflow-drag.d.ts +8 -0
  24. package/dist/typings/workflow-drag.js +19 -0
  25. package/dist/typings/workflow-drag.js.map +1 -0
  26. package/dist/typings/workflow-json.d.mts +1 -1
  27. package/dist/typings/workflow-json.d.ts +1 -1
  28. package/dist/typings/workflow-line.d.mts +1 -1
  29. package/dist/typings/workflow-line.d.ts +1 -1
  30. package/dist/typings/workflow-node.d.mts +1 -1
  31. package/dist/typings/workflow-node.d.ts +1 -1
  32. package/dist/typings/workflow-node.js.map +1 -1
  33. package/dist/typings/workflow-operation.d.mts +24 -0
  34. package/dist/typings/workflow-operation.d.ts +24 -0
  35. package/dist/typings/workflow-operation.js +31 -0
  36. package/dist/typings/workflow-operation.js.map +1 -0
  37. package/dist/typings/workflow-registry.d.mts +1 -1
  38. package/dist/typings/workflow-registry.d.ts +1 -1
  39. package/dist/{workflow-line-entity-BJQBRDgJ.d.mts → workflow-line-entity-CF97dniV.d.mts} +90 -170
  40. package/dist/{workflow-line-entity-CEitdjhk.d.ts → workflow-line-entity-niuFXSbE.d.ts} +90 -170
  41. package/package.json +9 -9
  42. package/dist/esm/chunk-DE4324TR.js.map +0 -1
package/dist/index.js CHANGED
@@ -52,6 +52,8 @@ __export(src_exports, {
52
52
  WorkflowNodeEntity: () => WorkflowNodeEntity,
53
53
  WorkflowNodeLinesData: () => WorkflowNodeLinesData,
54
54
  WorkflowNodePortsData: () => WorkflowNodePortsData,
55
+ WorkflowOperationBaseService: () => WorkflowOperationBaseService,
56
+ WorkflowOperationBaseServiceImpl: () => WorkflowOperationBaseServiceImpl,
55
57
  WorkflowPortEntity: () => WorkflowPortEntity,
56
58
  WorkflowResetLayoutService: () => WorkflowResetLayoutService,
57
59
  WorkflowSelectService: () => WorkflowSelectService,
@@ -65,21 +67,21 @@ __export(src_exports, {
65
67
  getAntiOverlapPosition: () => getAntiOverlapPosition,
66
68
  getPortEntityId: () => getPortEntityId,
67
69
  nanoid: () => nanoid,
68
- useConfigEntity: () => import_core24.useConfigEntity,
70
+ useConfigEntity: () => import_core25.useConfigEntity,
69
71
  useCurrentDomNode: () => useCurrentDomNode,
70
72
  useCurrentEntity: () => useCurrentEntity,
71
- useEntities: () => import_core24.useEntities,
72
- useEntityDataFromContext: () => import_core24.useEntityDataFromContext,
73
- useEntityFromContext: () => import_core24.useEntityFromContext,
74
- useListenEvents: () => import_core24.useListenEvents,
73
+ useEntities: () => import_core25.useEntities,
74
+ useEntityDataFromContext: () => import_core25.useEntityDataFromContext,
75
+ useEntityFromContext: () => import_core25.useEntityFromContext,
76
+ useListenEvents: () => import_core25.useListenEvents,
75
77
  useNodeRender: () => useNodeRender,
76
- usePlayground: () => import_core24.usePlayground,
77
- usePlaygroundContainer: () => import_core24.usePlaygroundContainer,
78
- usePlaygroundContext: () => import_core24.usePlaygroundContext,
79
- usePlaygroundLatest: () => import_core24.usePlaygroundLatest,
78
+ usePlayground: () => import_core25.usePlayground,
79
+ usePlaygroundContainer: () => import_core25.usePlaygroundContainer,
80
+ usePlaygroundContext: () => import_core25.usePlaygroundContext,
81
+ usePlaygroundLatest: () => import_core25.usePlaygroundLatest,
80
82
  usePlaygroundReadonlyState: () => usePlaygroundReadonlyState,
81
- useRefresh: () => import_core24.useRefresh,
82
- useService: () => import_core24.useService,
83
+ useRefresh: () => import_core25.useRefresh,
84
+ useService: () => import_core25.useService,
83
85
  useWorkflowDocument: () => useWorkflowDocument
84
86
  });
85
87
  module.exports = __toCommonJS(src_exports);
@@ -97,14 +99,14 @@ var WorkflowCommands = /* @__PURE__ */ ((WorkflowCommands2) => {
97
99
  })(WorkflowCommands || {});
98
100
 
99
101
  // src/hooks/index.ts
100
- var import_core24 = require("@flowgram.ai/core");
102
+ var import_core25 = require("@flowgram.ai/core");
101
103
 
102
104
  // src/hooks/use-node-render.tsx
103
105
  var import_react2 = require("react");
104
106
  var import_reactive = require("@flowgram.ai/reactive");
105
107
  var import_node = require("@flowgram.ai/node");
106
- var import_document10 = require("@flowgram.ai/document");
107
- var import_core20 = require("@flowgram.ai/core");
108
+ var import_document12 = require("@flowgram.ai/document");
109
+ var import_core21 = require("@flowgram.ai/core");
108
110
 
109
111
  // src/service/workflow-select-service.ts
110
112
  var import_inversify = require("inversify");
@@ -178,11 +180,12 @@ var import_core8 = require("@flowgram.ai/core");
178
180
 
179
181
  // src/entity-datas/workflow-node-ports-data.ts
180
182
  var import_lodash_es = require("lodash-es");
181
- var import_document2 = require("@flowgram.ai/document");
183
+ var import_document3 = require("@flowgram.ai/document");
182
184
  var import_core5 = require("@flowgram.ai/core");
183
185
 
184
186
  // src/entities/workflow-port-entity.ts
185
187
  var import_utils5 = require("@flowgram.ai/utils");
188
+ var import_document2 = require("@flowgram.ai/document");
186
189
  var import_core4 = require("@flowgram.ai/core");
187
190
  var PORT_SIZE = 24;
188
191
  var WorkflowPortEntity = class extends import_core4.Entity {
@@ -230,7 +233,7 @@ var WorkflowPortEntity = class extends import_core4.Entity {
230
233
  }
231
234
  get point() {
232
235
  const { targetElement } = this;
233
- const { bounds } = this.node.getData(import_core4.TransformData);
236
+ const { bounds } = this.node.getData(import_document2.FlowNodeTransformData);
234
237
  if (targetElement) {
235
238
  const pos = domReactToBounds(targetElement.getBoundingClientRect()).center;
236
239
  return this.entityManager.getEntity(import_core4.PlaygroundConfigEntity).getPosFromMouseEvent({
@@ -259,7 +262,7 @@ var WorkflowPortEntity = class extends import_core4.Entity {
259
262
  */
260
263
  get relativePosition() {
261
264
  const { point } = this;
262
- const { bounds } = this.node.getData(import_core4.TransformData);
265
+ const { bounds } = this.node.getData(import_document2.FlowNodeTransformData);
263
266
  return {
264
267
  x: point.x - bounds.x,
265
268
  y: point.y - bounds.y
@@ -362,7 +365,7 @@ var WorkflowNodePortsData = class extends import_core5.EntityData {
362
365
  * 动态计算点位,通过 dom 的 data-port-key
363
366
  */
364
367
  updateDynamicPorts() {
365
- const domNode = this.entity.getData(import_document2.FlowNodeRenderData).node;
368
+ const domNode = this.entity.getData(import_document3.FlowNodeRenderData).node;
366
369
  const elements = domNode.querySelectorAll("[data-port-id]");
367
370
  const staticPorts = this._staticPorts;
368
371
  const dynamicPorts = [];
@@ -1139,20 +1142,20 @@ WorkflowHoverService = __decorateClass([
1139
1142
  var import_nanoid3 = require("nanoid");
1140
1143
  var import_inversify6 = require("inversify");
1141
1144
  var import_utils16 = require("@flowgram.ai/utils");
1142
- var import_document7 = require("@flowgram.ai/document");
1143
1145
  var import_document8 = require("@flowgram.ai/document");
1146
+ var import_document9 = require("@flowgram.ai/document");
1144
1147
  var import_core15 = require("@flowgram.ai/core");
1145
1148
 
1146
1149
  // src/workflow-lines-manager.ts
1147
1150
  var import_lodash_es3 = require("lodash-es");
1148
1151
  var import_inversify3 = require("inversify");
1149
1152
  var import_utils12 = require("@flowgram.ai/utils");
1150
- var import_document4 = require("@flowgram.ai/document");
1153
+ var import_document5 = require("@flowgram.ai/document");
1151
1154
  var import_core12 = require("@flowgram.ai/core");
1152
1155
 
1153
1156
  // src/workflow-document-option.ts
1154
1157
  var import_form_core2 = require("@flowgram.ai/form-core");
1155
- var import_document3 = require("@flowgram.ai/document");
1158
+ var import_document4 = require("@flowgram.ai/document");
1156
1159
  var import_core11 = require("@flowgram.ai/core");
1157
1160
 
1158
1161
  // src/utils/flow-node-form-data.ts
@@ -1185,6 +1188,9 @@ var LineColors = /* @__PURE__ */ ((LineColors2) => {
1185
1188
  return LineColors2;
1186
1189
  })(LineColors || {});
1187
1190
 
1191
+ // src/typings/workflow-operation.ts
1192
+ var WorkflowOperationBaseService = Symbol("WorkflowOperationBaseService");
1193
+
1188
1194
  // src/typings/index.ts
1189
1195
  var URLParams = Symbol("");
1190
1196
 
@@ -1235,7 +1241,7 @@ var WorkflowDocumentOptionsDefault = {
1235
1241
  const nodeMeta = node.getNodeMeta();
1236
1242
  const subCanvas = nodeMeta.subCanvas?.(node);
1237
1243
  if (subCanvas?.isCanvas === false) {
1238
- const canvasNodeTransform = subCanvas.canvasNode.getData(import_document3.FlowNodeTransformData);
1244
+ const canvasNodeTransform = subCanvas.canvasNode.getData(import_document4.FlowNodeTransformData);
1239
1245
  const { x, y } = canvasNodeTransform.transform.position;
1240
1246
  metaData.canvasPosition = { x, y };
1241
1247
  }
@@ -1533,12 +1539,12 @@ var WorkflowLinesManager = class {
1533
1539
  * @param pos - 鼠标位置
1534
1540
  */
1535
1541
  getNodeFromMousePos(pos) {
1536
- const allNodes = this.document.getAllNodes();
1542
+ const allNodes = this.document.getAllNodes().sort((a, b) => this.getNodeIndex(a) - this.getNodeIndex(b));
1537
1543
  const containNodes = [];
1538
1544
  const { selection } = this.selectService;
1539
1545
  const zoom = this.entityManager.getEntity(import_core12.PlaygroundConfigEntity)?.config?.zoom || 1;
1540
1546
  allNodes.forEach((node) => {
1541
- const { bounds } = node.getData(import_document4.FlowNodeTransformData);
1547
+ const { bounds } = node.getData(import_document5.FlowNodeTransformData);
1542
1548
  if (bounds.clone().pad(4 / zoom).contains(pos.x, pos.y)) {
1543
1549
  containNodes.push(node);
1544
1550
  }
@@ -1560,6 +1566,10 @@ var WorkflowLinesManager = class {
1560
1566
  registerData(line) {
1561
1567
  line.addData(WorkflowLineRenderData);
1562
1568
  }
1569
+ getNodeIndex(node) {
1570
+ const nodeRenderData = node.getData(import_document5.FlowNodeRenderData);
1571
+ return nodeRenderData.stackIndex;
1572
+ }
1563
1573
  };
1564
1574
  __decorateClass([
1565
1575
  (0, import_inversify3.inject)(WorkflowHoverService)
@@ -1582,12 +1592,12 @@ var import_nanoid2 = require("nanoid");
1582
1592
  var import_inversify5 = require("inversify");
1583
1593
  var import_utils14 = require("@flowgram.ai/utils");
1584
1594
  var import_form_core3 = require("@flowgram.ai/form-core");
1585
- var import_document6 = require("@flowgram.ai/document");
1595
+ var import_document7 = require("@flowgram.ai/document");
1586
1596
  var import_core14 = require("@flowgram.ai/core");
1587
1597
 
1588
1598
  // src/layout/free-layout.ts
1589
1599
  var import_inversify4 = require("inversify");
1590
- var import_document5 = require("@flowgram.ai/document");
1600
+ var import_document6 = require("@flowgram.ai/document");
1591
1601
  var import_core13 = require("@flowgram.ai/core");
1592
1602
  var import_utils13 = require("@flowgram.ai/utils");
1593
1603
  var FREE_LAYOUT_KEY = "free-layout";
@@ -1602,12 +1612,12 @@ var FreeLayout = class {
1602
1612
  * 更新布局
1603
1613
  */
1604
1614
  update() {
1605
- if (this.document.root.getData(import_document5.FlowNodeTransformData)?.localDirty) {
1615
+ if (this.document.root.getData(import_document6.FlowNodeTransformData)?.localDirty) {
1606
1616
  this.document.root.clearMemoGlobal();
1607
1617
  }
1608
1618
  }
1609
1619
  syncTransform(node) {
1610
- const transform = node.getData(import_document5.FlowNodeTransformData);
1620
+ const transform = node.getData(import_document6.FlowNodeTransformData);
1611
1621
  if (!transform.localDirty) {
1612
1622
  return;
1613
1623
  }
@@ -1621,7 +1631,7 @@ var FreeLayout = class {
1621
1631
  }
1622
1632
  node.parent.clearMemoGlobal();
1623
1633
  node.parent.clearMemoLocal();
1624
- const parentTransform = node.parent.getData(import_document5.FlowNodeTransformData);
1634
+ const parentTransform = node.parent.getData(import_document6.FlowNodeTransformData);
1625
1635
  parentTransform.transform.fireChange();
1626
1636
  }
1627
1637
  /**
@@ -1630,7 +1640,7 @@ var FreeLayout = class {
1630
1640
  */
1631
1641
  getPadding(node) {
1632
1642
  const { padding } = node.getNodeMeta();
1633
- const transform = node.getData(import_document5.FlowNodeTransformData);
1643
+ const transform = node.getData(import_document6.FlowNodeTransformData);
1634
1644
  if (padding) {
1635
1645
  return typeof padding === "function" ? padding(transform) : padding;
1636
1646
  }
@@ -1674,7 +1684,7 @@ __decorateClass([
1674
1684
  (0, import_inversify4.inject)(import_core13.PlaygroundConfigEntity)
1675
1685
  ], FreeLayout.prototype, "playgroundConfig", 2);
1676
1686
  __decorateClass([
1677
- (0, import_inversify4.inject)(import_document5.FlowDocumentProvider)
1687
+ (0, import_inversify4.inject)(import_document6.FlowDocumentProvider)
1678
1688
  ], FreeLayout.prototype, "documentProvider", 2);
1679
1689
  FreeLayout = __decorateClass([
1680
1690
  (0, import_inversify4.injectable)()
@@ -1683,7 +1693,7 @@ FreeLayout = __decorateClass([
1683
1693
  // src/workflow-document.ts
1684
1694
  var nanoid2 = (0, import_nanoid2.customAlphabet)("1234567890", 5);
1685
1695
  var WorkflowDocumentProvider = Symbol("WorkflowDocumentProvider");
1686
- var WorkflowDocument = class extends import_document6.FlowDocument {
1696
+ var WorkflowDocument = class extends import_document7.FlowDocument {
1687
1697
  constructor() {
1688
1698
  super(...arguments);
1689
1699
  this._onContentChangeEmitter = new import_utils14.Emitter();
@@ -1776,7 +1786,7 @@ var WorkflowDocument = class extends import_document6.FlowDocument {
1776
1786
  const { formMeta } = registry;
1777
1787
  const meta = node.getNodeMeta();
1778
1788
  const formData = getFlowNodeFormData(node);
1779
- const transform = node.getData(import_document6.FlowNodeTransformData);
1789
+ const transform = node.getData(import_document7.FlowNodeTransformData);
1780
1790
  const freeLayout = this.layout;
1781
1791
  transform.onDataChange(() => {
1782
1792
  freeLayout.syncTransform(node);
@@ -1824,10 +1834,10 @@ var WorkflowDocument = class extends import_document6.FlowDocument {
1824
1834
  );
1825
1835
  node.toDispose.push(
1826
1836
  import_utils14.Disposable.create(() => {
1827
- if (!node.parent || node.parent.flowNodeType === import_document6.FlowNodeBaseType.ROOT) {
1837
+ if (!node.parent || node.parent.flowNodeType === import_document7.FlowNodeBaseType.ROOT) {
1828
1838
  return;
1829
1839
  }
1830
- const parentTransform = node.parent.getData(import_document6.FlowNodeTransformData);
1840
+ const parentTransform = node.parent.getData(import_document7.FlowNodeTransformData);
1831
1841
  setTimeout(() => {
1832
1842
  parentTransform.fireChange();
1833
1843
  }, 0);
@@ -1908,10 +1918,10 @@ var WorkflowDocument = class extends import_document6.FlowDocument {
1908
1918
  );
1909
1919
  }
1910
1920
  getAllNodes() {
1911
- return this.entityManager.getEntities(WorkflowNodeEntity).filter((n) => n.id !== import_document6.FlowNodeBaseType.ROOT);
1921
+ return this.entityManager.getEntities(WorkflowNodeEntity).filter((n) => n.id !== import_document7.FlowNodeBaseType.ROOT);
1912
1922
  }
1913
1923
  getAllPorts() {
1914
- return this.entityManager.getEntities(WorkflowPortEntity).filter((p) => p.node.id !== import_document6.FlowNodeBaseType.ROOT);
1924
+ return this.entityManager.getEntities(WorkflowPortEntity).filter((p) => p.node.id !== import_document7.FlowNodeBaseType.ROOT);
1915
1925
  }
1916
1926
  /**
1917
1927
  * 获取画布中的非游离节点
@@ -1928,8 +1938,8 @@ var WorkflowDocument = class extends import_document6.FlowDocument {
1928
1938
  }));
1929
1939
  const startNodeId = allNode.find((node) => node.isStart).id;
1930
1940
  const endNodeId = allNode.find((node) => node.isNodeEnd).id;
1931
- const nodeInSubCanvas = allNode.filter((node) => node.parent?.flowNodeType === import_document6.FlowNodeBaseType.SUB_CANVAS).map((node) => node.id);
1932
- const associatedCache = /* @__PURE__ */ new Set([endNodeId, ...nodeInSubCanvas]);
1941
+ const nodeInContainer = allNode.filter((node) => node.parent?.getNodeMeta().isContainer).map((node) => node.id);
1942
+ const associatedCache = /* @__PURE__ */ new Set([endNodeId, ...nodeInContainer]);
1933
1943
  const bfs = (nodeId) => {
1934
1944
  if (associatedCache.has(nodeId)) {
1935
1945
  return;
@@ -2099,8 +2109,8 @@ var WorkflowDocument = class extends import_document6.FlowDocument {
2099
2109
  const flattenEdgeJSONs = [...rootEdges];
2100
2110
  const rootBlockIDs = rootNodes.map((node) => node.id);
2101
2111
  const rootEdgeIDs = rootEdges.map((edge) => this.getEdgeID(edge));
2102
- nodeBlocks.set(import_document6.FlowNodeBaseType.ROOT, rootBlockIDs);
2103
- nodeEdges.set(import_document6.FlowNodeBaseType.ROOT, rootEdgeIDs);
2112
+ nodeBlocks.set(import_document7.FlowNodeBaseType.ROOT, rootBlockIDs);
2113
+ nodeEdges.set(import_document7.FlowNodeBaseType.ROOT, rootEdgeIDs);
2104
2114
  rootNodes.forEach((nodeJSON) => {
2105
2115
  const { blocks, edges } = nodeJSON;
2106
2116
  if (blocks) {
@@ -2143,8 +2153,8 @@ var WorkflowDocument = class extends import_document6.FlowDocument {
2143
2153
  };
2144
2154
  const nodeMap = /* @__PURE__ */ new Map();
2145
2155
  const edgeMap = /* @__PURE__ */ new Map();
2146
- const rootBlockSet = new Set(nodeBlocks.get(import_document6.FlowNodeBaseType.ROOT) ?? []);
2147
- const rootEdgeSet = new Set(nodeEdges.get(import_document6.FlowNodeBaseType.ROOT) ?? []);
2156
+ const rootBlockSet = new Set(nodeBlocks.get(import_document7.FlowNodeBaseType.ROOT) ?? []);
2157
+ const rootEdgeSet = new Set(nodeEdges.get(import_document7.FlowNodeBaseType.ROOT) ?? []);
2148
2158
  flattenJSON.nodes.forEach((nodeJSON) => {
2149
2159
  nodeMap.set(nodeJSON.id, nodeJSON);
2150
2160
  });
@@ -2204,7 +2214,7 @@ var WorkflowDocument = class extends import_document6.FlowDocument {
2204
2214
  }
2205
2215
  toLineJSON(line) {
2206
2216
  const lineJSON = line.toJSON();
2207
- if (!line.to || !line.info.to || !line.toPort) {
2217
+ if (!line.from || !line.info.from || !line.fromPort || !line.to || !line.info.to || !line.toPort) {
2208
2218
  return;
2209
2219
  }
2210
2220
  const fromSubCanvas = this.getNodeSubCanvas(line.from);
@@ -2322,18 +2332,19 @@ var WorkflowDragService = class {
2322
2332
  }
2323
2333
  /**
2324
2334
  * 拖拽选中节点
2325
- * @param event
2335
+ * @param triggerEvent
2326
2336
  */
2327
- startDragSelectedNodes(event) {
2337
+ startDragSelectedNodes(triggerEvent) {
2328
2338
  let { selectedNodes } = this.selectService;
2329
- if (selectedNodes.length === 0 || this.playgroundConfig.readonly || this.playgroundConfig.disabled) {
2339
+ if (selectedNodes.length === 0 || this.playgroundConfig.readonly || this.playgroundConfig.disabled || this.isDragging) {
2330
2340
  return Promise.resolve(false);
2331
2341
  }
2342
+ this.isDragging = true;
2332
2343
  const sameParent = this.childrenOfContainer(selectedNodes);
2333
- if (sameParent && sameParent.flowNodeType !== import_document8.FlowNodeBaseType.ROOT) {
2344
+ if (sameParent && sameParent.flowNodeType !== import_document9.FlowNodeBaseType.ROOT) {
2334
2345
  selectedNodes = [sameParent];
2335
2346
  }
2336
- const { altKey } = event;
2347
+ const { altKey } = triggerEvent;
2337
2348
  let startPosition = this.getNodesPosition(selectedNodes);
2338
2349
  let startPositions = selectedNodes.map((node) => {
2339
2350
  const transform = node.getData(import_core15.TransformData);
@@ -2342,11 +2353,19 @@ var WorkflowDragService = class {
2342
2353
  let dragSuccess = false;
2343
2354
  const startTime = Date.now();
2344
2355
  const dragger = new import_core15.PlaygroundDrag({
2345
- onDragStart: () => {
2346
- this.isDragging = true;
2356
+ onDragStart: (dragEvent) => {
2357
+ this._nodesDragEmitter.fire({
2358
+ type: "onDragStart",
2359
+ nodes: selectedNodes,
2360
+ startPositions,
2361
+ altKey,
2362
+ dragEvent,
2363
+ triggerEvent,
2364
+ dragger
2365
+ });
2347
2366
  },
2348
- onDrag: (e) => {
2349
- if (!dragSuccess && checkDragSuccess(Date.now() - startTime, e)) {
2367
+ onDrag: (dragEvent) => {
2368
+ if (!dragSuccess && checkDragSuccess(Date.now() - startTime, dragEvent)) {
2350
2369
  dragSuccess = true;
2351
2370
  if (altKey) {
2352
2371
  const tryCopyNodes = selectedNodes;
@@ -2369,10 +2388,11 @@ var WorkflowDragService = class {
2369
2388
  }
2370
2389
  }
2371
2390
  const offset = this.getDragPosOffset({
2372
- event: e,
2391
+ event: dragEvent,
2373
2392
  selectedNodes,
2374
2393
  startPosition
2375
2394
  });
2395
+ const positions = [];
2376
2396
  selectedNodes.forEach((node, index) => {
2377
2397
  const transform = node.getData(import_core15.TransformData);
2378
2398
  const nodeStartPosition = startPositions[index];
@@ -2382,26 +2402,40 @@ var WorkflowDragService = class {
2382
2402
  };
2383
2403
  if (node.collapsedChildren?.length > 0) {
2384
2404
  node.collapsedChildren.forEach((childNode) => {
2385
- const childNodeTransformData = childNode.getData(import_document7.FlowNodeTransformData);
2405
+ const childNodeTransformData = childNode.getData(import_document8.FlowNodeTransformData);
2386
2406
  childNodeTransformData.fireChange();
2387
2407
  });
2388
2408
  }
2389
2409
  transform.update({
2390
2410
  position: newPosition
2391
2411
  });
2412
+ positions.push(newPosition);
2413
+ });
2414
+ this._nodesDragEmitter.fire({
2415
+ type: "onDragging",
2416
+ nodes: selectedNodes,
2417
+ startPositions,
2418
+ positions,
2419
+ altKey,
2420
+ dragEvent,
2421
+ triggerEvent,
2422
+ dragger
2392
2423
  });
2393
2424
  },
2394
- onDragEnd: () => {
2425
+ onDragEnd: (dragEvent) => {
2395
2426
  this.isDragging = false;
2396
2427
  this._nodesDragEmitter.fire({
2397
2428
  type: "onDragEnd",
2398
2429
  nodes: selectedNodes,
2399
2430
  startPositions,
2400
- altKey
2431
+ altKey,
2432
+ dragEvent,
2433
+ triggerEvent,
2434
+ dragger
2401
2435
  });
2402
2436
  }
2403
2437
  });
2404
- return dragger.start(event.clientX, event.clientY, this.playgroundConfig).then(() => dragSuccess);
2438
+ return dragger.start(triggerEvent.clientX, triggerEvent.clientY, this.playgroundConfig)?.then(() => dragSuccess);
2405
2439
  }
2406
2440
  /**
2407
2441
  * 通过拖入卡片添加
@@ -2473,6 +2507,13 @@ var WorkflowDragService = class {
2473
2507
  },
2474
2508
  onDragEnd: async (e) => {
2475
2509
  const dropNode = this._dropNode;
2510
+ const { allowDrop } = this.canDropToNode({
2511
+ dragNodeType: type,
2512
+ dropNode
2513
+ });
2514
+ if (!allowDrop) {
2515
+ return this.clearDrop();
2516
+ }
2476
2517
  const dragNode = await this.dropCard(type, e, data, dropNode);
2477
2518
  this.clearDrop();
2478
2519
  if (dragNode) {
@@ -2499,7 +2540,7 @@ var WorkflowDragService = class {
2499
2540
  if (!mousePos) {
2500
2541
  return { x: 0, y: 0 };
2501
2542
  }
2502
- if (!subNodeType || !containerNode || containerNode.flowNodeType === import_document8.FlowNodeBaseType.ROOT) {
2543
+ if (!subNodeType || !containerNode || containerNode.flowNodeType === import_document9.FlowNodeBaseType.ROOT) {
2503
2544
  return mousePos;
2504
2545
  }
2505
2546
  const isParentEmpty = !containerNode.children || containerNode.children.length === 0;
@@ -2526,6 +2567,22 @@ var WorkflowDragService = class {
2526
2567
  dispose: () => this.posAdjusters.delete(adjuster)
2527
2568
  };
2528
2569
  }
2570
+ /**
2571
+ * 判断是否可以放置节点
2572
+ */
2573
+ canDropToNode(params) {
2574
+ const { dragNodeType, dropNode } = params;
2575
+ if (!dragNodeType) {
2576
+ return {
2577
+ allowDrop: false,
2578
+ message: "Please select a node to drop"
2579
+ };
2580
+ }
2581
+ return {
2582
+ allowDrop: true,
2583
+ dropNode
2584
+ };
2585
+ }
2529
2586
  /**
2530
2587
  * 获取拖拽偏移
2531
2588
  */
@@ -2556,23 +2613,24 @@ var WorkflowDragService = class {
2556
2613
  return offset;
2557
2614
  }
2558
2615
  updateDroppableTransforms() {
2559
- this._droppableTransforms = this.document.getRenderDatas(import_document7.FlowNodeTransformData, false).filter((transform) => {
2616
+ this._droppableTransforms = this.document.getRenderDatas(import_document8.FlowNodeTransformData, false).filter((transform) => {
2560
2617
  const { entity } = transform;
2561
2618
  if (entity.originParent) {
2562
2619
  return this.nodeSelectable(entity) && this.nodeSelectable(entity.originParent);
2563
2620
  }
2564
2621
  return this.nodeSelectable(entity);
2565
- }).filter((transform) => {
2566
- const { entity } = transform;
2567
- return entity.flowNodeType === import_document8.FlowNodeBaseType.SUB_CANVAS;
2568
- });
2622
+ }).filter((transform) => this.isContainer(transform.entity));
2623
+ }
2624
+ /** 是否容器节点 */
2625
+ isContainer(node) {
2626
+ return node?.getNodeMeta().isContainer ?? false;
2569
2627
  }
2570
2628
  /**
2571
2629
  * 获取节点整体位置
2572
2630
  */
2573
2631
  getNodesPosition(nodes) {
2574
2632
  const selectedBounds = import_utils16.Rectangle.enlarge(
2575
- nodes.map((n) => n.getData(import_document7.FlowNodeTransformData).bounds)
2633
+ nodes.map((n) => n.getData(import_document8.FlowNodeTransformData).bounds)
2576
2634
  );
2577
2635
  const position = {
2578
2636
  x: selectedBounds.x,
@@ -2622,7 +2680,7 @@ var WorkflowDragService = class {
2622
2680
  return {
2623
2681
  hasError: false
2624
2682
  };
2625
- } else if (toNode.flowNodeType === import_document8.FlowNodeBaseType.SUB_CANVAS) {
2683
+ } else if (this.isContainer(toNode)) {
2626
2684
  return {
2627
2685
  hasError: false
2628
2686
  };
@@ -2657,6 +2715,7 @@ var WorkflowDragService = class {
2657
2715
  if (originLine?.disabled || isFromInActivePort || this.playgroundConfig.readonly || this.playgroundConfig.disabled) {
2658
2716
  return { dragSuccess: false, newLine: void 0 };
2659
2717
  }
2718
+ this.selectService.clear();
2660
2719
  const config = this.playgroundConfig;
2661
2720
  const deferred = new import_utils16.PromiseDeferred();
2662
2721
  const preCursor = config.cursor;
@@ -2702,7 +2761,7 @@ var WorkflowDragService = class {
2702
2761
  type: "onDrag"
2703
2762
  });
2704
2763
  this.setLineColor(line, this.linesManager.lineColor.drawing);
2705
- if (toNode && toNode.flowNodeType !== import_document8.FlowNodeBaseType.SUB_CANVAS) {
2764
+ if (toNode && !this.isContainer(toNode)) {
2706
2765
  const portsData = toNode.getData(WorkflowNodePortsData);
2707
2766
  toPort = portsData.inputPorts[0];
2708
2767
  const { hasError } = this.handleDragOnNode(toNode, fromPort, line, toPort, originLine);
@@ -2831,7 +2890,7 @@ __decorateClass([
2831
2890
  (0, import_inversify6.inject)(WorkflowSelectService)
2832
2891
  ], WorkflowDragService.prototype, "selectService", 2);
2833
2892
  __decorateClass([
2834
- (0, import_inversify6.inject)(import_document7.FlowOperationBaseService)
2893
+ (0, import_inversify6.inject)(import_document8.FlowOperationBaseService)
2835
2894
  ], WorkflowDragService.prototype, "operationService", 2);
2836
2895
  __decorateClass([
2837
2896
  (0, import_inversify6.inject)(WorkflowDocumentOptions)
@@ -2850,13 +2909,13 @@ var import_core18 = require("@flowgram.ai/core");
2850
2909
  var import_utils17 = require("@flowgram.ai/utils");
2851
2910
 
2852
2911
  // src/utils/layout-to-positions.ts
2853
- var import_document9 = require("@flowgram.ai/document");
2912
+ var import_document10 = require("@flowgram.ai/document");
2854
2913
  var import_core16 = require("@flowgram.ai/core");
2855
2914
  var layoutToPositions = async (nodes, nodePositionMap) => {
2856
2915
  const newNodePositionMap = {};
2857
2916
  nodes.forEach((node) => {
2858
2917
  const transform = node.getData(import_core16.TransformData);
2859
- const nodeTransform = node.getData(import_document9.FlowNodeTransformData);
2918
+ const nodeTransform = node.getData(import_document10.FlowNodeTransformData);
2860
2919
  newNodePositionMap[node.id] = {
2861
2920
  x: transform.position.x,
2862
2921
  y: transform.position.y + nodeTransform.bounds.height / 2
@@ -2874,7 +2933,7 @@ var layoutToPositions = async (nodes, nodePositionMap) => {
2874
2933
  const deltaY = (nodePositionMap[node.id].y - transform.bounds.height / 2 - transform.position.y) * v.d / 100;
2875
2934
  if (node.collapsedChildren?.length > 0) {
2876
2935
  node.collapsedChildren.forEach((childNode) => {
2877
- const childNodeTransformData = childNode.getData(import_document9.FlowNodeTransformData);
2936
+ const childNodeTransformData = childNode.getData(import_document10.FlowNodeTransformData);
2878
2937
  childNodeTransformData.fireChange();
2879
2938
  });
2880
2939
  }
@@ -2953,12 +3012,47 @@ WorkflowResetLayoutService = __decorateClass([
2953
3012
  (0, import_inversify7.injectable)()
2954
3013
  ], WorkflowResetLayoutService);
2955
3014
 
3015
+ // src/service/workflow-operation-base-service.ts
3016
+ var import_inversify8 = require("inversify");
3017
+ var import_utils19 = require("@flowgram.ai/utils");
3018
+ var import_document11 = require("@flowgram.ai/document");
3019
+ var import_core19 = require("@flowgram.ai/core");
3020
+ var WorkflowOperationBaseServiceImpl = class extends import_document11.FlowOperationBaseServiceImpl {
3021
+ constructor() {
3022
+ super(...arguments);
3023
+ this.onNodePostionUpdateEmitter = new import_utils19.Emitter();
3024
+ this.onNodePostionUpdate = this.onNodePostionUpdateEmitter.event;
3025
+ }
3026
+ updateNodePosition(nodeOrId, position) {
3027
+ const node = this.toNodeEntity(nodeOrId);
3028
+ if (!node) {
3029
+ return;
3030
+ }
3031
+ const transformData = node.getData(import_core19.TransformData);
3032
+ const oldPosition = {
3033
+ x: transformData.position.x,
3034
+ y: transformData.position.y
3035
+ };
3036
+ transformData.update({
3037
+ position
3038
+ });
3039
+ this.onNodePostionUpdateEmitter.fire({
3040
+ node,
3041
+ oldPosition,
3042
+ newPosition: position
3043
+ });
3044
+ }
3045
+ };
3046
+ __decorateClass([
3047
+ (0, import_inversify8.inject)(WorkflowDocument)
3048
+ ], WorkflowOperationBaseServiceImpl.prototype, "document", 2);
3049
+
2956
3050
  // src/hooks/use-playground-readonly-state.ts
2957
3051
  var import_react = require("react");
2958
- var import_core19 = require("@flowgram.ai/core");
3052
+ var import_core20 = require("@flowgram.ai/core");
2959
3053
  function usePlaygroundReadonlyState(listenChange) {
2960
- const playground = (0, import_core19.usePlayground)();
2961
- const refresh = (0, import_core19.useRefresh)();
3054
+ const playground = (0, import_core20.usePlayground)();
3055
+ const refresh = (0, import_core20.useRefresh)();
2962
3056
  (0, import_react.useEffect)(() => {
2963
3057
  let dispose = void 0;
2964
3058
  if (listenChange) {
@@ -2974,12 +3068,12 @@ function checkTargetDraggable(el) {
2974
3068
  return el && el.tagName !== "INPUT" && el.tagName !== "TEXTAREA" && !el.closest(".flow-canvas-not-draggable");
2975
3069
  }
2976
3070
  function useNodeRender(nodeFromProps) {
2977
- const node = nodeFromProps || (0, import_react2.useContext)(import_core20.PlaygroundEntityContext);
2978
- const renderData = node.getData(import_document10.FlowNodeRenderData);
3071
+ const node = nodeFromProps || (0, import_react2.useContext)(import_core21.PlaygroundEntityContext);
3072
+ const renderData = node.getData(import_document12.FlowNodeRenderData);
2979
3073
  const portsData = node.getData(WorkflowNodePortsData);
2980
3074
  const readonly = usePlaygroundReadonlyState();
2981
- const dragService = (0, import_core20.useService)(WorkflowDragService);
2982
- const selectionService = (0, import_core20.useService)(WorkflowSelectService);
3075
+ const dragService = (0, import_core21.useService)(WorkflowDragService);
3076
+ const selectionService = (0, import_core21.useService)(WorkflowSelectService);
2983
3077
  const isDragging = (0, import_react2.useRef)(false);
2984
3078
  const nodeRef = (0, import_react2.useRef)(null);
2985
3079
  const [linkingNodeId, setLinkingNodeId] = (0, import_react2.useState)("");
@@ -3005,7 +3099,7 @@ function useNodeRender(nodeFromProps) {
3005
3099
  return;
3006
3100
  }
3007
3101
  isDragging.current = true;
3008
- dragService.startDragSelectedNodes(e).finally(
3102
+ dragService.startDragSelectedNodes(e)?.finally(
3009
3103
  () => setTimeout(() => {
3010
3104
  isDragging.current = false;
3011
3105
  })
@@ -3018,7 +3112,7 @@ function useNodeRender(nodeFromProps) {
3018
3112
  if (isDragging.current) {
3019
3113
  return;
3020
3114
  }
3021
- if (e.metaKey || e.shiftKey || e.ctrlKey) {
3115
+ if (e.shiftKey) {
3022
3116
  selectionService.toggleSelect(node);
3023
3117
  } else {
3024
3118
  selectionService.selectNode(node);
@@ -3030,7 +3124,7 @@ function useNodeRender(nodeFromProps) {
3030
3124
  [node]
3031
3125
  );
3032
3126
  const deleteNode = (0, import_react2.useCallback)(() => node.dispose(), [node]);
3033
- (0, import_core20.useListenEvents)(portsData.onDataChange);
3127
+ (0, import_core21.useListenEvents)(portsData.onDataChange);
3034
3128
  const isFirefox = navigator?.userAgent?.includes?.("Firefox");
3035
3129
  const onFocus = (0, import_react2.useCallback)(() => {
3036
3130
  if (isFirefox) {
@@ -3087,24 +3181,24 @@ function useNodeRender(nodeFromProps) {
3087
3181
  }
3088
3182
 
3089
3183
  // src/hooks/use-current-dom-node.ts
3090
- var import_document11 = require("@flowgram.ai/document");
3091
- var import_core21 = require("@flowgram.ai/core");
3184
+ var import_document13 = require("@flowgram.ai/document");
3185
+ var import_core22 = require("@flowgram.ai/core");
3092
3186
  function useCurrentDomNode() {
3093
- const entity = (0, import_core21.useEntityFromContext)();
3094
- const renderData = entity.getData(import_document11.FlowNodeRenderData);
3187
+ const entity = (0, import_core22.useEntityFromContext)();
3188
+ const renderData = entity.getData(import_document13.FlowNodeRenderData);
3095
3189
  return renderData.node;
3096
3190
  }
3097
3191
 
3098
3192
  // src/hooks/use-current-entity.ts
3099
- var import_core22 = require("@flowgram.ai/core");
3193
+ var import_core23 = require("@flowgram.ai/core");
3100
3194
  function useCurrentEntity() {
3101
- return (0, import_core22.useEntityFromContext)();
3195
+ return (0, import_core23.useEntityFromContext)();
3102
3196
  }
3103
3197
 
3104
3198
  // src/hooks/use-workflow-document.ts
3105
- var import_core23 = require("@flowgram.ai/core");
3199
+ var import_core24 = require("@flowgram.ai/core");
3106
3200
  function useWorkflowDocument() {
3107
- return (0, import_core23.useService)(WorkflowDocument);
3201
+ return (0, import_core24.useService)(WorkflowDocument);
3108
3202
  }
3109
3203
 
3110
3204
  // src/constants.ts
@@ -3120,18 +3214,18 @@ var InteractiveType = /* @__PURE__ */ ((InteractiveType2) => {
3120
3214
  })(InteractiveType || {});
3121
3215
 
3122
3216
  // src/workflow-document-container-module.ts
3123
- var import_inversify9 = require("inversify");
3124
- var import_document13 = require("@flowgram.ai/document");
3125
- var import_utils19 = require("@flowgram.ai/utils");
3217
+ var import_inversify10 = require("inversify");
3218
+ var import_utils20 = require("@flowgram.ai/utils");
3219
+ var import_document15 = require("@flowgram.ai/document");
3126
3220
 
3127
3221
  // src/workflow-document-contribution.ts
3128
- var import_inversify8 = require("inversify");
3129
- var import_document12 = require("@flowgram.ai/document");
3222
+ var import_inversify9 = require("inversify");
3223
+ var import_document14 = require("@flowgram.ai/document");
3130
3224
  var WorkflowDocumentContribution = class {
3131
3225
  registerDocument(document2) {
3132
3226
  document2.registerNodeDatas(
3133
- import_document12.FlowNodeTransformData,
3134
- import_document12.FlowNodeRenderData,
3227
+ import_document14.FlowNodeTransformData,
3228
+ import_document14.FlowNodeRenderData,
3135
3229
  WorkflowNodePortsData,
3136
3230
  WorkflowNodeLinesData
3137
3231
  );
@@ -3139,10 +3233,10 @@ var WorkflowDocumentContribution = class {
3139
3233
  }
3140
3234
  };
3141
3235
  __decorateClass([
3142
- (0, import_inversify8.inject)(FreeLayout)
3236
+ (0, import_inversify9.inject)(FreeLayout)
3143
3237
  ], WorkflowDocumentContribution.prototype, "freeLayout", 2);
3144
3238
  WorkflowDocumentContribution = __decorateClass([
3145
- (0, import_inversify8.injectable)()
3239
+ (0, import_inversify9.injectable)()
3146
3240
  ], WorkflowDocumentContribution);
3147
3241
 
3148
3242
  // src/utils/get-url-params.ts
@@ -3155,7 +3249,7 @@ function getUrlParams() {
3155
3249
  }
3156
3250
 
3157
3251
  // src/workflow-document-container-module.ts
3158
- var WorkflowDocumentContainerModule = new import_inversify9.ContainerModule(
3252
+ var WorkflowDocumentContainerModule = new import_inversify10.ContainerModule(
3159
3253
  (bind, unbind, isBound, rebind) => {
3160
3254
  bind(WorkflowDocument).toSelf().inSingletonScope();
3161
3255
  bind(WorkflowLinesManager).toSelf().inSingletonScope();
@@ -3164,18 +3258,19 @@ var WorkflowDocumentContainerModule = new import_inversify9.ContainerModule(
3164
3258
  bind(WorkflowSelectService).toSelf().inSingletonScope();
3165
3259
  bind(WorkflowHoverService).toSelf().inSingletonScope();
3166
3260
  bind(WorkflowResetLayoutService).toSelf().inSingletonScope();
3261
+ bind(WorkflowOperationBaseService).to(WorkflowOperationBaseServiceImpl).inSingletonScope();
3167
3262
  bind(URLParams).toDynamicValue(() => getUrlParams()).inSingletonScope();
3168
- (0, import_utils19.bindContributions)(bind, WorkflowDocumentContribution, [import_document13.FlowDocumentContribution]);
3263
+ (0, import_utils20.bindContributions)(bind, WorkflowDocumentContribution, [import_document15.FlowDocumentContribution]);
3169
3264
  bind(WorkflowDocumentOptions).toConstantValue({
3170
3265
  ...WorkflowDocumentOptionsDefault
3171
3266
  });
3172
- rebind(import_document13.FlowDocument).toService(WorkflowDocument);
3267
+ rebind(import_document15.FlowDocument).toService(WorkflowDocument);
3173
3268
  bind(WorkflowDocumentProvider).toDynamicValue((ctx) => () => ctx.container.get(WorkflowDocument)).inSingletonScope();
3174
3269
  }
3175
3270
  );
3176
3271
 
3177
3272
  // src/utils/simple-line.ts
3178
- var import_utils20 = require("@flowgram.ai/utils");
3273
+ var import_utils21 = require("@flowgram.ai/utils");
3179
3274
  var LINE_PADDING = 12;
3180
3275
  var WorkflowSimpleLineContribution = class {
3181
3276
  constructor(entity) {
@@ -3189,11 +3284,11 @@ var WorkflowSimpleLineContribution = class {
3189
3284
  return Number.MAX_SAFE_INTEGER;
3190
3285
  }
3191
3286
  const [start, end] = this.data.points;
3192
- return import_utils20.Point.getDistance(pos, this.projectPointOnLine(pos, start, end));
3287
+ return import_utils21.Point.getDistance(pos, this.projectPointOnLine(pos, start, end));
3193
3288
  }
3194
3289
  get bounds() {
3195
3290
  if (!this.data) {
3196
- return new import_utils20.Rectangle();
3291
+ return new import_utils21.Rectangle();
3197
3292
  }
3198
3293
  return this.data.bbox;
3199
3294
  }
@@ -3218,7 +3313,7 @@ var WorkflowSimpleLineContribution = class {
3218
3313
  y: toPos.y + targetOffset.y
3219
3314
  }
3220
3315
  ];
3221
- const bbox = import_utils20.Rectangle.createRectangleWithTwoPoints(points[0], points[1]);
3316
+ const bbox = import_utils21.Rectangle.createRectangleWithTwoPoints(points[0], points[1]);
3222
3317
  const adjustedPoints = points.map((p) => ({
3223
3318
  x: p.x - bbox.x + LINE_PADDING,
3224
3319
  y: p.y - bbox.y + LINE_PADDING
@@ -3274,6 +3369,8 @@ WorkflowSimpleLineContribution.type = "WorkflowSimpleLineContribution";
3274
3369
  WorkflowNodeEntity,
3275
3370
  WorkflowNodeLinesData,
3276
3371
  WorkflowNodePortsData,
3372
+ WorkflowOperationBaseService,
3373
+ WorkflowOperationBaseServiceImpl,
3277
3374
  WorkflowPortEntity,
3278
3375
  WorkflowResetLayoutService,
3279
3376
  WorkflowSelectService,