@flowgram.ai/free-layout-core 0.1.0-alpha.4 → 0.1.0-alpha.6

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 +165 -62
  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 +211 -107
  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-BCAgoA18.d.mts} +95 -170
  40. package/dist/{workflow-line-entity-CEitdjhk.d.ts → workflow-line-entity-DIyrK9yz.d.ts} +95 -170
  41. package/package.json +9 -9
  42. package/dist/esm/chunk-DE4324TR.js.map +0 -1
@@ -4,4 +4,4 @@ var URLParams = Symbol("");
4
4
  export {
5
5
  URLParams
6
6
  };
7
- //# sourceMappingURL=chunk-DE4324TR.js.map
7
+ //# sourceMappingURL=chunk-IYUZVBAO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/typings/index.ts"],"sourcesContent":["export * from './workflow-json';\nexport * from './workflow-edge';\nexport * from './workflow-node';\nexport * from './workflow-registry';\nexport * from './workflow-line';\nexport * from './workflow-sub-canvas';\nexport * from './workflow-operation';\nexport * from './workflow-drag';\n\nexport const URLParams = Symbol('');\n\nexport interface URLParams {\n [key: string]: string;\n}\n"],"mappings":";AASO,IAAM,YAAY,OAAO,EAAE;","names":[]}
@@ -0,0 +1,7 @@
1
+ // src/typings/workflow-operation.ts
2
+ var WorkflowOperationBaseService = Symbol("WorkflowOperationBaseService");
3
+
4
+ export {
5
+ WorkflowOperationBaseService
6
+ };
7
+ //# sourceMappingURL=chunk-LJH3TSLZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/typings/workflow-operation.ts"],"sourcesContent":["import { IPoint, Event } from '@flowgram.ai/utils';\nimport {\n FlowNodeEntity,\n FlowNodeEntityOrId,\n FlowOperationBaseService,\n} from '@flowgram.ai/document';\n\nexport interface NodePostionUpdateEvent {\n node: FlowNodeEntity;\n oldPosition: IPoint;\n newPosition: IPoint;\n}\n\nexport interface WorkflowOperationBaseService extends FlowOperationBaseService {\n /**\n * 节点位置更新事件\n */\n readonly onNodePostionUpdate: Event<NodePostionUpdateEvent>;\n /**\n * 更新节点位置\n * @param nodeOrId\n * @param position\n * @returns\n */\n updateNodePosition(nodeOrId: FlowNodeEntityOrId, position: IPoint): void;\n}\n\nexport const WorkflowOperationBaseService = Symbol('WorkflowOperationBaseService');\n"],"mappings":";AA2BO,IAAM,+BAA+B,OAAO,8BAA8B;","names":[]}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=chunk-TQLT57GW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/dist/esm/index.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import {
2
2
  URLParams
3
- } from "./chunk-DE4324TR.js";
3
+ } from "./chunk-IYUZVBAO.js";
4
+ import "./chunk-KNYZRMIO.js";
5
+ import "./chunk-NU6G5HF4.js";
6
+ import "./chunk-TQLT57GW.js";
4
7
  import "./chunk-CGOMTQ3G.js";
5
8
  import {
6
9
  WorkflowContentChangeType
@@ -9,12 +12,13 @@ import {
9
12
  LineColors,
10
13
  LineType
11
14
  } from "./chunk-PT4ZVDZZ.js";
15
+ import "./chunk-DDJTYHXN.js";
16
+ import {
17
+ WorkflowOperationBaseService
18
+ } from "./chunk-LJH3TSLZ.js";
12
19
  import {
13
20
  __decorateClass
14
21
  } from "./chunk-EUXUH3YW.js";
15
- import "./chunk-DDJTYHXN.js";
16
- import "./chunk-KNYZRMIO.js";
17
- import "./chunk-NU6G5HF4.js";
18
22
 
19
23
  // src/workflow-commands.ts
20
24
  var WorkflowCommands = /* @__PURE__ */ ((WorkflowCommands2) => {
@@ -47,7 +51,7 @@ import {
47
51
  import { useCallback, useEffect as useEffect2, useRef, useState, useContext, useMemo } from "react";
48
52
  import { useObserve } from "@flowgram.ai/reactive";
49
53
  import { getNodeForm } from "@flowgram.ai/node";
50
- import { FlowNodeRenderData as FlowNodeRenderData2 } from "@flowgram.ai/document";
54
+ import { FlowNodeRenderData as FlowNodeRenderData3 } from "@flowgram.ai/document";
51
55
  import { PlaygroundEntityContext, useListenEvents, useService } from "@flowgram.ai/core";
52
56
 
53
57
  // src/service/workflow-select-service.ts
@@ -131,6 +135,7 @@ import { EntityData, SizeData } from "@flowgram.ai/core";
131
135
 
132
136
  // src/entities/workflow-port-entity.ts
133
137
  import { Rectangle as Rectangle3, Emitter } from "@flowgram.ai/utils";
138
+ import { FlowNodeTransformData } from "@flowgram.ai/document";
134
139
  import {
135
140
  Entity,
136
141
  PlaygroundConfigEntity,
@@ -182,7 +187,7 @@ var WorkflowPortEntity = class extends Entity {
182
187
  }
183
188
  get point() {
184
189
  const { targetElement } = this;
185
- const { bounds } = this.node.getData(TransformData3);
190
+ const { bounds } = this.node.getData(FlowNodeTransformData);
186
191
  if (targetElement) {
187
192
  const pos = domReactToBounds(targetElement.getBoundingClientRect()).center;
188
193
  return this.entityManager.getEntity(PlaygroundConfigEntity).getPosFromMouseEvent({
@@ -211,7 +216,7 @@ var WorkflowPortEntity = class extends Entity {
211
216
  */
212
217
  get relativePosition() {
213
218
  const { point } = this;
214
- const { bounds } = this.node.getData(TransformData3);
219
+ const { bounds } = this.node.getData(FlowNodeTransformData);
215
220
  return {
216
221
  x: point.x - bounds.x,
217
222
  y: point.y - bounds.y
@@ -242,10 +247,17 @@ var WorkflowPortEntity = class extends Entity {
242
247
  }
243
248
  /**
244
249
  * 当前点位上连接的线条
250
+ * @deprecated use `availableLines` instead
245
251
  */
246
252
  get lines() {
247
253
  return this.allLines.filter((line) => !line.isDrawing);
248
254
  }
255
+ /**
256
+ * 当前有效的线条,不包含正在画的线条和隐藏的线条(这个出现在线条重连会先把原来的线条隐藏)
257
+ */
258
+ get availableLines() {
259
+ return this.allLines.filter((line) => !line.isDrawing && !line.isHidden);
260
+ }
249
261
  /**
250
262
  * 当前点位上连接的线条(包含 isDrawing === true 的线条)
251
263
  */
@@ -1099,7 +1111,7 @@ import {
1099
1111
  delay as delay2
1100
1112
  } from "@flowgram.ai/utils";
1101
1113
  import {
1102
- FlowNodeTransformData as FlowNodeTransformData5,
1114
+ FlowNodeTransformData as FlowNodeTransformData6,
1103
1115
  FlowOperationBaseService
1104
1116
  } from "@flowgram.ai/document";
1105
1117
  import { FlowNodeBaseType as FlowNodeBaseType2 } from "@flowgram.ai/document";
@@ -1114,12 +1126,12 @@ import {
1114
1126
  import { last } from "lodash-es";
1115
1127
  import { inject as inject3, injectable as injectable3 } from "inversify";
1116
1128
  import { Disposable as Disposable2, DisposableCollection, Emitter as Emitter3 } from "@flowgram.ai/utils";
1117
- import { FlowNodeTransformData as FlowNodeTransformData2 } from "@flowgram.ai/document";
1129
+ import { FlowNodeRenderData as FlowNodeRenderData2, FlowNodeTransformData as FlowNodeTransformData3 } from "@flowgram.ai/document";
1118
1130
  import { EntityManager as EntityManager2, PlaygroundConfigEntity as PlaygroundConfigEntity2, TransformData as TransformData6 } from "@flowgram.ai/core";
1119
1131
 
1120
1132
  // src/workflow-document-option.ts
1121
1133
  import { FlowNodeErrorData } from "@flowgram.ai/form-core";
1122
- import { FlowNodeTransformData } from "@flowgram.ai/document";
1134
+ import { FlowNodeTransformData as FlowNodeTransformData2 } from "@flowgram.ai/document";
1123
1135
  import { TransformData as TransformData5 } from "@flowgram.ai/core";
1124
1136
 
1125
1137
  // src/utils/flow-node-form-data.ts
@@ -1170,7 +1182,7 @@ var WorkflowDocumentOptionsDefault = {
1170
1182
  const nodeMeta = node.getNodeMeta();
1171
1183
  const subCanvas = nodeMeta.subCanvas?.(node);
1172
1184
  if (subCanvas?.isCanvas === false) {
1173
- const canvasNodeTransform = subCanvas.canvasNode.getData(FlowNodeTransformData);
1185
+ const canvasNodeTransform = subCanvas.canvasNode.getData(FlowNodeTransformData2);
1174
1186
  const { x, y } = canvasNodeTransform.transform.position;
1175
1187
  metaData.canvasPosition = { x, y };
1176
1188
  }
@@ -1468,12 +1480,12 @@ var WorkflowLinesManager = class {
1468
1480
  * @param pos - 鼠标位置
1469
1481
  */
1470
1482
  getNodeFromMousePos(pos) {
1471
- const allNodes = this.document.getAllNodes();
1483
+ const allNodes = this.document.getAllNodes().sort((a, b) => this.getNodeIndex(a) - this.getNodeIndex(b));
1472
1484
  const containNodes = [];
1473
1485
  const { selection } = this.selectService;
1474
1486
  const zoom = this.entityManager.getEntity(PlaygroundConfigEntity2)?.config?.zoom || 1;
1475
1487
  allNodes.forEach((node) => {
1476
- const { bounds } = node.getData(FlowNodeTransformData2);
1488
+ const { bounds } = node.getData(FlowNodeTransformData3);
1477
1489
  if (bounds.clone().pad(4 / zoom).contains(pos.x, pos.y)) {
1478
1490
  containNodes.push(node);
1479
1491
  }
@@ -1495,6 +1507,10 @@ var WorkflowLinesManager = class {
1495
1507
  registerData(line) {
1496
1508
  line.addData(WorkflowLineRenderData);
1497
1509
  }
1510
+ getNodeIndex(node) {
1511
+ const nodeRenderData = node.getData(FlowNodeRenderData2);
1512
+ return nodeRenderData.stackIndex;
1513
+ }
1498
1514
  };
1499
1515
  __decorateClass([
1500
1516
  inject3(WorkflowHoverService)
@@ -1517,7 +1533,7 @@ import { customAlphabet } from "nanoid";
1517
1533
  import { inject as inject5, injectable as injectable5, optional, postConstruct } from "inversify";
1518
1534
  import { Disposable as Disposable3, Emitter as Emitter4 } from "@flowgram.ai/utils";
1519
1535
  import { NodeEngineContext } from "@flowgram.ai/form-core";
1520
- import { FlowDocument, FlowNodeBaseType, FlowNodeTransformData as FlowNodeTransformData4 } from "@flowgram.ai/document";
1536
+ import { FlowDocument, FlowNodeBaseType, FlowNodeTransformData as FlowNodeTransformData5 } from "@flowgram.ai/document";
1521
1537
  import {
1522
1538
  injectPlaygroundContext,
1523
1539
  PlaygroundConfigEntity as PlaygroundConfigEntity4,
@@ -1529,7 +1545,7 @@ import {
1529
1545
  import { inject as inject4, injectable as injectable4 } from "inversify";
1530
1546
  import {
1531
1547
  FlowDocumentProvider,
1532
- FlowNodeTransformData as FlowNodeTransformData3
1548
+ FlowNodeTransformData as FlowNodeTransformData4
1533
1549
  } from "@flowgram.ai/document";
1534
1550
  import { PlaygroundConfigEntity as PlaygroundConfigEntity3, TransformData as TransformData7 } from "@flowgram.ai/core";
1535
1551
  import {
@@ -1549,12 +1565,12 @@ var FreeLayout = class {
1549
1565
  * 更新布局
1550
1566
  */
1551
1567
  update() {
1552
- if (this.document.root.getData(FlowNodeTransformData3)?.localDirty) {
1568
+ if (this.document.root.getData(FlowNodeTransformData4)?.localDirty) {
1553
1569
  this.document.root.clearMemoGlobal();
1554
1570
  }
1555
1571
  }
1556
1572
  syncTransform(node) {
1557
- const transform = node.getData(FlowNodeTransformData3);
1573
+ const transform = node.getData(FlowNodeTransformData4);
1558
1574
  if (!transform.localDirty) {
1559
1575
  return;
1560
1576
  }
@@ -1568,7 +1584,7 @@ var FreeLayout = class {
1568
1584
  }
1569
1585
  node.parent.clearMemoGlobal();
1570
1586
  node.parent.clearMemoLocal();
1571
- const parentTransform = node.parent.getData(FlowNodeTransformData3);
1587
+ const parentTransform = node.parent.getData(FlowNodeTransformData4);
1572
1588
  parentTransform.transform.fireChange();
1573
1589
  }
1574
1590
  /**
@@ -1577,7 +1593,7 @@ var FreeLayout = class {
1577
1593
  */
1578
1594
  getPadding(node) {
1579
1595
  const { padding } = node.getNodeMeta();
1580
- const transform = node.getData(FlowNodeTransformData3);
1596
+ const transform = node.getData(FlowNodeTransformData4);
1581
1597
  if (padding) {
1582
1598
  return typeof padding === "function" ? padding(transform) : padding;
1583
1599
  }
@@ -1723,7 +1739,7 @@ var WorkflowDocument = class extends FlowDocument {
1723
1739
  const { formMeta } = registry;
1724
1740
  const meta = node.getNodeMeta();
1725
1741
  const formData = getFlowNodeFormData(node);
1726
- const transform = node.getData(FlowNodeTransformData4);
1742
+ const transform = node.getData(FlowNodeTransformData5);
1727
1743
  const freeLayout = this.layout;
1728
1744
  transform.onDataChange(() => {
1729
1745
  freeLayout.syncTransform(node);
@@ -1774,7 +1790,7 @@ var WorkflowDocument = class extends FlowDocument {
1774
1790
  if (!node.parent || node.parent.flowNodeType === FlowNodeBaseType.ROOT) {
1775
1791
  return;
1776
1792
  }
1777
- const parentTransform = node.parent.getData(FlowNodeTransformData4);
1793
+ const parentTransform = node.parent.getData(FlowNodeTransformData5);
1778
1794
  setTimeout(() => {
1779
1795
  parentTransform.fireChange();
1780
1796
  }, 0);
@@ -1875,8 +1891,8 @@ var WorkflowDocument = class extends FlowDocument {
1875
1891
  }));
1876
1892
  const startNodeId = allNode.find((node) => node.isStart).id;
1877
1893
  const endNodeId = allNode.find((node) => node.isNodeEnd).id;
1878
- const nodeInSubCanvas = allNode.filter((node) => node.parent?.flowNodeType === FlowNodeBaseType.SUB_CANVAS).map((node) => node.id);
1879
- const associatedCache = /* @__PURE__ */ new Set([endNodeId, ...nodeInSubCanvas]);
1894
+ const nodeInContainer = allNode.filter((node) => node.parent?.getNodeMeta().isContainer).map((node) => node.id);
1895
+ const associatedCache = /* @__PURE__ */ new Set([endNodeId, ...nodeInContainer]);
1880
1896
  const bfs = (nodeId) => {
1881
1897
  if (associatedCache.has(nodeId)) {
1882
1898
  return;
@@ -2151,7 +2167,7 @@ var WorkflowDocument = class extends FlowDocument {
2151
2167
  }
2152
2168
  toLineJSON(line) {
2153
2169
  const lineJSON = line.toJSON();
2154
- if (!line.to || !line.info.to || !line.toPort) {
2170
+ if (!line.from || !line.info.from || !line.fromPort || !line.to || !line.info.to || !line.toPort) {
2155
2171
  return;
2156
2172
  }
2157
2173
  const fromSubCanvas = this.getNodeSubCanvas(line.from);
@@ -2269,18 +2285,19 @@ var WorkflowDragService = class {
2269
2285
  }
2270
2286
  /**
2271
2287
  * 拖拽选中节点
2272
- * @param event
2288
+ * @param triggerEvent
2273
2289
  */
2274
- startDragSelectedNodes(event) {
2290
+ startDragSelectedNodes(triggerEvent) {
2275
2291
  let { selectedNodes } = this.selectService;
2276
- if (selectedNodes.length === 0 || this.playgroundConfig.readonly || this.playgroundConfig.disabled) {
2292
+ if (selectedNodes.length === 0 || this.playgroundConfig.readonly || this.playgroundConfig.disabled || this.isDragging) {
2277
2293
  return Promise.resolve(false);
2278
2294
  }
2295
+ this.isDragging = true;
2279
2296
  const sameParent = this.childrenOfContainer(selectedNodes);
2280
2297
  if (sameParent && sameParent.flowNodeType !== FlowNodeBaseType2.ROOT) {
2281
2298
  selectedNodes = [sameParent];
2282
2299
  }
2283
- const { altKey } = event;
2300
+ const { altKey } = triggerEvent;
2284
2301
  let startPosition = this.getNodesPosition(selectedNodes);
2285
2302
  let startPositions = selectedNodes.map((node) => {
2286
2303
  const transform = node.getData(TransformData9);
@@ -2289,11 +2306,19 @@ var WorkflowDragService = class {
2289
2306
  let dragSuccess = false;
2290
2307
  const startTime = Date.now();
2291
2308
  const dragger = new PlaygroundDrag({
2292
- onDragStart: () => {
2293
- this.isDragging = true;
2309
+ onDragStart: (dragEvent) => {
2310
+ this._nodesDragEmitter.fire({
2311
+ type: "onDragStart",
2312
+ nodes: selectedNodes,
2313
+ startPositions,
2314
+ altKey,
2315
+ dragEvent,
2316
+ triggerEvent,
2317
+ dragger
2318
+ });
2294
2319
  },
2295
- onDrag: (e) => {
2296
- if (!dragSuccess && checkDragSuccess(Date.now() - startTime, e)) {
2320
+ onDrag: (dragEvent) => {
2321
+ if (!dragSuccess && checkDragSuccess(Date.now() - startTime, dragEvent)) {
2297
2322
  dragSuccess = true;
2298
2323
  if (altKey) {
2299
2324
  const tryCopyNodes = selectedNodes;
@@ -2316,10 +2341,11 @@ var WorkflowDragService = class {
2316
2341
  }
2317
2342
  }
2318
2343
  const offset = this.getDragPosOffset({
2319
- event: e,
2344
+ event: dragEvent,
2320
2345
  selectedNodes,
2321
2346
  startPosition
2322
2347
  });
2348
+ const positions = [];
2323
2349
  selectedNodes.forEach((node, index) => {
2324
2350
  const transform = node.getData(TransformData9);
2325
2351
  const nodeStartPosition = startPositions[index];
@@ -2329,26 +2355,40 @@ var WorkflowDragService = class {
2329
2355
  };
2330
2356
  if (node.collapsedChildren?.length > 0) {
2331
2357
  node.collapsedChildren.forEach((childNode) => {
2332
- const childNodeTransformData = childNode.getData(FlowNodeTransformData5);
2358
+ const childNodeTransformData = childNode.getData(FlowNodeTransformData6);
2333
2359
  childNodeTransformData.fireChange();
2334
2360
  });
2335
2361
  }
2336
2362
  transform.update({
2337
2363
  position: newPosition
2338
2364
  });
2365
+ positions.push(newPosition);
2366
+ });
2367
+ this._nodesDragEmitter.fire({
2368
+ type: "onDragging",
2369
+ nodes: selectedNodes,
2370
+ startPositions,
2371
+ positions,
2372
+ altKey,
2373
+ dragEvent,
2374
+ triggerEvent,
2375
+ dragger
2339
2376
  });
2340
2377
  },
2341
- onDragEnd: () => {
2378
+ onDragEnd: (dragEvent) => {
2342
2379
  this.isDragging = false;
2343
2380
  this._nodesDragEmitter.fire({
2344
2381
  type: "onDragEnd",
2345
2382
  nodes: selectedNodes,
2346
2383
  startPositions,
2347
- altKey
2384
+ altKey,
2385
+ dragEvent,
2386
+ triggerEvent,
2387
+ dragger
2348
2388
  });
2349
2389
  }
2350
2390
  });
2351
- return dragger.start(event.clientX, event.clientY, this.playgroundConfig).then(() => dragSuccess);
2391
+ return dragger.start(triggerEvent.clientX, triggerEvent.clientY, this.playgroundConfig)?.then(() => dragSuccess);
2352
2392
  }
2353
2393
  /**
2354
2394
  * 通过拖入卡片添加
@@ -2420,7 +2460,11 @@ var WorkflowDragService = class {
2420
2460
  },
2421
2461
  onDragEnd: async (e) => {
2422
2462
  const dropNode = this._dropNode;
2423
- const dragNode = await this.dropCard(type, e, data, dropNode);
2463
+ const { allowDrop } = this.canDropToNode({
2464
+ dragNodeType: type,
2465
+ dropNode
2466
+ });
2467
+ const dragNode = allowDrop ? await this.dropCard(type, e, data, dropNode) : void 0;
2424
2468
  this.clearDrop();
2425
2469
  if (dragNode) {
2426
2470
  domNode.remove();
@@ -2473,6 +2517,22 @@ var WorkflowDragService = class {
2473
2517
  dispose: () => this.posAdjusters.delete(adjuster)
2474
2518
  };
2475
2519
  }
2520
+ /**
2521
+ * 判断是否可以放置节点
2522
+ */
2523
+ canDropToNode(params) {
2524
+ const { dragNodeType, dropNode } = params;
2525
+ if (!dragNodeType) {
2526
+ return {
2527
+ allowDrop: false,
2528
+ message: "Please select a node to drop"
2529
+ };
2530
+ }
2531
+ return {
2532
+ allowDrop: true,
2533
+ dropNode
2534
+ };
2535
+ }
2476
2536
  /**
2477
2537
  * 获取拖拽偏移
2478
2538
  */
@@ -2503,23 +2563,24 @@ var WorkflowDragService = class {
2503
2563
  return offset;
2504
2564
  }
2505
2565
  updateDroppableTransforms() {
2506
- this._droppableTransforms = this.document.getRenderDatas(FlowNodeTransformData5, false).filter((transform) => {
2566
+ this._droppableTransforms = this.document.getRenderDatas(FlowNodeTransformData6, false).filter((transform) => {
2507
2567
  const { entity } = transform;
2508
2568
  if (entity.originParent) {
2509
2569
  return this.nodeSelectable(entity) && this.nodeSelectable(entity.originParent);
2510
2570
  }
2511
2571
  return this.nodeSelectable(entity);
2512
- }).filter((transform) => {
2513
- const { entity } = transform;
2514
- return entity.flowNodeType === FlowNodeBaseType2.SUB_CANVAS;
2515
- });
2572
+ }).filter((transform) => this.isContainer(transform.entity));
2573
+ }
2574
+ /** 是否容器节点 */
2575
+ isContainer(node) {
2576
+ return node?.getNodeMeta().isContainer ?? false;
2516
2577
  }
2517
2578
  /**
2518
2579
  * 获取节点整体位置
2519
2580
  */
2520
2581
  getNodesPosition(nodes) {
2521
2582
  const selectedBounds = Rectangle8.enlarge(
2522
- nodes.map((n) => n.getData(FlowNodeTransformData5).bounds)
2583
+ nodes.map((n) => n.getData(FlowNodeTransformData6).bounds)
2523
2584
  );
2524
2585
  const position = {
2525
2586
  x: selectedBounds.x,
@@ -2569,7 +2630,7 @@ var WorkflowDragService = class {
2569
2630
  return {
2570
2631
  hasError: false
2571
2632
  };
2572
- } else if (toNode.flowNodeType === FlowNodeBaseType2.SUB_CANVAS) {
2633
+ } else if (this.isContainer(toNode)) {
2573
2634
  return {
2574
2635
  hasError: false
2575
2636
  };
@@ -2604,6 +2665,7 @@ var WorkflowDragService = class {
2604
2665
  if (originLine?.disabled || isFromInActivePort || this.playgroundConfig.readonly || this.playgroundConfig.disabled) {
2605
2666
  return { dragSuccess: false, newLine: void 0 };
2606
2667
  }
2668
+ this.selectService.clear();
2607
2669
  const config = this.playgroundConfig;
2608
2670
  const deferred = new PromiseDeferred();
2609
2671
  const preCursor = config.cursor;
@@ -2649,9 +2711,12 @@ var WorkflowDragService = class {
2649
2711
  type: "onDrag"
2650
2712
  });
2651
2713
  this.setLineColor(line, this.linesManager.lineColor.drawing);
2652
- if (toNode && toNode.flowNodeType !== FlowNodeBaseType2.SUB_CANVAS) {
2714
+ if (toNode && !this.isContainer(toNode)) {
2653
2715
  const portsData = toNode.getData(WorkflowNodePortsData);
2654
- toPort = portsData.inputPorts[0];
2716
+ const { inputPorts } = portsData;
2717
+ if (inputPorts.length === 1) {
2718
+ toPort = inputPorts[0];
2719
+ }
2655
2720
  const { hasError } = this.handleDragOnNode(toNode, fromPort, line, toPort, originLine);
2656
2721
  lineErrorReset = hasError;
2657
2722
  }
@@ -2797,13 +2862,13 @@ import { EntityManager as EntityManager3 } from "@flowgram.ai/core";
2797
2862
  import { DisposableCollection as DisposableCollection3, Emitter as Emitter6 } from "@flowgram.ai/utils";
2798
2863
 
2799
2864
  // src/utils/layout-to-positions.ts
2800
- import { FlowNodeTransformData as FlowNodeTransformData6 } from "@flowgram.ai/document";
2865
+ import { FlowNodeTransformData as FlowNodeTransformData7 } from "@flowgram.ai/document";
2801
2866
  import { TransformData as TransformData10, startTween } from "@flowgram.ai/core";
2802
2867
  var layoutToPositions = async (nodes, nodePositionMap) => {
2803
2868
  const newNodePositionMap = {};
2804
2869
  nodes.forEach((node) => {
2805
2870
  const transform = node.getData(TransformData10);
2806
- const nodeTransform = node.getData(FlowNodeTransformData6);
2871
+ const nodeTransform = node.getData(FlowNodeTransformData7);
2807
2872
  newNodePositionMap[node.id] = {
2808
2873
  x: transform.position.x,
2809
2874
  y: transform.position.y + nodeTransform.bounds.height / 2
@@ -2821,7 +2886,7 @@ var layoutToPositions = async (nodes, nodePositionMap) => {
2821
2886
  const deltaY = (nodePositionMap[node.id].y - transform.bounds.height / 2 - transform.position.y) * v.d / 100;
2822
2887
  if (node.collapsedChildren?.length > 0) {
2823
2888
  node.collapsedChildren.forEach((childNode) => {
2824
- const childNodeTransformData = childNode.getData(FlowNodeTransformData6);
2889
+ const childNodeTransformData = childNode.getData(FlowNodeTransformData7);
2825
2890
  childNodeTransformData.fireChange();
2826
2891
  });
2827
2892
  }
@@ -2900,6 +2965,41 @@ WorkflowResetLayoutService = __decorateClass([
2900
2965
  injectable7()
2901
2966
  ], WorkflowResetLayoutService);
2902
2967
 
2968
+ // src/service/workflow-operation-base-service.ts
2969
+ import { inject as inject8 } from "inversify";
2970
+ import { Emitter as Emitter7 } from "@flowgram.ai/utils";
2971
+ import { FlowOperationBaseServiceImpl } from "@flowgram.ai/document";
2972
+ import { TransformData as TransformData11 } from "@flowgram.ai/core";
2973
+ var WorkflowOperationBaseServiceImpl = class extends FlowOperationBaseServiceImpl {
2974
+ constructor() {
2975
+ super(...arguments);
2976
+ this.onNodePostionUpdateEmitter = new Emitter7();
2977
+ this.onNodePostionUpdate = this.onNodePostionUpdateEmitter.event;
2978
+ }
2979
+ updateNodePosition(nodeOrId, position) {
2980
+ const node = this.toNodeEntity(nodeOrId);
2981
+ if (!node) {
2982
+ return;
2983
+ }
2984
+ const transformData = node.getData(TransformData11);
2985
+ const oldPosition = {
2986
+ x: transformData.position.x,
2987
+ y: transformData.position.y
2988
+ };
2989
+ transformData.update({
2990
+ position
2991
+ });
2992
+ this.onNodePostionUpdateEmitter.fire({
2993
+ node,
2994
+ oldPosition,
2995
+ newPosition: position
2996
+ });
2997
+ }
2998
+ };
2999
+ __decorateClass([
3000
+ inject8(WorkflowDocument)
3001
+ ], WorkflowOperationBaseServiceImpl.prototype, "document", 2);
3002
+
2903
3003
  // src/hooks/use-playground-readonly-state.ts
2904
3004
  import { useEffect } from "react";
2905
3005
  import { usePlayground, useRefresh } from "@flowgram.ai/core";
@@ -2922,7 +3022,7 @@ function checkTargetDraggable(el) {
2922
3022
  }
2923
3023
  function useNodeRender(nodeFromProps) {
2924
3024
  const node = nodeFromProps || useContext(PlaygroundEntityContext);
2925
- const renderData = node.getData(FlowNodeRenderData2);
3025
+ const renderData = node.getData(FlowNodeRenderData3);
2926
3026
  const portsData = node.getData(WorkflowNodePortsData);
2927
3027
  const readonly = usePlaygroundReadonlyState();
2928
3028
  const dragService = useService(WorkflowDragService);
@@ -2952,7 +3052,7 @@ function useNodeRender(nodeFromProps) {
2952
3052
  return;
2953
3053
  }
2954
3054
  isDragging.current = true;
2955
- dragService.startDragSelectedNodes(e).finally(
3055
+ dragService.startDragSelectedNodes(e)?.finally(
2956
3056
  () => setTimeout(() => {
2957
3057
  isDragging.current = false;
2958
3058
  })
@@ -2965,7 +3065,7 @@ function useNodeRender(nodeFromProps) {
2965
3065
  if (isDragging.current) {
2966
3066
  return;
2967
3067
  }
2968
- if (e.metaKey || e.shiftKey || e.ctrlKey) {
3068
+ if (e.shiftKey) {
2969
3069
  selectionService.toggleSelect(node);
2970
3070
  } else {
2971
3071
  selectionService.selectNode(node);
@@ -3034,11 +3134,11 @@ function useNodeRender(nodeFromProps) {
3034
3134
  }
3035
3135
 
3036
3136
  // src/hooks/use-current-dom-node.ts
3037
- import { FlowNodeRenderData as FlowNodeRenderData3 } from "@flowgram.ai/document";
3137
+ import { FlowNodeRenderData as FlowNodeRenderData4 } from "@flowgram.ai/document";
3038
3138
  import { useEntityFromContext } from "@flowgram.ai/core";
3039
3139
  function useCurrentDomNode() {
3040
3140
  const entity = useEntityFromContext();
3041
- const renderData = entity.getData(FlowNodeRenderData3);
3141
+ const renderData = entity.getData(FlowNodeRenderData4);
3042
3142
  return renderData.node;
3043
3143
  }
3044
3144
 
@@ -3068,20 +3168,20 @@ var InteractiveType = /* @__PURE__ */ ((InteractiveType2) => {
3068
3168
 
3069
3169
  // src/workflow-document-container-module.ts
3070
3170
  import { ContainerModule } from "inversify";
3071
- import { FlowDocument as FlowDocument2, FlowDocumentContribution } from "@flowgram.ai/document";
3072
3171
  import { bindContributions } from "@flowgram.ai/utils";
3172
+ import { FlowDocument as FlowDocument2, FlowDocumentContribution } from "@flowgram.ai/document";
3073
3173
 
3074
3174
  // src/workflow-document-contribution.ts
3075
- import { injectable as injectable8, inject as inject8 } from "inversify";
3175
+ import { injectable as injectable8, inject as inject9 } from "inversify";
3076
3176
  import {
3077
- FlowNodeRenderData as FlowNodeRenderData4,
3078
- FlowNodeTransformData as FlowNodeTransformData7
3177
+ FlowNodeRenderData as FlowNodeRenderData5,
3178
+ FlowNodeTransformData as FlowNodeTransformData8
3079
3179
  } from "@flowgram.ai/document";
3080
3180
  var WorkflowDocumentContribution = class {
3081
3181
  registerDocument(document2) {
3082
3182
  document2.registerNodeDatas(
3083
- FlowNodeTransformData7,
3084
- FlowNodeRenderData4,
3183
+ FlowNodeTransformData8,
3184
+ FlowNodeRenderData5,
3085
3185
  WorkflowNodePortsData,
3086
3186
  WorkflowNodeLinesData
3087
3187
  );
@@ -3089,7 +3189,7 @@ var WorkflowDocumentContribution = class {
3089
3189
  }
3090
3190
  };
3091
3191
  __decorateClass([
3092
- inject8(FreeLayout)
3192
+ inject9(FreeLayout)
3093
3193
  ], WorkflowDocumentContribution.prototype, "freeLayout", 2);
3094
3194
  WorkflowDocumentContribution = __decorateClass([
3095
3195
  injectable8()
@@ -3114,6 +3214,7 @@ var WorkflowDocumentContainerModule = new ContainerModule(
3114
3214
  bind(WorkflowSelectService).toSelf().inSingletonScope();
3115
3215
  bind(WorkflowHoverService).toSelf().inSingletonScope();
3116
3216
  bind(WorkflowResetLayoutService).toSelf().inSingletonScope();
3217
+ bind(WorkflowOperationBaseService).to(WorkflowOperationBaseServiceImpl).inSingletonScope();
3117
3218
  bind(URLParams).toDynamicValue(() => getUrlParams()).inSingletonScope();
3118
3219
  bindContributions(bind, WorkflowDocumentContribution, [FlowDocumentContribution]);
3119
3220
  bind(WorkflowDocumentOptions).toConstantValue({
@@ -3223,6 +3324,8 @@ export {
3223
3324
  WorkflowNodeEntity,
3224
3325
  WorkflowNodeLinesData,
3225
3326
  WorkflowNodePortsData,
3327
+ WorkflowOperationBaseService,
3328
+ WorkflowOperationBaseServiceImpl,
3226
3329
  WorkflowPortEntity,
3227
3330
  WorkflowResetLayoutService,
3228
3331
  WorkflowSelectService,